Skip to main content

Guide: Node (Express)

Step 1: Extract the Bearer Token from request header

A authorized request should contain an Authorization header with Bearer <access_token> as its content. Extract the Authorization Token from the request header:

// auth_middleware.ts

import { IncomingHttpHeaders } from 'http';

const extractBearerTokenFromHeaders = ({ authorization }: IncomingHttpHeaders) => {
const bearerTokenIdentifier = 'Bearer';

if (!authorization) {
throw new Error({ code: 'auth.authorization_header_missing', status: 401 });
}

if (!authorization.startsWith(bearerTokenIdentifier)) {
throw new Error({ code: 'auth.authorization_token_type_not_supported', status: 401 });
}

return authorization.slice(bearerTokenIdentifier.length + 1);
};

Step 2: Token validation

For demonstration, we use jose package to validate the token's signature, expiration status, and required claims.

Install jose as your dependency

npm i jose --save

Retrieve Logto's OIDC configurations

You will need a JWK public key set and the token issuer to verify the signature and source of the received JWS token. All the latest public Logto Authorization Configurations can be found at https://<your-logto-domain>/oidc/.well-known/openid-configuration.

e.g. Call https://tenant-id.logto.app/oidc/.well-known/openid-configuration. And locate the following two fields in the response body:

{
"jwks_uri": "https://tenant-id.logto.app/oidc/jwks",
"issuer": "https://tenant-id.logto.app/oidc"
}

Add auth middleware

Jose's jwtVerify method may helps you to verify the token's JWS format, token signature, issuer, audience and the expiration status. A exception will be thrown if validation failed.

warning

If you use Role-based access control, scope validation is also required.

// auth-middleware.ts

import { createRemoteJWKSet, jwtVerify } from 'jose';

//...

export const verifyAuthFromRequest = async (req, res, next) => {
// Extract the token
const token = extractBearerTokenFromHeaders(req.headers);

const { payload } = await jwtVerify(
token, // The raw Bearer Token extracted from the request header
createRemoteJWKSet(new URL('https://<your-logto-domain>/oidc/jwks')), // generate a jwks using jwks_uri inquired from Logto server
{
// expected issuer of the token, should be issued by the Logto server
issuer: 'https://<your-logto-domain>/oidc',
// expected audience token, should be the resource indicator of the current API
audience: '<your request listener resource indicator>',
}
);

// if you are using RBAC
assert(payload.scope.includes('some_scope'));

// custom payload logic
userId = payload.sub;

return next();
};

Apply middleware to your API

import { verifyAuthFromRequest } from '/middleware/auth-middleware.ts';

app.get('/user/:id', verifyAuthFromRequest, (req, res, next) => {
// Custom code
});