auth

Main authentication module for my projects
git clone git://git.finwo.net/app/auth
Log | Files | Refs

context.js (2576B)


      1 import { HttpError } from '../http/http-error.js';
      2 import { resolveClientForHost, resolveHostContext } from '../host-context.js';
      3 import { isVirtualClient } from './clients.js';
      4 
      5 export function requestOrigin(req) {
      6   const forwarded = String(req.headers['x-forwarded-proto'] || '')
      7     .split(',')[0]
      8     .trim();
      9   const proto = forwarded || (req.socket?.encrypted ? 'https' : 'http');
     10   return `${proto}://${req.headers.host}`;
     11 }
     12 
     13 export function canonicalIssuer(publicUrl, realmSlug) {
     14   const base = String(publicUrl || '').replace(/\/+$/, '');
     15   return `${base}/oidc/${encodeURIComponent(realmSlug)}`;
     16 }
     17 
     18 function pathSegments(req) {
     19   const pathname = String(req.url || '/').split('?')[0];
     20   return pathname
     21     .split('/')
     22     .filter(Boolean)
     23     .map((segment) => decodeURIComponent(segment));
     24 }
     25 
     26 export async function resolveOidcContext(req, { publicUrl } = {}) {
     27   const segments = pathSegments(req);
     28   const origin = requestOrigin(req);
     29   const hostContext = await resolveHostContext(req, { publicUrl });
     30 
     31   if (hostContext.mode === 'client') {
     32     if (segments.length !== 1) throw new HttpError(404, 'not_found', 'Not found');
     33     return {
     34       mode: 'client',
     35       host: hostContext.host,
     36       origin,
     37       realm: hostContext.realm,
     38       clientId: hostContext.clientId,
     39       action: segments[0],
     40     };
     41   }
     42 
     43   if (segments.length !== 2) throw new HttpError(404, 'not_found', 'Not found');
     44   const clientId = segments[0];
     45   const action = segments[1];
     46 
     47   if (hostContext.mode === 'realm') {
     48     const resolved = isVirtualClient(clientId)
     49       ? { realm: hostContext.realm, clientId }
     50       : await resolveClientForHost(hostContext, clientId);
     51     return {
     52       mode: 'realm',
     53       host: hostContext.host,
     54       origin,
     55       realm: resolved.realm,
     56       clientId: resolved.clientId,
     57       action,
     58     };
     59   }
     60 
     61   const resolved = await resolveClientForHost(hostContext, clientId);
     62   return {
     63     mode: 'canonical',
     64     host: hostContext.host,
     65     origin,
     66     realm: resolved.realm,
     67     clientId: resolved.clientId,
     68     action,
     69   };
     70 }
     71 
     72 export function endpointBase(context) {
     73   if (context.mode === 'client') return `${context.origin}/oidc`;
     74   return `${context.origin}/oidc/${encodeURIComponent(context.clientId)}`;
     75 }
     76 
     77 export function endpointUrls(context) {
     78   const base = endpointBase(context);
     79   return {
     80     openid_configuration: `${base}/openid-configuration`,
     81     login: `${base}/login`,
     82     authorize: `${base}/authorize`,
     83     token: `${base}/token`,
     84     userinfo: `${base}/userinfo`,
     85     jwks: `${base}/jwks`,
     86     logout: `${base}/logout`,
     87   };
     88 }