@ttoss/auth-postgresdb 0.1.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.
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/dist/index.cjs +507 -0
- package/dist/index.d.cts +244 -0
- package/dist/index.d.mts +244 -0
- package/dist/index.mjs +475 -0
- package/package.json +54 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
|
|
2
|
+
import { AuthCodeStore, ClientStore, ConsentGrant, ConsentGrantStore, RefreshTokenStore } from "@ttoss/auth-core";
|
|
3
|
+
import { Model } from "@ttoss/postgresdb";
|
|
4
|
+
|
|
5
|
+
//#region src/models/OAuthAuthCode.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* A short-lived authorization code with its bound PKCE challenge.
|
|
8
|
+
*
|
|
9
|
+
* The primary key is the code's SHA-256 hash, never the code itself: a code
|
|
10
|
+
* travels through a browser redirect and a client's URL bar, so storing it in
|
|
11
|
+
* plaintext would make a database dump yield replayable codes.
|
|
12
|
+
*/
|
|
13
|
+
declare class OAuthAuthCode extends Model {
|
|
14
|
+
/** SHA-256 hash (hex) of the authorization code. */
|
|
15
|
+
codeHash: string;
|
|
16
|
+
/** The `client_id` the code was issued to. */
|
|
17
|
+
clientId: string;
|
|
18
|
+
/** The redirect URI the code was issued for (must match on exchange). */
|
|
19
|
+
redirectUri: string;
|
|
20
|
+
/** The PKCE `code_challenge` (S256) bound to this code. */
|
|
21
|
+
codeChallenge: string;
|
|
22
|
+
/** The scopes granted to this code. */
|
|
23
|
+
scopes: string[];
|
|
24
|
+
/** The authenticated end-user subject identifier. */
|
|
25
|
+
subject: string;
|
|
26
|
+
/** Instant after which the code is invalid. */
|
|
27
|
+
expiresAt: Date;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/models/OAuthClient.d.ts
|
|
31
|
+
/**
|
|
32
|
+
* A registered OAuth client (RFC 7591 dynamic client registration).
|
|
33
|
+
*
|
|
34
|
+
* The RFC's registered fields get their own columns so they can be queried and
|
|
35
|
+
* indexed; any additional metadata a client submits is kept verbatim in
|
|
36
|
+
* `metadata`, because `OAuthClientMetadata` is an open shape.
|
|
37
|
+
*/
|
|
38
|
+
declare class OAuthClient extends Model {
|
|
39
|
+
/** The `client_id` issued by the authorization server. */
|
|
40
|
+
clientId: string;
|
|
41
|
+
/**
|
|
42
|
+
* Client secret for confidential clients, `null` for public clients
|
|
43
|
+
* (`token_endpoint_auth_method: 'none'`).
|
|
44
|
+
*/
|
|
45
|
+
clientSecret: string | null;
|
|
46
|
+
/** Human-readable client name shown on consent screens. */
|
|
47
|
+
clientName: string | null;
|
|
48
|
+
/** Exact redirect URIs registered for this client. */
|
|
49
|
+
redirectUris: string[];
|
|
50
|
+
/** OAuth grant types the client may use. */
|
|
51
|
+
grantTypes: string[] | null;
|
|
52
|
+
/** OAuth response types the client may use. */
|
|
53
|
+
responseTypes: string[] | null;
|
|
54
|
+
/** Client authentication method at the token endpoint. */
|
|
55
|
+
tokenEndpointAuthMethod: string | null;
|
|
56
|
+
/** Space-separated scopes the client may request. */
|
|
57
|
+
scope: string | null;
|
|
58
|
+
/** Unix timestamp (seconds) when the client was registered. */
|
|
59
|
+
clientIdIssuedAt: number | null;
|
|
60
|
+
/**
|
|
61
|
+
* Registration metadata outside the columns above, preserved so a client's
|
|
62
|
+
* submitted document round-trips unchanged (e.g. `logo_uri`, `client_uri`).
|
|
63
|
+
*/
|
|
64
|
+
metadata: Record<string, unknown>;
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/models/OAuthConsent.d.ts
|
|
68
|
+
/**
|
|
69
|
+
* A single-use consent handoff, correlated by the PKCE `code_challenge`.
|
|
70
|
+
*
|
|
71
|
+
* This is the record an external consent screen writes on approval so the
|
|
72
|
+
* restarted `/authorize` request can be approved without asking again — it is
|
|
73
|
+
* not a durable "user X trusts client Y" grant, which is an app-level
|
|
74
|
+
* authorization decision and belongs in the app's own schema.
|
|
75
|
+
*/
|
|
76
|
+
declare class OAuthConsent extends Model {
|
|
77
|
+
/** The PKCE `code_challenge` the consent was recorded against. */
|
|
78
|
+
codeChallenge: string;
|
|
79
|
+
/** The authenticated end-user subject identifier. */
|
|
80
|
+
subject: string;
|
|
81
|
+
/** The scopes the user approved. */
|
|
82
|
+
scopes: string[];
|
|
83
|
+
/** Instant after which the consent is no longer usable. */
|
|
84
|
+
expiresAt: Date;
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/models/OAuthRefreshToken.d.ts
|
|
88
|
+
/**
|
|
89
|
+
* A refresh token tracked for OAuth 2.1 rotation, stored by hash so a database
|
|
90
|
+
* dump yields no usable credentials.
|
|
91
|
+
*
|
|
92
|
+
* `consumedAt` marks a rotated token. Presenting one again is reuse, and
|
|
93
|
+
* `createRefreshRotation` revokes the whole `(clientId, subject)` token set —
|
|
94
|
+
* which is why the store adapter must report a live token's `consumedAt` as
|
|
95
|
+
* absent rather than as `null`.
|
|
96
|
+
*/
|
|
97
|
+
declare class OAuthRefreshToken extends Model {
|
|
98
|
+
/** SHA-256 hash (hex) of the opaque refresh token. */
|
|
99
|
+
tokenHash: string;
|
|
100
|
+
/** The `client_id` the token was issued to. */
|
|
101
|
+
clientId: string;
|
|
102
|
+
/** The authenticated end-user subject identifier. */
|
|
103
|
+
subject: string;
|
|
104
|
+
/** The scopes granted to this token. */
|
|
105
|
+
scopes: string[];
|
|
106
|
+
/** Instant after which the token is invalid. */
|
|
107
|
+
expiresAt: Date;
|
|
108
|
+
/** Instant the token was rotated (consumed), or `null` while it is live. */
|
|
109
|
+
consumedAt: Date | null;
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/models/index.d.ts
|
|
113
|
+
/**
|
|
114
|
+
* The OAuth data model, ready to register alongside the application's own
|
|
115
|
+
* models so `ttoss-postgresdb sync` and `erd` cover these tables like any
|
|
116
|
+
* other instead of them being a side-channel schema the CLI cannot see.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* import { oauthModels } from '@ttoss/auth-postgresdb';
|
|
121
|
+
* import { initialize } from '@ttoss/postgresdb';
|
|
122
|
+
*
|
|
123
|
+
* export const db = await initialize({ models: { ...oauthModels, User } });
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
declare const oauthModels: {
|
|
127
|
+
OAuthAuthCode: typeof OAuthAuthCode;
|
|
128
|
+
OAuthClient: typeof OAuthClient;
|
|
129
|
+
OAuthConsent: typeof OAuthConsent;
|
|
130
|
+
OAuthRefreshToken: typeof OAuthRefreshToken;
|
|
131
|
+
};
|
|
132
|
+
/** The shape a `db` handle must have to back the OAuth stores. */
|
|
133
|
+
type OAuthModels = typeof oauthModels;
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/stores/createConsentStore.d.ts
|
|
136
|
+
/** A {@link ConsentGrantStore} plus the write side an app's consent page needs. */
|
|
137
|
+
interface PostgresdbConsentStore extends ConsentGrantStore {
|
|
138
|
+
/**
|
|
139
|
+
* Record an approval so the restarted `/authorize` request can consume it.
|
|
140
|
+
* Call this from the consent page's approve handler, before navigating back
|
|
141
|
+
* to the authorization server's `/authorize`.
|
|
142
|
+
*/
|
|
143
|
+
saveConsentGrant: (grant: ConsentGrant & {
|
|
144
|
+
codeChallenge: string;
|
|
145
|
+
}) => Promise<void>;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Creates a consent store backed by the `oauth_consents` table, for use with
|
|
149
|
+
* `createRedirectConsentOnAuthorize`.
|
|
150
|
+
*
|
|
151
|
+
* Reads and deletes satisfy `ConsentGrantStore`; `saveConsentGrant` covers the
|
|
152
|
+
* write the consent page performs. Grants are single-use — the `onAuthorize`
|
|
153
|
+
* hook deletes each one as it consumes it.
|
|
154
|
+
*/
|
|
155
|
+
declare const createConsentStore: ({
|
|
156
|
+
model
|
|
157
|
+
}: {
|
|
158
|
+
/** The `OAuthConsent` model class, taken from the app's `db` handle. */model: typeof OAuthConsent;
|
|
159
|
+
}) => PostgresdbConsentStore;
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/createPostgresdbOAuthStores.d.ts
|
|
162
|
+
/** The durable OAuth stores returned by {@link createPostgresdbOAuthStores}. */
|
|
163
|
+
interface PostgresdbOAuthStores {
|
|
164
|
+
/** Dynamic client registrations, for `createOAuthHandlers`. */
|
|
165
|
+
clientStore: ClientStore;
|
|
166
|
+
/** Single-use authorization codes, stored by hash. */
|
|
167
|
+
authCodeStore: AuthCodeStore;
|
|
168
|
+
/** Consent handoff records for `createRedirectConsentOnAuthorize`. */
|
|
169
|
+
consentStore: PostgresdbConsentStore;
|
|
170
|
+
/** Tracked refresh tokens, for `createRefreshRotation`. */
|
|
171
|
+
refreshTokenStore: RefreshTokenStore;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Creates every durable OAuth store from a `@ttoss/postgresdb` `db` handle.
|
|
175
|
+
*
|
|
176
|
+
* The stores are mechanical adapters between the `@ttoss/auth-core` store
|
|
177
|
+
* contracts and Sequelize, so an app that already uses `@ttoss/postgresdb` does
|
|
178
|
+
* not have to write them — nor reach around its own ORM to inject a raw `pg`
|
|
179
|
+
* query runner.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```typescript
|
|
183
|
+
* import { createPostgresdbOAuthStores, oauthModels } from '@ttoss/auth-postgresdb';
|
|
184
|
+
* import { initialize } from '@ttoss/postgresdb';
|
|
185
|
+
*
|
|
186
|
+
* const db = await initialize({ models: { ...oauthModels, User } });
|
|
187
|
+
*
|
|
188
|
+
* const { clientStore, authCodeStore, consentStore, refreshTokenStore } =
|
|
189
|
+
* createPostgresdbOAuthStores({ db });
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
declare const createPostgresdbOAuthStores: ({
|
|
193
|
+
db
|
|
194
|
+
}: {
|
|
195
|
+
/**
|
|
196
|
+
* The handle returned by `@ttoss/postgresdb`'s `initialize`, with
|
|
197
|
+
* `oauthModels` among its registered models.
|
|
198
|
+
*/
|
|
199
|
+
db: OAuthModels;
|
|
200
|
+
}) => PostgresdbOAuthStores;
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region src/stores/createAuthCodeStore.d.ts
|
|
203
|
+
/**
|
|
204
|
+
* Creates an {@link AuthCodeStore} backed by the `oauth_auth_codes` table,
|
|
205
|
+
* storing codes by SHA-256 hash.
|
|
206
|
+
*
|
|
207
|
+
* The engine hands the store the plaintext code on every call and never compares
|
|
208
|
+
* the returned `code` against anything — it reads only `clientId`,
|
|
209
|
+
* `redirectUri`, `codeChallenge`, `scopes`, `subject`, and `expiresAt`. So the
|
|
210
|
+
* adapter hashes to find the row and echoes the presented value back, and a
|
|
211
|
+
* database dump yields no replayable codes.
|
|
212
|
+
*/
|
|
213
|
+
declare const createAuthCodeStore: ({
|
|
214
|
+
model
|
|
215
|
+
}: {
|
|
216
|
+
/** The `OAuthAuthCode` model class, taken from the app's `db` handle. */model: typeof OAuthAuthCode;
|
|
217
|
+
}) => AuthCodeStore;
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/stores/createClientStore.d.ts
|
|
220
|
+
/**
|
|
221
|
+
* Creates a {@link ClientStore} backed by the `oauth_clients` table.
|
|
222
|
+
*
|
|
223
|
+
* `register` upserts, so re-registering an existing `client_id` replaces the
|
|
224
|
+
* stored document rather than failing on the primary key.
|
|
225
|
+
*/
|
|
226
|
+
declare const createClientStore: ({
|
|
227
|
+
model
|
|
228
|
+
}: {
|
|
229
|
+
/** The `OAuthClient` model class, taken from the app's `db` handle. */model: typeof OAuthClient;
|
|
230
|
+
}) => ClientStore;
|
|
231
|
+
//#endregion
|
|
232
|
+
//#region src/stores/createRefreshTokenStore.d.ts
|
|
233
|
+
/**
|
|
234
|
+
* Creates a {@link RefreshTokenStore} backed by the `oauth_refresh_tokens`
|
|
235
|
+
* table, keyed by token hash and by the `(clientId, subject)` owner that
|
|
236
|
+
* `deleteByOwner` revokes on reuse detection.
|
|
237
|
+
*/
|
|
238
|
+
declare const createRefreshTokenStore: ({
|
|
239
|
+
model
|
|
240
|
+
}: {
|
|
241
|
+
/** The `OAuthRefreshToken` model class, taken from the app's `db` handle. */model: typeof OAuthRefreshToken;
|
|
242
|
+
}) => RefreshTokenStore;
|
|
243
|
+
//#endregion
|
|
244
|
+
export { OAuthAuthCode, OAuthClient, OAuthConsent, type OAuthModels, OAuthRefreshToken, type PostgresdbConsentStore, type PostgresdbOAuthStores, createAuthCodeStore, createClientStore, createConsentStore, createPostgresdbOAuthStores, createRefreshTokenStore, oauthModels };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
|
|
2
|
+
import { AuthCodeStore, ClientStore, ConsentGrant, ConsentGrantStore, RefreshTokenStore } from "@ttoss/auth-core";
|
|
3
|
+
import { Model } from "@ttoss/postgresdb";
|
|
4
|
+
|
|
5
|
+
//#region src/models/OAuthAuthCode.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* A short-lived authorization code with its bound PKCE challenge.
|
|
8
|
+
*
|
|
9
|
+
* The primary key is the code's SHA-256 hash, never the code itself: a code
|
|
10
|
+
* travels through a browser redirect and a client's URL bar, so storing it in
|
|
11
|
+
* plaintext would make a database dump yield replayable codes.
|
|
12
|
+
*/
|
|
13
|
+
declare class OAuthAuthCode extends Model {
|
|
14
|
+
/** SHA-256 hash (hex) of the authorization code. */
|
|
15
|
+
codeHash: string;
|
|
16
|
+
/** The `client_id` the code was issued to. */
|
|
17
|
+
clientId: string;
|
|
18
|
+
/** The redirect URI the code was issued for (must match on exchange). */
|
|
19
|
+
redirectUri: string;
|
|
20
|
+
/** The PKCE `code_challenge` (S256) bound to this code. */
|
|
21
|
+
codeChallenge: string;
|
|
22
|
+
/** The scopes granted to this code. */
|
|
23
|
+
scopes: string[];
|
|
24
|
+
/** The authenticated end-user subject identifier. */
|
|
25
|
+
subject: string;
|
|
26
|
+
/** Instant after which the code is invalid. */
|
|
27
|
+
expiresAt: Date;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/models/OAuthClient.d.ts
|
|
31
|
+
/**
|
|
32
|
+
* A registered OAuth client (RFC 7591 dynamic client registration).
|
|
33
|
+
*
|
|
34
|
+
* The RFC's registered fields get their own columns so they can be queried and
|
|
35
|
+
* indexed; any additional metadata a client submits is kept verbatim in
|
|
36
|
+
* `metadata`, because `OAuthClientMetadata` is an open shape.
|
|
37
|
+
*/
|
|
38
|
+
declare class OAuthClient extends Model {
|
|
39
|
+
/** The `client_id` issued by the authorization server. */
|
|
40
|
+
clientId: string;
|
|
41
|
+
/**
|
|
42
|
+
* Client secret for confidential clients, `null` for public clients
|
|
43
|
+
* (`token_endpoint_auth_method: 'none'`).
|
|
44
|
+
*/
|
|
45
|
+
clientSecret: string | null;
|
|
46
|
+
/** Human-readable client name shown on consent screens. */
|
|
47
|
+
clientName: string | null;
|
|
48
|
+
/** Exact redirect URIs registered for this client. */
|
|
49
|
+
redirectUris: string[];
|
|
50
|
+
/** OAuth grant types the client may use. */
|
|
51
|
+
grantTypes: string[] | null;
|
|
52
|
+
/** OAuth response types the client may use. */
|
|
53
|
+
responseTypes: string[] | null;
|
|
54
|
+
/** Client authentication method at the token endpoint. */
|
|
55
|
+
tokenEndpointAuthMethod: string | null;
|
|
56
|
+
/** Space-separated scopes the client may request. */
|
|
57
|
+
scope: string | null;
|
|
58
|
+
/** Unix timestamp (seconds) when the client was registered. */
|
|
59
|
+
clientIdIssuedAt: number | null;
|
|
60
|
+
/**
|
|
61
|
+
* Registration metadata outside the columns above, preserved so a client's
|
|
62
|
+
* submitted document round-trips unchanged (e.g. `logo_uri`, `client_uri`).
|
|
63
|
+
*/
|
|
64
|
+
metadata: Record<string, unknown>;
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/models/OAuthConsent.d.ts
|
|
68
|
+
/**
|
|
69
|
+
* A single-use consent handoff, correlated by the PKCE `code_challenge`.
|
|
70
|
+
*
|
|
71
|
+
* This is the record an external consent screen writes on approval so the
|
|
72
|
+
* restarted `/authorize` request can be approved without asking again — it is
|
|
73
|
+
* not a durable "user X trusts client Y" grant, which is an app-level
|
|
74
|
+
* authorization decision and belongs in the app's own schema.
|
|
75
|
+
*/
|
|
76
|
+
declare class OAuthConsent extends Model {
|
|
77
|
+
/** The PKCE `code_challenge` the consent was recorded against. */
|
|
78
|
+
codeChallenge: string;
|
|
79
|
+
/** The authenticated end-user subject identifier. */
|
|
80
|
+
subject: string;
|
|
81
|
+
/** The scopes the user approved. */
|
|
82
|
+
scopes: string[];
|
|
83
|
+
/** Instant after which the consent is no longer usable. */
|
|
84
|
+
expiresAt: Date;
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/models/OAuthRefreshToken.d.ts
|
|
88
|
+
/**
|
|
89
|
+
* A refresh token tracked for OAuth 2.1 rotation, stored by hash so a database
|
|
90
|
+
* dump yields no usable credentials.
|
|
91
|
+
*
|
|
92
|
+
* `consumedAt` marks a rotated token. Presenting one again is reuse, and
|
|
93
|
+
* `createRefreshRotation` revokes the whole `(clientId, subject)` token set —
|
|
94
|
+
* which is why the store adapter must report a live token's `consumedAt` as
|
|
95
|
+
* absent rather than as `null`.
|
|
96
|
+
*/
|
|
97
|
+
declare class OAuthRefreshToken extends Model {
|
|
98
|
+
/** SHA-256 hash (hex) of the opaque refresh token. */
|
|
99
|
+
tokenHash: string;
|
|
100
|
+
/** The `client_id` the token was issued to. */
|
|
101
|
+
clientId: string;
|
|
102
|
+
/** The authenticated end-user subject identifier. */
|
|
103
|
+
subject: string;
|
|
104
|
+
/** The scopes granted to this token. */
|
|
105
|
+
scopes: string[];
|
|
106
|
+
/** Instant after which the token is invalid. */
|
|
107
|
+
expiresAt: Date;
|
|
108
|
+
/** Instant the token was rotated (consumed), or `null` while it is live. */
|
|
109
|
+
consumedAt: Date | null;
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/models/index.d.ts
|
|
113
|
+
/**
|
|
114
|
+
* The OAuth data model, ready to register alongside the application's own
|
|
115
|
+
* models so `ttoss-postgresdb sync` and `erd` cover these tables like any
|
|
116
|
+
* other instead of them being a side-channel schema the CLI cannot see.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* import { oauthModels } from '@ttoss/auth-postgresdb';
|
|
121
|
+
* import { initialize } from '@ttoss/postgresdb';
|
|
122
|
+
*
|
|
123
|
+
* export const db = await initialize({ models: { ...oauthModels, User } });
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
declare const oauthModels: {
|
|
127
|
+
OAuthAuthCode: typeof OAuthAuthCode;
|
|
128
|
+
OAuthClient: typeof OAuthClient;
|
|
129
|
+
OAuthConsent: typeof OAuthConsent;
|
|
130
|
+
OAuthRefreshToken: typeof OAuthRefreshToken;
|
|
131
|
+
};
|
|
132
|
+
/** The shape a `db` handle must have to back the OAuth stores. */
|
|
133
|
+
type OAuthModels = typeof oauthModels;
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/stores/createConsentStore.d.ts
|
|
136
|
+
/** A {@link ConsentGrantStore} plus the write side an app's consent page needs. */
|
|
137
|
+
interface PostgresdbConsentStore extends ConsentGrantStore {
|
|
138
|
+
/**
|
|
139
|
+
* Record an approval so the restarted `/authorize` request can consume it.
|
|
140
|
+
* Call this from the consent page's approve handler, before navigating back
|
|
141
|
+
* to the authorization server's `/authorize`.
|
|
142
|
+
*/
|
|
143
|
+
saveConsentGrant: (grant: ConsentGrant & {
|
|
144
|
+
codeChallenge: string;
|
|
145
|
+
}) => Promise<void>;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Creates a consent store backed by the `oauth_consents` table, for use with
|
|
149
|
+
* `createRedirectConsentOnAuthorize`.
|
|
150
|
+
*
|
|
151
|
+
* Reads and deletes satisfy `ConsentGrantStore`; `saveConsentGrant` covers the
|
|
152
|
+
* write the consent page performs. Grants are single-use — the `onAuthorize`
|
|
153
|
+
* hook deletes each one as it consumes it.
|
|
154
|
+
*/
|
|
155
|
+
declare const createConsentStore: ({
|
|
156
|
+
model
|
|
157
|
+
}: {
|
|
158
|
+
/** The `OAuthConsent` model class, taken from the app's `db` handle. */model: typeof OAuthConsent;
|
|
159
|
+
}) => PostgresdbConsentStore;
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/createPostgresdbOAuthStores.d.ts
|
|
162
|
+
/** The durable OAuth stores returned by {@link createPostgresdbOAuthStores}. */
|
|
163
|
+
interface PostgresdbOAuthStores {
|
|
164
|
+
/** Dynamic client registrations, for `createOAuthHandlers`. */
|
|
165
|
+
clientStore: ClientStore;
|
|
166
|
+
/** Single-use authorization codes, stored by hash. */
|
|
167
|
+
authCodeStore: AuthCodeStore;
|
|
168
|
+
/** Consent handoff records for `createRedirectConsentOnAuthorize`. */
|
|
169
|
+
consentStore: PostgresdbConsentStore;
|
|
170
|
+
/** Tracked refresh tokens, for `createRefreshRotation`. */
|
|
171
|
+
refreshTokenStore: RefreshTokenStore;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Creates every durable OAuth store from a `@ttoss/postgresdb` `db` handle.
|
|
175
|
+
*
|
|
176
|
+
* The stores are mechanical adapters between the `@ttoss/auth-core` store
|
|
177
|
+
* contracts and Sequelize, so an app that already uses `@ttoss/postgresdb` does
|
|
178
|
+
* not have to write them — nor reach around its own ORM to inject a raw `pg`
|
|
179
|
+
* query runner.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```typescript
|
|
183
|
+
* import { createPostgresdbOAuthStores, oauthModels } from '@ttoss/auth-postgresdb';
|
|
184
|
+
* import { initialize } from '@ttoss/postgresdb';
|
|
185
|
+
*
|
|
186
|
+
* const db = await initialize({ models: { ...oauthModels, User } });
|
|
187
|
+
*
|
|
188
|
+
* const { clientStore, authCodeStore, consentStore, refreshTokenStore } =
|
|
189
|
+
* createPostgresdbOAuthStores({ db });
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
declare const createPostgresdbOAuthStores: ({
|
|
193
|
+
db
|
|
194
|
+
}: {
|
|
195
|
+
/**
|
|
196
|
+
* The handle returned by `@ttoss/postgresdb`'s `initialize`, with
|
|
197
|
+
* `oauthModels` among its registered models.
|
|
198
|
+
*/
|
|
199
|
+
db: OAuthModels;
|
|
200
|
+
}) => PostgresdbOAuthStores;
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region src/stores/createAuthCodeStore.d.ts
|
|
203
|
+
/**
|
|
204
|
+
* Creates an {@link AuthCodeStore} backed by the `oauth_auth_codes` table,
|
|
205
|
+
* storing codes by SHA-256 hash.
|
|
206
|
+
*
|
|
207
|
+
* The engine hands the store the plaintext code on every call and never compares
|
|
208
|
+
* the returned `code` against anything — it reads only `clientId`,
|
|
209
|
+
* `redirectUri`, `codeChallenge`, `scopes`, `subject`, and `expiresAt`. So the
|
|
210
|
+
* adapter hashes to find the row and echoes the presented value back, and a
|
|
211
|
+
* database dump yields no replayable codes.
|
|
212
|
+
*/
|
|
213
|
+
declare const createAuthCodeStore: ({
|
|
214
|
+
model
|
|
215
|
+
}: {
|
|
216
|
+
/** The `OAuthAuthCode` model class, taken from the app's `db` handle. */model: typeof OAuthAuthCode;
|
|
217
|
+
}) => AuthCodeStore;
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/stores/createClientStore.d.ts
|
|
220
|
+
/**
|
|
221
|
+
* Creates a {@link ClientStore} backed by the `oauth_clients` table.
|
|
222
|
+
*
|
|
223
|
+
* `register` upserts, so re-registering an existing `client_id` replaces the
|
|
224
|
+
* stored document rather than failing on the primary key.
|
|
225
|
+
*/
|
|
226
|
+
declare const createClientStore: ({
|
|
227
|
+
model
|
|
228
|
+
}: {
|
|
229
|
+
/** The `OAuthClient` model class, taken from the app's `db` handle. */model: typeof OAuthClient;
|
|
230
|
+
}) => ClientStore;
|
|
231
|
+
//#endregion
|
|
232
|
+
//#region src/stores/createRefreshTokenStore.d.ts
|
|
233
|
+
/**
|
|
234
|
+
* Creates a {@link RefreshTokenStore} backed by the `oauth_refresh_tokens`
|
|
235
|
+
* table, keyed by token hash and by the `(clientId, subject)` owner that
|
|
236
|
+
* `deleteByOwner` revokes on reuse detection.
|
|
237
|
+
*/
|
|
238
|
+
declare const createRefreshTokenStore: ({
|
|
239
|
+
model
|
|
240
|
+
}: {
|
|
241
|
+
/** The `OAuthRefreshToken` model class, taken from the app's `db` handle. */model: typeof OAuthRefreshToken;
|
|
242
|
+
}) => RefreshTokenStore;
|
|
243
|
+
//#endregion
|
|
244
|
+
export { OAuthAuthCode, OAuthClient, OAuthConsent, type OAuthModels, OAuthRefreshToken, type PostgresdbConsentStore, type PostgresdbOAuthStores, createAuthCodeStore, createClientStore, createConsentStore, createPostgresdbOAuthStores, createRefreshTokenStore, oauthModels };
|