overview
nyckel
Authentication for hybrid web apps
A fairly extensive Auth0-interfacing collection of TypeScript modules that allow authentication with Auth0 throughout a hybrid web app, consisting of both browser- and server rendered frontends as well as backends. Authentication is handled as distributed sessions containing JWTs that are cross-validated when permissions are necessary, to prevent stale tokens.
Details
Nyckel is a collection of TypeScript modules for server-side/client-side hybrid web apps, providing both session support and authentication support using Auth0. The main goal behind this project was to simplify handling of user authentication in web projects and make a fully tested abstraction of what is typically quite complex code. In the end, this is achieved via a public-facing API that is very simple to use and hopefully is perceived as non-magic and intuitive.
The packages
@nyckel/express-middleware
This package is an express middleware, combining all of the other packages into a fully fledged authentication solution under some specific routes:
/auth/login
- an user-facing endpoint from which authentication is initiated
/auth/logout
- an user-facing endpoint from which the current session is ended and user is properly logged out (via Auth0)
/auth/loggedout
- an endpoint which serves as the callback location from an Auth0 logout
/auth/callback
- an endpoint which serves as the callback location from an Auth0 authentication attempt
@nyckel/http-middleware
This package provides utilities for accessing the current session and user of an HTTP request. For instance, the user can be provided as the following type:
type UserInRequest = {
get(): Promise<
| ({
accessTokenData: DecodedAccessToken;
idTokenData: DecodedIdToken;
accessToken: string;
idToken: string;
expiresIn: number;
})
| null
>;
userInfo(): Promise<any>;
fullUserData(): Promise<any>;
roles(): Promise<any>;
permissions(): Promise<any>;
}
@nyckel/sessions
This package provides a simple session manager using Redis as a backing store, with support for locking a single session during important reads and writes. All sessions are encrypted and stored under hashed keys, resulting in that only valid client requests can access the session data.
@nyckel/authentication
This package provides the interfacing with the Auth0 authentication API and is used by the other packages to handle user-facing authentication.
The APIs of this package are mainly for use in @nyckel/http-middleware
, which provides some helper functions for user authentication.
@nyckel/management
This package provides the interfacing with the Auth0 management API and is used by the other packages server-side to verify roles and permissions.
The APIs of this package are mainly for use in @nyckel/http-middleware
, which provides some helper functions for checking roles and permissions.
Usage example
import express from "express";
import cookieParser from "cookie-parser";
import { createGlobalAuthenticationConfig } from "@nyckel/authentication";
import { createSessionManager } from "@nyckel/sessions";
import { nyckelExpressMiddleware, asyncHandler } from "@nyckel/express-middleware";
const app = express();
app.use(cookieParser());
const authConfig = createGlobalAuthenticationConfig(/* ... omitted ... */);
const authManagementConfig = createGlobalAuthenticationConfig(/* ... omitted ... */);
const sessionManager = createSessionManager(/* ... omitted ... */);
const authMiddleware = nyckelExpressMiddleware(/* ... omitted ... */);
app.use(authMiddleware);
app.get(
"/",
// asyncHandler calls 'next(err)' if the promise rejects
asyncHandler(async (req, res, next) => {
const user = await req.user.get();
if (user != null) {
res.write("<p>" + Math.floor(user.expiresIn / 1000) + "</p>");
res.write("<a href='/auth/logout'>log out</a>");
} else {
res.write("<a href='/auth/login'>log in</a>");
}
res.write("<h3>req.user.get()</h3>");
res.write("<pre>" + JSON.stringify(user, null, " ") + "</pre>");
res.write("<h3>req.user.userInfo()</h3>");
res.write("<pre>" + JSON.stringify(await req.user.userInfo(), null, " ") + "</pre>");
res.write("<h3>req.user.fullUserData()</h3>");
res.write("<pre>" + JSON.stringify(await req.user.fullUserData(), null, " ") + "</pre>");
res.write("<h3>req.user.roles()</h3>");
res.write("<pre>" + JSON.stringify(await req.user.roles(), null, " ") + "</pre>");
res.write("<h3>req.user.permissions()</h3>");
res.write("<pre>" + JSON.stringify(await req.user.permissions(), null, " ") + "</pre>");
res.end();
})
);
app.listen(8000);
Part of activity
Tags
- Authentication
Technologies
- TypeScript
- Auth0
- Jest