@eventuras/fides-auth 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +311 -0
  3. package/dist/build-CNL3v39v.js +977 -0
  4. package/dist/decode_jwt-1J26fl4I.js +25 -0
  5. package/dist/decrypt-Cahlu_6Y.js +92 -0
  6. package/dist/deflate-koSuX7FB.js +1015 -0
  7. package/dist/index.d.ts +11 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +6 -0
  10. package/dist/logger.d.ts +83 -0
  11. package/dist/logger.d.ts.map +1 -0
  12. package/dist/logger.js +46 -0
  13. package/dist/oauth-browser.d.ts +62 -0
  14. package/dist/oauth-browser.d.ts.map +1 -0
  15. package/dist/oauth-browser.js +49 -0
  16. package/dist/oauth.d.ts +145 -0
  17. package/dist/oauth.d.ts.map +1 -0
  18. package/dist/oauth.js +165 -0
  19. package/dist/providers/vipps/client.d.ts +62 -0
  20. package/dist/providers/vipps/client.d.ts.map +1 -0
  21. package/dist/providers/vipps/index.d.ts +11 -0
  22. package/dist/providers/vipps/index.d.ts.map +1 -0
  23. package/dist/providers/vipps/index.js +120 -0
  24. package/dist/providers/vipps/types.d.ts +107 -0
  25. package/dist/providers/vipps/types.d.ts.map +1 -0
  26. package/dist/rate-limit.d.ts +28 -0
  27. package/dist/rate-limit.d.ts.map +1 -0
  28. package/dist/rate-limit.js +26 -0
  29. package/dist/session-refresh.d.ts +13 -0
  30. package/dist/session-refresh.d.ts.map +1 -0
  31. package/dist/session-refresh.js +27 -0
  32. package/dist/session-validation-BxObT3wC.js +66 -0
  33. package/dist/session-validation.d.ts +24 -0
  34. package/dist/session-validation.d.ts.map +1 -0
  35. package/dist/session-validation.js +2 -0
  36. package/dist/silent-login.d.ts +103 -0
  37. package/dist/silent-login.d.ts.map +1 -0
  38. package/dist/silent-login.js +50 -0
  39. package/dist/types.d.ts +24 -0
  40. package/dist/types.d.ts.map +1 -0
  41. package/dist/types.js +0 -0
  42. package/dist/utils-ByMRF7b2.js +379 -0
  43. package/dist/utils.d.ts +83 -0
  44. package/dist/utils.d.ts.map +1 -0
  45. package/dist/utils.js +2 -0
  46. package/package.json +101 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Fides Auth - OAuth/OIDC Authentication Library
3
+ *
4
+ * Generic authentication utilities with support for multiple providers.
5
+ */
6
+ export * from './logger';
7
+ export * from './session-refresh';
8
+ export * from './session-validation';
9
+ export * from './utils';
10
+ export * from './types';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ import { configureLogger as e, createLogger as t } from "./logger.js";
2
+ import { a as n, c as r, d as i, i as a, l as o, n as s, o as c, r as l, s as u, t as d, u as f } from "./utils-ByMRF7b2.js";
3
+ import { n as p, t as m } from "./session-validation-BxObT3wC.js";
4
+ import { refreshSession as h } from "./session-refresh.js";
5
+ import "./types.js";
6
+ export { d as accessTokenExpires, e as configureLogger, s as createEncryptedJWT, t as createLogger, l as decrypt, a as encrypt, n as generateToken, c as getSessionSecret, u as getSessionSecretUint8Array, r as hexToUint8Array, m as isSession, h as refreshSession, o as sha256, f as sha512, i as toHex, p as validateSessionJwt };
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Pluggable logger for fides-auth.
3
+ *
4
+ * By default, uses a console-based logger. Users can provide their own
5
+ * implementation (pino, winston, etc.) via `configureLogger()`.
6
+ *
7
+ * @example
8
+ * // Use default console logger (no setup needed)
9
+ * import { createLogger } from '@eventuras/fides-auth/logger';
10
+ * const logger = createLogger({ namespace: 'my-app:auth' });
11
+ * logger.info('Authentication successful');
12
+ *
13
+ * @example
14
+ * // Plug in pino
15
+ * import pino from 'pino';
16
+ * import { configureLogger } from '@eventuras/fides-auth/logger';
17
+ *
18
+ * const pinoInstance = pino();
19
+ * configureLogger({
20
+ * create({ namespace, context }) {
21
+ * return pinoInstance.child({ namespace, ...context });
22
+ * },
23
+ * });
24
+ *
25
+ * @example
26
+ * // Plug in @eventuras/logger
27
+ * import { Logger } from '@eventuras/logger';
28
+ * import { configureLogger } from '@eventuras/fides-auth/logger';
29
+ *
30
+ * configureLogger({
31
+ * create(options) {
32
+ * return Logger.create(options);
33
+ * },
34
+ * });
35
+ */
36
+ /**
37
+ * Logger interface compatible with pino, winston, and console.
38
+ *
39
+ * All methods accept either:
40
+ * - A string message: `logger.info('hello')`
41
+ * - A context object and message: `logger.info({ userId: 123 }, 'User logged in')`
42
+ */
43
+ export interface FidesLogger {
44
+ debug(data?: Record<string, unknown> | string, msg?: string): void;
45
+ info(data?: Record<string, unknown> | string, msg?: string): void;
46
+ warn(data?: Record<string, unknown> | string, msg?: string): void;
47
+ error(data?: Record<string, unknown> | string, msg?: string): void;
48
+ }
49
+ /** Options for creating a logger instance. */
50
+ export interface FidesLoggerOptions {
51
+ /** Namespace for log filtering (e.g., 'fides-auth:oauth') */
52
+ namespace: string;
53
+ /** Persistent context fields included in every log entry */
54
+ context?: Record<string, unknown>;
55
+ }
56
+ /** Factory that creates logger instances. Implement this to integrate your preferred logger. */
57
+ export interface FidesLoggerFactory {
58
+ create(options: FidesLoggerOptions): FidesLogger;
59
+ }
60
+ /**
61
+ * Configure a custom logger factory for fides-auth.
62
+ *
63
+ * Can be called at any time — even after modules have already created loggers.
64
+ * Existing loggers will pick up the new factory on their next log call.
65
+ *
66
+ * If not called, fides-auth uses a console-based logger.
67
+ *
68
+ * @param factory - A factory that creates logger instances
69
+ */
70
+ export declare function configureLogger(factory: FidesLoggerFactory): void;
71
+ /**
72
+ * Create a logger instance using the configured factory.
73
+ *
74
+ * Returns a lazy proxy: the underlying logger is created (or re-created)
75
+ * on first use and whenever the factory is changed via `configureLogger()`.
76
+ * This means module-scope loggers work correctly even when `configureLogger()`
77
+ * is called after module imports.
78
+ *
79
+ * @param options - Logger options including namespace and optional context
80
+ * @returns A logger instance
81
+ */
82
+ export declare function createLogger(options: FidesLoggerOptions): FidesLogger;
83
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnE,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClE,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpE;AAED,8CAA8C;AAC9C,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,gGAAgG;AAChG,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAAC;CAClD;AAkED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAGjE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAkBrE"}
package/dist/logger.js ADDED
@@ -0,0 +1,46 @@
1
+ //#region src/logger.ts
2
+ var e = class {
3
+ prefix;
4
+ constructor(e, t) {
5
+ this.prefix = `[${e}]${t && Object.keys(t).length > 0 ? ` ${JSON.stringify(t)}` : ""}`;
6
+ }
7
+ debug(e, t) {
8
+ typeof e == "string" ? console.debug(this.prefix, e) : t ? console.debug(this.prefix, t, e) : e && console.debug(this.prefix, e);
9
+ }
10
+ info(e, t) {
11
+ typeof e == "string" ? console.info(this.prefix, e) : t ? console.info(this.prefix, t, e) : e && console.info(this.prefix, e);
12
+ }
13
+ warn(e, t) {
14
+ typeof e == "string" ? console.warn(this.prefix, e) : t ? console.warn(this.prefix, t, e) : e && console.warn(this.prefix, e);
15
+ }
16
+ error(e, t) {
17
+ typeof e == "string" ? console.error(this.prefix, e) : t ? console.error(this.prefix, t, e) : e && console.error(this.prefix, e);
18
+ }
19
+ }, t = { create({ namespace: t, context: n }) {
20
+ return new e(t, n);
21
+ } }, n = 0;
22
+ function r(e) {
23
+ t = e, n++;
24
+ }
25
+ function i(e) {
26
+ let r = null, i = -1;
27
+ function a() {
28
+ return (r === null || i !== n) && (r = t.create(e), i = n), r;
29
+ }
30
+ return {
31
+ debug(e, t) {
32
+ a().debug(e, t);
33
+ },
34
+ info(e, t) {
35
+ a().info(e, t);
36
+ },
37
+ warn(e, t) {
38
+ a().warn(e, t);
39
+ },
40
+ error(e, t) {
41
+ a().error(e, t);
42
+ }
43
+ };
44
+ }
45
+ //#endregion
46
+ export { r as configureLogger, i as createLogger };
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Browser-compatible OAuth 2.0 + PKCE helpers
3
+ *
4
+ * This module provides OAuth 2.0 helpers that work in browser environments.
5
+ * Unlike `oauth.ts` which uses openid-client (Node.js only), this uses
6
+ * browser-native Web Crypto API for PKCE generation.
7
+ *
8
+ * **Use this in:**
9
+ * - Vite/React SPAs
10
+ * - Browser-only applications
11
+ * - Any frontend that can't use Node.js APIs
12
+ *
13
+ * **Usage:**
14
+ * ```typescript
15
+ * import { generatePKCE, buildAuthorizationUrl, exchangeCodeForTokens }
16
+ * from '@eventuras/fides-auth/oauth-browser';
17
+ *
18
+ * // 1. Start OAuth flow
19
+ * const pkce = await generatePKCE();
20
+ * sessionStorage.setItem('code_verifier', pkce.code_verifier);
21
+ * sessionStorage.setItem('state', pkce.state);
22
+ *
23
+ * const authUrl = buildAuthorizationUrl(config, pkce);
24
+ * window.location.href = authUrl;
25
+ *
26
+ * // 2. Handle callback
27
+ * const code = new URLSearchParams(window.location.search).get('code');
28
+ * const verifier = sessionStorage.getItem('code_verifier');
29
+ * const tokens = await exchangeCodeForTokens(config, code, verifier);
30
+ * ```
31
+ */
32
+ /** Configuration for browser-side OAuth / OIDC flows (no client secret). */
33
+ export interface OAuthConfig {
34
+ issuer: string;
35
+ clientId: string;
36
+ redirect_uri: string;
37
+ scope: string;
38
+ }
39
+ /** PKCE parameters for a browser-initiated authorization request. */
40
+ export interface PKCEParams {
41
+ code_verifier: string;
42
+ code_challenge: string;
43
+ state: string;
44
+ }
45
+ /**
46
+ * Generate PKCE parameters for OAuth flow
47
+ */
48
+ export declare function generatePKCE(): Promise<PKCEParams>;
49
+ /**
50
+ * Build authorization URL for OAuth flow
51
+ */
52
+ export declare function buildAuthorizationUrl(config: OAuthConfig, pkce: PKCEParams): string;
53
+ /**
54
+ * Exchange authorization code for tokens
55
+ */
56
+ export declare function exchangeCodeForTokens(config: OAuthConfig, code: string, codeVerifier: string): Promise<{
57
+ access_token: string;
58
+ id_token: string;
59
+ refresh_token?: string;
60
+ expires_in: number;
61
+ }>;
62
+ //# sourceMappingURL=oauth-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-browser.d.ts","sourceRoot":"","sources":["../src/oauth-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qEAAqE;AACrE,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AA+BD;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,CAUxD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,UAAU,GACf,MAAM,CAYR;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAqBD"}
@@ -0,0 +1,49 @@
1
+ //#region src/oauth-browser.ts
2
+ function e(e) {
3
+ let t = new Uint8Array(e);
4
+ return crypto.getRandomValues(t), Array.from(t).map((e) => "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"[e % 66]).join("");
5
+ }
6
+ async function t(e) {
7
+ let t = new TextEncoder().encode(e), n = await crypto.subtle.digest("SHA-256", t);
8
+ return btoa(String.fromCharCode(...new Uint8Array(n))).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
9
+ }
10
+ async function n() {
11
+ let n = e(128);
12
+ return {
13
+ code_verifier: n,
14
+ code_challenge: await t(n),
15
+ state: e(32)
16
+ };
17
+ }
18
+ function r(e, t) {
19
+ let n = new URLSearchParams({
20
+ client_id: e.clientId,
21
+ redirect_uri: e.redirect_uri,
22
+ response_type: "code",
23
+ scope: e.scope,
24
+ state: t.state,
25
+ code_challenge: t.code_challenge,
26
+ code_challenge_method: "S256"
27
+ });
28
+ return `${e.issuer}/auth?${n.toString()}`;
29
+ }
30
+ async function i(e, t, n) {
31
+ let r = await fetch(`${e.issuer}/token`, {
32
+ method: "POST",
33
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
34
+ body: new URLSearchParams({
35
+ grant_type: "authorization_code",
36
+ code: t,
37
+ redirect_uri: e.redirect_uri,
38
+ client_id: e.clientId,
39
+ code_verifier: n
40
+ })
41
+ });
42
+ if (!r.ok) {
43
+ let e = await r.text();
44
+ throw Error(`Token exchange failed: ${r.status} - ${e}`);
45
+ }
46
+ return r.json();
47
+ }
48
+ //#endregion
49
+ export { r as buildAuthorizationUrl, i as exchangeCodeForTokens, n as generatePKCE };
@@ -0,0 +1,145 @@
1
+ import { Session } from './types';
2
+ import * as openid from 'openid-client';
3
+ export type { Configuration, TokenEndpointResponse } from 'openid-client';
4
+ /** Default OIDC scope requesting user identity, profile, email, and offline access. */
5
+ export declare const defaultScope = "openid profile email offline_access";
6
+ /** Configuration for server-side OAuth / OIDC flows. */
7
+ export type OAuthConfig = {
8
+ issuer: string;
9
+ clientId: string;
10
+ clientSecret: string;
11
+ redirect_uri: string;
12
+ scope: string;
13
+ };
14
+ /**
15
+ * Refreshes an access token using a refresh token grant.
16
+ *
17
+ * @param oAuthConfig - OAuth configuration for the identity provider
18
+ * @param refreshToken - The refresh token to exchange
19
+ * @returns Token endpoint response containing new access and refresh tokens
20
+ */
21
+ export declare function refreshAccessToken(oAuthConfig: OAuthConfig, refreshToken: string): Promise<openid.TokenEndpointResponse>;
22
+ /** PKCE parameters generated for an authorization request. */
23
+ export interface PKCEOptions {
24
+ code_verifier: string;
25
+ code_challenge: string;
26
+ state: string;
27
+ parameters: Record<string, string>;
28
+ }
29
+ /**
30
+ * Creates PKCE parameters for an OAuth flow.
31
+ *
32
+ * @param config - OAuthConfig configuration including the redirect URI and scope.
33
+ * @returns A promise that resolves to an object containing:
34
+ * - code_verifier: The randomly generated PKCE code verifier.
35
+ * - code_challenge: The derived PKCE code challenge.
36
+ * - state: A random state to protect against CSRF.
37
+ * - parameters: A Record<string,string> with the assembled parameters.
38
+ */
39
+ export declare function buildPKCEOptions(config: OAuthConfig): Promise<PKCEOptions>;
40
+ /**
41
+ * Builds an authorization URL with PKCE parameters.
42
+ *
43
+ * @param config - Discovered OpenID Configuration (use openid.discovery() to obtain)
44
+ * @param pkceOptions - The PKCE options (e.g., code challenge, state, parameters)
45
+ * @returns A Promise that resolves to the authorization URL
46
+ */
47
+ export declare function buildAuthorizationUrl(config: openid.Configuration, pkceOptions: PKCEOptions): Promise<URL>;
48
+ /**
49
+ * Convenience function to discover OpenID configuration and build authorization URL.
50
+ * This combines discovery + buildAuthorizationUrl in one call.
51
+ *
52
+ * @param oauthConfig - Your OAuth configuration
53
+ * @param pkceOptions - The PKCE options (e.g., code challenge, state, parameters)
54
+ * @returns A Promise that resolves to the authorization URL
55
+ */
56
+ export declare function discoverAndBuildAuthorizationUrl(oauthConfig: OAuthConfig, pkceOptions: PKCEOptions): Promise<URL>;
57
+ /**
58
+ * Configuration for OAuth client credentials flow (machine-to-machine authentication)
59
+ */
60
+ export type ClientCredentialsConfig = {
61
+ /** OAuth token endpoint URL */
62
+ tokenEndpoint: string;
63
+ /** OAuth client ID */
64
+ clientId: string;
65
+ /** OAuth client secret */
66
+ clientSecret: string;
67
+ /** Optional scope for the access token */
68
+ scope?: string;
69
+ };
70
+ /**
71
+ * Exchanges an authorization code for tokens using OIDC discovery and PKCE.
72
+ *
73
+ * @param oauthConfig - OAuth configuration
74
+ * @param callbackUrl - The full callback URL with query parameters from the OIDC provider
75
+ * @param codeVerifier - The PKCE code verifier stored during login initiation
76
+ * @param expectedState - The state parameter stored during login initiation
77
+ * @returns Token response from the OIDC provider
78
+ */
79
+ export declare function exchangeAuthorizationCode(oauthConfig: OAuthConfig, callbackUrl: URL, codeVerifier: string, expectedState: string): Promise<openid.TokenEndpointResponse>;
80
+ /**
81
+ * Result of extracting user information from an OIDC token response.
82
+ */
83
+ export interface OidcUserInfo {
84
+ sub: string;
85
+ name: string;
86
+ email: string;
87
+ roles: string[];
88
+ }
89
+ /**
90
+ * Extracts user information from an OIDC token response.
91
+ * Decodes the ID token and extracts standard claims plus roles from a configurable claim.
92
+ *
93
+ * @param tokens - Token response from the OIDC provider
94
+ * @param rolesClaim - Name of the claim containing user roles (default: 'roles')
95
+ * @returns Extracted user information
96
+ */
97
+ export declare function extractUserFromTokens(tokens: openid.TokenEndpointResponse, rolesClaim?: string): OidcUserInfo;
98
+ /**
99
+ * Builds a Session object from an OIDC token response.
100
+ * Maps provider tokens and user claims into the internal Session format.
101
+ *
102
+ * @param tokens - Token response from the OIDC provider
103
+ * @param rolesClaim - Name of the claim containing user roles (default: 'roles')
104
+ * @returns A Session object ready to be encrypted and stored
105
+ */
106
+ export declare function buildSessionFromTokens(tokens: openid.TokenEndpointResponse, rolesClaim?: string): Session;
107
+ /**
108
+ * Validates a return URL against open redirect attacks.
109
+ * Ensures the URL is same-origin and passes optional custom validation.
110
+ *
111
+ * @param returnTo - The raw returnTo path/URL to validate
112
+ * @param applicationOrigin - The application's origin URL (e.g., 'https://example.com')
113
+ * @param defaultPath - Fallback path if validation fails (default: '/')
114
+ * @param validate - Optional custom validation function for the pathname
115
+ * @returns A safe, validated URL
116
+ */
117
+ export declare function validateReturnUrl(returnTo: string | null | undefined, applicationOrigin: string, defaultPath?: string, validate?: (pathname: string) => boolean): URL;
118
+ /**
119
+ * Discovers the OIDC provider's end_session_endpoint and builds a logout URL.
120
+ * Returns null if the provider doesn't expose an end_session_endpoint.
121
+ *
122
+ * @param oauthConfig - OAuth configuration (issuer, clientId, clientSecret)
123
+ * @param postLogoutRedirectUri - URL to redirect to after provider logout
124
+ * @returns Logout URL or null if not supported
125
+ */
126
+ export declare function buildOidcLogoutUrl(oauthConfig: OAuthConfig, postLogoutRedirectUri: string): Promise<URL | null>;
127
+ /**
128
+ * Performs OAuth 2.0 client credentials grant flow for machine-to-machine authentication.
129
+ *
130
+ * @param config - Client credentials configuration including token endpoint, client ID, and secret
131
+ * @returns Token response from the OAuth provider
132
+ * @throws Error if the token request fails
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * const tokens = await clientCredentialsGrant({
137
+ * tokenEndpoint: 'https://api.example.com/oauth2/token',
138
+ * clientId: 'my-client-id',
139
+ * clientSecret: 'my-client-secret',
140
+ * scope: 'api:read api:write',
141
+ * });
142
+ * ```
143
+ */
144
+ export declare function clientCredentialsGrant(config: ClientCredentialsConfig): Promise<openid.TokenEndpointResponse>;
145
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
package/dist/oauth.js ADDED
@@ -0,0 +1,165 @@
1
+ import { createLogger as e } from "./logger.js";
2
+ import { t } from "./decode_jwt-1J26fl4I.js";
3
+ import { a as n, c as r, i, n as a, o, r as s, s as c, t as l } from "./build-CNL3v39v.js";
4
+ //#region src/oauth.ts
5
+ var u = e({ namespace: "fides-auth:oauth" }), d = "openid profile email offline_access";
6
+ async function f(e, t) {
7
+ u.debug({ issuer: e.issuer }, "Starting token refresh");
8
+ try {
9
+ let i = await r(await n(new URL(e.issuer), e.clientId, e.clientSecret, l(e.clientSecret)), t, { scope: e.scope });
10
+ return u.info({
11
+ hasAccessToken: !!i.access_token,
12
+ hasRefreshToken: !!i.refresh_token,
13
+ expiresIn: i.expires_in
14
+ }, "Token refresh successful"), i;
15
+ } catch (t) {
16
+ let n = t;
17
+ throw n?.code === "OAUTH_RESPONSE_BODY_ERROR" && n?.error === "invalid_grant" ? u.info({
18
+ error: n.error,
19
+ error_description: n.error_description,
20
+ issuer: e.issuer
21
+ }, "Token refresh failed - refresh token expired or invalid") : u.error({
22
+ error: t,
23
+ issuer: e.issuer
24
+ }, "Token refresh failed"), t;
25
+ }
26
+ }
27
+ async function p(e) {
28
+ let t = o(), n = await i(t), r = c(), a = {
29
+ redirect_uri: e.redirect_uri,
30
+ scope: e.scope ?? "openid profile email offline_access",
31
+ code_challenge: n,
32
+ code_challenge_method: "S256",
33
+ state: r
34
+ };
35
+ return u.info({
36
+ redirectUri: e.redirect_uri,
37
+ scope: a.scope
38
+ }, "PKCE parameters generated"), {
39
+ code_verifier: t,
40
+ code_challenge: n,
41
+ state: r,
42
+ parameters: a
43
+ };
44
+ }
45
+ async function m(e, t) {
46
+ try {
47
+ let n = s(e, t.parameters);
48
+ return u.info({ authUrl: n.origin }, "Authorization URL built successfully"), n;
49
+ } catch (e) {
50
+ throw u.error({ error: e }, "Failed to build authorization URL"), e;
51
+ }
52
+ }
53
+ async function h(e, t) {
54
+ u.debug({ issuer: e.issuer }, "Discovering OpenID configuration");
55
+ try {
56
+ return m(await n(new URL(e.issuer), e.clientId, e.clientSecret, l(e.clientSecret)), t);
57
+ } catch (t) {
58
+ throw u.error({
59
+ error: t,
60
+ issuer: e.issuer
61
+ }, "Failed to discover config or build URL"), t;
62
+ }
63
+ }
64
+ async function g(e, t, r, i) {
65
+ u.debug({
66
+ issuer: e.issuer,
67
+ clientId: e.clientId
68
+ }, "Exchanging authorization code for tokens");
69
+ let o = await a(await n(new URL(e.issuer), e.clientId, e.clientSecret, l(e.clientSecret)), t, {
70
+ pkceCodeVerifier: r,
71
+ expectedState: i
72
+ }, { redirect_uri: e.redirect_uri });
73
+ return u.info({
74
+ hasAccessToken: !!o.access_token,
75
+ hasRefreshToken: !!o.refresh_token,
76
+ expiresIn: o.expires_in
77
+ }, "Authorization code exchange successful"), o;
78
+ }
79
+ function _(e, n = "roles") {
80
+ if (!e.id_token) throw Error("OIDC token response is missing id_token");
81
+ let r = t(e.id_token), i = r[n], a = typeof i == "string" ? [i] : [], o = Array.isArray(i) ? i : a;
82
+ return u.debug({
83
+ sub: r.sub,
84
+ rolesClaim: n,
85
+ rolesCount: o.length
86
+ }, "Extracted user from ID token"), {
87
+ sub: r.sub ?? "",
88
+ name: r.name,
89
+ email: r.email,
90
+ roles: o
91
+ };
92
+ }
93
+ function v(e, t = "roles") {
94
+ if (!e.access_token) throw Error("OIDC token response is missing access_token");
95
+ let n = _(e, t);
96
+ return {
97
+ tokens: {
98
+ accessToken: e.access_token,
99
+ accessTokenExpiresAt: e.expires_in ? new Date(Date.now() + e.expires_in * 1e3) : void 0,
100
+ refreshToken: e.refresh_token
101
+ },
102
+ user: {
103
+ name: n.name,
104
+ email: n.email,
105
+ roles: n.roles
106
+ }
107
+ };
108
+ }
109
+ function y(e, t, n = "/", r) {
110
+ let i = e ?? n, a;
111
+ try {
112
+ a = new URL(i, t);
113
+ } catch {
114
+ return u.warn({ returnTo: i }, "Invalid returnTo URL, using default"), new URL(n, t);
115
+ }
116
+ let o = new URL(t);
117
+ return a.origin === o.origin ? r && !r(a.pathname) ? (u.warn({ pathname: a.pathname }, "returnTo failed custom validation, falling back to default"), new URL(n, t)) : a : (u.error({
118
+ returnTo: i,
119
+ redirectOrigin: a.origin,
120
+ applicationOrigin: o.origin
121
+ }, "Possible open redirect attack: returnTo points outside application origin"), new URL(n, t));
122
+ }
123
+ async function b(e, t) {
124
+ try {
125
+ let r = (await n(new URL(e.issuer), e.clientId, e.clientSecret, l(e.clientSecret))).serverMetadata().end_session_endpoint;
126
+ if (!r) return u.info({ issuer: e.issuer }, "No end_session_endpoint found"), null;
127
+ let i = new URL(r);
128
+ return i.searchParams.set("client_id", e.clientId), i.searchParams.set("post_logout_redirect_uri", t), u.debug({ logoutUrl: i.toString() }, "Built OIDC logout URL"), i;
129
+ } catch (t) {
130
+ return u.warn({
131
+ error: t,
132
+ issuer: e.issuer
133
+ }, "OIDC discovery failed for logout"), null;
134
+ }
135
+ }
136
+ async function x(e) {
137
+ try {
138
+ let t = new URLSearchParams({
139
+ grant_type: "client_credentials",
140
+ client_id: e.clientId,
141
+ client_secret: e.clientSecret
142
+ });
143
+ e.scope && t.set("scope", e.scope);
144
+ let n = await fetch(e.tokenEndpoint, {
145
+ method: "POST",
146
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
147
+ body: t
148
+ });
149
+ if (!n.ok) {
150
+ let e = await n.text();
151
+ throw u.error({
152
+ status: n.status,
153
+ error: e
154
+ }, "Client credentials grant failed"), Error(`Client credentials grant failed: ${n.status} - ${e}`);
155
+ }
156
+ return await n.json();
157
+ } catch (t) {
158
+ throw u.error({
159
+ error: t,
160
+ tokenEndpoint: e.tokenEndpoint
161
+ }, "Client credentials grant error"), t;
162
+ }
163
+ }
164
+ //#endregion
165
+ export { m as buildAuthorizationUrl, b as buildOidcLogoutUrl, p as buildPKCEOptions, v as buildSessionFromTokens, x as clientCredentialsGrant, d as defaultScope, h as discoverAndBuildAuthorizationUrl, g as exchangeAuthorizationCode, _ as extractUserFromTokens, f as refreshAccessToken, y as validateReturnUrl };
@@ -0,0 +1,62 @@
1
+ import { PKCEOptions } from '../../oauth';
2
+ import { VippsLoginConfig, VippsUserInfo } from './types';
3
+ /**
4
+ * Vipps Login Client
5
+ *
6
+ * Client for Vipps Login (OIDC) authentication flow.
7
+ * Implements OAuth/OIDC operations with PKCE for Vipps.
8
+ */
9
+ import * as openid from 'openid-client';
10
+ /**
11
+ * Vipps Login Client
12
+ *
13
+ * Handles Vipps Login (OIDC) authentication flow using PKCE.
14
+ */
15
+ export declare class VippsLoginClient {
16
+ private readonly config;
17
+ private readonly oauthConfig;
18
+ private configPromise;
19
+ constructor(config: VippsLoginConfig);
20
+ /**
21
+ * Get OpenID Configuration (cached)
22
+ * This ensures we use the same Configuration instance across all operations
23
+ */
24
+ private getConfig;
25
+ /**
26
+ * Build PKCE options for authorization flow
27
+ *
28
+ * @returns PKCE options including code_verifier, code_challenge, and state
29
+ */
30
+ buildPKCEOptions(): Promise<PKCEOptions>;
31
+ /**
32
+ * Build authorization URL for Vipps Login
33
+ *
34
+ * @param pkceOptions - PKCE options from buildPKCEOptions()
35
+ * @returns Authorization URL to redirect user to
36
+ */
37
+ buildAuthorizationUrl(pkceOptions: PKCEOptions): Promise<URL>;
38
+ /**
39
+ * Exchange authorization code for tokens
40
+ *
41
+ * @param callbackUrl - The full callback URL with code parameter from Vipps
42
+ * @param codeVerifier - PKCE code verifier from initial request
43
+ * @param expectedState - Expected state value for validation (optional)
44
+ * @returns Token response with access_token, id_token, and refresh_token
45
+ */
46
+ exchangeCodeForTokens(callbackUrl: string | URL, codeVerifier: string, expectedState?: string): Promise<openid.TokenEndpointResponse>;
47
+ /**
48
+ * Get user information from Vipps userinfo endpoint
49
+ *
50
+ * @param accessToken - Access token from token exchange
51
+ * @returns Vipps user information
52
+ */
53
+ getUserInfo(accessToken: string): Promise<VippsUserInfo>;
54
+ /**
55
+ * Refresh access token using refresh token
56
+ *
57
+ * @param refreshToken - Refresh token from initial token exchange
58
+ * @returns New token response
59
+ */
60
+ refreshTokens(refreshToken: string): Promise<openid.TokenEndpointResponse>;
61
+ }
62
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/providers/vipps/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AAOjB;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,aAAa,CAA8C;gBAEvD,MAAM,EAAE,gBAAgB;IAwBpC;;;OAGG;YACW,SAAS;IAYvB;;;;OAIG;IACG,gBAAgB,IAAI,OAAO,CAAC,WAAW,CAAC;IAK9C;;;;;OAKG;IACG,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;IAMnE;;;;;;;OAOG;IACG,qBAAqB,CACzB,WAAW,EAAE,MAAM,GAAG,GAAG,EACzB,YAAY,EAAE,MAAM,EACpB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC;IAgCxC;;;;;OAKG;IACG,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAsD9D;;;;;OAKG;IACG,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC;CAsBjF"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Vipps Login Provider
3
+ *
4
+ * OAuth/OIDC provider implementation for Vipps Login.
5
+ * Can be used directly or integrated with framework-specific auth systems.
6
+ *
7
+ * @see https://developer.vippsmobilepay.com/docs/APIs/login-api/
8
+ */
9
+ export * from './types';
10
+ export * from './client';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/vipps/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC"}