@absolutejs/auth 0.35.0 → 0.36.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import type { RouteString } from '../types';
2
2
  import { type SigningKey } from './keys';
3
3
  import type { OnClientRegistration } from './registration';
4
- import type { AuthorizationCodeStore, ClientAssertionJtiStore, ClientRegistrationTokenStore, DeviceAuthorizationStore, InitialAccessTokenStore, LogoutDeliveryStore, OAuthClientStore, OidcRefreshTokenStore, PushedAuthorizationRequestStore } from './types';
4
+ import type { AuthorizationCodeStore, BackchannelAuthStore, ClientAssertionJtiStore, ClientRegistrationTokenStore, DeviceAuthorizationStore, InitialAccessTokenStore, LogoutDeliveryStore, OAuthClient, OAuthClientStore, OidcRefreshTokenStore, PushedAuthorizationRequestStore } from './types';
5
5
  export declare const DEFAULT_OIDC_ROUTE: RouteString;
6
6
  export type OidcProviderConfig<UserType> = {
7
7
  accessTokenTtlMs?: number;
@@ -13,6 +13,22 @@ export type OidcProviderConfig<UserType> = {
13
13
  deviceAuthorizationStore?: DeviceAuthorizationStore;
14
14
  deviceCodeTtlMs?: number;
15
15
  devicePollIntervalSeconds?: number;
16
+ backchannelAuthStore?: BackchannelAuthStore;
17
+ backchannelAuthTtlMs?: number;
18
+ backchannelPollIntervalSeconds?: number;
19
+ resolveBackchannelUser?: (hint: {
20
+ client: OAuthClient;
21
+ loginHint: string;
22
+ }) => Promise<{
23
+ sub: string;
24
+ } | undefined>;
25
+ onBackchannelAuthRequest?: (context: {
26
+ authReqId: string;
27
+ bindingMessage: string | undefined;
28
+ clientId: string;
29
+ scopes: string[];
30
+ userSub: string;
31
+ }) => Promise<void> | void;
16
32
  getAccessTokenClaims?: (context: {
17
33
  audience?: string;
18
34
  clientId: string;
@@ -182,3 +198,58 @@ export declare const exchangeDeviceCode: <UserType>({ clientId, config, deviceCo
182
198
  dpopJkt?: string;
183
199
  now?: number;
184
200
  }) => Promise<DeviceCodeExchangeResult>;
201
+ export declare const CIBA_GRANT_TYPE = "urn:openid:params:grant-type:ciba";
202
+ export type BackchannelAuthResponse = {
203
+ auth_req_id: string;
204
+ expires_in: number;
205
+ interval: number;
206
+ };
207
+ export type BackchannelAuthError = 'expired_login_hint_token' | 'invalid_client' | 'invalid_request' | 'unknown_user_id';
208
+ export declare const issueBackchannelAuth: <UserType>({ clientId, config, loginHint, bindingMessage, now, requestedScopes }: {
209
+ clientId: string;
210
+ config: OidcProviderConfig<UserType>;
211
+ loginHint: string;
212
+ bindingMessage?: string;
213
+ now?: number;
214
+ requestedScopes: string[];
215
+ }) => Promise<{
216
+ error: BackchannelAuthError;
217
+ ok: false;
218
+ } | ({
219
+ ok: true;
220
+ } & BackchannelAuthResponse)>;
221
+ export type BackchannelDecisionResult = {
222
+ error: 'already_decided' | 'expired_token' | 'invalid_auth_req_id' | 'not_configured';
223
+ ok: false;
224
+ } | {
225
+ ok: true;
226
+ };
227
+ export declare const approveBackchannelAuth: <UserType>({ authReqId, config, userSub }: {
228
+ authReqId: string;
229
+ config: OidcProviderConfig<UserType>;
230
+ userSub?: string;
231
+ }) => Promise<BackchannelDecisionResult>;
232
+ export declare const denyBackchannelAuth: <UserType>({ authReqId, config }: {
233
+ authReqId: string;
234
+ config: OidcProviderConfig<UserType>;
235
+ }) => Promise<BackchannelDecisionResult>;
236
+ export type BackchannelExchangeError = 'access_denied' | 'authorization_pending' | 'expired_token' | 'invalid_grant' | 'slow_down';
237
+ export type BackchannelExchangeResult = {
238
+ access_token: string;
239
+ expires_in: number;
240
+ id_token: string;
241
+ ok: true;
242
+ refresh_token: string;
243
+ scope: string;
244
+ token_type: 'Bearer' | 'DPoP';
245
+ } | {
246
+ error: BackchannelExchangeError;
247
+ ok: false;
248
+ };
249
+ export declare const exchangeBackchannelAuth: <UserType>({ authReqId, clientId, config, dpopJkt, now }: {
250
+ authReqId: string;
251
+ clientId: string;
252
+ config: OidcProviderConfig<UserType>;
253
+ dpopJkt?: string;
254
+ now?: number;
255
+ }) => Promise<BackchannelExchangeResult>;
@@ -1,5 +1,6 @@
1
- import type { AuthorizationCodeStore, ClientAssertionJtiStore, ClientRegistrationTokenStore, DeviceAuthorizationStore, InitialAccessTokenStore, LogoutDeliveryStore, OAuthClient, OAuthClientStore, OidcRefreshTokenStore, PushedAuthorizationRequestStore } from './types';
1
+ import type { AuthorizationCodeStore, BackchannelAuthStore, ClientAssertionJtiStore, ClientRegistrationTokenStore, DeviceAuthorizationStore, InitialAccessTokenStore, LogoutDeliveryStore, OAuthClient, OAuthClientStore, OidcRefreshTokenStore, PushedAuthorizationRequestStore } from './types';
2
2
  export declare const createInMemoryAuthorizationCodeStore: () => AuthorizationCodeStore;
3
+ export declare const createInMemoryBackchannelAuthStore: () => BackchannelAuthStore;
3
4
  export declare const createInMemoryClientAssertionJtiStore: () => ClientAssertionJtiStore;
4
5
  export declare const createInMemoryClientRegistrationTokenStore: () => ClientRegistrationTokenStore;
5
6
  export declare const createInMemoryDeviceAuthorizationStore: () => DeviceAuthorizationStore;
@@ -1,5 +1,216 @@
1
1
  import { type AnyPgDatabase } from '../stores/postgres';
2
- import type { AuthorizationCodeStore, ClientAssertionJtiStore, ClientRegistrationTokenStore, DeviceAuthorizationStore, InitialAccessTokenStore, LogoutDeliveryStore, OAuthClientStore, OidcRefreshTokenStore, PushedAuthorizationRequestStore } from './types';
2
+ import type { AuthorizationCodeStore, BackchannelAuthStore, ClientAssertionJtiStore, ClientRegistrationTokenStore, DeviceAuthorizationStore, InitialAccessTokenStore, LogoutDeliveryStore, OAuthClientStore, OidcRefreshTokenStore, PushedAuthorizationRequestStore } from './types';
3
+ export declare const oauthBackchannelAuthRequestsTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
4
+ name: "auth_oauth_backchannel_auth_requests";
5
+ schema: undefined;
6
+ columns: {
7
+ auth_req_id: import("drizzle-orm/pg-core").PgColumn<{
8
+ name: "auth_req_id";
9
+ tableName: "auth_oauth_backchannel_auth_requests";
10
+ dataType: "string";
11
+ columnType: "PgVarchar";
12
+ data: string;
13
+ driverParam: string;
14
+ notNull: true;
15
+ hasDefault: false;
16
+ isPrimaryKey: true;
17
+ isAutoincrement: false;
18
+ hasRuntimeDefault: false;
19
+ enumValues: [string, ...string[]];
20
+ baseColumn: never;
21
+ identity: undefined;
22
+ generated: undefined;
23
+ }, {}, {
24
+ length: 255;
25
+ }>;
26
+ binding_message: import("drizzle-orm/pg-core").PgColumn<{
27
+ name: "binding_message";
28
+ tableName: "auth_oauth_backchannel_auth_requests";
29
+ dataType: "string";
30
+ columnType: "PgText";
31
+ data: string;
32
+ driverParam: string;
33
+ notNull: false;
34
+ hasDefault: false;
35
+ isPrimaryKey: false;
36
+ isAutoincrement: false;
37
+ hasRuntimeDefault: false;
38
+ enumValues: [string, ...string[]];
39
+ baseColumn: never;
40
+ identity: undefined;
41
+ generated: undefined;
42
+ }, {}, {}>;
43
+ client_id: import("drizzle-orm/pg-core").PgColumn<{
44
+ name: "client_id";
45
+ tableName: "auth_oauth_backchannel_auth_requests";
46
+ dataType: "string";
47
+ columnType: "PgVarchar";
48
+ data: string;
49
+ driverParam: string;
50
+ notNull: true;
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
+ created_at_ms: import("drizzle-orm/pg-core").PgColumn<{
63
+ name: "created_at_ms";
64
+ tableName: "auth_oauth_backchannel_auth_requests";
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
+ expires_at_ms: import("drizzle-orm/pg-core").PgColumn<{
80
+ name: "expires_at_ms";
81
+ tableName: "auth_oauth_backchannel_auth_requests";
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
+ interval_seconds: import("drizzle-orm/pg-core").PgColumn<{
97
+ name: "interval_seconds";
98
+ tableName: "auth_oauth_backchannel_auth_requests";
99
+ dataType: "number";
100
+ columnType: "PgBigInt53";
101
+ data: number;
102
+ driverParam: string | number;
103
+ notNull: true;
104
+ hasDefault: false;
105
+ isPrimaryKey: false;
106
+ isAutoincrement: false;
107
+ hasRuntimeDefault: false;
108
+ enumValues: undefined;
109
+ baseColumn: never;
110
+ identity: undefined;
111
+ generated: undefined;
112
+ }, {}, {}>;
113
+ last_polled_at_ms: import("drizzle-orm/pg-core").PgColumn<{
114
+ name: "last_polled_at_ms";
115
+ tableName: "auth_oauth_backchannel_auth_requests";
116
+ dataType: "number";
117
+ columnType: "PgBigInt53";
118
+ data: number;
119
+ driverParam: string | number;
120
+ notNull: false;
121
+ hasDefault: false;
122
+ isPrimaryKey: false;
123
+ isAutoincrement: false;
124
+ hasRuntimeDefault: false;
125
+ enumValues: undefined;
126
+ baseColumn: never;
127
+ identity: undefined;
128
+ generated: undefined;
129
+ }, {}, {}>;
130
+ scopes: import("drizzle-orm/pg-core").PgColumn<{
131
+ name: "scopes";
132
+ tableName: "auth_oauth_backchannel_auth_requests";
133
+ dataType: "array";
134
+ columnType: "PgArray";
135
+ data: string[];
136
+ driverParam: string | string[];
137
+ notNull: true;
138
+ hasDefault: false;
139
+ isPrimaryKey: false;
140
+ isAutoincrement: false;
141
+ hasRuntimeDefault: false;
142
+ enumValues: [string, ...string[]];
143
+ baseColumn: import("drizzle-orm").Column<{
144
+ name: "scopes";
145
+ tableName: "auth_oauth_backchannel_auth_requests";
146
+ dataType: "string";
147
+ columnType: "PgText";
148
+ data: string;
149
+ driverParam: string;
150
+ notNull: false;
151
+ hasDefault: false;
152
+ isPrimaryKey: false;
153
+ isAutoincrement: false;
154
+ hasRuntimeDefault: false;
155
+ enumValues: [string, ...string[]];
156
+ baseColumn: never;
157
+ identity: undefined;
158
+ generated: undefined;
159
+ }, {}, {}>;
160
+ identity: undefined;
161
+ generated: undefined;
162
+ }, {}, {
163
+ baseBuilder: import("drizzle-orm/pg-core").PgColumnBuilder<{
164
+ name: "scopes";
165
+ dataType: "string";
166
+ columnType: "PgText";
167
+ data: string;
168
+ enumValues: [string, ...string[]];
169
+ driverParam: string;
170
+ }, {}, {}, import("drizzle-orm").ColumnBuilderExtraConfig>;
171
+ size: undefined;
172
+ }>;
173
+ status: import("drizzle-orm/pg-core").PgColumn<{
174
+ name: "status";
175
+ tableName: "auth_oauth_backchannel_auth_requests";
176
+ dataType: "string";
177
+ columnType: "PgVarchar";
178
+ data: string;
179
+ driverParam: string;
180
+ notNull: true;
181
+ hasDefault: false;
182
+ isPrimaryKey: false;
183
+ isAutoincrement: false;
184
+ hasRuntimeDefault: false;
185
+ enumValues: [string, ...string[]];
186
+ baseColumn: never;
187
+ identity: undefined;
188
+ generated: undefined;
189
+ }, {}, {
190
+ length: 16;
191
+ }>;
192
+ user_sub: import("drizzle-orm/pg-core").PgColumn<{
193
+ name: "user_sub";
194
+ tableName: "auth_oauth_backchannel_auth_requests";
195
+ dataType: "string";
196
+ columnType: "PgVarchar";
197
+ data: string;
198
+ driverParam: string;
199
+ notNull: false;
200
+ hasDefault: false;
201
+ isPrimaryKey: false;
202
+ isAutoincrement: false;
203
+ hasRuntimeDefault: false;
204
+ enumValues: [string, ...string[]];
205
+ baseColumn: never;
206
+ identity: undefined;
207
+ generated: undefined;
208
+ }, {}, {
209
+ length: 255;
210
+ }>;
211
+ };
212
+ dialect: "pg";
213
+ }>;
3
214
  export declare const oauthClientAssertionJtisTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
4
215
  name: "auth_oauth_client_assertion_jtis";
5
216
  schema: undefined;
@@ -1386,3 +1597,5 @@ export declare const createPostgresLogoutDeliveryStore: (db: AnyPgDatabase) => L
1386
1597
  export declare const createPostgresOAuthClientStore: (db: AnyPgDatabase) => OAuthClientStore;
1387
1598
  export declare const createPostgresOidcRefreshTokenStore: (db: AnyPgDatabase) => OidcRefreshTokenStore;
1388
1599
  export declare const createPostgresPushedAuthorizationRequestStore: (db: AnyPgDatabase) => PushedAuthorizationRequestStore;
1600
+ export declare const createNeonBackchannelAuthStore: (databaseUrl: string) => BackchannelAuthStore;
1601
+ export declare const createPostgresBackchannelAuthStore: (db: AnyPgDatabase) => BackchannelAuthStore;
@@ -68,6 +68,7 @@ export declare const oidcProviderRoutes: <UserType>(config: OidcProviderConfig<U
68
68
  resource?: string | undefined;
69
69
  refresh_token?: string | undefined;
70
70
  device_code?: string | undefined;
71
+ auth_req_id?: string | undefined;
71
72
  client_secret?: string | undefined;
72
73
  grant_type?: string | undefined;
73
74
  code?: string | undefined;
@@ -190,6 +191,35 @@ export declare const oidcProviderRoutes: <UserType>(config: OidcProviderConfig<U
190
191
  };
191
192
  };
192
193
  };
194
+ } & {
195
+ [x: string]: {
196
+ post: {
197
+ body: {
198
+ client_id?: string | undefined;
199
+ scope?: string | undefined;
200
+ client_secret?: string | undefined;
201
+ binding_message?: string | undefined;
202
+ login_hint?: string | undefined;
203
+ };
204
+ params: {};
205
+ query: unknown;
206
+ headers: {
207
+ authorization?: string | undefined;
208
+ };
209
+ response: {
210
+ 200: Response;
211
+ 422: {
212
+ type: "validation";
213
+ on: string;
214
+ summary?: string;
215
+ message?: string;
216
+ found?: unknown;
217
+ property?: string;
218
+ expected?: string;
219
+ };
220
+ };
221
+ };
222
+ };
193
223
  } & {
194
224
  [x: string]: {
195
225
  post: {
@@ -115,3 +115,25 @@ export type DeviceAuthorizationStore = {
115
115
  saveDeviceAuthorization: (deviceAuthorization: DeviceAuthorization) => Promise<void>;
116
116
  updateStatus: (deviceCodeHash: string, status: DeviceAuthorizationStatus, userSub?: string) => Promise<void>;
117
117
  };
118
+ export type BackchannelAuthStatus = 'approved' | 'denied' | 'pending';
119
+ export type BackchannelAuthRequest = {
120
+ authReqId: string;
121
+ bindingMessage?: string;
122
+ clientId: string;
123
+ createdAt: number;
124
+ expiresAt: number;
125
+ /** Poll-mode interval seconds. Bumped by 5 each time the client polls faster than
126
+ * allowed (returns `slow_down` until the new interval has elapsed). */
127
+ intervalSeconds: number;
128
+ lastPolledAt?: number;
129
+ scopes: string[];
130
+ status: BackchannelAuthStatus;
131
+ userSub?: string;
132
+ };
133
+ export type BackchannelAuthStore = {
134
+ deleteByAuthReqId: (authReqId: string) => Promise<void>;
135
+ findByAuthReqId: (authReqId: string) => Promise<BackchannelAuthRequest | undefined>;
136
+ recordPoll: (authReqId: string, at: number) => Promise<void>;
137
+ saveBackchannelAuth: (request: BackchannelAuthRequest) => Promise<void>;
138
+ updateStatus: (authReqId: string, status: BackchannelAuthStatus, userSub?: string) => Promise<void>;
139
+ };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.35.0",
2
+ "version": "0.36.0-beta.0",
3
3
  "name": "@absolutejs/auth",
4
4
  "description": "An authorization library for absolutejs",
5
5
  "repository": {