@absolutejs/auth 0.68.2 → 0.69.1

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,11 @@
1
+ import type { OAuthClientStore } from './types';
2
+ export declare const ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV: "ABSOLUTE_AUTH_NATIVE_CLIENTS";
3
+ export type AbsoluteNativeAuthClient = {
4
+ clientId: string;
5
+ issuer: string;
6
+ name: string;
7
+ redirectUri: string;
8
+ scopes: string[];
9
+ };
10
+ export declare const parseAbsoluteNativeAuthClients: (source?: string | undefined) => AbsoluteNativeAuthClient[];
11
+ export declare const withAbsoluteNativeAuthClients: (clientStore: OAuthClientStore, issuer: string, clients?: AbsoluteNativeAuthClient[]) => OAuthClientStore;
@@ -1,5 +1,5 @@
1
1
  import { type AnyPgDatabase } from '../stores/postgres';
2
- import type { AuthorizationCodeStore, BackchannelAuthStore, ClientAssertionJtiStore, ClientRegistrationTokenStore, DeviceAuthorizationStore, InitialAccessTokenStore, LogoutDeliveryStore, OAuthClientStore, OidcRefreshTokenStore, PushedAuthorizationRequestStore } from './types';
2
+ import type { AuthorizationCodeStore, BackchannelAuthStore, ClientAssertionJtiStore, ClientRegistrationTokenStore, DeviceAuthorizationStore, InitialAccessTokenStore, LogoutDeliveryStore, OAuthClientStore, OidcRefreshTokenStore, PushedAuthorizationRequestStore, SocketTicketStore } from './types';
3
3
  export declare const oauthBackchannelAuthRequestsTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
4
4
  name: "auth_oauth_backchannel_auth_requests";
5
5
  schema: undefined;
@@ -1102,6 +1102,21 @@ export declare const oauthRefreshTokensTable: import("drizzle-orm/pg-core").PgTa
1102
1102
  identity: undefined;
1103
1103
  generated: undefined;
1104
1104
  }>;
1105
+ consumed_token_hashes: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_refresh_tokens", import("drizzle-orm/pg-core").SetHasDefault<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").SetDimensions<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>, 1>>>, {
1106
+ name: string;
1107
+ tableName: "auth_oauth_refresh_tokens";
1108
+ dataType: "string";
1109
+ data: string[];
1110
+ driverParam: string | string[];
1111
+ notNull: true;
1112
+ hasDefault: true;
1113
+ isPrimaryKey: false;
1114
+ isAutoincrement: false;
1115
+ hasRuntimeDefault: false;
1116
+ enumValues: undefined;
1117
+ identity: undefined;
1118
+ generated: undefined;
1119
+ }>;
1105
1120
  created_at_ms: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_refresh_tokens", import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgBigInt53Builder>, {
1106
1121
  name: string;
1107
1122
  tableName: "auth_oauth_refresh_tokens";
@@ -1147,6 +1162,36 @@ export declare const oauthRefreshTokensTable: import("drizzle-orm/pg-core").PgTa
1147
1162
  identity: undefined;
1148
1163
  generated: undefined;
1149
1164
  }>;
1165
+ family_id: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_refresh_tokens", import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>, {
1166
+ name: string;
1167
+ tableName: "auth_oauth_refresh_tokens";
1168
+ dataType: "string";
1169
+ data: string;
1170
+ driverParam: string;
1171
+ notNull: true;
1172
+ hasDefault: false;
1173
+ isPrimaryKey: false;
1174
+ isAutoincrement: false;
1175
+ hasRuntimeDefault: false;
1176
+ enumValues: undefined;
1177
+ identity: undefined;
1178
+ generated: undefined;
1179
+ }>;
1180
+ revoked_at_ms: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_refresh_tokens", import("drizzle-orm/pg-core").PgBigInt53Builder, {
1181
+ name: string;
1182
+ tableName: "auth_oauth_refresh_tokens";
1183
+ dataType: "number int53";
1184
+ data: number;
1185
+ driverParam: string | number;
1186
+ notNull: false;
1187
+ hasDefault: false;
1188
+ isPrimaryKey: false;
1189
+ isAutoincrement: false;
1190
+ hasRuntimeDefault: false;
1191
+ enumValues: undefined;
1192
+ identity: undefined;
1193
+ generated: undefined;
1194
+ }>;
1150
1195
  scopes: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_refresh_tokens", import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").SetDimensions<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>, 1>>, {
1151
1196
  name: string;
1152
1197
  tableName: "auth_oauth_refresh_tokens";
@@ -1195,6 +1240,103 @@ export declare const oauthRefreshTokensTable: import("drizzle-orm/pg-core").PgTa
1195
1240
  };
1196
1241
  dialect: "pg";
1197
1242
  }>;
1243
+ export declare const oauthSocketTicketsTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
1244
+ name: "auth_oauth_socket_tickets";
1245
+ schema: undefined;
1246
+ columns: {
1247
+ audience: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_socket_tickets", import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>, {
1248
+ name: string;
1249
+ tableName: "auth_oauth_socket_tickets";
1250
+ dataType: "string";
1251
+ data: string;
1252
+ driverParam: string;
1253
+ notNull: true;
1254
+ hasDefault: false;
1255
+ isPrimaryKey: false;
1256
+ isAutoincrement: false;
1257
+ hasRuntimeDefault: false;
1258
+ enumValues: undefined;
1259
+ identity: undefined;
1260
+ generated: undefined;
1261
+ }>;
1262
+ client_id: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_socket_tickets", import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>, {
1263
+ name: string;
1264
+ tableName: "auth_oauth_socket_tickets";
1265
+ dataType: "string";
1266
+ data: string;
1267
+ driverParam: string;
1268
+ notNull: true;
1269
+ hasDefault: false;
1270
+ isPrimaryKey: false;
1271
+ isAutoincrement: false;
1272
+ hasRuntimeDefault: false;
1273
+ enumValues: undefined;
1274
+ identity: undefined;
1275
+ generated: undefined;
1276
+ }>;
1277
+ expires_at_ms: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_socket_tickets", import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgBigInt53Builder>, {
1278
+ name: string;
1279
+ tableName: "auth_oauth_socket_tickets";
1280
+ dataType: "number int53";
1281
+ data: number;
1282
+ driverParam: string | number;
1283
+ notNull: true;
1284
+ hasDefault: false;
1285
+ isPrimaryKey: false;
1286
+ isAutoincrement: false;
1287
+ hasRuntimeDefault: false;
1288
+ enumValues: undefined;
1289
+ identity: undefined;
1290
+ generated: undefined;
1291
+ }>;
1292
+ scopes: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_socket_tickets", import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").SetDimensions<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>, 1>>, {
1293
+ name: string;
1294
+ tableName: "auth_oauth_socket_tickets";
1295
+ dataType: "string";
1296
+ data: string[];
1297
+ driverParam: string | string[];
1298
+ notNull: true;
1299
+ hasDefault: false;
1300
+ isPrimaryKey: false;
1301
+ isAutoincrement: false;
1302
+ hasRuntimeDefault: false;
1303
+ enumValues: undefined;
1304
+ identity: undefined;
1305
+ generated: undefined;
1306
+ }>;
1307
+ subject: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_socket_tickets", import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>, {
1308
+ name: string;
1309
+ tableName: "auth_oauth_socket_tickets";
1310
+ dataType: "string";
1311
+ data: string;
1312
+ driverParam: string;
1313
+ notNull: true;
1314
+ hasDefault: false;
1315
+ isPrimaryKey: false;
1316
+ isAutoincrement: false;
1317
+ hasRuntimeDefault: false;
1318
+ enumValues: undefined;
1319
+ identity: undefined;
1320
+ generated: undefined;
1321
+ }>;
1322
+ ticket_hash: import("drizzle-orm/pg-core").PgBuildColumn<"auth_oauth_socket_tickets", import("drizzle-orm/pg-core").SetIsPrimaryKey<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>, {
1323
+ name: string;
1324
+ tableName: "auth_oauth_socket_tickets";
1325
+ dataType: "string";
1326
+ data: string;
1327
+ driverParam: string;
1328
+ notNull: true;
1329
+ hasDefault: false;
1330
+ isPrimaryKey: false;
1331
+ isAutoincrement: false;
1332
+ hasRuntimeDefault: false;
1333
+ enumValues: undefined;
1334
+ identity: undefined;
1335
+ generated: undefined;
1336
+ }>;
1337
+ };
1338
+ dialect: "pg";
1339
+ }>;
1198
1340
  export declare const createNeonAuthorizationCodeStore: (databaseUrl: string) => AuthorizationCodeStore;
1199
1341
  export declare const createNeonClientAssertionJtiStore: (databaseUrl: string) => ClientAssertionJtiStore;
1200
1342
  export declare const createNeonClientRegistrationTokenStore: (databaseUrl: string) => ClientRegistrationTokenStore;
@@ -1215,3 +1357,5 @@ export declare const createPostgresOidcRefreshTokenStore: <DB extends AnyPgDatab
1215
1357
  export declare const createPostgresPushedAuthorizationRequestStore: <DB extends AnyPgDatabase>(db: DB) => PushedAuthorizationRequestStore;
1216
1358
  export declare const createNeonBackchannelAuthStore: (databaseUrl: string) => BackchannelAuthStore;
1217
1359
  export declare const createPostgresBackchannelAuthStore: <DB extends AnyPgDatabase>(db: DB) => BackchannelAuthStore;
1360
+ export declare const createNeonSocketTicketStore: (databaseUrl: string) => SocketTicketStore;
1361
+ export declare const createPostgresSocketTicketStore: <DB extends AnyPgDatabase>(db: DB) => SocketTicketStore;
@@ -0,0 +1,7 @@
1
+ import { Elysia } from 'elysia';
2
+ import { type OidcProviderConfig } from './config';
3
+ /** Isolated plugin keeps the already-large provider route type from expanding
4
+ * for applications that do not enable socket tickets. */
5
+ type SocketTicketRoutes = <UserType>(config: OidcProviderConfig<UserType>) => Elysia;
6
+ export declare const socketTicketRoutes: SocketTicketRoutes;
7
+ export {};
@@ -0,0 +1,21 @@
1
+ import type { AuthPrincipal } from '../principal';
2
+ import type { SocketTicketStore } from './types';
3
+ export declare const consumeSocketTicket: <UserType>({ audience, getUser, now, store, ticket }: {
4
+ audience: string;
5
+ getUser: (subject: string) => Promise<UserType | null> | UserType | null;
6
+ now?: number;
7
+ store: SocketTicketStore;
8
+ ticket: string;
9
+ }) => Promise<AuthPrincipal<UserType> | undefined>;
10
+ export declare const issueSocketTicket: ({ audience, clientId, now, scopes, store, subject, ttlMs }: {
11
+ audience: string;
12
+ clientId: string;
13
+ now?: number;
14
+ scopes: string[];
15
+ store: SocketTicketStore;
16
+ subject: string;
17
+ ttlMs?: number;
18
+ }) => Promise<{
19
+ expiresInMs: number;
20
+ ticket: string;
21
+ }>;
@@ -78,6 +78,8 @@ export type OidcRefreshToken = {
78
78
  createdAt: number;
79
79
  dpopJkt?: string;
80
80
  expiresAt: number;
81
+ /** Stable identifier shared by every rotation descendant of one grant. */
82
+ familyId: string;
81
83
  scopes: string[];
82
84
  tokenHash: string;
83
85
  userId: string;
@@ -94,8 +96,26 @@ export type OidcRefreshTokenStore = {
94
96
  getToken: (tokenHash: string) => Promise<OidcRefreshToken | undefined>;
95
97
  listClientIdsForUser: (userId: string) => Promise<string[]>;
96
98
  listConnections: () => Promise<OidcRefreshTokenConnection[]>;
99
+ /** Revoke a family when a previously consumed token is presented again. */
100
+ revokeByConsumedToken: (tokenHash: string) => Promise<boolean>;
101
+ /** Atomically replace the active family token, or revoke on detected reuse. */
102
+ rotateToken: (currentTokenHash: string, replacement: OidcRefreshToken) => Promise<boolean>;
97
103
  saveToken: (token: OidcRefreshToken) => Promise<void>;
98
104
  };
105
+ /** Server-side record for a short-lived, one-time WebSocket bootstrap ticket. */
106
+ export type SocketTicket = {
107
+ audience: string;
108
+ clientId: string;
109
+ expiresAt: number;
110
+ scopes: string[];
111
+ subject: string;
112
+ ticketHash: string;
113
+ };
114
+ export type SocketTicketStore = {
115
+ /** Atomically delete and return a ticket. Expired tickets return undefined. */
116
+ consumeTicket: (ticketHash: string, now?: number) => Promise<SocketTicket | undefined>;
117
+ saveTicket: (ticket: SocketTicket) => Promise<void>;
118
+ };
99
119
  export type DeviceAuthorizationStatus = 'approved' | 'denied' | 'pending';
100
120
  export type DeviceAuthorization = {
101
121
  clientId: string;
@@ -0,0 +1,39 @@
1
+ import type { OidcProviderConfig } from './oidc/config';
2
+ export type AuthPrincipal<UserType> = {
3
+ kind: 'access-token';
4
+ audience: string;
5
+ clientId: string;
6
+ scopes: string[];
7
+ subject: string;
8
+ user: UserType;
9
+ } | {
10
+ kind: 'session';
11
+ subject: string;
12
+ user: UserType;
13
+ };
14
+ export type AccessTokenPrincipalConfig<UserType> = {
15
+ audience?: string;
16
+ getUser: (subject: string) => Promise<UserType | null> | UserType | null;
17
+ oidc: OidcProviderConfig<UserType>;
18
+ };
19
+ export type VerifiedAccessToken = {
20
+ audience: string;
21
+ clientId: string;
22
+ scopes: string[];
23
+ subject: string;
24
+ };
25
+ /** Resolve a mobile/public-client access token into the same typed application
26
+ * user carried by a browser session. DPoP-bound tokens fail closed until the
27
+ * resource proof verifier is enabled in the next hardening phase. */
28
+ export declare const resolveAccessTokenPrincipal: <UserType>({ authorization, config, now }: {
29
+ authorization?: string;
30
+ config: AccessTokenPrincipalConfig<UserType>;
31
+ now?: number;
32
+ }) => Promise<AuthPrincipal<UserType> | undefined>;
33
+ /** Verify an Absolute OAuth access token without resolving its application user. */
34
+ export declare const verifyOidcAccessToken: <UserType>({ authorization, audience, now, oidc }: {
35
+ authorization?: string;
36
+ audience?: string;
37
+ now?: number;
38
+ oidc: OidcProviderConfig<UserType>;
39
+ }) => Promise<VerifiedAccessToken | undefined>;
@@ -1,5 +1,6 @@
1
1
  import { Elysia } from 'elysia';
2
2
  import type { AuthSessionSource } from '../session/types';
3
+ import { type AccessTokenPrincipalConfig, type AuthPrincipal } from '../principal';
3
4
  type AuthFailError = {
4
5
  readonly code: 'Bad Request';
5
6
  readonly message: 'Cookies are missing';
@@ -7,7 +8,8 @@ type AuthFailError = {
7
8
  readonly code: 'Unauthorized';
8
9
  readonly message: 'User is not authenticated';
9
10
  };
10
- export declare const protectRoutePlugin: <UserType>({ authSessionStore }?: {
11
+ export declare const protectRoutePlugin: <UserType>({ accessTokens, authSessionStore }?: {
12
+ accessTokens?: AccessTokenPrincipalConfig<UserType>;
11
13
  authSessionStore?: AuthSessionSource<UserType>;
12
14
  }) => Elysia<"", "local", {
13
15
  decorator: {};
@@ -16,7 +18,8 @@ export declare const protectRoutePlugin: <UserType>({ authSessionStore }?: {
16
18
  unregisteredSession: import("..").UnregisteredSessionRecord;
17
19
  };
18
20
  derive: {
19
- readonly protectRoute: <AuthReturn, AuthFailReturn = never>(handleAuth: (user: UserType) => AuthReturn | Promise<AuthReturn>, handleAuthFail?: (error: AuthFailError) => AuthFailReturn) => Promise<import("elysia").ElysiaStatus<"Bad Request", "Cookies are missing", 400> | import("elysia").ElysiaStatus<"Unauthorized", "User is not authenticated", 401> | AuthReturn | NonNullable<AuthFailReturn>>;
21
+ readonly authPrincipal: AuthPrincipal<UserType> | undefined;
22
+ readonly protectRoute: <AuthReturn, AuthFailReturn = never>(handleAuth: (user: UserType) => AuthReturn | Promise<AuthReturn>, handleAuthFail?: (error: AuthFailError) => AuthFailReturn) => import("elysia").ElysiaStatus<"Bad Request", "Cookies are missing", 400> | import("elysia").ElysiaStatus<"Unauthorized", "User is not authenticated", 401> | AuthReturn | Promise<AuthReturn> | NonNullable<AuthFailReturn>;
20
23
  };
21
24
  }, {
22
25
  typebox: {};
@@ -33,7 +36,8 @@ export declare const protectRoutePlugin: <UserType>({ authSessionStore }?: {
33
36
  macroFn: {};
34
37
  parser: {};
35
38
  response: import("elysia/types").ExtractErrorFromHandle<{
36
- readonly protectRoute: <AuthReturn, AuthFailReturn = never>(handleAuth: (user: UserType) => AuthReturn | Promise<AuthReturn>, handleAuthFail?: (error: AuthFailError) => AuthFailReturn) => Promise<import("elysia").ElysiaStatus<"Bad Request", "Cookies are missing", 400> | import("elysia").ElysiaStatus<"Unauthorized", "User is not authenticated", 401> | AuthReturn | NonNullable<AuthFailReturn>>;
39
+ readonly authPrincipal: AuthPrincipal<UserType> | undefined;
40
+ readonly protectRoute: <AuthReturn, AuthFailReturn = never>(handleAuth: (user: UserType) => AuthReturn | Promise<AuthReturn>, handleAuthFail?: (error: AuthFailError) => AuthFailReturn) => import("elysia").ElysiaStatus<"Bad Request", "Cookies are missing", 400> | import("elysia").ElysiaStatus<"Unauthorized", "User is not authenticated", 401> | AuthReturn | Promise<AuthReturn> | NonNullable<AuthFailReturn>;
37
41
  }>;
38
42
  }, {}, import("elysia/types").DefaultEphemeral, import("elysia/types").DefaultEphemeral>;
39
43
  export {};
@@ -1,6 +1,8 @@
1
1
  import { Elysia } from 'elysia';
2
2
  import type { AuthSessionSource } from '../session/types';
3
- export declare const requireAuthPlugin: <UserType>({ authSessionStore }?: {
3
+ import { type AccessTokenPrincipalConfig, type AuthPrincipal } from '../principal';
4
+ export declare const requireAuthPlugin: <UserType>({ accessTokens, authSessionStore }?: {
5
+ accessTokens?: AccessTokenPrincipalConfig<UserType>;
4
6
  authSessionStore?: AuthSessionSource<UserType>;
5
7
  }) => Elysia<"", "local", {
6
8
  decorator: {};
@@ -9,6 +11,7 @@ export declare const requireAuthPlugin: <UserType>({ authSessionStore }?: {
9
11
  unregisteredSession: import("..").UnregisteredSessionRecord;
10
12
  };
11
13
  derive: {
14
+ readonly authPrincipal: AuthPrincipal<UserType> | undefined;
12
15
  readonly user: NonNullable<UserType> | null;
13
16
  };
14
17
  }, {