SPA + API: Node.js Implementation for the API
This document is part of the SPA + API Architecture Scenario and it explains how to implement the API in Node.js. Please refer to the scenario for information on the implemented solution.
1. Define the API endpoints
We will use the Express web application framework to build our Node.js API.
Create a package.json File
Create a folder for your API, navigate into it and run
npm init. This will setup your
You can leave the default settings or change them as you see fit.
package.json looks like the following:
Install the Dependencies
Next, we need to set our dependencies. We will use the following modules:
express: This module adds the Express web application framework.
cors: This module adds support for enabling CORS which is required since the API will be called from a Single-Page Application running on a different domain inside a web browser.
jwks-rsa: This library retrieves RSA signing keys from a JWKS (JSON Web Key Set) endpoint. Using
expressJwtSecretwe can generate a secret provider that will provide the right signing key to
express-jwtbased on the
kidin the JWT header. For more information refer to the node-jwks-rsa GitHub repository.
express-jwt: This module lets you authenticate HTTP requests using JWT tokens in your Node.js applications. It provides several functions that make working with JWTs easier. For more information refer to the express-jwt GitHub repository.
body-parser: This is a Node.js body parsing middleware. It extracts the entire body portion of an incoming request stream and exposes it on
req.bodyas something easier to interface with. For more information and several alternatives refer to the body-parser GitHub repository.
To install these dependencies run the following:
Implement the Endpoints
Navigate to your API directory and create a
server.js file. Your code needs to:
- Get the dependencies.
- Implement the endpoint(s).
- Launch the API server.
This is our sample implementation:
Launch your API server using
node server and make an HTTP POST request to
localhost:8080/timesheets. You should see a JSON response with the message
This is the POST /timesheets endpoint.
So now we have our endpoint but anyone can call it. Continue to the next paragraph to see how we can fix this.
2. Secure the API endpoints
In order to validate our token we will use the
jwt function, provided by the express-jwt middleware, and the
jwks-rsa to retrieve our secret. The libraries do the following:
express-jwtwill decode the token and pass the request, the header and the payload to
jwks-rsawill then download all signing keys from the JWKS endpoint and see if a one of the signing keys matches the
kidin the header of the JWT. If none of the signing keys match the incoming
kid, an error will be thrown. If we have a match, we will pass the right signing key to
express-jwtwill the continue its own logic to validate the signature of the token, the expiration,
The steps we will follow in our code are:
- Create the middleware function to validate the Access Token.
- Enable the use of the middleware in our routes.
You can also write some code to actually save the timesheet to a database. This is our sample implementation (some code is omitted for brevity):
If we launch our server now and do an HTTP POST to
localhost:8080/timesheets we should get the error message
Missing or invalid token (which is perfectly fine since we didn’t send an Access Token in our request).
In order to test the working scenario as well we need to:
- Get an Access Token. For details on how to do so refer to: Get an Access Token.
- Invoke the API while adding an
Authorizationheader to our request with the value
Bearer ACCESS_TOKEN(where ACCESS_TOKEN is the value of the token we retrieved in the first step).
3. Check the application permissions
In this step we will add to our implementation the ability to check if the application has permissions (or
scope) to use our endpoint in order to create a timesheet. In particular we want to ensure that the token has the correct scope, which is
In order to do this we will make use of the
express-jwt-authz Node.js package, so go ahead and add that to your project:
Now it is as simple as adding a call to
jwtAuthz(...) to your middleware to ensure that the JWT contain a particular scope in order to execute a particular endpoint.
The express-jwt-authz library, which is used in conjunction with express-jwt, validates the JWT and ensures it bears the correct permissions to call the desired endpoint. For more information refer to the express-jwt-authz GitHub repository.
This is our sample implementation (some code is omitted for brevity):
If we invoke our API with a token that does not include this scope we should get the error message Forbidden with the HTTP status code
403. You can test this by removing this scope from your API.
4. Determine the User Identity
express-jwt middleware which is used to validate the JWT, also sets the
req.user with the information contained in the JWT. If you want to use the
sub claim to identify the user uniquely, you can simply use
In the case of the timesheets application however, we want to use the email address of the user as the unique identifier.
The first thing we need to do is to write a rule which will add the email address of the user to the Access Token. Go to the Rules section of the Dashboard and click on the Create Rule button.
You can give the rule a descriptive name, for example
Add email to Access Token, and then use the following code for the rule:
namespace is used to ensure the claim has a unique name and does not clash with the names of any of the standard OIDC claims. You can typically use the URL of your application or API as the namespace.
Now, inside your API, you can retrieve the value of the claim from
req.user, and use that as the unique user identity which you can associate with timesheet entries.