UNPKG

delfi-pkce-auth

Version:

Simple PKCE authentication helper for integrating SLB Delfi OAuth2 into Node.js apps.

94 lines (76 loc) 2.33 kB
const crypto = require("crypto"); let config = {}; function initialize(userConfig) { config = { ...userConfig, authorizationEndpoint: "https://csi.slb.com/v2/auth", tokenEndpoint: "https://csi.slb.com/v2/token" }; } function ensureInitialized() { if (!config.clientId || !config.redirectUri) { throw new Error("delfi-pkce-auth is not initialized with clientId and redirectUri."); } } function base64URLEncode(buffer) { return buffer.toString('base64') .replace(/=/g, '') .replace(/\+/g, '-') .replace(/\//g, '_'); } function generateCodeVerifier() { return base64URLEncode(crypto.randomBytes(32)); } function generateCodeChallenge(codeVerifier) { const hash = crypto.createHash('sha256').update(codeVerifier).digest(); return base64URLEncode(hash); } function getAuthUrl(codeChallenge) { ensureInitialized(); const url = new URL(config.authorizationEndpoint); const scope = ["openid"]; if (config.audience) { scope.push(config.audience); } url.searchParams.set("response_type", "code"); url.searchParams.set("client_id", config.clientId); url.searchParams.set("redirect_uri", config.redirectUri); url.searchParams.set("code_challenge", codeChallenge); url.searchParams.set("code_challenge_method", "S256"); url.searchParams.set("scope", scope.join(" ")); return url.toString(); } async function exchangeCodeForToken(code, codeVerifier) { ensureInitialized(); const fetch = require('node-fetch'); const response = await fetch(config.tokenEndpoint, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "authorization_code", client_id: config.clientId, code, redirect_uri: config.redirectUri, code_verifier: codeVerifier }) }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Failed to fetch token: ${response.statusText} - ${errorText}`); } return await response.json(); }; // Helper function to return to the app if there is a valid token in the session. function getAccessToken(req) { return req.session?.token || null; } module.exports = { initialize, generateCodeVerifier, generateCodeChallenge, getAuthUrl, exchangeCodeForToken, getAccessToken };