@absolutejs/auth 0.26.0-beta.4 → 0.26.0-beta.6

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.
@@ -0,0 +1,34 @@
1
+ import type { AuditEmitter } from '../audit/config';
2
+ import type { ScimTokenStore } from '../scim/types';
3
+ import type { SSOConnectionStore, SSOConnectionType } from '../sso/types';
4
+ import type { OrganizationId } from '../tenancy';
5
+ import type { RouteString } from '../types';
6
+ import type { SetupCapability, SetupSessionStore } from './types';
7
+ export declare const DEFAULT_PORTAL_ROUTE: RouteString;
8
+ export declare const DEFAULT_SETUP_SESSION_TTL_MS: number;
9
+ export type PortalConfig = {
10
+ setupSessionStore: SetupSessionStore;
11
+ onScimTokenCreated?: (context: {
12
+ organizationId: OrganizationId;
13
+ tokenId: string;
14
+ }) => void | Promise<void>;
15
+ onSsoConnectionConfigured?: (context: {
16
+ organizationId: OrganizationId;
17
+ type: SSOConnectionType;
18
+ }) => void | Promise<void>;
19
+ portalRoute?: RouteString;
20
+ scimRoute?: RouteString;
21
+ scimTokenStore?: ScimTokenStore;
22
+ ssoConnectionStore?: SSOConnectionStore;
23
+ ssoRoute?: RouteString;
24
+ };
25
+ export type PortalRouteProps = PortalConfig & {
26
+ emit?: AuditEmitter;
27
+ };
28
+ export type SetupSessionRequest = {
29
+ capabilities: SetupCapability[];
30
+ createdBy?: string;
31
+ organizationId: OrganizationId;
32
+ setupSessionDurationMs?: number;
33
+ setupSessionStore: SetupSessionStore;
34
+ };
@@ -0,0 +1,2 @@
1
+ import type { SetupSessionStore } from './types';
2
+ export declare const createInMemorySetupSessionStore: () => SetupSessionStore;
@@ -0,0 +1,10 @@
1
+ import { type SetupSessionRequest } from './config';
2
+ import type { SetupSession, SetupSessionStore } from './types';
3
+ export declare const createSetupSession: ({ capabilities, createdBy, organizationId, setupSessionDurationMs, setupSessionStore }: SetupSessionRequest) => Promise<{
4
+ setupSession: SetupSession;
5
+ token: string;
6
+ }>;
7
+ export declare const resolveSetupSession: ({ authorization, setupSessionStore }: {
8
+ authorization: string | undefined;
9
+ setupSessionStore: SetupSessionStore;
10
+ }) => Promise<SetupSession | undefined>;
@@ -0,0 +1,140 @@
1
+ import { type AnyPgDatabase } from '../stores/postgres';
2
+ import type { SetupCapability, SetupSessionStore } from './types';
3
+ export declare const setupSessionsTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
4
+ name: "auth_setup_sessions";
5
+ schema: undefined;
6
+ columns: {
7
+ capabilities: import("drizzle-orm/pg-core").PgColumn<{
8
+ name: "capabilities";
9
+ tableName: "auth_setup_sessions";
10
+ dataType: "json";
11
+ columnType: "PgJsonb";
12
+ data: SetupCapability[];
13
+ driverParam: unknown;
14
+ notNull: true;
15
+ hasDefault: true;
16
+ isPrimaryKey: false;
17
+ isAutoincrement: false;
18
+ hasRuntimeDefault: false;
19
+ enumValues: undefined;
20
+ baseColumn: never;
21
+ identity: undefined;
22
+ generated: undefined;
23
+ }, {}, {
24
+ $type: SetupCapability[];
25
+ }>;
26
+ created_at_ms: import("drizzle-orm/pg-core").PgColumn<{
27
+ name: "created_at_ms";
28
+ tableName: "auth_setup_sessions";
29
+ dataType: "number";
30
+ columnType: "PgBigInt53";
31
+ data: number;
32
+ driverParam: string | number;
33
+ notNull: true;
34
+ hasDefault: false;
35
+ isPrimaryKey: false;
36
+ isAutoincrement: false;
37
+ hasRuntimeDefault: false;
38
+ enumValues: undefined;
39
+ baseColumn: never;
40
+ identity: undefined;
41
+ generated: undefined;
42
+ }, {}, {}>;
43
+ created_by: import("drizzle-orm/pg-core").PgColumn<{
44
+ name: "created_by";
45
+ tableName: "auth_setup_sessions";
46
+ dataType: "string";
47
+ columnType: "PgVarchar";
48
+ data: string;
49
+ driverParam: string;
50
+ notNull: false;
51
+ hasDefault: false;
52
+ isPrimaryKey: false;
53
+ isAutoincrement: false;
54
+ hasRuntimeDefault: false;
55
+ enumValues: [string, ...string[]];
56
+ baseColumn: never;
57
+ identity: undefined;
58
+ generated: undefined;
59
+ }, {}, {
60
+ length: 255;
61
+ }>;
62
+ expires_at_ms: import("drizzle-orm/pg-core").PgColumn<{
63
+ name: "expires_at_ms";
64
+ tableName: "auth_setup_sessions";
65
+ dataType: "number";
66
+ columnType: "PgBigInt53";
67
+ data: number;
68
+ driverParam: string | number;
69
+ notNull: true;
70
+ hasDefault: false;
71
+ isPrimaryKey: false;
72
+ isAutoincrement: false;
73
+ hasRuntimeDefault: false;
74
+ enumValues: undefined;
75
+ baseColumn: never;
76
+ identity: undefined;
77
+ generated: undefined;
78
+ }, {}, {}>;
79
+ organization_id: import("drizzle-orm/pg-core").PgColumn<{
80
+ name: "organization_id";
81
+ tableName: "auth_setup_sessions";
82
+ dataType: "string";
83
+ columnType: "PgVarchar";
84
+ data: string;
85
+ driverParam: string;
86
+ notNull: true;
87
+ hasDefault: false;
88
+ isPrimaryKey: false;
89
+ isAutoincrement: false;
90
+ hasRuntimeDefault: false;
91
+ enumValues: [string, ...string[]];
92
+ baseColumn: never;
93
+ identity: undefined;
94
+ generated: undefined;
95
+ }, {}, {
96
+ length: 255;
97
+ }>;
98
+ setup_session_id: import("drizzle-orm/pg-core").PgColumn<{
99
+ name: "setup_session_id";
100
+ tableName: "auth_setup_sessions";
101
+ dataType: "string";
102
+ columnType: "PgVarchar";
103
+ data: string;
104
+ driverParam: string;
105
+ notNull: true;
106
+ hasDefault: false;
107
+ isPrimaryKey: true;
108
+ isAutoincrement: false;
109
+ hasRuntimeDefault: false;
110
+ enumValues: [string, ...string[]];
111
+ baseColumn: never;
112
+ identity: undefined;
113
+ generated: undefined;
114
+ }, {}, {
115
+ length: 255;
116
+ }>;
117
+ token_hash: import("drizzle-orm/pg-core").PgColumn<{
118
+ name: "token_hash";
119
+ tableName: "auth_setup_sessions";
120
+ dataType: "string";
121
+ columnType: "PgVarchar";
122
+ data: string;
123
+ driverParam: string;
124
+ notNull: true;
125
+ hasDefault: false;
126
+ isPrimaryKey: false;
127
+ isAutoincrement: false;
128
+ hasRuntimeDefault: false;
129
+ enumValues: [string, ...string[]];
130
+ baseColumn: never;
131
+ identity: undefined;
132
+ generated: undefined;
133
+ }, {}, {
134
+ length: 255;
135
+ }>;
136
+ };
137
+ dialect: "pg";
138
+ }>;
139
+ export declare const createNeonSetupSessionStore: (databaseUrl: string) => SetupSessionStore;
140
+ export declare const createPostgresSetupSessionStore: (db: AnyPgDatabase) => SetupSessionStore;
@@ -0,0 +1,160 @@
1
+ import { Elysia } from 'elysia';
2
+ import { type PortalRouteProps } from './config';
3
+ export declare const portalRoutes: ({ emit, onScimTokenCreated, onSsoConnectionConfigured, portalRoute, scimRoute, scimTokenStore, setupSessionStore, ssoConnectionStore, ssoRoute }: PortalRouteProps) => Elysia<"", {
4
+ decorator: {};
5
+ store: {};
6
+ derive: {};
7
+ resolve: {};
8
+ }, {
9
+ typebox: {};
10
+ error: {};
11
+ }, {
12
+ schema: {};
13
+ standaloneSchema: {};
14
+ macro: {};
15
+ macroFn: {};
16
+ parser: {};
17
+ response: {};
18
+ }, {
19
+ [x: string]: {
20
+ session: {
21
+ get: {
22
+ body: unknown;
23
+ params: {};
24
+ query: unknown;
25
+ headers: unknown;
26
+ response: {
27
+ 200: {
28
+ readonly capabilities: import("./types").SetupCapability[];
29
+ readonly configured: {
30
+ readonly oidc: boolean;
31
+ readonly saml: boolean;
32
+ };
33
+ readonly expiresAt: number;
34
+ readonly oidc: {
35
+ redirectUri: string;
36
+ } | undefined;
37
+ readonly organizationId: string;
38
+ readonly saml: {
39
+ acsUrl: string;
40
+ entityId: string;
41
+ metadataUrl: string;
42
+ } | undefined;
43
+ readonly scim: {
44
+ baseUrl: string;
45
+ } | undefined;
46
+ };
47
+ 401: "Invalid or expired setup link";
48
+ };
49
+ };
50
+ };
51
+ };
52
+ } & {
53
+ [x: string]: {
54
+ connection: {
55
+ saml: {
56
+ put: {
57
+ body: {
58
+ idpSloUrl?: string | undefined;
59
+ idpEntityId: string;
60
+ idpSsoUrl: string;
61
+ idpX509Cert: string;
62
+ };
63
+ params: {};
64
+ query: unknown;
65
+ headers: unknown;
66
+ response: {
67
+ 200: {
68
+ readonly configured: true;
69
+ readonly type: "saml";
70
+ };
71
+ 401: "Invalid or expired setup link";
72
+ 403: "This setup link cannot configure SAML";
73
+ 422: {
74
+ type: "validation";
75
+ on: string;
76
+ summary?: string;
77
+ message?: string;
78
+ found?: unknown;
79
+ property?: string;
80
+ expected?: string;
81
+ };
82
+ 501: "SSO is not configured";
83
+ };
84
+ };
85
+ };
86
+ };
87
+ };
88
+ } & {
89
+ [x: string]: {
90
+ connection: {
91
+ oidc: {
92
+ put: {
93
+ body: {
94
+ redirectUri?: string | undefined;
95
+ scopes?: string[] | undefined;
96
+ issuer: string;
97
+ clientId: string;
98
+ clientSecret: string;
99
+ };
100
+ params: {};
101
+ query: unknown;
102
+ headers: unknown;
103
+ response: {
104
+ 200: {
105
+ readonly configured: true;
106
+ readonly type: "oidc";
107
+ };
108
+ 401: "Invalid or expired setup link";
109
+ 403: "This setup link cannot configure OIDC";
110
+ 422: {
111
+ type: "validation";
112
+ on: string;
113
+ summary?: string;
114
+ message?: string;
115
+ found?: unknown;
116
+ property?: string;
117
+ expected?: string;
118
+ };
119
+ 501: "SSO is not configured";
120
+ };
121
+ };
122
+ };
123
+ };
124
+ };
125
+ } & {
126
+ [x: string]: {
127
+ scim: {
128
+ token: {
129
+ post: {
130
+ body: unknown;
131
+ params: {};
132
+ query: unknown;
133
+ headers: unknown;
134
+ response: {
135
+ 200: {
136
+ readonly baseUrl: `${string}/${string}`;
137
+ readonly token: string;
138
+ readonly tokenId: string;
139
+ };
140
+ 401: "Invalid or expired setup link";
141
+ 403: "This setup link cannot configure SCIM";
142
+ 501: "SCIM is not configured";
143
+ };
144
+ };
145
+ };
146
+ };
147
+ };
148
+ }, {
149
+ derive: {};
150
+ resolve: {};
151
+ schema: {};
152
+ standaloneSchema: {};
153
+ response: {};
154
+ }, {
155
+ derive: {};
156
+ resolve: {};
157
+ schema: {};
158
+ standaloneSchema: {};
159
+ response: {};
160
+ }>;
@@ -0,0 +1,16 @@
1
+ import type { OrganizationId } from '../tenancy';
2
+ export type SetupCapability = 'scim' | 'sso_oidc' | 'sso_saml';
3
+ export type SetupSession = {
4
+ capabilities: SetupCapability[];
5
+ createdAt: number;
6
+ createdBy?: string;
7
+ expiresAt: number;
8
+ organizationId: OrganizationId;
9
+ setupSessionId: string;
10
+ tokenHash: string;
11
+ };
12
+ export type SetupSessionStore = {
13
+ deleteSetupSession: (setupSessionId: string) => Promise<void>;
14
+ getSetupSessionByTokenHash: (tokenHash: string) => Promise<SetupSession | undefined>;
15
+ saveSetupSession: (session: SetupSession) => Promise<void>;
16
+ };
package/dist/types.d.ts CHANGED
@@ -11,6 +11,7 @@ import type { LockoutConfig } from './lockout/config';
11
11
  import type { MfaConfig } from './mfa/config';
12
12
  import type { OrganizationsConfig } from './organizations/config';
13
13
  import type { PasswordlessConfig } from './passwordless/config';
14
+ import type { PortalConfig } from './portal/config';
14
15
  import type { RolesConfig } from './roles/config';
15
16
  import type { ScimConfig } from './scim/config';
16
17
  import type { SessionsConfig } from './session/sessionsConfig';
@@ -217,6 +218,11 @@ export type AuthConfig<UserType> = {
217
218
  * one (caller becomes owner), invite/accept/revoke by email, and list/remove members. Ties the
218
219
  * bare `organizationId` used by SSO/SCIM/RBAC into a real tenant model with org-scoped roles. */
219
220
  organizations?: OrganizationsConfig<UserType>;
221
+ /** Admin portal — the WorkOS self-serve "setup link" model, headless. When present, mounts
222
+ * `{portalRoute}` endpoints a customer's IT admin (holding a scoped setup token from
223
+ * `createSetupSession`) calls to read the service-provider URLs and configure their own SSO
224
+ * connection / SCIM token. JSON contract, so the portal UI can be built in any framework. */
225
+ portal?: PortalConfig;
220
226
  /** Org-scoped roles & permissions (builds on `organizations`). When present, mounts routes to
221
227
  * list an org's role definitions and set a member's roles. Pair with
222
228
  * `createMembershipPermissionResolver` to make `authorization.hasPermission` turnkey. */
@@ -268,6 +274,12 @@ export type AuthConfig<UserType> = {
268
274
  onProfileError?: OnProfileError;
269
275
  onSessionCleanup?: OnSessionCleanup<UserType>;
270
276
  };
277
+ /** The serializable subset of `AuthConfig` — the route paths, session durations, and
278
+ * limits that can live in a data file (`auth.config.ts` via `defineAuthSettings`) and
279
+ * be edited from tooling, separate from the code wiring (stores, hooks, callbacks)
280
+ * that stays in the `auth()` call. Spread alongside the rest:
281
+ * `auth({ ...defineAuthSettings({...}), authSessionStore, providersConfiguration })`. */
282
+ export type AuthSettings = Pick<AuthConfig<unknown>, 'authorizeRoute' | 'callbackRoute' | 'cleanupIntervalMs' | 'maxSessions' | 'profileRoute' | 'refreshRoute' | 'revokeRoute' | 'sessionDurationMs' | 'signoutRoute' | 'statusRoute' | 'unregisteredSessionDurationMs'>;
271
283
  export type ClientProviderEntry = {
272
284
  clientName?: string;
273
285
  providerInstance: OAuth2Client<ProviderOption>;
package/dist/utils.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { OAuth2Client, OAuth2TokenResponse, ProviderOption } from 'citra';
2
2
  import { Cookie } from 'elysia';
3
3
  import { AuthHtmxConfig } from './htmx/types';
4
- import { AuthConfig, InsantiateUserSessionProps, OAuth2ConfigurationOptions, ResolvedOAuthAuthorization, SessionRecord, UnregisteredSessionRecord, UserSessionId } from './types';
4
+ import { AuthConfig, AuthSettings, InsantiateUserSessionProps, OAuth2ConfigurationOptions, ResolvedOAuthAuthorization, SessionRecord, UnregisteredSessionRecord, UserSessionId } from './types';
5
5
  export declare const defineAuthConfig: <UserType>(configuration: AuthConfig<UserType>) => AuthConfig<UserType>;
6
6
  export declare const defineAuthHtmxConfig: (htmxConfig: AuthHtmxConfig) => AuthHtmxConfig;
7
+ export declare const defineAuthSettings: (settings: AuthSettings) => AuthSettings;
7
8
  export declare const defineProvidersConfiguration: (providersConfiguration: OAuth2ConfigurationOptions) => OAuth2ConfigurationOptions;
8
9
  export declare const getStatus: <UserType>(session: SessionRecord<UserType>, user_session_id: Cookie<UserSessionId | undefined>) => Promise<{
9
10
  error: {
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.26.0-beta.4",
2
+ "version": "0.26.0-beta.6",
3
3
  "name": "@absolutejs/auth",
4
4
  "description": "An authorization library for absolutejs",
5
5
  "repository": {