Oslo

oslo/oauth2

Provides utilities for working OAuth 2.0 based on RFC 6749 and RFC 7636. Can be used for OpenID Connect.

Functions

Classes

Interfaces

Types

Example

import { OAuth2Client } from "oslo/oauth2";

const authorizeEndpoint = "https://github.com/login/oauth/authorize";
const tokenEndpoint = "https://github.com/login/oauth/access_token";

const client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
	redirectURI: "http://localhost:3000/login/github/callback"
});

Create an authorization URL

import { generateState } from "oslo/oauth2";

const state = generateState();

const url = await client.createAuthorizationURL({
	state,
	scopes: ["user:email"]
});

It also supports the PKCE flow:

import { generateState, generateCodeVerifier } from "oslo/oauth2";

const state = generateState();
const codeVerifier = generateCodeVerifier();

// S256 method by default
const url = await client.createAuthorizationURL({
	state,
	scopes: ["user:email"],
	codeVerifier
});

Validate an authorization code

By default OAuth2Client.validateAuthorizationCode() sends credentials with the HTTP basic auth scheme.

import { OAuth2RequestError } from "oslo/oauth2";

if (!storedState || !state || storedState !== state) {
	// error
}

// ...

try {
	const { accessToken, refreshToken } = await client.validateAuthorizationCode<{
		refreshToken: string;
	}>(code, {
		credentials: clientSecret,
		authenticateWith: "request_body"
	});
} catch (e) {
	if (e instanceof OAuth2RequestError) {
		// see https://www.rfc-editor.org/rfc/rfc6749#section-5.2
		const { request, message, description } = e;
	}
	// unknown error
}

This also supports the PKCE flow:

await client.validateAuthorizationCode<{
	refreshToken: string;
}>(code, {
	credentials: clientSecret,
	codeVerifier
});

Refresh an access token

import { OAuth2RequestError } from "oslo/oauth2";

try {
	const { accessToken, refreshToken } = await client.refreshAccessToken<{
		refreshToken: string;
	}>(code, {
		credentials: clientSecret,
		authenticateWith: "request_body"
	});
} catch (e) {
	if (e instanceof OAuth2RequestError) {
		// see https://www.rfc-editor.org/rfc/rfc6749#section-5.2
		const { request, message, description } = e;
	}
	// unknown error
}