Keycloak can secure your Node.js Express API by acting as an OAuth 2.0 authorization server, issuing JWTs that your API validates.
Let’s see this in action. Imagine a simple Express app that needs to protect a /users endpoint.
const express = require('express');
const jwt = require('express-jwt');
const jwksClient = require('jwks-rsa');
const app = express();
// Middleware to validate JWTs
const checkJwt = jwt({
secret: jwksRsa.expressJwtSecret({
cache: true,
rateLimit: true,
jwksUri: 'http://localhost:8080/realms/myrealm/.well-known/openid-configuration/jwks'
}),
audience: 'my-api-client',
issuer: 'http://localhost:8080/realms/myrealm',
algorithms: ['RS256']
});
// Protected route
app.get('/users', checkJwt, (req, res) => {
res.json({ message: 'Hello from protected users endpoint!' });
});
app.listen(3000, () => {
console.log('API listening on port 3000');
});
Here’s how it works under the hood:
- Keycloak Setup: You’ll need a Keycloak instance running. Inside Keycloak, create a realm (e.g.,
myrealm). Within that realm, create a client (e.g.,my-api-client). This client represents your Node.js application. Configure it with a "Confidential" access type and set a "Valid Redirect URIs" (e.g.,http://localhost:3000/*). Keycloak will generate signing keys for your realm. - Node.js Integration:
- Install necessary packages:
npm install express express-jwt jwks-rsa. - The
express-jwtmiddleware is the core of the protection. It intercepts incoming requests to protected routes. jwks-rsais used to fetch the public keys from Keycloak’s JWKS (JSON Web Key Set) endpoint. These keys are whatexpress-jwtuses to verify the signature of the JWT.secret: This is configured to usejwksRsa.expressJwtSecretwhich dynamically fetches the public keys from the JWKS URI provided by Keycloak. ThecacheandrateLimitoptions are crucial for performance and security in production.audience: This should match theresourcesetting for your client in Keycloak. It ensures the token was intended for this specific API.issuer: This must match the Keycloak realm URL. It verifies that the token was issued by the expected Keycloak instance.algorithms: Specifies the signing algorithm used by Keycloak (typically RS256).
- Install necessary packages:
- Client Authentication: A separate client (e.g., a web app or mobile app) will authenticate with Keycloak using OAuth 2.0 flows (like Authorization Code Flow). Upon successful authentication, Keycloak issues an ID Token and an Access Token (both JWTs) to the client.
- API Request: The client then includes the Access Token in the
Authorizationheader of requests to your protected Node.js API, usually as aBearertoken:Authorization: Bearer <access_token>. - Token Validation: When your Node.js API receives a request to
/users, thecheckJwtmiddleware runs. It extracts theBearertoken, fetches Keycloak’s public keys usingjwks-rsa, and verifies the JWT’s signature, expiration, audience, and issuer. If all checks pass, the middleware allows the request to proceed to your route handler. If not, it returns a401 Unauthorizedor403 Forbiddenerror.
The most surprising thing about this setup is that your Node.js API doesn’t need to store any secrets or keys related to user authentication. All cryptographic verification is done against Keycloak’s public keys, which are readily available and regularly rotated by Keycloak itself. This dramatically simplifies secret management for your API services.
The next step is to handle different user roles and permissions, which are also encoded within the JWT claims.