Node.js REST API Bitbucket Login

Making user registration and login fast and easy is an important part of developing a new application. Not so long ago, registration forms were mandatory, and, often, users didn’t like them much. These forms required users to manually populate data, sometimes 10 or even more input fields, and not every user wanted to spend their precious time on that. Because of that, a lot of web applications lost potential users. Additionally we had login forms, in which users had to enter their usernames/emails and passwords. Often, users would forget their passwords and wouldn’t bother going through the process of password recovery, because they would find it tedious. So again, our application would lose its users.
Nowadays, we have a much better way to register and login users to our applications. We can now allow users to register using their social network accounts which they usually have. In this tutorial we will allow users to register and login with their Bitbucket accounts. So, if users want to create a new account in our application, they only need to press a single button provided by our application and then just approve the access to their data on Bitbucket. Similarly, login is just a click of a button away from our users, but this time it is not even necessary to allow the access to the data. No password, no username, just a single click of a button :) It’s that easy.
In this tutorial we will integrate Bitbucket authentication to a REST API created using Express.js. On the backend side we will use MongoDB as a database, Node.js and Express.js. On the frontend side we will implement simple application that will enable us to demonstrate the entire registration and login workflow.
What Is OAuth?
OAuth is an open standard for distributed authentication and authorization. The standard was developed by Twitter in 2006, and it is commonly used as a way for Internet users to authorize websites or applications to access their information on other websites without giving them passwords to their accounts. It is used by many well known companies such as Google, Twitter, Facebook, Bitbucket and Microsoft. A comprehensive list of OAuth providers can be found on this link.
What does this means for our application? It means that users can register and use it without entering any data in our registration form. They just need to authorize the application to access their data on a selected OAuth provider, and they are ready to use it. Just one click. Isn’t that amazing? Additionally, a security benefit of logging in in this manner is that users don’t need to remember passwords for our application, and we don’t need to store those passwords. This also prevents security holes caused by password reuse and inappropriate storing of passwords.
Authentication Workflow
In this section we will describe the process of the Bitbucket authentication. To demonstrate workflow we will use a client application written in React and a backend REST API that is written in Express.js. Similar process can be applied for any single page application (SPA) and the REST API backend.
When users want to register for our application, they will click the login button. When the button is clicked, our client application will request an access token from Bitbucket. Then, the user will be presented with a dialog to allow the application to access some of their Bitbucket data. If the user gives their permission, our client application will get the Bitbucket access token in response. At this moment we can access user data from the client application, but an account is not yet created at our backend. In order to create new user account, our client application sends a request to our backend with the Bitbucket access token. The backend needs to verify the Bitbucket access token, so it sends a verification request directly to Bitbucket. If the Bitbucket token is valid, the Bitbucket server will send user data back to our application. Upon receiving this data, the backend server has verified that the user credentials are valid and will create a user profile in our application with data received from Bitbucket. After that, the backend needs to create a JSON Web Token (JWT) which will be used to identify the user. This token is then sent in a response to the client application. The client application will receive JWT and save it for further use. Every request that goes to the backend server should contain a JWT which uniquely identifies the user. The described flow is shown in figure 1.
The process for user login is similar, so we will not describe it in details. During the login process, users do not need to allow the application to access its Bitbucket data and the backend will not use the Bitbucket data to create a new user, but instead it will update the user profile data on our backend.

In the following sections we will go through the process of creating a demo application in order to illustrate what we have just described.
Creating a New Bitbucket Application
In order to make it possible for users to log into our application with their Bitbucket accounts, we need to create an OAuth consumer on the Bitbucket. This is a necessary step for getting key and secret code required for all future communication between our application and the Bitbucket. It is needed so that our application could identify itself to Bitbucket. Bitbucket provides a well-written documentation that can be found here.
On Dasboard page we need to click on avatar in the bottom left, and select Bitbucket settings option.

From left navigation then we need to choose OAuth. This will open page where we can create new consumer, new application that will use Bitbucket API, or manage all authorized application that we are using on Bitbucket.

In next step we will create new consumer. By clicking on Add consumer button we will open page for adding new consumer. On the page we have to enter information about our application:
- name — The display name for our consumer. This must be unique within our account.
- callback URL — Required for OAuth 2.0 consumers. This will be route in our React application that parse token and finish login with our backend. In our case we will put there http://localhost:3000. When user load application, application will automatically try to parse token and do the authentication.
- permissions — Permissions that are needed for our application. In our case we need data about account(email and read) and in case if we use v1 of Bitbucket API we will need to read repositories of user.

Back on OAuth page we can find our new application. When click on it’s name we will be able to see key and secrete that we need in order to communicate with Bitbucket API.
Client Setup — React
In this section we will create a client application in React. The application will demonstrate how to implement Bitbucket authorization in React. For setting up project we have used Create React App. On project site can be found great documentation how to install the tool. So we will skip that part.
New application can be created with command:
create-react-app frontendAfter that we need to install only dependency that we need for this example:
npm i axios -SWhat is axios?Axios is promise based HTTP client for the browser and Node.js. We will use it in this example to communicate with our backend.
Client Flow
Bitbucket doesn’t have React library for user logging. Because of that when user press login button we will open page for user logging on Bitbucket. URL of Bitbucket application that we need to use is little bit specific because it has to contain key of our application: https://bitbucket.org/site/oauth2/authorize?client_id={key}&response_type=token. If user manage to log in into Bitbucket, Bitbucket will redirect user to callback URL of consumer application. URL on which user is redirected should contain location of our React application and access token. On page loading we will parse access token from URL and use that token to authorize user on our backend application.
Now goes the funny part, the code :)
React Application
The whole client application is in app.jsx file. Firstly we will explain the constructor. In constructor we are creating HTTP client that knows how to communicate with our backend application. Except for that we are also initializing state.
When the component is mounted, we want to parse URL. Why do we want to do that? When user click on login button, our application will open Bitbucket page for authentication. If user is successfully authenticated, Bitbucket will send him to callback URL of our application, with access token in URL. We need to parse URL in order to extract access token from URL. If we find access token in URL we will try to login user into our backend application. If URL is missing access token parameter, our user is not authenticated.
The authenticate method is used for user authentication. Firstly we are sending POST request with access token that we got from Bitbucket to our backend application. If our backend application respond without error, that means that user is authenticated. In response there is x-auth-token — token that is issued from our backend application and doesn’t have anything with access token issued by Bitbucket. By using x-auth-token we are creating new axios client. This is needed so that every request from now on that we are sending to our backend application would have token, and in that way every request will be connected to authenticated user. Last step is to set state of our client application. Basically we are storing into state information about user data, token, Bitbucket key and flag that user is authenticated.
The bitbucketLogin method is used for opening page for user authentication. Before we open page we must create appropriate URL, so that Bitbucket could know that user want to allow our application to access its data. That is done by using key that we got when we created application on our Bitbucket account.
The next method is logout. Logout is pretty simple. We just need to remove any data about user and token. Also we want to set flag that user is not authenticated anymore.
Last but not list, there is method that is used for rendering our application page. If user is authenticated we are showing its mail and logout button. On the other hand if user is not authenticated we will just show him login button.
Backend Setup — Node.js, Express.js
In this chapter we will describe our backend. We have decided that we want to create our backend application based on Node.js and Express.js. We will create REST API and the user should be able to log in with his Bitbucket account. At the end we will have a fully functional backend application on which the user will be able to create a new account, and to log into it with their Bitbucket account.
Dependencies
For creating REST API we will use Express.js. Parsing incoming request bodies in a middleware before our handlers will be done by body-parser. Handling JWT will be done by express-jwt and jsonwebtoken. Authentication will be done with passport, and for Bitbucket authentication we will use passport-bitbucket-token library. As database we will use MongoDB, and Mongoose to communicate with the database. Last but not least, we will need to enable CORS on our server and for that we will use cors library.
Database Model
We will persist user information in the database. As a database we will use MongoDB. For communication with MongoDB we can use MongoDB Node.js Driver or Mongoose. Mongoose internally uses MongoDB Node.js Driver for the communication with MongoDB. The questions we should be asking ourselves are: “Do we want to use the raw driver? Do we need an object-document modeling tool?” In a complex web application we will have many types of entities in database. By using object modeling framework(ODM, a counterpart to ORMs from the SQL world) we will be able to create better encapsulation of data and to skip some lower level work. Because of that we will use Mongoose for communication with MongoDB. On the official project page we can find the definition of Mongoose:
MongoDB object modeling tool designed to work in an asynchronous environment. Mongoose provides a straight-forward, schema-based solution to model your application data. It includes built-in type casting, validation, query building, business logic hooks and more, out of the box.
We have only one entity to model and that is user. We are only interested in the user’s email information from their Bitbucket profile, so that is the only thing that we will include. Also we will persist user access token and Bitbucket profile id.
An interesting thing to notice here, is that by putting select to false in bitbucketProvider object, we exclude bitbucketProvider field in result of queries by default. In order to get user with bitbucketProvider field, we need to specify explicitly in the query that we want that.
In UserSchema we have to add one static method that will be used for creating a new user if user doesn’t exist already. That method is upsertBitbucketUser.
What we try to do in this method, is, first, to find the user by their Bitbucket profile id. If we find a user with a matching Bitbucket profile id, that means that user already have an account, which is associated with their Bitbucket profile. In that case we don’t need to do anything here. If we haven’t found a user, we will create a new user and save it in the database.
Passport Configuration
As mentioned, for authentication, we will use the Passport library. Passport is authentication middleware for Node.js. It’s extremely flexible and modular. Passport supports many authentication mechanisms, which are referred to as strategies, so there is a local strategy, for login with username and password, a Facebook strategy, a Twitter strategy, a Bitbucket strategy, etc. A list of all strategies can be found on the official site.
We will use passport-bitbucket-token, the Passport strategy for authenticating with Bitbucket access tokens using the OAuth 2.0 API. There is also the passport-bitbucket library that contains a strategy for Bitbucket authentication, but this library is not suitable for REST API. It is better suited for Express.js applications which are used with some server rendering library.
The code for initialization of Passport with Bitbucket strategy looks like this:
In order to initialize the strategy we need to supply our Bitbucket application key and secret. Those two pieces of information will be used to identify our application. We also have to supply a verify callback function. In our case this function calls the static method upserBitbucketUser from User model, which will check if the given user exist, and if not, create one.
Token Handling
JWT, as explained on Wikipedia:
JWT is a JSON-based open standard (RFC 7519) for creating access tokens that assert some number of claims. For example, a server could generate a token that has the claim “logged in as admin” and provide that to a client. The client could then use that token to prove that it is logged in as admin.
In our example we will only store the user’s ID in a token, sign it, and send it to the frontend. For creating JWT we will use jsonwebtoken library.
In the function createToken we are getting user (auth) as function argument, and use the id to create a token. In this case we are using my-secret as private key; in production we should use either the secret for HMAC algorithms, or the PEM encoded private key for RSA and ECDSA as stated in the library documentation. The function generateToken has request and response, and because of that it has access to current user. So we will generate a token and put it in the request object. sendToken is a function that will take the token from request object and put it in the header.
For validation of the JWT in every frontend request, we will use express-jwt. How do we use express-jwt? If the token is valid, req.auth will be set with the JSON object decoded to be used by later middleware for authorization and access control. The authenticate function does exactly that:
Property secret should have the same value as in the createToken function. By setting requestProperty we have the changed property name into name which we will put into the decoded JSON object. The property getToken is a function that is used to extract a token from request, and in this case the token is in the header x-auth-token.
Authentication Flow
So, by now, we have all the building blocks. We have to connect all of our blocks in a system that will do the Bitbucket authentication. For authentication, we will create REST endpoint with the path : http://localhost:3000/api/v1/auth/bitbucket. We will also create an endpoint from which we can get the currently authenticated user: http://localhost:3000/api/v1/auth/me.
For authentication, we are creating a route for POST HTTP method. When the user calls this endpoint, we first use Passport to authenticate the user. After that, we add the middleware, in which we are checking if there is a user with the given Bitbucket account in system. If one is not found, we send response with 401 HTTP status code. If the user is found, we create an auth object, into which we put just user ID. The next middleware is for generating the token, and after that we use middleware for sending that token.
To get current user, we first need to create a middleware which will find the user in the database. That will be done via the getCurrentUser function. Function getOne takes the found user, and sends it as a response. The endpoint for getting current user is, basically :
- Authenticate user and find it’s ID
- Find current user in database
- Return current user as response
CORS
Currently, we have two applications, React application and Node.js/Express.js application, hosted on two servers. If we don’t set up CORS, our React application will not be able to communicate with the backend. In order to enable CORS on our backend, we will use the Node.js library cors.
By setting origin to true, we have allowed any origin to access the resource. methods is used to control Access-Control-Allow-Methods CORS header, and with this string we have allowed almost all HTTP methods. With the property credentials we are controlling the Access-Control-Allow-Credentials CORS header. The last, and very important property, exposedHeaders, is used to indicate which headers can be exposed as part of the response. If we haven’t set this property, the client library would ignore our custom header with user token.
HTTPS — Make Sure You Use It
You MUST use HTTPS in production!
In this demo we will work on our local machine and we will NOT using HTTPS — but you MUST use HTTPS in production. Without it, all API authentication mechanisms are compromised.
You have been warned.
Conclusion
Congratulations! You now have a fully functional example of Bitbucket authentication. We have created a React application that can communicate with REST API and authenticate a user with Bitbucket account. We have also created a Node.js/Express.js application that exposes REST API for that purpose.
The complete source code from this project can be found at the following GitHub repository:
I hope you have enjoyed this tutorial, and learned a thing, or two. There is obviously much more to be done, but this should get you started.
If you have any questions or issues getting this to work feel free to contact me on Twitter @robince885 or in the comments below. You can find more information about me on LinkedIn:
I would like to thank @vdimitrieski for his help and support. Feel free to contact him as well. Some more information about him and what he is doing you can found on his LinkedIn:
I would also like to thank my dear friend Srđan Gavrilović for helping me with English. More information about him you can find on his LinkedIn:
