@aooth/idp 0.2.1 → 0.2.2

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.
package/dist/index.cjs CHANGED
@@ -3,7 +3,7 @@ let node_crypto = require("node:crypto");
3
3
  let _aooth_auth = require("@aooth/auth");
4
4
  let jose = require("jose");
5
5
  let _aooth_user = require("@aooth/user");
6
- //#region src/errors.ts
6
+ // src/errors.ts
7
7
  const defaultMessages = {
8
8
  UNKNOWN_PROVIDER: "Unknown identity provider",
9
9
  INVALID_CONFIG: "Invalid OAuth provider configuration",
@@ -25,8 +25,7 @@ var OAuthError = class extends Error {
25
25
  this.details = details;
26
26
  }
27
27
  };
28
- //#endregion
29
- //#region src/types.ts
28
+ // src/types.ts
30
29
  /** Structural check used by the registry to feature-detect `applyDefaults`. */
31
30
  function isConfigurableProvider(p) {
32
31
  return typeof p.applyDefaults === "function";
@@ -44,8 +43,7 @@ function resolveFederatedPolicy(policy = {}) {
44
43
  trustEmailVerifiedFrom: policy.trustEmailVerifiedFrom ?? []
45
44
  };
46
45
  }
47
- //#endregion
48
- //#region src/pkce.ts
46
+ // src/pkce.ts
49
47
  /**
50
48
  * PKCE / CSRF primitives (RFC 7636 + OIDC nonce). All values are URL-safe
51
49
  * base64url with no padding, so they ride in query params and cookies without
@@ -107,8 +105,7 @@ function deriveSeededPkce(secret, seed) {
107
105
  method: "S256"
108
106
  };
109
107
  }
110
- //#endregion
111
- //#region src/state.ts
108
+ // src/state.ts
112
109
  const DEFAULT_TTL_SEC = 600;
113
110
  function toKey(secret) {
114
111
  return typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
@@ -163,8 +160,7 @@ async function verifyState(token, secret, opts = {}) {
163
160
  if (typeof payload.uid === "string") out.userId = payload.uid;
164
161
  return out;
165
162
  }
166
- //#endregion
167
- //#region src/providers/oauth2-shared.ts
163
+ // src/providers/oauth2-shared.ts
168
164
  /** Resolve the effective `fetch`: an injected impl, else the global `fetch`. */
169
165
  function resolveFetch(impl) {
170
166
  return impl ?? globalThis.fetch;
@@ -213,8 +209,7 @@ function buildAuthorizeUrl(endpoint, args, opts = {}) {
213
209
  for (const [k, v] of Object.entries(opts.extraParams ?? {})) url.searchParams.set(k, v);
214
210
  return url.toString();
215
211
  }
216
- //#endregion
217
- //#region src/providers/oidc.ts
212
+ // src/providers/oidc.ts
218
213
  const DEFAULT_SCOPES$1 = [
219
214
  "openid",
220
215
  "email",
@@ -416,11 +411,11 @@ var OidcProvider = class {
416
411
  * token's hash, the hash chosen by the id_token's `alg` (RS256 → SHA-256).
417
412
  */
418
413
  function atHash(accessToken, alg) {
419
- const digest = (0, node_crypto.createHash)(alg.endsWith("384") ? "sha384" : alg.endsWith("512") ? "sha512" : "sha256").update(accessToken).digest();
414
+ const sha = alg.endsWith("384") ? "sha384" : alg.endsWith("512") ? "sha512" : "sha256";
415
+ const digest = (0, node_crypto.createHash)(sha).update(accessToken).digest();
420
416
  return digest.subarray(0, digest.length / 2).toString("base64url");
421
417
  }
422
- //#endregion
423
- //#region src/providers/google.ts
418
+ // src/providers/google.ts
424
419
  /** Google's stable OIDC issuer — endpoints + JWKS are discovered from it. */
425
420
  const GOOGLE_ISSUER = "https://accounts.google.com";
426
421
  /**
@@ -438,8 +433,7 @@ var GoogleProvider = class extends OidcProvider {
438
433
  });
439
434
  }
440
435
  };
441
- //#endregion
442
- //#region src/providers/github.ts
436
+ // src/providers/github.ts
443
437
  const GITHUB_AUTHORIZE = "https://github.com/login/oauth/authorize";
444
438
  const GITHUB_TOKEN = "https://github.com/login/oauth/access_token";
445
439
  const GITHUB_USER = "https://api.github.com/user";
@@ -576,8 +570,7 @@ var GithubProvider = class {
576
570
  }, { label: `GitHub API (${url})` });
577
571
  }
578
572
  };
579
- //#endregion
580
- //#region src/providers/apple.ts
573
+ // src/providers/apple.ts
581
574
  /** Apple's stable OIDC issuer — endpoints + JWKS are discovered from it. */
582
575
  const APPLE_ISSUER = "https://appleid.apple.com";
583
576
  /** Apple ID tokens are always ES256. */
@@ -681,8 +674,7 @@ var AppleProvider = class extends OidcProvider {
681
674
  return profile;
682
675
  }
683
676
  };
684
- //#endregion
685
- //#region src/providers/fake.ts
677
+ // src/providers/fake.ts
686
678
  /**
687
679
  * Deterministic, network-free {@link IdentityProvider} for unit tests and the
688
680
  * `DEMO_MODE=test` fake-IdP e2e route (RFC §9). `exchange` resolves a `code`
@@ -719,8 +711,7 @@ var FakeIdentityProvider = class {
719
711
  });
720
712
  }
721
713
  };
722
- //#endregion
723
- //#region src/registry.ts
714
+ // src/registry.ts
724
715
  const DEFAULT_CALLBACK_TEMPLATE = "/auth/oauth/:provider/callback";
725
716
  /**
726
717
  * Holds the configured {@link IdentityProvider}s + {@link FederatedPolicy} +
@@ -802,8 +793,7 @@ var OAuthProviderRegistry = class {
802
793
  return deriveSeededPkce(this.stateSecret, seed);
803
794
  }
804
795
  };
805
- //#endregion
806
- //#region src/federated-login-service.ts
796
+ // src/federated-login-service.ts
807
797
  /**
808
798
  * The core federated-login logic (RFC §3.5): map a verified provider profile to
809
799
  * an aooth user id. Pure orchestration over `UserService` + `FederatedIdentityStore`
@@ -940,7 +930,6 @@ var FederatedLoginService = class {
940
930
  return this.federated.touchLogin(profile.provider, profile.subject, (0, _aooth_user.pickDefinedProfile)(profile));
941
931
  }
942
932
  };
943
- //#endregion
944
933
  exports.AppleProvider = AppleProvider;
945
934
  exports.FakeIdentityProvider = FakeIdentityProvider;
946
935
  exports.FederatedLoginService = FederatedLoginService;
package/dist/index.d.cts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { Clock } from "@aooth/auth";
2
2
  import { FederatedIdentity, FederatedIdentityStore, FederatedProfileSnapshot, UserService } from "@aooth/user";
3
3
  import { JWTPayload, JWTVerifyGetKey } from "jose";
4
- //#region src/errors.d.ts
5
4
  /**
6
5
  * Federated-login failure taxonomy (RFC IDP.md §8). Mirrors `AuthError` /
7
6
  * `UserAuthError` — a typed `Error` with a stable `type` code, an optional
@@ -30,14 +29,12 @@ type OAuthErrorType =
30
29
  "ID_TOKEN_INVALID" |
31
30
  /** Policy needed a verified email but the provider returned none. */
32
31
  "EMAIL_UNAVAILABLE";
33
- declare class OAuthError extends Error {
32
+ export declare class OAuthError extends Error {
34
33
  readonly type: OAuthErrorType;
35
34
  readonly details?: Record<string, unknown> | undefined;
36
35
  readonly name = "OAuthError";
37
36
  constructor(type: OAuthErrorType, message?: string, details?: Record<string, unknown> | undefined);
38
37
  }
39
- //#endregion
40
- //#region src/types.d.ts
41
38
  /**
42
39
  * A provider profile normalized to a single shape across Google / OIDC / etc.
43
40
  * Structural superset of `@aooth/user`'s {@link FederatedProfileSnapshot} (the
@@ -139,7 +136,7 @@ interface ConfigurableProvider extends IdentityProvider {
139
136
  applyDefaults(shared: SharedProviderConfig): void;
140
137
  }
141
138
  /** Structural check used by the registry to feature-detect `applyDefaults`. */
142
- declare function isConfigurableProvider(p: IdentityProvider): p is ConfigurableProvider;
139
+ export declare function isConfigurableProvider(p: IdentityProvider): p is ConfigurableProvider;
143
140
  /**
144
141
  * How a federated login that matches an existing local account **by email**
145
142
  * is handled (RFC §4 — the account-takeover-sensitive knob).
@@ -166,9 +163,9 @@ interface FederatedPolicy {
166
163
  }
167
164
  type ResolvedFederatedPolicy = Required<FederatedPolicy>;
168
165
  /** Default username strategy: the verified email, else the stable `provider:subject`. */
169
- declare function defaultUsernameStrategy(p: NormalizedProfile): string;
166
+ export declare function defaultUsernameStrategy(p: NormalizedProfile): string;
170
167
  /** Apply RFC §4 safe defaults over a partial policy. */
171
- declare function resolveFederatedPolicy(policy?: FederatedPolicy): ResolvedFederatedPolicy;
168
+ export declare function resolveFederatedPolicy(policy?: FederatedPolicy): ResolvedFederatedPolicy;
172
169
  /**
173
170
  * The outcome of {@link FederatedLoginService.resolveUser} (decision #1). A
174
171
  * discriminated union — richer than the RFC's `{ userId, isNew }` sketch — so
@@ -205,8 +202,6 @@ type ResolveOutcome =
205
202
  kind: "denied";
206
203
  reason: "signup-disabled" | "email-unavailable";
207
204
  };
208
- //#endregion
209
- //#region src/pkce.d.ts
210
205
  interface PkcePair {
211
206
  /** The high-entropy secret kept server-side (cookie / wf state). */
212
207
  verifier: string;
@@ -229,13 +224,13 @@ interface SeededPkce {
229
224
  * Mint a fresh PKCE pair. The 32-byte verifier base64url-encodes to 43 chars,
230
225
  * comfortably inside RFC 7636's 43–128 range.
231
226
  */
232
- declare function createPkcePair(): PkcePair;
227
+ export declare function createPkcePair(): PkcePair;
233
228
  /** Recompute the S256 challenge for a known verifier (verification side). */
234
- declare function pkceChallengeFor(verifier: string): string;
229
+ export declare function pkceChallengeFor(verifier: string): string;
235
230
  /** OIDC `nonce` — minted at `/start`, bound into state, asserted in `exchange()`. */
236
- declare function generateNonce(bytes?: number): string;
231
+ export declare function generateNonce(bytes?: number): string;
237
232
  /** Random component bound into the signed `state` (anti-CSRF / anti-replay). */
238
- declare function generateRandomState(bytes?: number): string;
233
+ export declare function generateRandomState(bytes?: number): string;
239
234
  /**
240
235
  * STATELESS PKCE: deterministically DERIVE the code verifier + OIDC nonce from
241
236
  * a non-secret `seed` and the server's HMAC `secret`, instead of minting them
@@ -255,9 +250,7 @@ declare function generateRandomState(bytes?: number): string;
255
250
  * Same output range as {@link createPkcePair}: a 32-byte HMAC-SHA256 digest →
256
251
  * a 43-char base64url verifier, inside RFC 7636's 43–128.
257
252
  */
258
- declare function deriveSeededPkce(secret: string | Uint8Array, seed: string): SeededPkce;
259
- //#endregion
260
- //#region src/state.d.ts
253
+ export declare function deriveSeededPkce(secret: string | Uint8Array, seed: string): SeededPkce;
261
254
  /**
262
255
  * The CSRF/replay binding carried across the OAuth bounce (RFC §7). Signed into
263
256
  * a compact HS256 JWT by {@link signState} so it is tamper-evident in the URL
@@ -293,15 +286,13 @@ interface VerifyStateOptions {
293
286
  * Sign the binding into a compact HS256 JWT. Field names are abbreviated to
294
287
  * keep the URL `state` short; {@link verifyState} maps them back.
295
288
  */
296
- declare function signState(payload: OAuthStatePayload, secret: string | Uint8Array, opts?: SignStateOptions): Promise<string>;
289
+ export declare function signState(payload: OAuthStatePayload, secret: string | Uint8Array, opts?: SignStateOptions): Promise<string>;
297
290
  /**
298
291
  * Verify + decode the signed state. Pins `HS256` (rejects `alg:none` / key
299
292
  * confusion). Throws {@link OAuthError} `STATE_EXPIRED` past TTL,
300
293
  * `STATE_INVALID` on any other signature/shape failure.
301
294
  */
302
- declare function verifyState(token: string, secret: string | Uint8Array, opts?: VerifyStateOptions): Promise<OAuthStatePayload>;
303
- //#endregion
304
- //#region src/providers/oidc.d.ts
295
+ export declare function verifyState(token: string, secret: string | Uint8Array, opts?: VerifyStateOptions): Promise<OAuthStatePayload>;
305
296
  /** The four endpoints the OIDC client needs — discovered or supplied explicitly. */
306
297
  interface OidcDiscoveryDocument {
307
298
  issuer: string;
@@ -365,7 +356,7 @@ interface OidcProviderOptions {
365
356
  *
366
357
  * `GoogleProvider` is a thin subclass pinning the issuer + algs.
367
358
  */
368
- declare class OidcProvider implements ConfigurableProvider {
359
+ export declare class OidcProvider implements ConfigurableProvider {
369
360
  readonly id: string;
370
361
  protected readonly issuer: string;
371
362
  protected readonly clientId: string;
@@ -413,8 +404,6 @@ declare class OidcProvider implements ConfigurableProvider {
413
404
  private validateDiscovery;
414
405
  private getJwks;
415
406
  }
416
- //#endregion
417
- //#region src/providers/google.d.ts
418
407
  /** Google options = OIDC options minus the pinned `id`/`issuer`. */
419
408
  type GoogleProviderOptions = Omit<OidcProviderOptions, "id" | "issuer">;
420
409
  /**
@@ -422,11 +411,9 @@ type GoogleProviderOptions = Omit<OidcProviderOptions, "id" | "issuer">;
422
411
  * (Google's only ID-token alg). Everything else — discovery, JWKS rotation,
423
412
  * the full §7 validation — is inherited from {@link OidcProvider}.
424
413
  */
425
- declare class GoogleProvider extends OidcProvider {
414
+ export declare class GoogleProvider extends OidcProvider {
426
415
  constructor(opts: GoogleProviderOptions);
427
416
  }
428
- //#endregion
429
- //#region src/providers/github.d.ts
430
417
  interface GithubProviderOptions {
431
418
  /** Provider id. Default `'github'`. */
432
419
  id?: string;
@@ -457,7 +444,7 @@ interface GithubProviderOptions {
457
444
  * Implements {@link ConfigurableProvider} so the registry can inject a shared
458
445
  * `fetch` (deterministic tests) / `clock`; a constructor value always wins.
459
446
  */
460
- declare class GithubProvider implements ConfigurableProvider {
447
+ export declare class GithubProvider implements ConfigurableProvider {
461
448
  readonly id: string;
462
449
  private readonly clientId;
463
450
  private readonly clientSecret;
@@ -486,8 +473,6 @@ declare class GithubProvider implements ConfigurableProvider {
486
473
  private fetchPrimaryEmail;
487
474
  private apiGet;
488
475
  }
489
- //#endregion
490
- //#region src/providers/apple.d.ts
491
476
  interface AppleProviderOptions extends Omit<OidcProviderOptions, "id" | "issuer" | "clientSecret" | "idTokenSigningAlgs" | "scopes"> {
492
477
  /** The Services ID — Sign in with Apple's OAuth `client_id` (and the id_token `aud`). */
493
478
  clientId: string;
@@ -527,15 +512,13 @@ interface AppleProviderOptions extends Omit<OidcProviderOptions, "id" | "issuer"
527
512
  * capture it, so `displayName` is undefined for Apple. Collect a display name
528
513
  * post-signup if you need one.
529
514
  */
530
- declare class AppleProvider extends OidcProvider {
515
+ export declare class AppleProvider extends OidcProvider {
531
516
  constructor(opts: AppleProviderOptions);
532
517
  /** `email`/`name` scope makes Apple POST the callback — declare `form_post`. */
533
518
  protected extraAuthorizationParams(_args: AuthorizationUrlArgs): Record<string, string>;
534
519
  /** Coerce Apple's STRING `email_verified` (the base sets only a real boolean). */
535
520
  protected normalize(payload: JWTPayload): NormalizedProfile;
536
521
  }
537
- //#endregion
538
- //#region src/providers/fake.d.ts
539
522
  interface FakeIdentityProviderOptions {
540
523
  /** Provider id. Default `'fake'`. */
541
524
  id?: string;
@@ -553,7 +536,7 @@ interface FakeIdentityProviderOptions {
553
536
  * It does NOT verify a nonce — it is the trusted test double; the real §7
554
537
  * nonce/JWKS assertions are exercised against {@link OidcProvider} with `jose`.
555
538
  */
556
- declare class FakeIdentityProvider implements IdentityProvider {
539
+ export declare class FakeIdentityProvider implements IdentityProvider {
557
540
  readonly id: string;
558
541
  private readonly authorizationEndpoint;
559
542
  private readonly defaultProfile?;
@@ -564,8 +547,6 @@ declare class FakeIdentityProvider implements IdentityProvider {
564
547
  authorizationUrl(args: AuthorizationUrlArgs): Promise<string>;
565
548
  exchange(args: ExchangeArgs): Promise<NormalizedProfile>;
566
549
  }
567
- //#endregion
568
- //#region src/registry.d.ts
569
550
  interface OAuthProviderRegistryOptions {
570
551
  /** Public origin — `redirect_uri` is built as `baseUrl` + the callback path (§3.7). */
571
552
  baseUrl: string;
@@ -595,7 +576,7 @@ interface OAuthProviderRegistryOptions {
595
576
  * each provider that implements `applyDefaults`, and builds the per-provider
596
577
  * fixed redirect URIs.
597
578
  */
598
- declare class OAuthProviderRegistry {
579
+ export declare class OAuthProviderRegistry {
599
580
  readonly baseUrl: string;
600
581
  readonly stateSecret: string;
601
582
  readonly policy: ResolvedFederatedPolicy;
@@ -628,8 +609,6 @@ declare class OAuthProviderRegistry {
628
609
  */
629
610
  deriveSeededPkce(seed: string): SeededPkce;
630
611
  }
631
- //#endregion
632
- //#region src/federated-login-service.d.ts
633
612
  interface FederatedLoginServiceDeps<T extends object = object> {
634
613
  /** Concrete user orchestrator (RFC: idp depends on the concrete class). */
635
614
  users: UserService<T>;
@@ -648,7 +627,7 @@ interface FederatedLoginServiceDeps<T extends object = object> {
648
627
  * Generic over the user shape `T` so a consumer's `UserService<DemoUser>` plugs
649
628
  * in directly; `resolveUser` only reads base `UserCredentials` fields.
650
629
  */
651
- declare class FederatedLoginService<T extends object = object> {
630
+ export declare class FederatedLoginService<T extends object = object> {
652
631
  private readonly users;
653
632
  private readonly federated;
654
633
  readonly policy: ResolvedFederatedPolicy;
@@ -698,5 +677,4 @@ declare class FederatedLoginService<T extends object = object> {
698
677
  private newIdentity;
699
678
  private touch;
700
679
  }
701
- //#endregion
702
- export { AppleProvider, type AppleProviderOptions, type AuthorizationUrlArgs, type ConfigurableProvider, type EmailMatchPolicy, type ExchangeArgs, FakeIdentityProvider, type FakeIdentityProviderOptions, FederatedLoginService, type FederatedLoginServiceDeps, type FederatedPolicy, type FetchLike, type FetchResponseLike, GithubProvider, type GithubProviderOptions, GoogleProvider, type GoogleProviderOptions, type IdentityProvider, type NormalizedProfile, OAuthError, type OAuthErrorType, OAuthProviderRegistry, type OAuthProviderRegistryOptions, type OAuthStatePayload, type OidcDiscoveryDocument, OidcProvider, type OidcProviderOptions, type PkcePair, type ResolveOutcome, type ResolvedFederatedPolicy, type SeededPkce, type SharedProviderConfig, type SignStateOptions, type VerifyStateOptions, createPkcePair, defaultUsernameStrategy, deriveSeededPkce, generateNonce, generateRandomState, isConfigurableProvider, pkceChallengeFor, resolveFederatedPolicy, signState, verifyState };
680
+ export type { AppleProviderOptions, AuthorizationUrlArgs, ConfigurableProvider, EmailMatchPolicy, ExchangeArgs, FakeIdentityProviderOptions, FederatedLoginServiceDeps, FederatedPolicy, FetchLike, FetchResponseLike, GithubProviderOptions, GoogleProviderOptions, IdentityProvider, NormalizedProfile, OAuthErrorType, OAuthProviderRegistryOptions, OAuthStatePayload, OidcDiscoveryDocument, OidcProviderOptions, PkcePair, ResolveOutcome, ResolvedFederatedPolicy, SeededPkce, SharedProviderConfig, SignStateOptions, VerifyStateOptions };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { Clock } from "@aooth/auth";
2
2
  import { JWTPayload, JWTVerifyGetKey } from "jose";
3
3
  import { FederatedIdentity, FederatedIdentityStore, FederatedProfileSnapshot, UserService } from "@aooth/user";
4
- //#region src/errors.d.ts
5
4
  /**
6
5
  * Federated-login failure taxonomy (RFC IDP.md §8). Mirrors `AuthError` /
7
6
  * `UserAuthError` — a typed `Error` with a stable `type` code, an optional
@@ -30,14 +29,12 @@ type OAuthErrorType =
30
29
  "ID_TOKEN_INVALID" |
31
30
  /** Policy needed a verified email but the provider returned none. */
32
31
  "EMAIL_UNAVAILABLE";
33
- declare class OAuthError extends Error {
32
+ export declare class OAuthError extends Error {
34
33
  readonly type: OAuthErrorType;
35
34
  readonly details?: Record<string, unknown> | undefined;
36
35
  readonly name = "OAuthError";
37
36
  constructor(type: OAuthErrorType, message?: string, details?: Record<string, unknown> | undefined);
38
37
  }
39
- //#endregion
40
- //#region src/types.d.ts
41
38
  /**
42
39
  * A provider profile normalized to a single shape across Google / OIDC / etc.
43
40
  * Structural superset of `@aooth/user`'s {@link FederatedProfileSnapshot} (the
@@ -139,7 +136,7 @@ interface ConfigurableProvider extends IdentityProvider {
139
136
  applyDefaults(shared: SharedProviderConfig): void;
140
137
  }
141
138
  /** Structural check used by the registry to feature-detect `applyDefaults`. */
142
- declare function isConfigurableProvider(p: IdentityProvider): p is ConfigurableProvider;
139
+ export declare function isConfigurableProvider(p: IdentityProvider): p is ConfigurableProvider;
143
140
  /**
144
141
  * How a federated login that matches an existing local account **by email**
145
142
  * is handled (RFC §4 — the account-takeover-sensitive knob).
@@ -166,9 +163,9 @@ interface FederatedPolicy {
166
163
  }
167
164
  type ResolvedFederatedPolicy = Required<FederatedPolicy>;
168
165
  /** Default username strategy: the verified email, else the stable `provider:subject`. */
169
- declare function defaultUsernameStrategy(p: NormalizedProfile): string;
166
+ export declare function defaultUsernameStrategy(p: NormalizedProfile): string;
170
167
  /** Apply RFC §4 safe defaults over a partial policy. */
171
- declare function resolveFederatedPolicy(policy?: FederatedPolicy): ResolvedFederatedPolicy;
168
+ export declare function resolveFederatedPolicy(policy?: FederatedPolicy): ResolvedFederatedPolicy;
172
169
  /**
173
170
  * The outcome of {@link FederatedLoginService.resolveUser} (decision #1). A
174
171
  * discriminated union — richer than the RFC's `{ userId, isNew }` sketch — so
@@ -205,8 +202,6 @@ type ResolveOutcome =
205
202
  kind: "denied";
206
203
  reason: "signup-disabled" | "email-unavailable";
207
204
  };
208
- //#endregion
209
- //#region src/pkce.d.ts
210
205
  interface PkcePair {
211
206
  /** The high-entropy secret kept server-side (cookie / wf state). */
212
207
  verifier: string;
@@ -229,13 +224,13 @@ interface SeededPkce {
229
224
  * Mint a fresh PKCE pair. The 32-byte verifier base64url-encodes to 43 chars,
230
225
  * comfortably inside RFC 7636's 43–128 range.
231
226
  */
232
- declare function createPkcePair(): PkcePair;
227
+ export declare function createPkcePair(): PkcePair;
233
228
  /** Recompute the S256 challenge for a known verifier (verification side). */
234
- declare function pkceChallengeFor(verifier: string): string;
229
+ export declare function pkceChallengeFor(verifier: string): string;
235
230
  /** OIDC `nonce` — minted at `/start`, bound into state, asserted in `exchange()`. */
236
- declare function generateNonce(bytes?: number): string;
231
+ export declare function generateNonce(bytes?: number): string;
237
232
  /** Random component bound into the signed `state` (anti-CSRF / anti-replay). */
238
- declare function generateRandomState(bytes?: number): string;
233
+ export declare function generateRandomState(bytes?: number): string;
239
234
  /**
240
235
  * STATELESS PKCE: deterministically DERIVE the code verifier + OIDC nonce from
241
236
  * a non-secret `seed` and the server's HMAC `secret`, instead of minting them
@@ -255,9 +250,7 @@ declare function generateRandomState(bytes?: number): string;
255
250
  * Same output range as {@link createPkcePair}: a 32-byte HMAC-SHA256 digest →
256
251
  * a 43-char base64url verifier, inside RFC 7636's 43–128.
257
252
  */
258
- declare function deriveSeededPkce(secret: string | Uint8Array, seed: string): SeededPkce;
259
- //#endregion
260
- //#region src/state.d.ts
253
+ export declare function deriveSeededPkce(secret: string | Uint8Array, seed: string): SeededPkce;
261
254
  /**
262
255
  * The CSRF/replay binding carried across the OAuth bounce (RFC §7). Signed into
263
256
  * a compact HS256 JWT by {@link signState} so it is tamper-evident in the URL
@@ -293,15 +286,13 @@ interface VerifyStateOptions {
293
286
  * Sign the binding into a compact HS256 JWT. Field names are abbreviated to
294
287
  * keep the URL `state` short; {@link verifyState} maps them back.
295
288
  */
296
- declare function signState(payload: OAuthStatePayload, secret: string | Uint8Array, opts?: SignStateOptions): Promise<string>;
289
+ export declare function signState(payload: OAuthStatePayload, secret: string | Uint8Array, opts?: SignStateOptions): Promise<string>;
297
290
  /**
298
291
  * Verify + decode the signed state. Pins `HS256` (rejects `alg:none` / key
299
292
  * confusion). Throws {@link OAuthError} `STATE_EXPIRED` past TTL,
300
293
  * `STATE_INVALID` on any other signature/shape failure.
301
294
  */
302
- declare function verifyState(token: string, secret: string | Uint8Array, opts?: VerifyStateOptions): Promise<OAuthStatePayload>;
303
- //#endregion
304
- //#region src/providers/oidc.d.ts
295
+ export declare function verifyState(token: string, secret: string | Uint8Array, opts?: VerifyStateOptions): Promise<OAuthStatePayload>;
305
296
  /** The four endpoints the OIDC client needs — discovered or supplied explicitly. */
306
297
  interface OidcDiscoveryDocument {
307
298
  issuer: string;
@@ -365,7 +356,7 @@ interface OidcProviderOptions {
365
356
  *
366
357
  * `GoogleProvider` is a thin subclass pinning the issuer + algs.
367
358
  */
368
- declare class OidcProvider implements ConfigurableProvider {
359
+ export declare class OidcProvider implements ConfigurableProvider {
369
360
  readonly id: string;
370
361
  protected readonly issuer: string;
371
362
  protected readonly clientId: string;
@@ -413,8 +404,6 @@ declare class OidcProvider implements ConfigurableProvider {
413
404
  private validateDiscovery;
414
405
  private getJwks;
415
406
  }
416
- //#endregion
417
- //#region src/providers/google.d.ts
418
407
  /** Google options = OIDC options minus the pinned `id`/`issuer`. */
419
408
  type GoogleProviderOptions = Omit<OidcProviderOptions, "id" | "issuer">;
420
409
  /**
@@ -422,11 +411,9 @@ type GoogleProviderOptions = Omit<OidcProviderOptions, "id" | "issuer">;
422
411
  * (Google's only ID-token alg). Everything else — discovery, JWKS rotation,
423
412
  * the full §7 validation — is inherited from {@link OidcProvider}.
424
413
  */
425
- declare class GoogleProvider extends OidcProvider {
414
+ export declare class GoogleProvider extends OidcProvider {
426
415
  constructor(opts: GoogleProviderOptions);
427
416
  }
428
- //#endregion
429
- //#region src/providers/github.d.ts
430
417
  interface GithubProviderOptions {
431
418
  /** Provider id. Default `'github'`. */
432
419
  id?: string;
@@ -457,7 +444,7 @@ interface GithubProviderOptions {
457
444
  * Implements {@link ConfigurableProvider} so the registry can inject a shared
458
445
  * `fetch` (deterministic tests) / `clock`; a constructor value always wins.
459
446
  */
460
- declare class GithubProvider implements ConfigurableProvider {
447
+ export declare class GithubProvider implements ConfigurableProvider {
461
448
  readonly id: string;
462
449
  private readonly clientId;
463
450
  private readonly clientSecret;
@@ -486,8 +473,6 @@ declare class GithubProvider implements ConfigurableProvider {
486
473
  private fetchPrimaryEmail;
487
474
  private apiGet;
488
475
  }
489
- //#endregion
490
- //#region src/providers/apple.d.ts
491
476
  interface AppleProviderOptions extends Omit<OidcProviderOptions, "id" | "issuer" | "clientSecret" | "idTokenSigningAlgs" | "scopes"> {
492
477
  /** The Services ID — Sign in with Apple's OAuth `client_id` (and the id_token `aud`). */
493
478
  clientId: string;
@@ -527,15 +512,13 @@ interface AppleProviderOptions extends Omit<OidcProviderOptions, "id" | "issuer"
527
512
  * capture it, so `displayName` is undefined for Apple. Collect a display name
528
513
  * post-signup if you need one.
529
514
  */
530
- declare class AppleProvider extends OidcProvider {
515
+ export declare class AppleProvider extends OidcProvider {
531
516
  constructor(opts: AppleProviderOptions);
532
517
  /** `email`/`name` scope makes Apple POST the callback — declare `form_post`. */
533
518
  protected extraAuthorizationParams(_args: AuthorizationUrlArgs): Record<string, string>;
534
519
  /** Coerce Apple's STRING `email_verified` (the base sets only a real boolean). */
535
520
  protected normalize(payload: JWTPayload): NormalizedProfile;
536
521
  }
537
- //#endregion
538
- //#region src/providers/fake.d.ts
539
522
  interface FakeIdentityProviderOptions {
540
523
  /** Provider id. Default `'fake'`. */
541
524
  id?: string;
@@ -553,7 +536,7 @@ interface FakeIdentityProviderOptions {
553
536
  * It does NOT verify a nonce — it is the trusted test double; the real §7
554
537
  * nonce/JWKS assertions are exercised against {@link OidcProvider} with `jose`.
555
538
  */
556
- declare class FakeIdentityProvider implements IdentityProvider {
539
+ export declare class FakeIdentityProvider implements IdentityProvider {
557
540
  readonly id: string;
558
541
  private readonly authorizationEndpoint;
559
542
  private readonly defaultProfile?;
@@ -564,8 +547,6 @@ declare class FakeIdentityProvider implements IdentityProvider {
564
547
  authorizationUrl(args: AuthorizationUrlArgs): Promise<string>;
565
548
  exchange(args: ExchangeArgs): Promise<NormalizedProfile>;
566
549
  }
567
- //#endregion
568
- //#region src/registry.d.ts
569
550
  interface OAuthProviderRegistryOptions {
570
551
  /** Public origin — `redirect_uri` is built as `baseUrl` + the callback path (§3.7). */
571
552
  baseUrl: string;
@@ -595,7 +576,7 @@ interface OAuthProviderRegistryOptions {
595
576
  * each provider that implements `applyDefaults`, and builds the per-provider
596
577
  * fixed redirect URIs.
597
578
  */
598
- declare class OAuthProviderRegistry {
579
+ export declare class OAuthProviderRegistry {
599
580
  readonly baseUrl: string;
600
581
  readonly stateSecret: string;
601
582
  readonly policy: ResolvedFederatedPolicy;
@@ -628,8 +609,6 @@ declare class OAuthProviderRegistry {
628
609
  */
629
610
  deriveSeededPkce(seed: string): SeededPkce;
630
611
  }
631
- //#endregion
632
- //#region src/federated-login-service.d.ts
633
612
  interface FederatedLoginServiceDeps<T extends object = object> {
634
613
  /** Concrete user orchestrator (RFC: idp depends on the concrete class). */
635
614
  users: UserService<T>;
@@ -648,7 +627,7 @@ interface FederatedLoginServiceDeps<T extends object = object> {
648
627
  * Generic over the user shape `T` so a consumer's `UserService<DemoUser>` plugs
649
628
  * in directly; `resolveUser` only reads base `UserCredentials` fields.
650
629
  */
651
- declare class FederatedLoginService<T extends object = object> {
630
+ export declare class FederatedLoginService<T extends object = object> {
652
631
  private readonly users;
653
632
  private readonly federated;
654
633
  readonly policy: ResolvedFederatedPolicy;
@@ -698,5 +677,4 @@ declare class FederatedLoginService<T extends object = object> {
698
677
  private newIdentity;
699
678
  private touch;
700
679
  }
701
- //#endregion
702
- export { AppleProvider, type AppleProviderOptions, type AuthorizationUrlArgs, type ConfigurableProvider, type EmailMatchPolicy, type ExchangeArgs, FakeIdentityProvider, type FakeIdentityProviderOptions, FederatedLoginService, type FederatedLoginServiceDeps, type FederatedPolicy, type FetchLike, type FetchResponseLike, GithubProvider, type GithubProviderOptions, GoogleProvider, type GoogleProviderOptions, type IdentityProvider, type NormalizedProfile, OAuthError, type OAuthErrorType, OAuthProviderRegistry, type OAuthProviderRegistryOptions, type OAuthStatePayload, type OidcDiscoveryDocument, OidcProvider, type OidcProviderOptions, type PkcePair, type ResolveOutcome, type ResolvedFederatedPolicy, type SeededPkce, type SharedProviderConfig, type SignStateOptions, type VerifyStateOptions, createPkcePair, defaultUsernameStrategy, deriveSeededPkce, generateNonce, generateRandomState, isConfigurableProvider, pkceChallengeFor, resolveFederatedPolicy, signState, verifyState };
680
+ export type { AppleProviderOptions, AuthorizationUrlArgs, ConfigurableProvider, EmailMatchPolicy, ExchangeArgs, FakeIdentityProviderOptions, FederatedLoginServiceDeps, FederatedPolicy, FetchLike, FetchResponseLike, GithubProviderOptions, GoogleProviderOptions, IdentityProvider, NormalizedProfile, OAuthErrorType, OAuthProviderRegistryOptions, OAuthStatePayload, OidcDiscoveryDocument, OidcProviderOptions, PkcePair, ResolveOutcome, ResolvedFederatedPolicy, SeededPkce, SharedProviderConfig, SignStateOptions, VerifyStateOptions };
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { createHash, createHmac, randomBytes } from "node:crypto";
2
2
  import { defaultClock } from "@aooth/auth";
3
3
  import { SignJWT, createRemoteJWKSet, errors, importPKCS8, jwtVerify } from "jose";
4
4
  import { UserAuthError, pickDefinedProfile } from "@aooth/user";
5
- //#region src/errors.ts
5
+ // src/errors.ts
6
6
  const defaultMessages = {
7
7
  UNKNOWN_PROVIDER: "Unknown identity provider",
8
8
  INVALID_CONFIG: "Invalid OAuth provider configuration",
@@ -24,8 +24,7 @@ var OAuthError = class extends Error {
24
24
  this.details = details;
25
25
  }
26
26
  };
27
- //#endregion
28
- //#region src/types.ts
27
+ // src/types.ts
29
28
  /** Structural check used by the registry to feature-detect `applyDefaults`. */
30
29
  function isConfigurableProvider(p) {
31
30
  return typeof p.applyDefaults === "function";
@@ -43,8 +42,7 @@ function resolveFederatedPolicy(policy = {}) {
43
42
  trustEmailVerifiedFrom: policy.trustEmailVerifiedFrom ?? []
44
43
  };
45
44
  }
46
- //#endregion
47
- //#region src/pkce.ts
45
+ // src/pkce.ts
48
46
  /**
49
47
  * PKCE / CSRF primitives (RFC 7636 + OIDC nonce). All values are URL-safe
50
48
  * base64url with no padding, so they ride in query params and cookies without
@@ -106,8 +104,7 @@ function deriveSeededPkce(secret, seed) {
106
104
  method: "S256"
107
105
  };
108
106
  }
109
- //#endregion
110
- //#region src/state.ts
107
+ // src/state.ts
111
108
  const DEFAULT_TTL_SEC = 600;
112
109
  function toKey(secret) {
113
110
  return typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
@@ -162,8 +159,7 @@ async function verifyState(token, secret, opts = {}) {
162
159
  if (typeof payload.uid === "string") out.userId = payload.uid;
163
160
  return out;
164
161
  }
165
- //#endregion
166
- //#region src/providers/oauth2-shared.ts
162
+ // src/providers/oauth2-shared.ts
167
163
  /** Resolve the effective `fetch`: an injected impl, else the global `fetch`. */
168
164
  function resolveFetch(impl) {
169
165
  return impl ?? globalThis.fetch;
@@ -212,8 +208,7 @@ function buildAuthorizeUrl(endpoint, args, opts = {}) {
212
208
  for (const [k, v] of Object.entries(opts.extraParams ?? {})) url.searchParams.set(k, v);
213
209
  return url.toString();
214
210
  }
215
- //#endregion
216
- //#region src/providers/oidc.ts
211
+ // src/providers/oidc.ts
217
212
  const DEFAULT_SCOPES$1 = [
218
213
  "openid",
219
214
  "email",
@@ -415,11 +410,11 @@ var OidcProvider = class {
415
410
  * token's hash, the hash chosen by the id_token's `alg` (RS256 → SHA-256).
416
411
  */
417
412
  function atHash(accessToken, alg) {
418
- const digest = createHash(alg.endsWith("384") ? "sha384" : alg.endsWith("512") ? "sha512" : "sha256").update(accessToken).digest();
413
+ const sha = alg.endsWith("384") ? "sha384" : alg.endsWith("512") ? "sha512" : "sha256";
414
+ const digest = createHash(sha).update(accessToken).digest();
419
415
  return digest.subarray(0, digest.length / 2).toString("base64url");
420
416
  }
421
- //#endregion
422
- //#region src/providers/google.ts
417
+ // src/providers/google.ts
423
418
  /** Google's stable OIDC issuer — endpoints + JWKS are discovered from it. */
424
419
  const GOOGLE_ISSUER = "https://accounts.google.com";
425
420
  /**
@@ -437,8 +432,7 @@ var GoogleProvider = class extends OidcProvider {
437
432
  });
438
433
  }
439
434
  };
440
- //#endregion
441
- //#region src/providers/github.ts
435
+ // src/providers/github.ts
442
436
  const GITHUB_AUTHORIZE = "https://github.com/login/oauth/authorize";
443
437
  const GITHUB_TOKEN = "https://github.com/login/oauth/access_token";
444
438
  const GITHUB_USER = "https://api.github.com/user";
@@ -575,8 +569,7 @@ var GithubProvider = class {
575
569
  }, { label: `GitHub API (${url})` });
576
570
  }
577
571
  };
578
- //#endregion
579
- //#region src/providers/apple.ts
572
+ // src/providers/apple.ts
580
573
  /** Apple's stable OIDC issuer — endpoints + JWKS are discovered from it. */
581
574
  const APPLE_ISSUER = "https://appleid.apple.com";
582
575
  /** Apple ID tokens are always ES256. */
@@ -680,8 +673,7 @@ var AppleProvider = class extends OidcProvider {
680
673
  return profile;
681
674
  }
682
675
  };
683
- //#endregion
684
- //#region src/providers/fake.ts
676
+ // src/providers/fake.ts
685
677
  /**
686
678
  * Deterministic, network-free {@link IdentityProvider} for unit tests and the
687
679
  * `DEMO_MODE=test` fake-IdP e2e route (RFC §9). `exchange` resolves a `code`
@@ -718,8 +710,7 @@ var FakeIdentityProvider = class {
718
710
  });
719
711
  }
720
712
  };
721
- //#endregion
722
- //#region src/registry.ts
713
+ // src/registry.ts
723
714
  const DEFAULT_CALLBACK_TEMPLATE = "/auth/oauth/:provider/callback";
724
715
  /**
725
716
  * Holds the configured {@link IdentityProvider}s + {@link FederatedPolicy} +
@@ -801,8 +792,7 @@ var OAuthProviderRegistry = class {
801
792
  return deriveSeededPkce(this.stateSecret, seed);
802
793
  }
803
794
  };
804
- //#endregion
805
- //#region src/federated-login-service.ts
795
+ // src/federated-login-service.ts
806
796
  /**
807
797
  * The core federated-login logic (RFC §3.5): map a verified provider profile to
808
798
  * an aooth user id. Pure orchestration over `UserService` + `FederatedIdentityStore`
@@ -939,5 +929,4 @@ var FederatedLoginService = class {
939
929
  return this.federated.touchLogin(profile.provider, profile.subject, pickDefinedProfile(profile));
940
930
  }
941
931
  };
942
- //#endregion
943
932
  export { AppleProvider, FakeIdentityProvider, FederatedLoginService, GithubProvider, GoogleProvider, OAuthError, OAuthProviderRegistry, OidcProvider, createPkcePair, defaultUsernameStrategy, deriveSeededPkce, generateNonce, generateRandomState, isConfigurableProvider, pkceChallengeFor, resolveFederatedPolicy, signState, verifyState };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aooth/idp",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Framework-agnostic OAuth2 / OIDC federated-login core for aoothjs (provider registry, PKCE/state, ID-token verification, account resolution)",
5
5
  "keywords": [
6
6
  "aoothjs",
@@ -43,12 +43,10 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "jose": "^6.2.3",
46
- "@aooth/auth": "0.2.1",
47
- "@aooth/user": "0.2.1"
48
- },
49
- "devDependencies": {
50
- "vitest": "npm:@voidzero-dev/vite-plus-test@latest"
46
+ "@aooth/auth": "0.2.2",
47
+ "@aooth/user": "0.2.2"
51
48
  },
49
+ "devDependencies": {},
52
50
  "scripts": {
53
51
  "build": "vp pack",
54
52
  "dev": "vp pack --watch",