@absolutejs/auth 0.27.0-beta.1 → 0.27.0-beta.11

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 (44) hide show
  1. package/dist/abuse/captcha.d.ts +11 -0
  2. package/dist/abuse/config.d.ts +29 -0
  3. package/dist/actions.d.ts +27 -0
  4. package/dist/adaptive/config.d.ts +13 -1
  5. package/dist/adaptive/fingerprint.d.ts +2 -0
  6. package/dist/adaptive/types.d.ts +13 -1
  7. package/dist/apikeys/routes.d.ts +1 -1
  8. package/dist/audit/export.d.ts +2 -0
  9. package/dist/audit/integrity.d.ts +19 -0
  10. package/dist/audit/siem.d.ts +11 -0
  11. package/dist/audit/types.d.ts +2 -1
  12. package/dist/credentials/config.d.ts +1 -0
  13. package/dist/credentials/emailValidation.d.ts +9 -0
  14. package/dist/credentials/login.d.ts +2 -1
  15. package/dist/credentials/passwordPolicy.d.ts +1 -0
  16. package/dist/credentials/routes.d.ts +1 -0
  17. package/dist/fga/config.d.ts +53 -0
  18. package/dist/fga/inMemoryStores.d.ts +3 -0
  19. package/dist/fga/postgresStores.d.ts +144 -0
  20. package/dist/fga/schema.d.ts +2 -0
  21. package/dist/fga/types.d.ts +28 -0
  22. package/dist/index.d.ts +6281 -3
  23. package/dist/index.js +10946 -9153
  24. package/dist/index.js.map +44 -19
  25. package/dist/mfa/rotation.d.ts +17 -0
  26. package/dist/mfa/types.d.ts +1 -0
  27. package/dist/oidc/config.d.ts +77 -0
  28. package/dist/oidc/dpop.d.ts +12 -0
  29. package/dist/oidc/inMemoryStores.d.ts +4 -0
  30. package/dist/oidc/keys.d.ts +21 -0
  31. package/dist/oidc/postgresStores.d.ts +573 -0
  32. package/dist/oidc/routes.d.ts +142 -0
  33. package/dist/oidc/types.d.ts +42 -0
  34. package/dist/organizations/operations.d.ts +7 -0
  35. package/dist/session/anonymous.d.ts +11 -0
  36. package/dist/session/impersonation.d.ts +29 -0
  37. package/dist/session/multiSession.d.ts +25 -0
  38. package/dist/session/promote.d.ts +3 -1
  39. package/dist/types.d.ts +24 -0
  40. package/dist/vault/config.d.ts +20 -0
  41. package/dist/vault/inMemoryVaultStore.d.ts +2 -0
  42. package/dist/vault/postgresVaultStore.d.ts +100 -0
  43. package/dist/vault/types.d.ts +14 -0
  44. package/package.json +1 -1
@@ -0,0 +1,142 @@
1
+ import { Elysia } from 'elysia';
2
+ import type { AuthSessionStore } from '../session/types';
3
+ import { type OidcProviderConfig } from './config';
4
+ export declare const oidcProviderRoutes: <UserType>(config: OidcProviderConfig<UserType> & {
5
+ authSessionStore?: AuthSessionStore<UserType>;
6
+ }) => Elysia<"", {
7
+ decorator: {};
8
+ store: {
9
+ session: import("..").SessionRecord<UserType>;
10
+ unregisteredSession: import("..").UnregisteredSessionRecord;
11
+ };
12
+ derive: {};
13
+ resolve: {};
14
+ }, {
15
+ typebox: {};
16
+ error: {};
17
+ }, {
18
+ schema: {};
19
+ standaloneSchema: {};
20
+ macro: {};
21
+ macroFn: {};
22
+ parser: {};
23
+ response: {};
24
+ }, {
25
+ [x: string]: {
26
+ get: {
27
+ body: unknown;
28
+ params: {};
29
+ query: {
30
+ client_id?: string | undefined;
31
+ scope?: string | undefined;
32
+ nonce?: string | undefined;
33
+ code_challenge?: string | undefined;
34
+ code_challenge_method?: string | undefined;
35
+ redirect_uri?: string | undefined;
36
+ response_type?: string | undefined;
37
+ state?: string | undefined;
38
+ };
39
+ headers: unknown;
40
+ response: {
41
+ 200: Response;
42
+ 422: {
43
+ type: "validation";
44
+ on: string;
45
+ summary?: string;
46
+ message?: string;
47
+ found?: unknown;
48
+ property?: string;
49
+ expected?: string;
50
+ };
51
+ };
52
+ };
53
+ };
54
+ } & {
55
+ [x: string]: {
56
+ post: {
57
+ body: {
58
+ client_id?: string | undefined;
59
+ scope?: string | undefined;
60
+ audience?: string | undefined;
61
+ resource?: string | undefined;
62
+ refresh_token?: string | undefined;
63
+ client_secret?: string | undefined;
64
+ grant_type?: string | undefined;
65
+ code?: string | undefined;
66
+ redirect_uri?: string | undefined;
67
+ code_verifier?: string | undefined;
68
+ subject_token?: string | undefined;
69
+ subject_token_type?: string | undefined;
70
+ };
71
+ params: {};
72
+ query: unknown;
73
+ headers: unknown;
74
+ response: {
75
+ 200: Response;
76
+ 422: {
77
+ type: "validation";
78
+ on: string;
79
+ summary?: string;
80
+ message?: string;
81
+ found?: unknown;
82
+ property?: string;
83
+ expected?: string;
84
+ };
85
+ };
86
+ };
87
+ };
88
+ } & {
89
+ [x: string]: {
90
+ get: {
91
+ body: unknown;
92
+ params: {};
93
+ query: unknown;
94
+ headers: unknown;
95
+ response: {
96
+ 200: {
97
+ keys: {
98
+ alg: string;
99
+ crv: string | undefined;
100
+ kid: string;
101
+ kty: string | undefined;
102
+ use: string;
103
+ x: string | undefined;
104
+ y: string | undefined;
105
+ }[];
106
+ };
107
+ };
108
+ };
109
+ };
110
+ } & {
111
+ ".well-known": {
112
+ "openid-configuration": {
113
+ get: {
114
+ body: unknown;
115
+ params: {};
116
+ query: unknown;
117
+ headers: unknown;
118
+ response: {
119
+ 200: Record<string, string | string[]>;
120
+ };
121
+ };
122
+ };
123
+ };
124
+ }, {
125
+ derive: {};
126
+ resolve: {};
127
+ schema: {};
128
+ standaloneSchema: {};
129
+ response: {};
130
+ }, {
131
+ derive: {};
132
+ resolve: {};
133
+ schema: {};
134
+ standaloneSchema: {};
135
+ response: {};
136
+ } & {
137
+ derive: {};
138
+ resolve: {};
139
+ schema: {};
140
+ standaloneSchema: {};
141
+ response: {};
142
+ }>;
@@ -0,0 +1,42 @@
1
+ export type OAuthClient = {
2
+ clientId: string;
3
+ hashedSecret?: string;
4
+ name: string;
5
+ redirectUris: string[];
6
+ scopes: string[];
7
+ };
8
+ export type OAuthClientStore = {
9
+ findClient: (clientId: string) => Promise<OAuthClient | undefined>;
10
+ };
11
+ export type AuthorizationCode = {
12
+ claims?: Record<string, unknown>;
13
+ clientId: string;
14
+ codeChallenge: string;
15
+ codeHash: string;
16
+ createdAt: number;
17
+ dpopJkt?: string;
18
+ expiresAt: number;
19
+ nonce?: string;
20
+ redirectUri: string;
21
+ scopes: string[];
22
+ userId: string;
23
+ };
24
+ export type AuthorizationCodeStore = {
25
+ consumeCode: (codeHash: string) => Promise<AuthorizationCode | undefined>;
26
+ saveCode: (code: AuthorizationCode) => Promise<void>;
27
+ };
28
+ export type OidcRefreshToken = {
29
+ claims?: Record<string, unknown>;
30
+ clientId: string;
31
+ createdAt: number;
32
+ dpopJkt?: string;
33
+ expiresAt: number;
34
+ scopes: string[];
35
+ tokenHash: string;
36
+ userId: string;
37
+ };
38
+ export type OidcRefreshTokenStore = {
39
+ consumeToken: (tokenHash: string) => Promise<OidcRefreshToken | undefined>;
40
+ deleteForUser: (userId: string) => Promise<void>;
41
+ saveToken: (token: OidcRefreshToken) => Promise<void>;
42
+ };
@@ -5,6 +5,13 @@ export declare const acceptInvitation: ({ organizationStore, token, userId }: {
5
5
  token: string;
6
6
  userId: string;
7
7
  }) => Promise<OrganizationMembership | undefined>;
8
+ export declare const autoAssignOrgsByEmail: ({ email, getOrgsForDomain, organizationStore, roles, userId }: {
9
+ email: string;
10
+ getOrgsForDomain: (domain: string) => Promise<OrganizationId[]> | OrganizationId[];
11
+ organizationStore: OrganizationStore;
12
+ roles?: string[];
13
+ userId: string;
14
+ }) => Promise<string[]>;
8
15
  export declare const createOrganization: ({ metadata, name, organizationStore, ownerRoles, ownerUserId }: {
9
16
  metadata?: Record<string, unknown>;
10
17
  name: string;
@@ -0,0 +1,11 @@
1
+ import type { Cookie } from 'elysia';
2
+ import type { SessionData, SessionRecord, UserSessionId } from '../types';
3
+ import type { AuthSessionStore } from './types';
4
+ export declare const createAnonymousSession: <UserType>({ authSessionStore, cookie, guestUser, inMemorySession, sessionDurationMs }: {
5
+ authSessionStore?: AuthSessionStore<UserType>;
6
+ cookie: Cookie<UserSessionId | undefined>;
7
+ guestUser: UserType;
8
+ inMemorySession: SessionRecord<UserType>;
9
+ sessionDurationMs?: number;
10
+ }) => Promise<`${string}-${string}-${string}-${string}-${string}`>;
11
+ export declare const isAnonymousSession: <UserType>(session: SessionData<UserType> | undefined) => boolean;
@@ -0,0 +1,29 @@
1
+ import type { Cookie } from 'elysia';
2
+ import type { AuditEvent } from '../audit/types';
3
+ import type { SessionData, SessionRecord, UserSessionId } from '../types';
4
+ import type { AuthSessionStore } from './types';
5
+ type Emit = (event: AuditEvent) => Promise<void> | void;
6
+ export declare const endImpersonation: <UserType>({ authSessionStore, cookie, emit, inMemorySession }: {
7
+ authSessionStore?: AuthSessionStore<UserType>;
8
+ cookie: Cookie<UserSessionId | undefined>;
9
+ emit?: Emit;
10
+ inMemorySession: SessionRecord<UserType>;
11
+ }) => Promise<{
12
+ restored: boolean;
13
+ }>;
14
+ export declare const isImpersonating: <UserType>(session: SessionData<UserType> | undefined) => boolean;
15
+ export declare const startImpersonation: <UserType>({ authSessionStore, cookie, emit, getUserId, impersonator, inMemorySession, sessionDurationMs, user }: {
16
+ authSessionStore?: AuthSessionStore<UserType>;
17
+ cookie: Cookie<UserSessionId | undefined>;
18
+ emit?: Emit;
19
+ getUserId?: (user: UserType) => string;
20
+ impersonator: {
21
+ actorEmail?: string;
22
+ actorId: string;
23
+ reason: string;
24
+ };
25
+ inMemorySession: SessionRecord<UserType>;
26
+ sessionDurationMs?: number;
27
+ user: UserType;
28
+ }) => Promise<`${string}-${string}-${string}-${string}-${string}`>;
29
+ export {};
@@ -0,0 +1,25 @@
1
+ import type { Cookie } from 'elysia';
2
+ import type { SessionRecord, UserSessionId } from '../types';
3
+ import type { AuthSessionStore } from './types';
4
+ export declare const addToSessionRing: (ring: Cookie<string | undefined>, sessionId: UserSessionId) => Cookie<string | undefined>;
5
+ export declare const listRingSessions: <UserType>({ authSessionStore, inMemorySession, ring }: {
6
+ authSessionStore?: AuthSessionStore<UserType>;
7
+ inMemorySession?: SessionRecord<UserType>;
8
+ ring: Cookie<string | undefined>;
9
+ }) => Promise<{
10
+ sessionId: UserSessionId;
11
+ user: UserType;
12
+ }[]>;
13
+ export declare const readSessionRing: (ring: Cookie<string | undefined>) => `${string}-${string}-${string}-${string}-${string}`[];
14
+ export declare const removeFromSessionRing: <UserType>({ activeCookie, authSessionStore, inMemorySession, ring, sessionId }: {
15
+ activeCookie?: Cookie<UserSessionId | undefined>;
16
+ authSessionStore?: AuthSessionStore<UserType>;
17
+ inMemorySession?: SessionRecord<UserType>;
18
+ ring: Cookie<string | undefined>;
19
+ sessionId: UserSessionId;
20
+ }) => Promise<void>;
21
+ export declare const switchActiveSession: ({ activeCookie, ring, sessionId }: {
22
+ activeCookie: Cookie<UserSessionId | undefined>;
23
+ ring: Cookie<string | undefined>;
24
+ sessionId: UserSessionId;
25
+ }) => boolean;
@@ -9,12 +9,14 @@ type ClearSessionProps<UserType> = {
9
9
  export declare const clearSession: <UserType>({ authSessionStore, cookie, inMemorySession }: ClearSessionProps<UserType>) => Promise<void>;
10
10
  export declare const persistWhen: (shouldPersist: boolean, persist: () => Promise<void>) => Promise<void>;
11
11
  type PromoteToSessionProps<UserType> = {
12
+ anonymous?: boolean;
12
13
  authSessionStore?: AuthSessionStore<UserType>;
13
14
  cookie: Cookie<UserSessionId | undefined>;
15
+ impersonator?: SessionData<UserType>['impersonator'];
14
16
  inMemorySession: SessionRecord<UserType>;
15
17
  samlLogout?: SessionData<UserType>['samlLogout'];
16
18
  sessionDurationMs: number;
17
19
  user: UserType;
18
20
  };
19
- export declare const promoteToSession: <UserType>({ authSessionStore, cookie, inMemorySession, samlLogout, sessionDurationMs, user }: PromoteToSessionProps<UserType>) => Promise<`${string}-${string}-${string}-${string}-${string}`>;
21
+ export declare const promoteToSession: <UserType>({ anonymous, authSessionStore, cookie, impersonator, inMemorySession, samlLogout, sessionDurationMs, user }: PromoteToSessionProps<UserType>) => Promise<`${string}-${string}-${string}-${string}-${string}`>;
20
22
  export {};
package/dist/types.d.ts CHANGED
@@ -10,6 +10,7 @@ import type { AuthIdentityConflict } from './errors';
10
10
  import type { AuthHtmxConfig, AuthHtmxUser } from './htmx/types';
11
11
  import type { LockoutConfig } from './lockout/config';
12
12
  import type { MfaConfig } from './mfa/config';
13
+ import type { OidcProviderConfig } from './oidc/config';
13
14
  import type { OrganizationsConfig } from './organizations/config';
14
15
  import type { PasswordlessConfig } from './passwordless/config';
15
16
  import type { PortalConfig } from './portal/config';
@@ -34,6 +35,17 @@ export type OAuth2ConfigurationOptions = {
34
35
  [Provider in ProviderOption]?: OAuth2ProviderConfiguration<Provider>;
35
36
  };
36
37
  export type UserSessionId = `${string}-${string}-${string}-${string}-${string}`;
38
+ /** Stamped on a session created via admin impersonation (`startImpersonation`). RFC 8693
39
+ * actor semantics: `actorId`/`actorEmail` are the admin acting as the user, `reason` is
40
+ * required and audited, `returnToSessionId` is the admin's own session to restore on exit.
41
+ * Surfaced by userStatus so your UI can show an "impersonating" banner. */
42
+ export type Impersonator = {
43
+ actorEmail?: string;
44
+ actorId: string;
45
+ reason: string;
46
+ returnToSessionId?: UserSessionId;
47
+ startedAt: number;
48
+ };
37
49
  export type SessionData<UserType> = {
38
50
  user: UserType;
39
51
  /** OAuth provider access token. Optional: credential / SSO sessions are not backed
@@ -53,6 +65,11 @@ export type SessionData<UserType> = {
53
65
  nameId: string;
54
66
  sessionIndex?: string;
55
67
  };
68
+ /** Present only when this session was created via admin impersonation. */
69
+ impersonator?: Impersonator;
70
+ /** True for a guest/anonymous session (createAnonymousSession) that can later be
71
+ * upgraded by a real login. */
72
+ anonymous?: boolean;
56
73
  };
57
74
  export type SessionRecord<UserType> = Record<UserSessionId, SessionData<UserType>>;
58
75
  export type UnregisteredSessionData = {
@@ -221,6 +238,13 @@ export type AuthConfig<UserType> = {
221
238
  * Pair with the exported `createApiKey` / `resolveApiPrincipal` / `hasScopes`
222
239
  * helpers to issue and guard with static keys. */
223
240
  apikeys?: ApiKeysConfig;
241
+ /** OAuth2 / OIDC provider — makes your app an identity provider ("Sign in with
242
+ * <yourapp>"). Mounts `{oidcRoute}/authorize` + `/token` + `/jwks` and
243
+ * `/.well-known/openid-configuration`: authorization_code + mandatory PKCE, ES256
244
+ * JWTs signed by a key you own (self-hosted JWKS), refresh-token rotation, and
245
+ * optional DPoP (RFC 9449) sender-constrained tokens. The authorize endpoint reuses
246
+ * the package session, so the IdP login gets passkeys / MFA / SSO for free. */
247
+ oidc?: OidcProviderConfig<UserType>;
224
248
  /** First-class multi-tenancy (the WorkOS model). When present, mounts organization +
225
249
  * membership + invitation routes under `{organizationsRoute}`: list the caller's orgs, create
226
250
  * one (caller becomes owner), invite/accept/revoke by email, and list/remove members. Ties the
@@ -0,0 +1,20 @@
1
+ import { type SecretCipher } from '../compliance/cipher';
2
+ import type { VaultStore } from './types';
3
+ export type Vault = {
4
+ delete: (ownerId: string, name: string) => Promise<void>;
5
+ get: (ownerId: string, name: string) => Promise<string | undefined>;
6
+ list: (ownerId: string) => Promise<string[]>;
7
+ put: (ownerId: string, name: string, value: string) => Promise<void>;
8
+ };
9
+ export declare const createVault: ({ cipher, store }: {
10
+ cipher: SecretCipher;
11
+ store: VaultStore;
12
+ }) => Vault;
13
+ export type VaultKeyRotationResult = {
14
+ rotated: number;
15
+ };
16
+ export declare const rotateVaultKey: ({ newKey, oldKey, store }: {
17
+ newKey: string;
18
+ oldKey: string;
19
+ store: VaultStore;
20
+ }) => Promise<VaultKeyRotationResult>;
@@ -0,0 +1,2 @@
1
+ import type { VaultStore } from './types';
2
+ export declare const createInMemoryVaultStore: () => VaultStore;
@@ -0,0 +1,100 @@
1
+ import { type AnyPgDatabase } from '../stores/postgres';
2
+ import type { VaultStore } from './types';
3
+ export declare const vaultEntriesTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
4
+ name: "auth_vault_entries";
5
+ schema: undefined;
6
+ columns: {
7
+ created_at_ms: import("drizzle-orm/pg-core").PgColumn<{
8
+ name: "created_at_ms";
9
+ tableName: "auth_vault_entries";
10
+ dataType: "number";
11
+ columnType: "PgBigInt53";
12
+ data: number;
13
+ driverParam: string | number;
14
+ notNull: true;
15
+ hasDefault: false;
16
+ isPrimaryKey: false;
17
+ isAutoincrement: false;
18
+ hasRuntimeDefault: false;
19
+ enumValues: undefined;
20
+ baseColumn: never;
21
+ identity: undefined;
22
+ generated: undefined;
23
+ }, {}, {}>;
24
+ encrypted_value: import("drizzle-orm/pg-core").PgColumn<{
25
+ name: "encrypted_value";
26
+ tableName: "auth_vault_entries";
27
+ dataType: "string";
28
+ columnType: "PgText";
29
+ data: string;
30
+ driverParam: string;
31
+ notNull: true;
32
+ hasDefault: false;
33
+ isPrimaryKey: false;
34
+ isAutoincrement: false;
35
+ hasRuntimeDefault: false;
36
+ enumValues: [string, ...string[]];
37
+ baseColumn: never;
38
+ identity: undefined;
39
+ generated: undefined;
40
+ }, {}, {}>;
41
+ name: import("drizzle-orm/pg-core").PgColumn<{
42
+ name: "name";
43
+ tableName: "auth_vault_entries";
44
+ dataType: "string";
45
+ columnType: "PgVarchar";
46
+ data: string;
47
+ driverParam: string;
48
+ notNull: true;
49
+ hasDefault: false;
50
+ isPrimaryKey: false;
51
+ isAutoincrement: false;
52
+ hasRuntimeDefault: false;
53
+ enumValues: [string, ...string[]];
54
+ baseColumn: never;
55
+ identity: undefined;
56
+ generated: undefined;
57
+ }, {}, {
58
+ length: 255;
59
+ }>;
60
+ owner_id: import("drizzle-orm/pg-core").PgColumn<{
61
+ name: "owner_id";
62
+ tableName: "auth_vault_entries";
63
+ dataType: "string";
64
+ columnType: "PgVarchar";
65
+ data: string;
66
+ driverParam: string;
67
+ notNull: true;
68
+ hasDefault: false;
69
+ isPrimaryKey: false;
70
+ isAutoincrement: false;
71
+ hasRuntimeDefault: false;
72
+ enumValues: [string, ...string[]];
73
+ baseColumn: never;
74
+ identity: undefined;
75
+ generated: undefined;
76
+ }, {}, {
77
+ length: 255;
78
+ }>;
79
+ updated_at_ms: import("drizzle-orm/pg-core").PgColumn<{
80
+ name: "updated_at_ms";
81
+ tableName: "auth_vault_entries";
82
+ dataType: "number";
83
+ columnType: "PgBigInt53";
84
+ data: number;
85
+ driverParam: string | number;
86
+ notNull: true;
87
+ hasDefault: false;
88
+ isPrimaryKey: false;
89
+ isAutoincrement: false;
90
+ hasRuntimeDefault: false;
91
+ enumValues: undefined;
92
+ baseColumn: never;
93
+ identity: undefined;
94
+ generated: undefined;
95
+ }, {}, {}>;
96
+ };
97
+ dialect: "pg";
98
+ }>;
99
+ export declare const createNeonVaultStore: (databaseUrl: string) => VaultStore;
100
+ export declare const createPostgresVaultStore: (db: AnyPgDatabase) => VaultStore;
@@ -0,0 +1,14 @@
1
+ export type VaultEntry = {
2
+ createdAt: number;
3
+ encryptedValue: string;
4
+ name: string;
5
+ ownerId: string;
6
+ updatedAt: number;
7
+ };
8
+ export type VaultStore = {
9
+ deleteEntry: (ownerId: string, name: string) => Promise<void>;
10
+ getEntry: (ownerId: string, name: string) => Promise<VaultEntry | undefined>;
11
+ listAllEntries: () => Promise<VaultEntry[]>;
12
+ listEntries: (ownerId: string) => Promise<VaultEntry[]>;
13
+ saveEntry: (entry: VaultEntry) => Promise<void>;
14
+ };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.27.0-beta.1",
2
+ "version": "0.27.0-beta.11",
3
3
  "name": "@absolutejs/auth",
4
4
  "description": "An authorization library for absolutejs",
5
5
  "repository": {