keycloak-express 1.0.0-alpha.2
Install from the command line:
Learn more about npm packages
$ npm install @bcgov/keycloak-express@1.0.0-alpha.2
Install via package.json:
"@bcgov/keycloak-express": "1.0.0-alpha.2"
About this version
TL/DR:
- Install package by following the steps at Installing the Package.
- Set up the package by following the steps at Getting Started with the Integration.
- For use with @bcgov/keycloak-react.
- General Information
- Installing the Package - Start Here!
- Getting Started with the Integration - Setting up after installing.
- Environment Variables - Required variables for initialization.
- Module Exports - Functions and Types available from the module.
- Initialization Options - Additional options.
- Authentication Flow - How it works from login button click.
- Authentication on an Endpoint - Require user to be signed in.
- Authorization on an Endpoint - Require user to have a permission.
- For running on a NodeJS:18 Express API.
- For Keycloak Gold Standard.
- Works with Vanilla JavaScript or Typescript 5.
- For use with @bcgov/keycloak-react
- Set up a personal access token (classic) with the
read:packages
permission. Suggested name:Read Packages
. Be sure to copy the access token.
- Run the following command to log into NPM where
Username
is your GitHub username (lowercase), andPassword
is the personal access token:
npm login --scope=@bcgov --registry=https://npm.pkg.github.com
- Run the install command from the Packages page.
- Add import
const { keycloak } = require('@bcgov/keycloak-express');
orimport { keycloak } from '@bcgov/keycloak-express';
to the top of the file that defines the express app. Addkeycloak(app);
below the definition of the express app, whereapp
is defined byexpress()
.
Example:
import express from 'express';
import { keycloak } from '@bcgov/keycloak-express';
// Define Express App
const app = express();
// Initialize Keycloak(app: express.Application, options?: KeycloakOptions).
keycloak(app);
- Add the required environment variables from the Environment Variables section below.
# Ensure the following environment variables are defined on the container.
ENVIRONMENT= # (local only) Set to 'local' when running container locally.
FRONTEND_PORT= # (local only) Port of the frontend application.
PORT= # (local only) Port of the backend application.
FRONTEND_URL= # (production only) URL of the frontend application.
BACKEND_URL= # (production only) URL of the backend application.
SSO_CLIENT_ID= # Keycloak client_id
SSO_CLIENT_SECRET= # Keycloak client_secret
SSO_AUTH_SERVER_URL= # Keycloak auth URL, see example below.
# https://dev.loginproxy.gov.bc.ca/auth/realms/standard/protocol/openid-connect
These are the functions and types exported by the @bcgov/keycloak-express
module.
import {
keycloak, // Initializes the keycloak service in your express app.
protectedRoute, // Middleware function used for authentication and authorization.
} from '@bcgov/keycloak-express';
// Types:
function keycloak(app: Application, options?: KeycloakOptions): void; // Application from 'express'.
function protectedRoute(roles?: string | string[], options?: { requireAllRoles?: boolean }): RequestHandler;
// Typescript Types
import {
KeycloakUser, // Base type for req.user
KeycloakIdirUser, // User types specific to Idir users
KeycloakBCeIDUser, // User types specific to BCeID users
KeycloakGithubUser, // User types specific to Github users
KeycloakOptions, // Type of optional second parameter for keycloak
} from '@bcgov/keycloak-express';
// Types:
type KeycloakIdirUser = {
identity_provider: "idir";
idir_user_guid: string;
idir_username: string;
given_name: string;
family_name: string;
};
type KeycloakBCeIDUser = {
identity_provider: "bceidbasic" | "bceidbusiness" | "bceidboth";
bceid_user_guid: string;
bceid_username: string;
bceid_business_name?: string;
};
type KeycloakGithubUser = {
identity_provider: "githubbcgov" | "githubpublic";
github_id: string;
github_username?: string;
orgs?: string;
given_name?: string;
family_name?: string;
first_name?: string;
last_name?: string;
};
type KeycloakUser = {
name?: string;
preferred_username: string;
email: string;
display_name: string;
client_roles?: string[];
scope?: string;
} & (KeycloakIdirUser | KeycloakBCeIDUser | KeycloakGithubUser);
interface KeycloakOptions {
afterUserLogin?: (userInfo: KeycloakUser) => void;
}
Optional second parameter to the keycloak()
function.
Currently supports the following functionality:
/*
* A function that will be passed the userInfo defined as the
* KeycloakUser type or the same as req.user.
*
* Use cases:
* - Add user to database upon first login.
* - Update a last login field in database.
*/
afterUserLogin?: (userInfo: KeycloakUser) => void;
Example usage:
import express from 'express';
import { keycloak } from '@bcgov/keycloak-express';
import { activateUser } from './src/utils'; // External function (not provided by keycloak-express).
// Define Express App
const app = express();
// Initialize Keycloak.
const keycloakOptions = { afterUserLogin: activateUser };
keycloak(app, keycloakOptions);
The Keycloak Authentication system begins when the user visits the frontend application.
- The user visits the frontend of the application. Here, the
KeycloakWrapper
component initializes and checks the URL for a query parameter namedtoken
.
-
If the
token
query parameter is found:- The component strips the URL of the access token.
- The user's information is set into the state using the token.
- The user can now access the frontend of the application.
-
If the
token
query parameter is not found, the component checks if the user is logged in by using the refresh token to get a new access token by communicating with the/api/oauth/token
endpoint.- If the refresh token exists and is valid, the user can now access the frontend of the application without seeing the login button, as their session is authenticated through the refresh token.
- If the refresh token doesn't exist or is invalid, the login button is displayed.
-
When the user clicks the login button, they are routed to the
/api/oauth/login
endpoint via a proxy pass, which then redirects them to the Keycloak login page. -
Upon successful login at the Keycloak login page, Keycloak redirects the user to the
/oauth/login/callback
endpoint. -
The authentication code returned by the callback endpoint is used to retrieve the access token and the refresh token for the user.
-
The user is redirected back to the frontend with the access token included as a
token
query parameter and the refresh token set as an httpOnly cookie. -
The
KeycloakWrapper
component re-initiates and the process repeats from step 1, this time with thetoken
query parameter available.
Require keycloak authentication before using an endpoint.
Import protectedRoute
from @bcgov/keycloak-express
and add as middleware.
import { protectedRoute } from '@bcgov/keycloak-express';
app.use("/users", protectedRoute(), usersRouter);
// Users must have 'Member' role.
app.use("/post", protectedRoute('Member'), postRouter);
// Users must have BOTH 'Member' and 'Commenter' roles.
app.use("/comment", protectedRoute(['Member', 'Commenter']), commentRouter);
// Users must have EITHER 'Member' or 'Verified' role.
app.use("/vote", protectedRoute(['Member', 'Verified'], { requireAllRoles: false }), voteRouter);
Get the keycloak user info in a protected endpoint.
IMPORTANT: req.user
is either populated or null and the req.user.client_roles
property is either a populated array or undefined.
Example within a controller of a protected route:
const user = req.user;
if (!user) return res.status(404).send("User not found.");
else {
if (!req.user?.client_roles?.includes('Admin'))
return res.status(403).send('User must be Admin.');
// Do something with user.
}
For all user properties reference SSO Keycloak Wiki - Identity Provider Attribute Mapping.
Example IDIR req.user
object (Typescript Type is KeycloakUser & KeycloakIdirUser
):
{
"idir_user_guid": "W7802F34D2390EFA9E7JK15923770279",
"identity_provider": "idir",
"idir_username": "JOHNDOE",
"name": "Doe, John CITZ:EX",
"preferred_username": "a7254c34i2755fea9e7ed15918356158@idir",
"given_name": "John",
"display_name": "Doe, John CITZ:EX",
"family_name": "Doe",
"email": "john.doe@gov.bc.ca",
"client_roles": ["Admin"]
}
Details
- keycloak-express
- bcgov
- over 1 year ago
- Apache-2.0
- 4 dependencies
Assets
- keycloak-express-1.0.0-alpha.2.tgz
Download activity
- Total downloads 3
- Last 30 days 0
- Last week 0
- Today 0