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.
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
});