@spfn/auth 0.3.0-beta.17 → 0.3.0-beta.19
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/README.md +155 -0
- package/dist/errors.d.ts +74 -2
- package/dist/errors.js +51 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +39 -2
- package/dist/index.js +43 -1
- package/dist/index.js.map +1 -1
- package/dist/{machine-principals-nrpFSvvB.d.ts → machine-principals-BD4tnASp.d.ts} +171 -1
- package/dist/nextjs/api.js +6 -1
- package/dist/nextjs/api.js.map +1 -1
- package/dist/nextjs/server.d.ts +57 -2
- package/dist/nextjs/server.js +18 -0
- package/dist/nextjs/server.js.map +1 -1
- package/dist/server.d.ts +1466 -51
- package/dist/server.js +1862 -398
- package/dist/server.js.map +1 -1
- package/migrations/20260918083158_foamy_roughhouse/migration.sql +55 -0
- package/migrations/20260918083158_foamy_roughhouse/snapshot.json +5271 -0
- package/package.json +1 -1
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AuthInitOptions,
|
|
2
|
-
export {
|
|
1
|
+
import { A as AuthInitOptions, u as OAuthProvider, s as VerificationPurpose, N as NewPasskey, v as Passkey, q as PermissionCategory, w as AuthContext } from './machine-principals-BD4tnASp.js';
|
|
2
|
+
export { x as ApproveDeviceAuthParams, y as AuthProfileOutcome, z as AuthProfileVerifier, B as ChangePasswordParams, E as CompletePasswordResetParams, G as CompleteSignupParams, H as ConfirmPasswordResetParams, d as ConfirmPasswordResetResult, J as ConfirmSignupLinkParams, C as ConfirmSignupLinkResult, M as DenyDeviceAuthParams, Q as DeviceAuthApprovedResult, T as DeviceAuthInfoParams, D as DeviceAuthInfoResult, W as DeviceAuthPendingResult, X as DeviceAuthPollResponseSchema, Y as DeviceNameSchema, Z as EmailSchema, _ as FingerprintSchema, $ as FinishPasskeyEnrollmentParams, F as FinishPasskeyEnrollmentResult, a0 as FinishPasskeyLoginParams, I as IssueOneTimeTokenResult, a1 as KEY_FINGERPRINT_PREFIX_LENGTH, a2 as KeyIdSchema, K as KeySummary, a3 as LoginParams, L as LoginResult, a4 as LogoutParams, a5 as MachinePrincipal, a6 as MachineVerifierRegistration, a7 as NativeVerifyOptions, a8 as NormalizedIdentity, l as OAuth2AuthorizationCodeIssued, a9 as OAuth2AuthorizeParams, k as OAuth2ConsentView, n as OAuth2GrantSummary, aa as OAuth2ScopeDescription, ab as OAuthCallbackParams, ac as OAuthCallbackResult, ad as OAuthCodeExchangeOptions, ae as OAuthNativeParams, i as OAuthNativeResult, af as OAuthStartParams, O as OAuthStartResult, ag as OAuthTokens, ah as PASSKEY_DEVICE_TYPES, ai as PASSKEY_LABEL_MAX_LENGTH, aj as PasskeyDeviceType, f as PasskeySummary, ak as PasswordSchema, al as PhoneSchema, am as PlatformSchema, an as PollDeviceAuthParams, ao as PollDeviceAuthResult, ap as PublicKeySchema, aq as RecentAuthenticationParams, ar as RegisterParams, as as RegisterPublicKeyParams, a as RegisterResult, at as RenamePasskeyParams, au as RequestPasswordResetParams, c as RequestPasswordResetResult, av as RequestSignupLinkParams, b as RequestSignupLinkResult, aw as RevokeAllKeysParams, h as RevokeAllKeysResult, ax as RevokeKeyParams, ay as RevokePasskeyParams, az as RotateKeyParams, g as RotateKeyResult, aA as SendVerificationCodeParams, S as SendVerificationCodeResult, aB as StartDeviceAuthParams, e as StartDeviceAuthResult, aC as StartPasskeyEnrollmentParams, aD as TargetTypeSchema, aE as UnlinkNotification, aF as UnlinkNotifyRejection, aG as UnlinkNotifyRequest, aH as UnlinkNotifyResult, aI as UserCodeSchema, V as VERIFICATION_PURPOSES, r as VERIFICATION_TARGET_TYPES, aJ as VerificationPurposeSchema, t as VerificationTargetType, aK as VerifyCodeParams, aL as VerifyCodeResult, aM as approveDeviceAuthService, aN as approveOAuth2AuthorizeService, aO as assertNotLastRecoveryCredential, aP as assertRecentAuthentication, m as authRouter, aQ as authenticate, aR as buildOAuthErrorUrl, aS as changePasswordService, aT as completePasswordResetService, aU as completeSignupService, aV as confirmPasswordResetService, aW as confirmSignupLinkService, aX as denyDeviceAuthService, aY as denyOAuth2AuthorizeService, aZ as describeOAuth2AuthorizeRequestService, a_ as finishPasskeyEnrollmentService, a$ as finishPasskeyLoginService, b0 as getDeviceAuthInfoService, b1 as getEnabledOAuthProviders, b2 as getGoogleAccessToken, b3 as getMachinePrincipal, b4 as getOAuthProvider, b5 as getRegisteredProviders, b6 as isOAuthProviderEnabled, b7 as issueOneTimeTokenService, b8 as listKeysService, b9 as listOAuth2GrantsService, ba as listPasskeysService, bb as loginService, bc as logoutService, bd as machineAuth, be as oauthCallbackService, bf as oauthNativeService, bg as oauthStartService, bh as oauthUnlinkNotifyService, bi as optionalAuth, bj as passkeys, bk as pollDeviceAuthService, bl as registerAuthProfile, bm as registerMachineVerifier, bn as registerOAuthProvider, bo as registerPublicKeyService, bp as registerService, bq as renamePasskeyService, br as requestPasswordResetService, bs as requestSignupLinkService, bt as requireEnabledProvider, bu as requireMachineScope, bv as resolveAuthenticatedUser, bw as revokeAllKeysService, bx as revokeAllOAuth2GrantsForUser, by as revokeKeyService, bz as revokeOAuth2GrantService, bA as revokePasskeyService, bB as rotateKeyService, bC as runAuthProfile, bD as selectAuthProfile, bE as sendVerificationCodeService, bF as startDeviceAuthService, bG as startPasskeyEnrollmentService, bH as startPasskeyLoginService, bI as verifyCodeService, bJ as verifyOneTimeTokenService } from './machine-principals-BD4tnASp.js';
|
|
3
3
|
import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
|
|
4
4
|
import { j as SocialProvider, K as KeyAlgorithmType, d as InvitationStatus, c as AccountDeletionRequestedBy, i as PurgeStrategy } from './types-DYyhze28.js';
|
|
5
5
|
export { A as ACCOUNT_DELETION_REQUESTED_BY, a as ACCOUNT_DELETION_REQUEST_STATUSES, b as AccountDeletionRequestStatus, I as INVITATION_STATUSES, e as KEY_ALGORITHM, f as KEY_DEVICE_NAME_MAX_LENGTH, g as KEY_PLATFORM, h as KeyPlatformType, P as PURGE_STRATEGIES, S as SOCIAL_PROVIDERS, U as USER_STATUSES, k as UserStatus } from './types-DYyhze28.js';
|
|
@@ -2478,6 +2478,227 @@ declare function verifyOpsTokenService(token: string): Promise<VerifiedOpsToken
|
|
|
2478
2478
|
declare function revokeOpsTokenService(id: number): Promise<OpsToken | null>;
|
|
2479
2479
|
declare function listOpsTokensService(): Promise<OpsToken[]>;
|
|
2480
2480
|
|
|
2481
|
+
/**
|
|
2482
|
+
* OAuth 2.1 Client Service
|
|
2483
|
+
*
|
|
2484
|
+
* RFC 7591 dynamic client registration, for public clients and nothing else.
|
|
2485
|
+
* `claude mcp add` and `codex mcp add` both begin here: the CLI discovers the
|
|
2486
|
+
* authorization server, registers itself unauthenticated, and gets back a
|
|
2487
|
+
* `client_id` it keeps on the user's disk.
|
|
2488
|
+
*
|
|
2489
|
+
* Unauthenticated registration means the table is a place anyone can write, so
|
|
2490
|
+
* two things bound it. The route rate-limits by IP, and this service caps how
|
|
2491
|
+
* many clients one IP may have standing that nobody has approved — a rate limit
|
|
2492
|
+
* alone would let an IP accumulate rows forever at a slow enough pace, because a
|
|
2493
|
+
* row costs nothing to make and lives until a job sweeps it. The cap looks back
|
|
2494
|
+
* an hour rather than over all time: it is a bound on how much junk one address
|
|
2495
|
+
* may have standing at once, not a lifetime quota on how many CLIs somebody may
|
|
2496
|
+
* ever connect.
|
|
2497
|
+
*
|
|
2498
|
+
* Every refusal here is RFC 7591 §3.2.2 shaped (`invalid_redirect_uri`,
|
|
2499
|
+
* `invalid_client_metadata`) rather than thrown, because the client reading it
|
|
2500
|
+
* is an OAuth client library that knows those two words and not this
|
|
2501
|
+
* application's error envelope. The route renders the shape; this decides it.
|
|
2502
|
+
*/
|
|
2503
|
+
/**
|
|
2504
|
+
* How many unapproved clients one IP may have standing.
|
|
2505
|
+
*
|
|
2506
|
+
* Generous against real use — a developer registering the same CLI on four
|
|
2507
|
+
* projects in an afternoon, each abandoned at the consent screen, is nowhere
|
|
2508
|
+
* near it — and small enough that the table cannot be filled from one address
|
|
2509
|
+
* between two sweeps of the purge job.
|
|
2510
|
+
*/
|
|
2511
|
+
declare const MAX_UNGRANTED_CLIENTS_PER_IP = 20;
|
|
2512
|
+
/** How long a client nobody approved is kept before the purge job deletes it. */
|
|
2513
|
+
declare const STALE_CLIENT_MAX_AGE_MS: number;
|
|
2514
|
+
/** The only grant types this authorization server issues. */
|
|
2515
|
+
declare const SUPPORTED_GRANT_TYPES: string[];
|
|
2516
|
+
/** The only response type. There is no implicit flow here. */
|
|
2517
|
+
declare const SUPPORTED_RESPONSE_TYPES: string[];
|
|
2518
|
+
/** Registration metadata as RFC 7591 names it, before anything is trusted. */
|
|
2519
|
+
interface OAuth2RegisterRequest {
|
|
2520
|
+
redirect_uris?: unknown;
|
|
2521
|
+
client_name?: unknown;
|
|
2522
|
+
token_endpoint_auth_method?: unknown;
|
|
2523
|
+
grant_types?: unknown;
|
|
2524
|
+
response_types?: unknown;
|
|
2525
|
+
}
|
|
2526
|
+
/** RFC 7591 §3.2.1 registration response. */
|
|
2527
|
+
interface OAuth2RegisteredClient {
|
|
2528
|
+
client_id: string;
|
|
2529
|
+
client_id_issued_at: number;
|
|
2530
|
+
client_name: string;
|
|
2531
|
+
redirect_uris: string[];
|
|
2532
|
+
token_endpoint_auth_method: string;
|
|
2533
|
+
grant_types: string[];
|
|
2534
|
+
response_types: string[];
|
|
2535
|
+
}
|
|
2536
|
+
/** A refusal in the shape the client's own OAuth library will read. */
|
|
2537
|
+
interface OAuth2RegisterRefusal {
|
|
2538
|
+
ok: false;
|
|
2539
|
+
status: 400 | 429;
|
|
2540
|
+
error: string;
|
|
2541
|
+
description: string;
|
|
2542
|
+
}
|
|
2543
|
+
type OAuth2RegisterResult = {
|
|
2544
|
+
ok: true;
|
|
2545
|
+
client: OAuth2RegisteredClient;
|
|
2546
|
+
} | OAuth2RegisterRefusal;
|
|
2547
|
+
/**
|
|
2548
|
+
* Register a public client.
|
|
2549
|
+
*
|
|
2550
|
+
* @param request - Metadata exactly as it arrived; nothing here is trusted
|
|
2551
|
+
* @param clientIp - Client IP for the standing cap, or null when unknowable
|
|
2552
|
+
*/
|
|
2553
|
+
declare function registerOAuth2ClientService(request: OAuth2RegisterRequest, clientIp: string | null): Promise<OAuth2RegisterResult>;
|
|
2554
|
+
/**
|
|
2555
|
+
* Delete clients nobody approved within a day — the `auth.oauth2.client-purge`
|
|
2556
|
+
* sweep.
|
|
2557
|
+
*
|
|
2558
|
+
* @returns how many rows the sweep removed
|
|
2559
|
+
*/
|
|
2560
|
+
declare function purgeStaleOAuth2ClientsService(): Promise<{
|
|
2561
|
+
deleted: number;
|
|
2562
|
+
}>;
|
|
2563
|
+
|
|
2564
|
+
/**
|
|
2565
|
+
* OAuth 2.1 Token Service
|
|
2566
|
+
*
|
|
2567
|
+
* The token endpoint's two grant types, and RFC 7009 revocation.
|
|
2568
|
+
*
|
|
2569
|
+
* Every failure on this endpoint answers `invalid_grant` — an unknown code, a
|
|
2570
|
+
* spent one, an expired one, a mismatched verifier, a code minted for another
|
|
2571
|
+
* client, a refresh token that never existed, one that was rotated away. That is
|
|
2572
|
+
* not laziness with error messages: the endpoint is public and unauthenticated,
|
|
2573
|
+
* and an error that distinguished "this code does not exist" from "this code
|
|
2574
|
+
* exists but is not yours" would answer the question an attacker holding a
|
|
2575
|
+
* stolen value is actually asking. `invalid_target` and `invalid_scope` are the
|
|
2576
|
+
* two exceptions, and both are decided from values the caller already knows.
|
|
2577
|
+
*
|
|
2578
|
+
* Nothing is spent or revoked before the presenter has shown it is the client the
|
|
2579
|
+
* credential belongs to. On the code path that means `client_id`, `redirect_uri`
|
|
2580
|
+
* and the PKCE verifier are all checked against the row before the code is
|
|
2581
|
+
* consumed — a caller that cannot satisfy them leaves the code unspent for the
|
|
2582
|
+
* real client and the grant untouched, because it has proved nothing about
|
|
2583
|
+
* itself and must therefore cost nobody anything.
|
|
2584
|
+
*
|
|
2585
|
+
* Two replays are detected rather than merely refused, and both revoke the whole
|
|
2586
|
+
* grant:
|
|
2587
|
+
*
|
|
2588
|
+
* - A code presented twice. The first exchange already produced tokens; if the
|
|
2589
|
+
* second presentation is the real client, somebody else holds those tokens.
|
|
2590
|
+
* - A rotated refresh token presented again. Same reasoning, and it is why a
|
|
2591
|
+
* rotated row is marked rather than deleted — a deleted row is
|
|
2592
|
+
* indistinguishable from one that never existed.
|
|
2593
|
+
*
|
|
2594
|
+
* Revoking the grant kills the replacement tokens too, which is the point: the
|
|
2595
|
+
* thief's pair and the client's pair both hang off the grant, and there is no
|
|
2596
|
+
* way to tell which is which.
|
|
2597
|
+
*/
|
|
2598
|
+
/** A token request as RFC 6749 names its fields, before anything is trusted. */
|
|
2599
|
+
interface OAuth2TokenRequest {
|
|
2600
|
+
grant_type?: string;
|
|
2601
|
+
code?: string;
|
|
2602
|
+
code_verifier?: string;
|
|
2603
|
+
client_id?: string;
|
|
2604
|
+
redirect_uri?: string;
|
|
2605
|
+
refresh_token?: string;
|
|
2606
|
+
resource?: string;
|
|
2607
|
+
scope?: string;
|
|
2608
|
+
}
|
|
2609
|
+
/** RFC 6749 §5.1, with `scope` always stated so a narrowed request is legible. */
|
|
2610
|
+
interface OAuth2TokenResponse {
|
|
2611
|
+
access_token: string;
|
|
2612
|
+
token_type: 'Bearer';
|
|
2613
|
+
expires_in: number;
|
|
2614
|
+
refresh_token: string;
|
|
2615
|
+
scope: string;
|
|
2616
|
+
}
|
|
2617
|
+
/** RFC 6749 §5.2: the code, and a sentence for whoever is reading the logs. */
|
|
2618
|
+
interface OAuth2TokenRefusal {
|
|
2619
|
+
ok: false;
|
|
2620
|
+
error: string;
|
|
2621
|
+
description: string;
|
|
2622
|
+
}
|
|
2623
|
+
type OAuth2TokenResult = {
|
|
2624
|
+
ok: true;
|
|
2625
|
+
tokens: OAuth2TokenResponse;
|
|
2626
|
+
} | OAuth2TokenRefusal;
|
|
2627
|
+
/**
|
|
2628
|
+
* Exchange a code or refresh a token.
|
|
2629
|
+
*
|
|
2630
|
+
* @param request - The form or JSON body, exactly as it arrived
|
|
2631
|
+
*/
|
|
2632
|
+
declare function oauth2TokenService(request: OAuth2TokenRequest): Promise<OAuth2TokenResult>;
|
|
2633
|
+
/**
|
|
2634
|
+
* Revoke a presented token.
|
|
2635
|
+
*
|
|
2636
|
+
* Answers nothing, ever. RFC 7009 §2.2 requires 200 for a token that was never
|
|
2637
|
+
* issued as well as for one that was, so a caller cannot use this endpoint to
|
|
2638
|
+
* ask whether a value it found somewhere is real.
|
|
2639
|
+
*
|
|
2640
|
+
* A refresh token takes the grant with it: a client presenting its refresh token
|
|
2641
|
+
* here is saying it is finished, and leaving that grant's access tokens alive
|
|
2642
|
+
* for eight more hours would be honouring half the request. An access token is
|
|
2643
|
+
* revoked alone — a client may be discarding one it no longer needs while still
|
|
2644
|
+
* holding the connection.
|
|
2645
|
+
*
|
|
2646
|
+
* A `client_id` that is not the token's is the same 200 and revokes nothing
|
|
2647
|
+
* (RFC 7009 §2.1). The endpoint has no client authentication to lean on, so this
|
|
2648
|
+
* does not stop anybody who holds the token from revoking it — what it stops is
|
|
2649
|
+
* one client tearing down another's connection by presenting a value it came
|
|
2650
|
+
* across, which is the only thing a public client's id can be asked to mean.
|
|
2651
|
+
* Which is also why it is required and not optional: RFC 7009 §2.1 has the
|
|
2652
|
+
* client authenticate per RFC 6749 §2.3, and §2.3.1 says a public client with no
|
|
2653
|
+
* credentials identifies itself with `client_id`. The route refuses a request
|
|
2654
|
+
* that carries none before this is called.
|
|
2655
|
+
*
|
|
2656
|
+
* @param token - The value to revoke, access or refresh
|
|
2657
|
+
* @param clientId - Checked against the token's client
|
|
2658
|
+
*/
|
|
2659
|
+
declare function revokeOAuth2TokenService(token: string, clientId: string): Promise<void>;
|
|
2660
|
+
|
|
2661
|
+
/**
|
|
2662
|
+
* OAuth 2.1 Access Token Verification
|
|
2663
|
+
*
|
|
2664
|
+
* `verifyAccessToken` is what `@spfn/mcp` calls on every request to `/mcp`. It
|
|
2665
|
+
* is the one function in this feature an application wires up by hand:
|
|
2666
|
+
*
|
|
2667
|
+
* ```typescript
|
|
2668
|
+
* createMcpRoute({ validateToken: verifyAccessToken })
|
|
2669
|
+
* ```
|
|
2670
|
+
*
|
|
2671
|
+
* Null for every refusal, and the same null for all of them — unknown, revoked,
|
|
2672
|
+
* expired, refresh-kind, grant revoked, wrong resource. The non-disclosure rule
|
|
2673
|
+
* `verifyOpsTokenService` keeps, for the same reason: this is a public endpoint
|
|
2674
|
+
* and the refusal must not tell a caller whether the value it presented was ever
|
|
2675
|
+
* real.
|
|
2676
|
+
*
|
|
2677
|
+
* The resource check is not a formality. An access token minted for one API is
|
|
2678
|
+
* refused by another (RFC 8707), so a token a user approved for their MCP server
|
|
2679
|
+
* cannot be replayed against a neighbouring deployment that happens to share this
|
|
2680
|
+
* authorization server.
|
|
2681
|
+
*/
|
|
2682
|
+
/** What a verified access token authorizes. */
|
|
2683
|
+
interface VerifiedOAuth2AccessToken {
|
|
2684
|
+
/** The public `client_id` of the CLI holding the token. */
|
|
2685
|
+
clientId: string;
|
|
2686
|
+
/** Scope names, as granted or as the refresh that minted it narrowed them to. */
|
|
2687
|
+
scopes: string[];
|
|
2688
|
+
/** Expiry as seconds since the epoch — the unit every OAuth field uses. */
|
|
2689
|
+
expiresAt: number;
|
|
2690
|
+
/** The account the CLI is acting for. */
|
|
2691
|
+
userId: string;
|
|
2692
|
+
}
|
|
2693
|
+
/**
|
|
2694
|
+
* Verify a bearer token presented to a protected resource.
|
|
2695
|
+
*
|
|
2696
|
+
* @param token - The raw bearer value
|
|
2697
|
+
* @param resource - The resource being accessed, e.g. `https://api.example.com/mcp`
|
|
2698
|
+
* @returns the principal, or null for any reason at all
|
|
2699
|
+
*/
|
|
2700
|
+
declare function verifyAccessToken(token: string, resource: string): Promise<VerifiedOAuth2AccessToken | null>;
|
|
2701
|
+
|
|
2481
2702
|
/**
|
|
2482
2703
|
* @spfn/auth - Database Schema Definition
|
|
2483
2704
|
*
|
|
@@ -4514,13 +4735,614 @@ declare const rolePermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
4514
4735
|
identity: undefined;
|
|
4515
4736
|
generated: undefined;
|
|
4516
4737
|
}>;
|
|
4517
|
-
permissionId: drizzle_orm_pg_core.PgBuildColumn<"role_permissions", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBigInt53Builder>, {
|
|
4738
|
+
permissionId: drizzle_orm_pg_core.PgBuildColumn<"role_permissions", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBigInt53Builder>, {
|
|
4739
|
+
name: string;
|
|
4740
|
+
tableName: "role_permissions";
|
|
4741
|
+
dataType: "number int53";
|
|
4742
|
+
data: number;
|
|
4743
|
+
driverParam: string | number;
|
|
4744
|
+
notNull: true;
|
|
4745
|
+
hasDefault: false;
|
|
4746
|
+
isPrimaryKey: false;
|
|
4747
|
+
isAutoincrement: false;
|
|
4748
|
+
hasRuntimeDefault: false;
|
|
4749
|
+
enumValues: undefined;
|
|
4750
|
+
identity: undefined;
|
|
4751
|
+
generated: undefined;
|
|
4752
|
+
}>;
|
|
4753
|
+
};
|
|
4754
|
+
dialect: "pg";
|
|
4755
|
+
}>;
|
|
4756
|
+
type RolePermission = typeof rolePermissions.$inferSelect;
|
|
4757
|
+
type NewRolePermission = typeof rolePermissions.$inferInsert;
|
|
4758
|
+
|
|
4759
|
+
/**
|
|
4760
|
+
* @spfn/auth - User-Permissions Override Entity
|
|
4761
|
+
*
|
|
4762
|
+
* Per-user permission grants/revocations
|
|
4763
|
+
*
|
|
4764
|
+
* Features:
|
|
4765
|
+
* - Grant additional permissions to specific users
|
|
4766
|
+
* - Revoke role-inherited permissions from specific users
|
|
4767
|
+
* - Temporary permissions with expiration
|
|
4768
|
+
* - Audit trail with reason field
|
|
4769
|
+
*
|
|
4770
|
+
* Priority:
|
|
4771
|
+
* User permissions override role permissions
|
|
4772
|
+
*/
|
|
4773
|
+
declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
4774
|
+
name: "user_permissions";
|
|
4775
|
+
schema: string;
|
|
4776
|
+
columns: {
|
|
4777
|
+
createdAt: drizzle_orm_pg_core.PgBuildColumn<"user_permissions", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>, {
|
|
4778
|
+
name: string;
|
|
4779
|
+
tableName: "user_permissions";
|
|
4780
|
+
dataType: "object date";
|
|
4781
|
+
data: Date;
|
|
4782
|
+
driverParam: string;
|
|
4783
|
+
notNull: true;
|
|
4784
|
+
hasDefault: true;
|
|
4785
|
+
isPrimaryKey: false;
|
|
4786
|
+
isAutoincrement: false;
|
|
4787
|
+
hasRuntimeDefault: false;
|
|
4788
|
+
enumValues: undefined;
|
|
4789
|
+
identity: undefined;
|
|
4790
|
+
generated: undefined;
|
|
4791
|
+
}>;
|
|
4792
|
+
updatedAt: drizzle_orm_pg_core.PgBuildColumn<"user_permissions", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>>, {
|
|
4793
|
+
name: string;
|
|
4794
|
+
tableName: "user_permissions";
|
|
4795
|
+
dataType: "object date";
|
|
4796
|
+
data: Date;
|
|
4797
|
+
driverParam: string;
|
|
4798
|
+
notNull: true;
|
|
4799
|
+
hasDefault: true;
|
|
4800
|
+
isPrimaryKey: false;
|
|
4801
|
+
isAutoincrement: false;
|
|
4802
|
+
hasRuntimeDefault: false;
|
|
4803
|
+
enumValues: undefined;
|
|
4804
|
+
identity: undefined;
|
|
4805
|
+
generated: undefined;
|
|
4806
|
+
}>;
|
|
4807
|
+
id: drizzle_orm_pg_core.PgBuildColumn<"user_permissions", drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgBigSerial53Builder>, {
|
|
4808
|
+
name: string;
|
|
4809
|
+
tableName: "user_permissions";
|
|
4810
|
+
dataType: "number int53";
|
|
4811
|
+
data: number;
|
|
4812
|
+
driverParam: number;
|
|
4813
|
+
notNull: true;
|
|
4814
|
+
hasDefault: true;
|
|
4815
|
+
isPrimaryKey: false;
|
|
4816
|
+
isAutoincrement: false;
|
|
4817
|
+
hasRuntimeDefault: false;
|
|
4818
|
+
enumValues: undefined;
|
|
4819
|
+
identity: undefined;
|
|
4820
|
+
generated: undefined;
|
|
4821
|
+
}>;
|
|
4822
|
+
userId: drizzle_orm_pg_core.PgBuildColumn<"user_permissions", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBigInt53Builder>, {
|
|
4823
|
+
name: string;
|
|
4824
|
+
tableName: "user_permissions";
|
|
4825
|
+
dataType: "number int53";
|
|
4826
|
+
data: number;
|
|
4827
|
+
driverParam: string | number;
|
|
4828
|
+
notNull: true;
|
|
4829
|
+
hasDefault: false;
|
|
4830
|
+
isPrimaryKey: false;
|
|
4831
|
+
isAutoincrement: false;
|
|
4832
|
+
hasRuntimeDefault: false;
|
|
4833
|
+
enumValues: undefined;
|
|
4834
|
+
identity: undefined;
|
|
4835
|
+
generated: undefined;
|
|
4836
|
+
}>;
|
|
4837
|
+
permissionId: drizzle_orm_pg_core.PgBuildColumn<"user_permissions", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBigInt53Builder>, {
|
|
4838
|
+
name: string;
|
|
4839
|
+
tableName: "user_permissions";
|
|
4840
|
+
dataType: "number int53";
|
|
4841
|
+
data: number;
|
|
4842
|
+
driverParam: string | number;
|
|
4843
|
+
notNull: true;
|
|
4844
|
+
hasDefault: false;
|
|
4845
|
+
isPrimaryKey: false;
|
|
4846
|
+
isAutoincrement: false;
|
|
4847
|
+
hasRuntimeDefault: false;
|
|
4848
|
+
enumValues: undefined;
|
|
4849
|
+
identity: undefined;
|
|
4850
|
+
generated: undefined;
|
|
4851
|
+
}>;
|
|
4852
|
+
granted: drizzle_orm_pg_core.PgBuildColumn<"user_permissions", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBooleanBuilder>>, {
|
|
4853
|
+
name: string;
|
|
4854
|
+
tableName: "user_permissions";
|
|
4855
|
+
dataType: "boolean";
|
|
4856
|
+
data: boolean;
|
|
4857
|
+
driverParam: boolean;
|
|
4858
|
+
notNull: true;
|
|
4859
|
+
hasDefault: true;
|
|
4860
|
+
isPrimaryKey: false;
|
|
4861
|
+
isAutoincrement: false;
|
|
4862
|
+
hasRuntimeDefault: false;
|
|
4863
|
+
enumValues: undefined;
|
|
4864
|
+
identity: undefined;
|
|
4865
|
+
generated: undefined;
|
|
4866
|
+
}>;
|
|
4867
|
+
reason: drizzle_orm_pg_core.PgBuildColumn<"user_permissions", drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>, {
|
|
4868
|
+
name: string;
|
|
4869
|
+
tableName: "user_permissions";
|
|
4870
|
+
dataType: "string";
|
|
4871
|
+
data: string;
|
|
4872
|
+
driverParam: string;
|
|
4873
|
+
notNull: false;
|
|
4874
|
+
hasDefault: false;
|
|
4875
|
+
isPrimaryKey: false;
|
|
4876
|
+
isAutoincrement: false;
|
|
4877
|
+
hasRuntimeDefault: false;
|
|
4878
|
+
enumValues: undefined;
|
|
4879
|
+
identity: undefined;
|
|
4880
|
+
generated: undefined;
|
|
4881
|
+
}>;
|
|
4882
|
+
expiresAt: drizzle_orm_pg_core.PgBuildColumn<"user_permissions", drizzle_orm_pg_core.PgTimestampBuilder, {
|
|
4883
|
+
name: string;
|
|
4884
|
+
tableName: "user_permissions";
|
|
4885
|
+
dataType: "object date";
|
|
4886
|
+
data: Date;
|
|
4887
|
+
driverParam: string;
|
|
4888
|
+
notNull: false;
|
|
4889
|
+
hasDefault: false;
|
|
4890
|
+
isPrimaryKey: false;
|
|
4891
|
+
isAutoincrement: false;
|
|
4892
|
+
hasRuntimeDefault: false;
|
|
4893
|
+
enumValues: undefined;
|
|
4894
|
+
identity: undefined;
|
|
4895
|
+
generated: undefined;
|
|
4896
|
+
}>;
|
|
4897
|
+
};
|
|
4898
|
+
dialect: "pg";
|
|
4899
|
+
}>;
|
|
4900
|
+
type UserPermission = typeof userPermissions.$inferSelect;
|
|
4901
|
+
type NewUserPermission = typeof userPermissions.$inferInsert;
|
|
4902
|
+
|
|
4903
|
+
/**
|
|
4904
|
+
* @spfn/auth - OAuth 2.1 Clients Entity
|
|
4905
|
+
*
|
|
4906
|
+
* One row per public client that registered itself through RFC 7591 dynamic
|
|
4907
|
+
* client registration — a `claude mcp add` on somebody's laptop, a `codex`
|
|
4908
|
+
* install, a second copy of either on the same machine. There is no secret
|
|
4909
|
+
* column because there is no secret: these clients run on the user's own
|
|
4910
|
+
* device, cannot keep one, and authenticate with `token_endpoint_auth_method:
|
|
4911
|
+
* "none"` plus PKCE.
|
|
4912
|
+
*
|
|
4913
|
+
* `oauth2_` and not `oauth_`: the `oauth` prefix in this package belongs to the
|
|
4914
|
+
* social-login client we are on the other side of (Google, Kakao). Everything
|
|
4915
|
+
* named `oauth2` here is the authorization server we run.
|
|
4916
|
+
*
|
|
4917
|
+
* Registration is unauthenticated by definition, so a row here is nothing but a
|
|
4918
|
+
* claim until a user approves it. `auth.oauth2.client-purge` deletes the rows
|
|
4919
|
+
* that never were: a client older than a day with no grant against it.
|
|
4920
|
+
*/
|
|
4921
|
+
declare const oauth2Clients: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
4922
|
+
name: "oauth2_clients";
|
|
4923
|
+
schema: string;
|
|
4924
|
+
columns: {
|
|
4925
|
+
createdAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_clients", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>, {
|
|
4926
|
+
name: string;
|
|
4927
|
+
tableName: "oauth2_clients";
|
|
4928
|
+
dataType: "object date";
|
|
4929
|
+
data: Date;
|
|
4930
|
+
driverParam: string;
|
|
4931
|
+
notNull: true;
|
|
4932
|
+
hasDefault: true;
|
|
4933
|
+
isPrimaryKey: false;
|
|
4934
|
+
isAutoincrement: false;
|
|
4935
|
+
hasRuntimeDefault: false;
|
|
4936
|
+
enumValues: undefined;
|
|
4937
|
+
identity: undefined;
|
|
4938
|
+
generated: undefined;
|
|
4939
|
+
}>;
|
|
4940
|
+
updatedAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_clients", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>>, {
|
|
4941
|
+
name: string;
|
|
4942
|
+
tableName: "oauth2_clients";
|
|
4943
|
+
dataType: "object date";
|
|
4944
|
+
data: Date;
|
|
4945
|
+
driverParam: string;
|
|
4946
|
+
notNull: true;
|
|
4947
|
+
hasDefault: true;
|
|
4948
|
+
isPrimaryKey: false;
|
|
4949
|
+
isAutoincrement: false;
|
|
4950
|
+
hasRuntimeDefault: false;
|
|
4951
|
+
enumValues: undefined;
|
|
4952
|
+
identity: undefined;
|
|
4953
|
+
generated: undefined;
|
|
4954
|
+
}>;
|
|
4955
|
+
id: drizzle_orm_pg_core.PgBuildColumn<"oauth2_clients", drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgBigSerial53Builder>, {
|
|
4956
|
+
name: string;
|
|
4957
|
+
tableName: "oauth2_clients";
|
|
4958
|
+
dataType: "number int53";
|
|
4959
|
+
data: number;
|
|
4960
|
+
driverParam: number;
|
|
4961
|
+
notNull: true;
|
|
4962
|
+
hasDefault: true;
|
|
4963
|
+
isPrimaryKey: false;
|
|
4964
|
+
isAutoincrement: false;
|
|
4965
|
+
hasRuntimeDefault: false;
|
|
4966
|
+
enumValues: undefined;
|
|
4967
|
+
identity: undefined;
|
|
4968
|
+
generated: undefined;
|
|
4969
|
+
}>;
|
|
4970
|
+
clientId: drizzle_orm_pg_core.PgBuildColumn<"oauth2_clients", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
|
|
4971
|
+
name: string;
|
|
4972
|
+
tableName: "oauth2_clients";
|
|
4973
|
+
dataType: "string";
|
|
4974
|
+
data: string;
|
|
4975
|
+
driverParam: string;
|
|
4976
|
+
notNull: true;
|
|
4977
|
+
hasDefault: false;
|
|
4978
|
+
isPrimaryKey: false;
|
|
4979
|
+
isAutoincrement: false;
|
|
4980
|
+
hasRuntimeDefault: false;
|
|
4981
|
+
enumValues: undefined;
|
|
4982
|
+
identity: undefined;
|
|
4983
|
+
generated: undefined;
|
|
4984
|
+
}>;
|
|
4985
|
+
clientName: drizzle_orm_pg_core.PgBuildColumn<"oauth2_clients", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
|
|
4986
|
+
name: string;
|
|
4987
|
+
tableName: "oauth2_clients";
|
|
4988
|
+
dataType: "string";
|
|
4989
|
+
data: string;
|
|
4990
|
+
driverParam: string;
|
|
4991
|
+
notNull: true;
|
|
4992
|
+
hasDefault: false;
|
|
4993
|
+
isPrimaryKey: false;
|
|
4994
|
+
isAutoincrement: false;
|
|
4995
|
+
hasRuntimeDefault: false;
|
|
4996
|
+
enumValues: undefined;
|
|
4997
|
+
identity: undefined;
|
|
4998
|
+
generated: undefined;
|
|
4999
|
+
}>;
|
|
5000
|
+
redirectUris: drizzle_orm_pg_core.PgBuildColumn<"oauth2_clients", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetDimensions<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>, 1>>, {
|
|
5001
|
+
name: string;
|
|
5002
|
+
tableName: "oauth2_clients";
|
|
5003
|
+
dataType: "string";
|
|
5004
|
+
data: string[];
|
|
5005
|
+
driverParam: string | string[];
|
|
5006
|
+
notNull: true;
|
|
5007
|
+
hasDefault: false;
|
|
5008
|
+
isPrimaryKey: false;
|
|
5009
|
+
isAutoincrement: false;
|
|
5010
|
+
hasRuntimeDefault: false;
|
|
5011
|
+
enumValues: undefined;
|
|
5012
|
+
identity: undefined;
|
|
5013
|
+
generated: undefined;
|
|
5014
|
+
}>;
|
|
5015
|
+
createdIp: drizzle_orm_pg_core.PgBuildColumn<"oauth2_clients", drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>, {
|
|
5016
|
+
name: string;
|
|
5017
|
+
tableName: "oauth2_clients";
|
|
5018
|
+
dataType: "string";
|
|
5019
|
+
data: string;
|
|
5020
|
+
driverParam: string;
|
|
5021
|
+
notNull: false;
|
|
5022
|
+
hasDefault: false;
|
|
5023
|
+
isPrimaryKey: false;
|
|
5024
|
+
isAutoincrement: false;
|
|
5025
|
+
hasRuntimeDefault: false;
|
|
5026
|
+
enumValues: undefined;
|
|
5027
|
+
identity: undefined;
|
|
5028
|
+
generated: undefined;
|
|
5029
|
+
}>;
|
|
5030
|
+
lastUsedAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_clients", drizzle_orm_pg_core.PgTimestampBuilder, {
|
|
5031
|
+
name: string;
|
|
5032
|
+
tableName: "oauth2_clients";
|
|
5033
|
+
dataType: "object date";
|
|
5034
|
+
data: Date;
|
|
5035
|
+
driverParam: string;
|
|
5036
|
+
notNull: false;
|
|
5037
|
+
hasDefault: false;
|
|
5038
|
+
isPrimaryKey: false;
|
|
5039
|
+
isAutoincrement: false;
|
|
5040
|
+
hasRuntimeDefault: false;
|
|
5041
|
+
enumValues: undefined;
|
|
5042
|
+
identity: undefined;
|
|
5043
|
+
generated: undefined;
|
|
5044
|
+
}>;
|
|
5045
|
+
};
|
|
5046
|
+
dialect: "pg";
|
|
5047
|
+
}>;
|
|
5048
|
+
type OAuth2Client = typeof oauth2Clients.$inferSelect;
|
|
5049
|
+
type NewOAuth2Client = typeof oauth2Clients.$inferInsert;
|
|
5050
|
+
|
|
5051
|
+
/**
|
|
5052
|
+
* @spfn/auth - OAuth 2.1 Grants Entity
|
|
5053
|
+
*
|
|
5054
|
+
* What a user actually consented to: this client, for this resource, with these
|
|
5055
|
+
* scopes. Codes and tokens all hang off a grant, so it is the one row that has
|
|
5056
|
+
* to be revoked to cut a CLI off — `GET /_auth/oauth2/grants` lists them and
|
|
5057
|
+
* `DELETE /_auth/oauth2/grants/:id` is the button.
|
|
5058
|
+
*
|
|
5059
|
+
* One row per (client, user, resource). Re-consenting updates `scopes` rather
|
|
5060
|
+
* than adding a second row, so a user who widens a CLI's access sees one entry
|
|
5061
|
+
* for it and not a pile of them, and revoking that entry revokes everything the
|
|
5062
|
+
* client holds.
|
|
5063
|
+
*
|
|
5064
|
+
* A global revocation — revoke-all, a password change, a password reset, a
|
|
5065
|
+
* deletion request — revokes every grant the user has, for the reason device
|
|
5066
|
+
* codes are refused in the same breath: a live grant still has a refresh token
|
|
5067
|
+
* against it, and "sign me out everywhere" that leaves one alive has not.
|
|
5068
|
+
*/
|
|
5069
|
+
declare const oauth2Grants: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
5070
|
+
name: "oauth2_grants";
|
|
5071
|
+
schema: string;
|
|
5072
|
+
columns: {
|
|
5073
|
+
createdAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_grants", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>, {
|
|
5074
|
+
name: string;
|
|
5075
|
+
tableName: "oauth2_grants";
|
|
5076
|
+
dataType: "object date";
|
|
5077
|
+
data: Date;
|
|
5078
|
+
driverParam: string;
|
|
5079
|
+
notNull: true;
|
|
5080
|
+
hasDefault: true;
|
|
5081
|
+
isPrimaryKey: false;
|
|
5082
|
+
isAutoincrement: false;
|
|
5083
|
+
hasRuntimeDefault: false;
|
|
5084
|
+
enumValues: undefined;
|
|
5085
|
+
identity: undefined;
|
|
5086
|
+
generated: undefined;
|
|
5087
|
+
}>;
|
|
5088
|
+
updatedAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_grants", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>>, {
|
|
5089
|
+
name: string;
|
|
5090
|
+
tableName: "oauth2_grants";
|
|
5091
|
+
dataType: "object date";
|
|
5092
|
+
data: Date;
|
|
5093
|
+
driverParam: string;
|
|
5094
|
+
notNull: true;
|
|
5095
|
+
hasDefault: true;
|
|
5096
|
+
isPrimaryKey: false;
|
|
5097
|
+
isAutoincrement: false;
|
|
5098
|
+
hasRuntimeDefault: false;
|
|
5099
|
+
enumValues: undefined;
|
|
5100
|
+
identity: undefined;
|
|
5101
|
+
generated: undefined;
|
|
5102
|
+
}>;
|
|
5103
|
+
id: drizzle_orm_pg_core.PgBuildColumn<"oauth2_grants", drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgBigSerial53Builder>, {
|
|
5104
|
+
name: string;
|
|
5105
|
+
tableName: "oauth2_grants";
|
|
5106
|
+
dataType: "number int53";
|
|
5107
|
+
data: number;
|
|
5108
|
+
driverParam: number;
|
|
5109
|
+
notNull: true;
|
|
5110
|
+
hasDefault: true;
|
|
5111
|
+
isPrimaryKey: false;
|
|
5112
|
+
isAutoincrement: false;
|
|
5113
|
+
hasRuntimeDefault: false;
|
|
5114
|
+
enumValues: undefined;
|
|
5115
|
+
identity: undefined;
|
|
5116
|
+
generated: undefined;
|
|
5117
|
+
}>;
|
|
5118
|
+
client: drizzle_orm_pg_core.PgBuildColumn<"oauth2_grants", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBigInt53Builder>, {
|
|
5119
|
+
name: string;
|
|
5120
|
+
tableName: "oauth2_grants";
|
|
5121
|
+
dataType: "number int53";
|
|
5122
|
+
data: number;
|
|
5123
|
+
driverParam: string | number;
|
|
5124
|
+
notNull: true;
|
|
5125
|
+
hasDefault: false;
|
|
5126
|
+
isPrimaryKey: false;
|
|
5127
|
+
isAutoincrement: false;
|
|
5128
|
+
hasRuntimeDefault: false;
|
|
5129
|
+
enumValues: undefined;
|
|
5130
|
+
identity: undefined;
|
|
5131
|
+
generated: undefined;
|
|
5132
|
+
}>;
|
|
5133
|
+
user: drizzle_orm_pg_core.PgBuildColumn<"oauth2_grants", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBigInt53Builder>, {
|
|
5134
|
+
name: string;
|
|
5135
|
+
tableName: "oauth2_grants";
|
|
5136
|
+
dataType: "number int53";
|
|
5137
|
+
data: number;
|
|
5138
|
+
driverParam: string | number;
|
|
5139
|
+
notNull: true;
|
|
5140
|
+
hasDefault: false;
|
|
5141
|
+
isPrimaryKey: false;
|
|
5142
|
+
isAutoincrement: false;
|
|
5143
|
+
hasRuntimeDefault: false;
|
|
5144
|
+
enumValues: undefined;
|
|
5145
|
+
identity: undefined;
|
|
5146
|
+
generated: undefined;
|
|
5147
|
+
}>;
|
|
5148
|
+
resource: drizzle_orm_pg_core.PgBuildColumn<"oauth2_grants", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
|
|
5149
|
+
name: string;
|
|
5150
|
+
tableName: "oauth2_grants";
|
|
5151
|
+
dataType: "string";
|
|
5152
|
+
data: string;
|
|
5153
|
+
driverParam: string;
|
|
5154
|
+
notNull: true;
|
|
5155
|
+
hasDefault: false;
|
|
5156
|
+
isPrimaryKey: false;
|
|
5157
|
+
isAutoincrement: false;
|
|
5158
|
+
hasRuntimeDefault: false;
|
|
5159
|
+
enumValues: undefined;
|
|
5160
|
+
identity: undefined;
|
|
5161
|
+
generated: undefined;
|
|
5162
|
+
}>;
|
|
5163
|
+
scopes: drizzle_orm_pg_core.PgBuildColumn<"oauth2_grants", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetDimensions<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>, 1>>, {
|
|
5164
|
+
name: string;
|
|
5165
|
+
tableName: "oauth2_grants";
|
|
5166
|
+
dataType: "string";
|
|
5167
|
+
data: string[];
|
|
5168
|
+
driverParam: string | string[];
|
|
5169
|
+
notNull: true;
|
|
5170
|
+
hasDefault: false;
|
|
5171
|
+
isPrimaryKey: false;
|
|
5172
|
+
isAutoincrement: false;
|
|
5173
|
+
hasRuntimeDefault: false;
|
|
5174
|
+
enumValues: undefined;
|
|
5175
|
+
identity: undefined;
|
|
5176
|
+
generated: undefined;
|
|
5177
|
+
}>;
|
|
5178
|
+
revokedAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_grants", drizzle_orm_pg_core.PgTimestampBuilder, {
|
|
5179
|
+
name: string;
|
|
5180
|
+
tableName: "oauth2_grants";
|
|
5181
|
+
dataType: "object date";
|
|
5182
|
+
data: Date;
|
|
5183
|
+
driverParam: string;
|
|
5184
|
+
notNull: false;
|
|
5185
|
+
hasDefault: false;
|
|
5186
|
+
isPrimaryKey: false;
|
|
5187
|
+
isAutoincrement: false;
|
|
5188
|
+
hasRuntimeDefault: false;
|
|
5189
|
+
enumValues: undefined;
|
|
5190
|
+
identity: undefined;
|
|
5191
|
+
generated: undefined;
|
|
5192
|
+
}>;
|
|
5193
|
+
};
|
|
5194
|
+
dialect: "pg";
|
|
5195
|
+
}>;
|
|
5196
|
+
type OAuth2Grant = typeof oauth2Grants.$inferSelect;
|
|
5197
|
+
type NewOAuth2Grant = typeof oauth2Grants.$inferInsert;
|
|
5198
|
+
|
|
5199
|
+
/**
|
|
5200
|
+
* @spfn/auth - OAuth 2.1 Authorization Codes Entity
|
|
5201
|
+
*
|
|
5202
|
+
* The 60-second, single-use ticket the consent screen hands back through the
|
|
5203
|
+
* client's own loopback listener, exchanged at the token endpoint for tokens.
|
|
5204
|
+
*
|
|
5205
|
+
* Only the SHA-256 hash is stored, as with device codes, ops tokens and signup
|
|
5206
|
+
* links: a dump of this table must not let its reader finish somebody's
|
|
5207
|
+
* authorization. The unique constraint on the hash doubles as the lookup index.
|
|
5208
|
+
*
|
|
5209
|
+
* `usedAt` is written by the same statement that reads the row, so of two token
|
|
5210
|
+
* requests arriving together exactly one gets tokens. A code presented twice is
|
|
5211
|
+
* the signature of a stolen code, and the second presentation revokes the whole
|
|
5212
|
+
* grant rather than merely refusing — by then the thief may already hold what
|
|
5213
|
+
* the first exchange produced.
|
|
5214
|
+
*/
|
|
5215
|
+
declare const oauth2AuthorizationCodes: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
5216
|
+
name: "oauth2_authorization_codes";
|
|
5217
|
+
schema: string;
|
|
5218
|
+
columns: {
|
|
5219
|
+
createdAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_authorization_codes", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>, {
|
|
5220
|
+
name: string;
|
|
5221
|
+
tableName: "oauth2_authorization_codes";
|
|
5222
|
+
dataType: "object date";
|
|
5223
|
+
data: Date;
|
|
5224
|
+
driverParam: string;
|
|
5225
|
+
notNull: true;
|
|
5226
|
+
hasDefault: true;
|
|
5227
|
+
isPrimaryKey: false;
|
|
5228
|
+
isAutoincrement: false;
|
|
5229
|
+
hasRuntimeDefault: false;
|
|
5230
|
+
enumValues: undefined;
|
|
5231
|
+
identity: undefined;
|
|
5232
|
+
generated: undefined;
|
|
5233
|
+
}>;
|
|
5234
|
+
updatedAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_authorization_codes", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>>, {
|
|
5235
|
+
name: string;
|
|
5236
|
+
tableName: "oauth2_authorization_codes";
|
|
5237
|
+
dataType: "object date";
|
|
5238
|
+
data: Date;
|
|
5239
|
+
driverParam: string;
|
|
5240
|
+
notNull: true;
|
|
5241
|
+
hasDefault: true;
|
|
5242
|
+
isPrimaryKey: false;
|
|
5243
|
+
isAutoincrement: false;
|
|
5244
|
+
hasRuntimeDefault: false;
|
|
5245
|
+
enumValues: undefined;
|
|
5246
|
+
identity: undefined;
|
|
5247
|
+
generated: undefined;
|
|
5248
|
+
}>;
|
|
5249
|
+
id: drizzle_orm_pg_core.PgBuildColumn<"oauth2_authorization_codes", drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgBigSerial53Builder>, {
|
|
5250
|
+
name: string;
|
|
5251
|
+
tableName: "oauth2_authorization_codes";
|
|
5252
|
+
dataType: "number int53";
|
|
5253
|
+
data: number;
|
|
5254
|
+
driverParam: number;
|
|
5255
|
+
notNull: true;
|
|
5256
|
+
hasDefault: true;
|
|
5257
|
+
isPrimaryKey: false;
|
|
5258
|
+
isAutoincrement: false;
|
|
5259
|
+
hasRuntimeDefault: false;
|
|
5260
|
+
enumValues: undefined;
|
|
5261
|
+
identity: undefined;
|
|
5262
|
+
generated: undefined;
|
|
5263
|
+
}>;
|
|
5264
|
+
codeHash: drizzle_orm_pg_core.PgBuildColumn<"oauth2_authorization_codes", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
|
|
5265
|
+
name: string;
|
|
5266
|
+
tableName: "oauth2_authorization_codes";
|
|
5267
|
+
dataType: "string";
|
|
5268
|
+
data: string;
|
|
5269
|
+
driverParam: string;
|
|
5270
|
+
notNull: true;
|
|
5271
|
+
hasDefault: false;
|
|
5272
|
+
isPrimaryKey: false;
|
|
5273
|
+
isAutoincrement: false;
|
|
5274
|
+
hasRuntimeDefault: false;
|
|
5275
|
+
enumValues: undefined;
|
|
5276
|
+
identity: undefined;
|
|
5277
|
+
generated: undefined;
|
|
5278
|
+
}>;
|
|
5279
|
+
grant: drizzle_orm_pg_core.PgBuildColumn<"oauth2_authorization_codes", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBigInt53Builder>, {
|
|
5280
|
+
name: string;
|
|
5281
|
+
tableName: "oauth2_authorization_codes";
|
|
5282
|
+
dataType: "number int53";
|
|
5283
|
+
data: number;
|
|
5284
|
+
driverParam: string | number;
|
|
5285
|
+
notNull: true;
|
|
5286
|
+
hasDefault: false;
|
|
5287
|
+
isPrimaryKey: false;
|
|
5288
|
+
isAutoincrement: false;
|
|
5289
|
+
hasRuntimeDefault: false;
|
|
5290
|
+
enumValues: undefined;
|
|
5291
|
+
identity: undefined;
|
|
5292
|
+
generated: undefined;
|
|
5293
|
+
}>;
|
|
5294
|
+
redirectUri: drizzle_orm_pg_core.PgBuildColumn<"oauth2_authorization_codes", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
|
|
5295
|
+
name: string;
|
|
5296
|
+
tableName: "oauth2_authorization_codes";
|
|
5297
|
+
dataType: "string";
|
|
5298
|
+
data: string;
|
|
5299
|
+
driverParam: string;
|
|
5300
|
+
notNull: true;
|
|
5301
|
+
hasDefault: false;
|
|
5302
|
+
isPrimaryKey: false;
|
|
5303
|
+
isAutoincrement: false;
|
|
5304
|
+
hasRuntimeDefault: false;
|
|
5305
|
+
enumValues: undefined;
|
|
5306
|
+
identity: undefined;
|
|
5307
|
+
generated: undefined;
|
|
5308
|
+
}>;
|
|
5309
|
+
codeChallenge: drizzle_orm_pg_core.PgBuildColumn<"oauth2_authorization_codes", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
|
|
5310
|
+
name: string;
|
|
5311
|
+
tableName: "oauth2_authorization_codes";
|
|
5312
|
+
dataType: "string";
|
|
5313
|
+
data: string;
|
|
5314
|
+
driverParam: string;
|
|
5315
|
+
notNull: true;
|
|
5316
|
+
hasDefault: false;
|
|
5317
|
+
isPrimaryKey: false;
|
|
5318
|
+
isAutoincrement: false;
|
|
5319
|
+
hasRuntimeDefault: false;
|
|
5320
|
+
enumValues: undefined;
|
|
5321
|
+
identity: undefined;
|
|
5322
|
+
generated: undefined;
|
|
5323
|
+
}>;
|
|
5324
|
+
expiresAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_authorization_codes", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>, {
|
|
5325
|
+
name: string;
|
|
5326
|
+
tableName: "oauth2_authorization_codes";
|
|
5327
|
+
dataType: "object date";
|
|
5328
|
+
data: Date;
|
|
5329
|
+
driverParam: string;
|
|
5330
|
+
notNull: true;
|
|
5331
|
+
hasDefault: false;
|
|
5332
|
+
isPrimaryKey: false;
|
|
5333
|
+
isAutoincrement: false;
|
|
5334
|
+
hasRuntimeDefault: false;
|
|
5335
|
+
enumValues: undefined;
|
|
5336
|
+
identity: undefined;
|
|
5337
|
+
generated: undefined;
|
|
5338
|
+
}>;
|
|
5339
|
+
usedAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_authorization_codes", drizzle_orm_pg_core.PgTimestampBuilder, {
|
|
4518
5340
|
name: string;
|
|
4519
|
-
tableName: "
|
|
4520
|
-
dataType: "
|
|
4521
|
-
data:
|
|
4522
|
-
driverParam: string
|
|
4523
|
-
notNull:
|
|
5341
|
+
tableName: "oauth2_authorization_codes";
|
|
5342
|
+
dataType: "object date";
|
|
5343
|
+
data: Date;
|
|
5344
|
+
driverParam: string;
|
|
5345
|
+
notNull: false;
|
|
4524
5346
|
hasDefault: false;
|
|
4525
5347
|
isPrimaryKey: false;
|
|
4526
5348
|
isAutoincrement: false;
|
|
@@ -4532,30 +5354,44 @@ declare const rolePermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
4532
5354
|
};
|
|
4533
5355
|
dialect: "pg";
|
|
4534
5356
|
}>;
|
|
4535
|
-
type
|
|
4536
|
-
type
|
|
5357
|
+
type OAuth2AuthorizationCode = typeof oauth2AuthorizationCodes.$inferSelect;
|
|
5358
|
+
type NewOAuth2AuthorizationCode = typeof oauth2AuthorizationCodes.$inferInsert;
|
|
4537
5359
|
|
|
4538
5360
|
/**
|
|
4539
|
-
* @spfn/auth -
|
|
5361
|
+
* @spfn/auth - OAuth 2.1 Tokens Entity
|
|
4540
5362
|
*
|
|
4541
|
-
*
|
|
5363
|
+
* Access and refresh tokens alike, one row each, distinguished by `kind`. Both
|
|
5364
|
+
* are opaque — `spfn_at_<64 hex>` and `spfn_rt_<64 hex>` — because whatever
|
|
5365
|
+
* verifies them is in the same process as this table, which is the same reason
|
|
5366
|
+
* ops tokens, device codes and signup links are opaque. A JWT would buy
|
|
5367
|
+
* stateless verification and pay for it by making revocation take effect only
|
|
5368
|
+
* at expiry, and revocation here is a button the user presses.
|
|
4542
5369
|
*
|
|
4543
|
-
*
|
|
4544
|
-
*
|
|
4545
|
-
* - Revoke role-inherited permissions from specific users
|
|
4546
|
-
* - Temporary permissions with expiration
|
|
4547
|
-
* - Audit trail with reason field
|
|
5370
|
+
* Only the SHA-256 hash is stored. The value exists in the clear exactly once,
|
|
5371
|
+
* in the token response.
|
|
4548
5372
|
*
|
|
4549
|
-
*
|
|
4550
|
-
*
|
|
5373
|
+
* `replacedAt` is what makes refresh rotation detectable: a rotated refresh is
|
|
5374
|
+
* not deleted, it is marked, so presenting it again is distinguishable from
|
|
5375
|
+
* presenting one that never existed. That presentation means the token leaked —
|
|
5376
|
+
* either the client or the thief is replaying — and the answer is to revoke the
|
|
5377
|
+
* grant, which kills the replacement as well.
|
|
4551
5378
|
*/
|
|
4552
|
-
|
|
4553
|
-
|
|
5379
|
+
/**
|
|
5380
|
+
* Which half of the pair a row is.
|
|
5381
|
+
*
|
|
5382
|
+
* One table rather than two: every rule that matters — revoked, expired, whose
|
|
5383
|
+
* grant, which scopes — is the same for both, and a single `kind` column keeps
|
|
5384
|
+
* "revoke everything under this grant" one statement.
|
|
5385
|
+
*/
|
|
5386
|
+
declare const OAUTH2_TOKEN_KINDS: readonly ["access", "refresh"];
|
|
5387
|
+
type OAuth2TokenKind = typeof OAUTH2_TOKEN_KINDS[number];
|
|
5388
|
+
declare const oauth2Tokens: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
5389
|
+
name: "oauth2_tokens";
|
|
4554
5390
|
schema: string;
|
|
4555
5391
|
columns: {
|
|
4556
|
-
createdAt: drizzle_orm_pg_core.PgBuildColumn<"
|
|
5392
|
+
createdAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>, {
|
|
4557
5393
|
name: string;
|
|
4558
|
-
tableName: "
|
|
5394
|
+
tableName: "oauth2_tokens";
|
|
4559
5395
|
dataType: "object date";
|
|
4560
5396
|
data: Date;
|
|
4561
5397
|
driverParam: string;
|
|
@@ -4568,9 +5404,9 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
4568
5404
|
identity: undefined;
|
|
4569
5405
|
generated: undefined;
|
|
4570
5406
|
}>;
|
|
4571
|
-
updatedAt: drizzle_orm_pg_core.PgBuildColumn<"
|
|
5407
|
+
updatedAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>>, {
|
|
4572
5408
|
name: string;
|
|
4573
|
-
tableName: "
|
|
5409
|
+
tableName: "oauth2_tokens";
|
|
4574
5410
|
dataType: "object date";
|
|
4575
5411
|
data: Date;
|
|
4576
5412
|
driverParam: string;
|
|
@@ -4583,9 +5419,9 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
4583
5419
|
identity: undefined;
|
|
4584
5420
|
generated: undefined;
|
|
4585
5421
|
}>;
|
|
4586
|
-
id: drizzle_orm_pg_core.PgBuildColumn<"
|
|
5422
|
+
id: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgBigSerial53Builder>, {
|
|
4587
5423
|
name: string;
|
|
4588
|
-
tableName: "
|
|
5424
|
+
tableName: "oauth2_tokens";
|
|
4589
5425
|
dataType: "number int53";
|
|
4590
5426
|
data: number;
|
|
4591
5427
|
driverParam: number;
|
|
@@ -4598,12 +5434,12 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
4598
5434
|
identity: undefined;
|
|
4599
5435
|
generated: undefined;
|
|
4600
5436
|
}>;
|
|
4601
|
-
|
|
5437
|
+
tokenHash: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
|
|
4602
5438
|
name: string;
|
|
4603
|
-
tableName: "
|
|
4604
|
-
dataType: "
|
|
4605
|
-
data:
|
|
4606
|
-
driverParam: string
|
|
5439
|
+
tableName: "oauth2_tokens";
|
|
5440
|
+
dataType: "string";
|
|
5441
|
+
data: string;
|
|
5442
|
+
driverParam: string;
|
|
4607
5443
|
notNull: true;
|
|
4608
5444
|
hasDefault: false;
|
|
4609
5445
|
isPrimaryKey: false;
|
|
@@ -4613,9 +5449,24 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
4613
5449
|
identity: undefined;
|
|
4614
5450
|
generated: undefined;
|
|
4615
5451
|
}>;
|
|
4616
|
-
|
|
5452
|
+
kind: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<["access", "refresh"] & [string, ...string[]]>>, {
|
|
4617
5453
|
name: string;
|
|
4618
|
-
tableName: "
|
|
5454
|
+
tableName: "oauth2_tokens";
|
|
5455
|
+
dataType: "string enum";
|
|
5456
|
+
data: "access" | "refresh";
|
|
5457
|
+
driverParam: string;
|
|
5458
|
+
notNull: true;
|
|
5459
|
+
hasDefault: false;
|
|
5460
|
+
isPrimaryKey: false;
|
|
5461
|
+
isAutoincrement: false;
|
|
5462
|
+
hasRuntimeDefault: false;
|
|
5463
|
+
enumValues: ["access", "refresh"] & [string, ...string[]];
|
|
5464
|
+
identity: undefined;
|
|
5465
|
+
generated: undefined;
|
|
5466
|
+
}>;
|
|
5467
|
+
grant: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBigInt53Builder>, {
|
|
5468
|
+
name: string;
|
|
5469
|
+
tableName: "oauth2_tokens";
|
|
4619
5470
|
dataType: "number int53";
|
|
4620
5471
|
data: number;
|
|
4621
5472
|
driverParam: string | number;
|
|
@@ -4628,14 +5479,14 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
4628
5479
|
identity: undefined;
|
|
4629
5480
|
generated: undefined;
|
|
4630
5481
|
}>;
|
|
4631
|
-
|
|
5482
|
+
scopes: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetDimensions<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>, 1>>, {
|
|
4632
5483
|
name: string;
|
|
4633
|
-
tableName: "
|
|
4634
|
-
dataType: "
|
|
4635
|
-
data:
|
|
4636
|
-
driverParam:
|
|
5484
|
+
tableName: "oauth2_tokens";
|
|
5485
|
+
dataType: "string";
|
|
5486
|
+
data: string[];
|
|
5487
|
+
driverParam: string | string[];
|
|
4637
5488
|
notNull: true;
|
|
4638
|
-
hasDefault:
|
|
5489
|
+
hasDefault: false;
|
|
4639
5490
|
isPrimaryKey: false;
|
|
4640
5491
|
isAutoincrement: false;
|
|
4641
5492
|
hasRuntimeDefault: false;
|
|
@@ -4643,11 +5494,26 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
4643
5494
|
identity: undefined;
|
|
4644
5495
|
generated: undefined;
|
|
4645
5496
|
}>;
|
|
4646
|
-
|
|
5497
|
+
expiresAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>, {
|
|
4647
5498
|
name: string;
|
|
4648
|
-
tableName: "
|
|
4649
|
-
dataType: "
|
|
4650
|
-
data:
|
|
5499
|
+
tableName: "oauth2_tokens";
|
|
5500
|
+
dataType: "object date";
|
|
5501
|
+
data: Date;
|
|
5502
|
+
driverParam: string;
|
|
5503
|
+
notNull: true;
|
|
5504
|
+
hasDefault: false;
|
|
5505
|
+
isPrimaryKey: false;
|
|
5506
|
+
isAutoincrement: false;
|
|
5507
|
+
hasRuntimeDefault: false;
|
|
5508
|
+
enumValues: undefined;
|
|
5509
|
+
identity: undefined;
|
|
5510
|
+
generated: undefined;
|
|
5511
|
+
}>;
|
|
5512
|
+
revokedAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.PgTimestampBuilder, {
|
|
5513
|
+
name: string;
|
|
5514
|
+
tableName: "oauth2_tokens";
|
|
5515
|
+
dataType: "object date";
|
|
5516
|
+
data: Date;
|
|
4651
5517
|
driverParam: string;
|
|
4652
5518
|
notNull: false;
|
|
4653
5519
|
hasDefault: false;
|
|
@@ -4658,9 +5524,24 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
4658
5524
|
identity: undefined;
|
|
4659
5525
|
generated: undefined;
|
|
4660
5526
|
}>;
|
|
4661
|
-
|
|
5527
|
+
replacedAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.PgTimestampBuilder, {
|
|
4662
5528
|
name: string;
|
|
4663
|
-
tableName: "
|
|
5529
|
+
tableName: "oauth2_tokens";
|
|
5530
|
+
dataType: "object date";
|
|
5531
|
+
data: Date;
|
|
5532
|
+
driverParam: string;
|
|
5533
|
+
notNull: false;
|
|
5534
|
+
hasDefault: false;
|
|
5535
|
+
isPrimaryKey: false;
|
|
5536
|
+
isAutoincrement: false;
|
|
5537
|
+
hasRuntimeDefault: false;
|
|
5538
|
+
enumValues: undefined;
|
|
5539
|
+
identity: undefined;
|
|
5540
|
+
generated: undefined;
|
|
5541
|
+
}>;
|
|
5542
|
+
lastUsedAt: drizzle_orm_pg_core.PgBuildColumn<"oauth2_tokens", drizzle_orm_pg_core.PgTimestampBuilder, {
|
|
5543
|
+
name: string;
|
|
5544
|
+
tableName: "oauth2_tokens";
|
|
4664
5545
|
dataType: "object date";
|
|
4665
5546
|
data: Date;
|
|
4666
5547
|
driverParam: string;
|
|
@@ -4676,8 +5557,8 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
4676
5557
|
};
|
|
4677
5558
|
dialect: "pg";
|
|
4678
5559
|
}>;
|
|
4679
|
-
type
|
|
4680
|
-
type
|
|
5560
|
+
type OAuth2Token = typeof oauth2Tokens.$inferSelect;
|
|
5561
|
+
type NewOAuth2Token = typeof oauth2Tokens.$inferInsert;
|
|
4681
5562
|
|
|
4682
5563
|
/**
|
|
4683
5564
|
* @spfn/auth - Auth Metadata Entity
|
|
@@ -7369,6 +8250,242 @@ declare class OpsTokensRepository extends BaseRepository {
|
|
|
7369
8250
|
}
|
|
7370
8251
|
declare const opsTokensRepository: OpsTokensRepository;
|
|
7371
8252
|
|
|
8253
|
+
/**
|
|
8254
|
+
* OAuth 2.1 Clients Repository
|
|
8255
|
+
*
|
|
8256
|
+
* Data access for dynamically registered public clients. Extends BaseRepository
|
|
8257
|
+
* for transaction context and read/write splitting like every other auth
|
|
8258
|
+
* repository.
|
|
8259
|
+
*/
|
|
8260
|
+
|
|
8261
|
+
declare class OAuth2ClientsRepository extends BaseRepository {
|
|
8262
|
+
create(data: NewOAuth2Client): Promise<OAuth2Client>;
|
|
8263
|
+
/**
|
|
8264
|
+
* Lookup by the public `client_id` — the authorize and token paths.
|
|
8265
|
+
*
|
|
8266
|
+
* Reads the primary, not the replica, for the reason the ops-token lookup
|
|
8267
|
+
* does: a client registered a moment ago is immediately used, and a replica
|
|
8268
|
+
* read would answer "unknown client" for the length of the replication lag,
|
|
8269
|
+
* at the one moment a CLI is being connected.
|
|
8270
|
+
*/
|
|
8271
|
+
findByClientId(clientId: string): Promise<OAuth2Client | null>;
|
|
8272
|
+
/** Fire-and-forget from the token-issuing path. */
|
|
8273
|
+
updateLastUsedById(id: number): Promise<void>;
|
|
8274
|
+
/**
|
|
8275
|
+
* Register a client unless this address is already at its standing cap.
|
|
8276
|
+
*
|
|
8277
|
+
* The count and the insert are one transaction whose first statement takes
|
|
8278
|
+
* an advisory lock on the address, and all three parts are load-bearing.
|
|
8279
|
+
* Counting on the replica lets replication lag hand out slots that are
|
|
8280
|
+
* already taken. Counting and inserting in two statements lets a second
|
|
8281
|
+
* registration read the same total between them. And a transaction alone
|
|
8282
|
+
* does not close that: under READ COMMITTED each concurrent transaction
|
|
8283
|
+
* counts the rows the others have not committed yet, so twenty requests
|
|
8284
|
+
* arriving together all see zero. The lock is the only part that makes the
|
|
8285
|
+
* cap a number rather than an average, and it is per address, so it costs
|
|
8286
|
+
* nobody else anything.
|
|
8287
|
+
*
|
|
8288
|
+
* @param data - The row to write when there is room for it
|
|
8289
|
+
* @param limit - The address, its cap, and how far back the cap looks
|
|
8290
|
+
* @returns the registered client, or null when the address is at its cap
|
|
8291
|
+
*/
|
|
8292
|
+
createWithinStandingCap(data: NewOAuth2Client, limit: {
|
|
8293
|
+
ip: string;
|
|
8294
|
+
max: number;
|
|
8295
|
+
windowMs: number;
|
|
8296
|
+
}): Promise<OAuth2Client | null>;
|
|
8297
|
+
/**
|
|
8298
|
+
* How many clients this IP registered within the window that nobody has
|
|
8299
|
+
* approved yet.
|
|
8300
|
+
*
|
|
8301
|
+
* The window is what makes this a standing-population cap rather than a
|
|
8302
|
+
* permanent quota. Rows are only freed by the purge job, which sweeps once
|
|
8303
|
+
* a day against a 24-hour threshold — so without a window a row registered
|
|
8304
|
+
* a minute after one sweep holds its slot for nearly two days, and twenty
|
|
8305
|
+
* developers behind one NAT lock their whole office out of registering.
|
|
8306
|
+
* A grant against the client takes it out of the count at any age: a client
|
|
8307
|
+
* somebody approved is not junk.
|
|
8308
|
+
*
|
|
8309
|
+
* Reads the primary, inside the caller's transaction, for the reason
|
|
8310
|
+
* `findByClientId` does — a row written a moment ago is exactly the row this
|
|
8311
|
+
* count exists to see.
|
|
8312
|
+
*/
|
|
8313
|
+
private countRecentUngrantedByIp;
|
|
8314
|
+
/**
|
|
8315
|
+
* Delete clients older than `before` that no user ever approved.
|
|
8316
|
+
*
|
|
8317
|
+
* A registration is an unauthenticated write, so the table fills with rows
|
|
8318
|
+
* from installs that were abandoned at the consent screen. A row with a
|
|
8319
|
+
* grant against it is never touched, whatever its age — that is somebody's
|
|
8320
|
+
* connected CLI.
|
|
8321
|
+
*
|
|
8322
|
+
* @returns how many rows this sweep removed
|
|
8323
|
+
*/
|
|
8324
|
+
deleteStaleUngranted(before: Date): Promise<number>;
|
|
8325
|
+
}
|
|
8326
|
+
declare const oauth2ClientsRepository: OAuth2ClientsRepository;
|
|
8327
|
+
|
|
8328
|
+
/**
|
|
8329
|
+
* OAuth 2.1 Grants Repository
|
|
8330
|
+
*
|
|
8331
|
+
* Data access for the consent records every code and token hangs off.
|
|
8332
|
+
*
|
|
8333
|
+
* Revocation is the operation that matters here, and it is always one statement
|
|
8334
|
+
* per table rather than a read-then-write: a grant being revoked at the same
|
|
8335
|
+
* moment as a refresh rotation must not let the rotation's successor survive,
|
|
8336
|
+
* and `where revoked_at is null` in the UPDATE is what makes the two orderings
|
|
8337
|
+
* produce the same end state.
|
|
8338
|
+
*/
|
|
8339
|
+
|
|
8340
|
+
/** A grant with the client it belongs to — what every list and lookup needs. */
|
|
8341
|
+
interface OAuth2GrantWithClient {
|
|
8342
|
+
grant: OAuth2Grant;
|
|
8343
|
+
client: OAuth2Client;
|
|
8344
|
+
}
|
|
8345
|
+
declare class OAuth2GrantsRepository extends BaseRepository {
|
|
8346
|
+
/**
|
|
8347
|
+
* Record a consent, or refresh the scopes of the one already there.
|
|
8348
|
+
*
|
|
8349
|
+
* Re-consenting is an upsert and not an insert: the unique index on
|
|
8350
|
+
* (client, user, resource) says one consent per triple, and a user who
|
|
8351
|
+
* approves a wider scope set is amending the consent they already gave, not
|
|
8352
|
+
* giving a second one. Revoking the entry they can see must revoke
|
|
8353
|
+
* everything the client holds, which a second row would break.
|
|
8354
|
+
*
|
|
8355
|
+
* `revokedAt: null` in the update is deliberate — approving again after
|
|
8356
|
+
* revoking is how a user reconnects a CLI they cut off.
|
|
8357
|
+
*/
|
|
8358
|
+
upsert(data: NewOAuth2Grant): Promise<OAuth2Grant>;
|
|
8359
|
+
/**
|
|
8360
|
+
* A grant and its client in one read — the shape the token and verification
|
|
8361
|
+
* paths need, since both have to check the client the caller claims and the
|
|
8362
|
+
* grant's revocation at once.
|
|
8363
|
+
*
|
|
8364
|
+
* Read primary: revocation is documented as taking effect immediately.
|
|
8365
|
+
*/
|
|
8366
|
+
findWithClientById(id: number): Promise<OAuth2GrantWithClient | null>;
|
|
8367
|
+
/** What the user's "connected apps" screen lists. Read replica. */
|
|
8368
|
+
listActiveByUserId(userId: number): Promise<OAuth2GrantWithClient[]>;
|
|
8369
|
+
/**
|
|
8370
|
+
* Revoke one live grant belonging to one user.
|
|
8371
|
+
*
|
|
8372
|
+
* The user id is part of the condition rather than checked beforehand: the
|
|
8373
|
+
* id in the URL comes from a caller, and a grant that is not theirs must not
|
|
8374
|
+
* be revocable by guessing a number. A miss is indistinguishable from an id
|
|
8375
|
+
* that does not exist, which is the answer the route gives.
|
|
8376
|
+
*
|
|
8377
|
+
* @returns the revoked row, or null if there was no live grant of that id
|
|
8378
|
+
* for that user
|
|
8379
|
+
*/
|
|
8380
|
+
revokeByIdForUser(id: number, userId: number): Promise<OAuth2Grant | null>;
|
|
8381
|
+
/** Revoke one grant by id, whoever it belongs to — the replay detections. */
|
|
8382
|
+
revokeById(id: number): Promise<OAuth2Grant | null>;
|
|
8383
|
+
/**
|
|
8384
|
+
* Revoke every live grant a user has — the authorization-server half of a
|
|
8385
|
+
* global revocation, beside `denyAllActiveByUserId`.
|
|
8386
|
+
*
|
|
8387
|
+
* @returns the grant ids this call revoked
|
|
8388
|
+
*/
|
|
8389
|
+
revokeAllActiveByUserId(userId: number): Promise<number[]>;
|
|
8390
|
+
/**
|
|
8391
|
+
* Revoke every live token under the given grants.
|
|
8392
|
+
*
|
|
8393
|
+
* Verification already refuses a token whose grant is revoked, so this is
|
|
8394
|
+
* belt and braces — but the belt is what a `SELECT` against this table shows
|
|
8395
|
+
* an operator, and a live-looking row under a dead grant reads as a hole.
|
|
8396
|
+
*
|
|
8397
|
+
* @returns how many tokens this call revoked
|
|
8398
|
+
*/
|
|
8399
|
+
revokeTokensOfGrants(grantIds: number[]): Promise<number>;
|
|
8400
|
+
}
|
|
8401
|
+
declare const oauth2GrantsRepository: OAuth2GrantsRepository;
|
|
8402
|
+
|
|
8403
|
+
/**
|
|
8404
|
+
* OAuth 2.1 Authorization Codes Repository
|
|
8405
|
+
*
|
|
8406
|
+
* Two operations and one of them is the whole point. `consume` is a conditional
|
|
8407
|
+
* UPDATE that names unspent and not-expired and writes `used_at` in the same
|
|
8408
|
+
* statement that reads the row, so of two token requests racing on one code
|
|
8409
|
+
* exactly one comes back with a row. Read-then-write would hand both of them
|
|
8410
|
+
* tokens.
|
|
8411
|
+
*
|
|
8412
|
+
* The TTL travels in that statement as `now()` evaluated by the database, for
|
|
8413
|
+
* the reason the device-code transitions carry theirs: the row is judged by the
|
|
8414
|
+
* same clock that stores it, so an app server whose clock drifted cannot extend
|
|
8415
|
+
* a code's life.
|
|
8416
|
+
*
|
|
8417
|
+
* `findByCodeHash` exists only to explain a miss. A code that is simply unknown
|
|
8418
|
+
* and one that was already spent get the same answer at the endpoint —
|
|
8419
|
+
* `invalid_grant` either way — but the spent one also revokes the grant, and
|
|
8420
|
+
* that decision needs the row.
|
|
8421
|
+
*/
|
|
8422
|
+
|
|
8423
|
+
declare class OAuth2AuthorizationCodesRepository extends BaseRepository {
|
|
8424
|
+
create(data: NewOAuth2AuthorizationCode): Promise<OAuth2AuthorizationCode>;
|
|
8425
|
+
/**
|
|
8426
|
+
* Spend a code, addressed by the hash the caller actually presented.
|
|
8427
|
+
*
|
|
8428
|
+
* @returns the row this call spent, or null when it was unknown, already
|
|
8429
|
+
* spent, or past its 60 seconds
|
|
8430
|
+
*/
|
|
8431
|
+
consume(codeHash: string): Promise<OAuth2AuthorizationCode | null>;
|
|
8432
|
+
/**
|
|
8433
|
+
* The row behind a miss, in any state. Deliberately unfiltered — which
|
|
8434
|
+
* refusal is owed is the service's decision, and a row filtered out here
|
|
8435
|
+
* would be indistinguishable from a code that never existed.
|
|
8436
|
+
*/
|
|
8437
|
+
findByCodeHash(codeHash: string): Promise<OAuth2AuthorizationCode | null>;
|
|
8438
|
+
}
|
|
8439
|
+
declare const oauth2AuthorizationCodesRepository: OAuth2AuthorizationCodesRepository;
|
|
8440
|
+
|
|
8441
|
+
/**
|
|
8442
|
+
* OAuth 2.1 Tokens Repository
|
|
8443
|
+
*
|
|
8444
|
+
* Access and refresh rows, and the rotation that turns one refresh into the
|
|
8445
|
+
* next.
|
|
8446
|
+
*
|
|
8447
|
+
* `rotate` is the code-consuming statement again, in the other table: mark the
|
|
8448
|
+
* presented refresh `replaced_at` only if it is live, and return it only when
|
|
8449
|
+
* THIS call was the one that marked it. Two clients refreshing the same token at
|
|
8450
|
+
* once therefore produce one rotation and one refusal, instead of two token
|
|
8451
|
+
* pairs off one refresh.
|
|
8452
|
+
*
|
|
8453
|
+
* Nothing is deleted. A rotated refresh keeps its row so that presenting it
|
|
8454
|
+
* again is distinguishable from presenting a token that never existed, which is
|
|
8455
|
+
* the entire reuse detection.
|
|
8456
|
+
*/
|
|
8457
|
+
|
|
8458
|
+
declare class OAuth2TokensRepository extends BaseRepository {
|
|
8459
|
+
create(data: NewOAuth2Token): Promise<OAuth2Token>;
|
|
8460
|
+
/**
|
|
8461
|
+
* Lookup by the token's hash — the verification and refresh paths.
|
|
8462
|
+
*
|
|
8463
|
+
* Primary, not replica: revocation is a button the user presses and is
|
|
8464
|
+
* documented as taking effect immediately, so a replica read would keep
|
|
8465
|
+
* authenticating a revoked token for the length of the replication lag.
|
|
8466
|
+
* Unfiltered, so the service can tell revoked from expired from unknown.
|
|
8467
|
+
*/
|
|
8468
|
+
findByTokenHash(tokenHash: string): Promise<OAuth2Token | null>;
|
|
8469
|
+
/**
|
|
8470
|
+
* Mark a live refresh token as replaced, addressed by its hash.
|
|
8471
|
+
*
|
|
8472
|
+
* @returns the row this call replaced, or null when it was unknown, already
|
|
8473
|
+
* rotated, revoked, or expired
|
|
8474
|
+
*/
|
|
8475
|
+
rotate(tokenHash: string): Promise<OAuth2Token | null>;
|
|
8476
|
+
/**
|
|
8477
|
+
* Revoke a live token by hash — RFC 7009.
|
|
8478
|
+
*
|
|
8479
|
+
* @returns the revoked row, or null when there was nothing live to revoke.
|
|
8480
|
+
* The endpoint answers 200 either way; the caller learns nothing
|
|
8481
|
+
* about whether the value it presented ever existed.
|
|
8482
|
+
*/
|
|
8483
|
+
revokeByTokenHash(tokenHash: string): Promise<OAuth2Token | null>;
|
|
8484
|
+
/** Fire-and-forget from the verification path, as ops tokens do. */
|
|
8485
|
+
updateLastUsedById(id: number): Promise<void>;
|
|
8486
|
+
}
|
|
8487
|
+
declare const oauth2TokensRepository: OAuth2TokensRepository;
|
|
8488
|
+
|
|
7372
8489
|
/**
|
|
7373
8490
|
* @spfn/auth - Email address normalization
|
|
7374
8491
|
*
|
|
@@ -8080,6 +9197,273 @@ declare function deriveCsrfToken(keyId: string): Promise<string>;
|
|
|
8080
9197
|
*/
|
|
8081
9198
|
declare function matchesCsrfToken(expected: string, presented: string | null | undefined): boolean;
|
|
8082
9199
|
|
|
9200
|
+
/**
|
|
9201
|
+
* OAuth 2.1 Authorization Server Configuration
|
|
9202
|
+
*
|
|
9203
|
+
* Singleton config, mirroring `lib/device-auth-config.ts`: a mutable
|
|
9204
|
+
* module-level value, set once from `createAuthLifecycle()` and read at request
|
|
9205
|
+
* time.
|
|
9206
|
+
*
|
|
9207
|
+
* Unlike the device-auth block this one has no defaults to fall back on, and
|
|
9208
|
+
* that is the feature: an application that does not pass `authorizationServer`
|
|
9209
|
+
* is not running an authorization server, and every route under
|
|
9210
|
+
* `/_auth/oauth2/*` answers 404 for it. Nothing here can be derived — the scope
|
|
9211
|
+
* names are the application's vocabulary, and inventing a set would publish
|
|
9212
|
+
* scopes in the metadata document that nothing honours.
|
|
9213
|
+
*/
|
|
9214
|
+
/**
|
|
9215
|
+
* Everything the authorization server needs, resolved.
|
|
9216
|
+
*
|
|
9217
|
+
* `issuer` and `authorizeUrl` are absolute; the defaults are derived here, once,
|
|
9218
|
+
* rather than at each use — the metadata document publishes them and a client
|
|
9219
|
+
* that read one value must not meet another on the next request.
|
|
9220
|
+
*/
|
|
9221
|
+
interface AuthorizationServerConfig {
|
|
9222
|
+
/** Origin the tokens are issued by, no path. `SPFN_API_URL` by default. */
|
|
9223
|
+
issuer: string;
|
|
9224
|
+
/**
|
|
9225
|
+
* Where `issuer` came from — the option name or the variable name — so the
|
|
9226
|
+
* boot refusal can tell an operator which one to edit.
|
|
9227
|
+
*/
|
|
9228
|
+
issuerSource: string;
|
|
9229
|
+
/** Consent screen, on the web app: `${appUrl}/oauth/authorize` by default. */
|
|
9230
|
+
authorizeUrl: string;
|
|
9231
|
+
/** Scope name to the one-line description the consent screen shows. */
|
|
9232
|
+
scopes: Record<string, string>;
|
|
9233
|
+
/** What an authorize request with no `scope` asks for. All of them by default. */
|
|
9234
|
+
defaultScopes: string[];
|
|
9235
|
+
/** `https://` origins a client may register a redirect URI on. Loopback needs no entry. */
|
|
9236
|
+
allowedRedirectOrigins: string[];
|
|
9237
|
+
accessTokenTtlMs: number;
|
|
9238
|
+
refreshTokenTtlMs: number;
|
|
9239
|
+
codeTtlMs: number;
|
|
9240
|
+
}
|
|
9241
|
+
/** Options as an application writes them. Everything but `scopes` has a default. */
|
|
9242
|
+
interface AuthorizationServerOptions {
|
|
9243
|
+
issuer?: string;
|
|
9244
|
+
authorizeUrl?: string;
|
|
9245
|
+
scopes: Record<string, string>;
|
|
9246
|
+
defaultScopes?: string[];
|
|
9247
|
+
allowedRedirectOrigins?: string[];
|
|
9248
|
+
accessTokenTtlMs?: number;
|
|
9249
|
+
refreshTokenTtlMs?: number;
|
|
9250
|
+
codeTtlMs?: number;
|
|
9251
|
+
}
|
|
9252
|
+
/** Eight hours. Long enough for a working session, short enough to matter. */
|
|
9253
|
+
declare const DEFAULT_ACCESS_TOKEN_TTL_MS: number;
|
|
9254
|
+
/** Thirty days. The CLI is expected to be reconnected about that often. */
|
|
9255
|
+
declare const DEFAULT_REFRESH_TOKEN_TTL_MS: number;
|
|
9256
|
+
/** Sixty seconds — the code travels from a browser redirect to a local listener. */
|
|
9257
|
+
declare const DEFAULT_CODE_TTL_MS: number;
|
|
9258
|
+
/** Path the consent screen is served at on the web app. */
|
|
9259
|
+
declare const AUTHORIZE_PATH = "/oauth/authorize";
|
|
9260
|
+
/** The API origin every default is derived from, and the boot check's subject. */
|
|
9261
|
+
declare function resolveIssuerSource(env?: Record<string, string | undefined>): {
|
|
9262
|
+
value: string | undefined;
|
|
9263
|
+
variable: string;
|
|
9264
|
+
};
|
|
9265
|
+
/**
|
|
9266
|
+
* Resolve the authorization server config, or clear it when the application
|
|
9267
|
+
* passed none. Called synchronously from `createAuthLifecycle()` for the reason
|
|
9268
|
+
* `configureDeviceAuth` is: nothing may serve a request under half a config.
|
|
9269
|
+
*
|
|
9270
|
+
* The issuer is reduced to the form this server publishes here, where every
|
|
9271
|
+
* other default is resolved, so the config is publishable in exactly one state
|
|
9272
|
+
* whether or not a lifecycle hook has run. It is not *validated* here: a value
|
|
9273
|
+
* this cannot reduce is stored as the operator wrote it and refused by
|
|
9274
|
+
* `assertAuthorizationServerIssuer` from `afterInfrastructure`, where a throw
|
|
9275
|
+
* exits the process instead of leaving a server listening without routes. See
|
|
9276
|
+
* `lifecycle.ts`.
|
|
9277
|
+
*/
|
|
9278
|
+
declare function configureAuthorizationServer(options?: AuthorizationServerOptions, env?: Record<string, string | undefined>): void;
|
|
9279
|
+
/**
|
|
9280
|
+
* The resolved config, or null when this application runs no authorization
|
|
9281
|
+
* server. Every route under `/_auth/oauth2/*` reads it and answers 404 on null.
|
|
9282
|
+
*/
|
|
9283
|
+
declare function getAuthorizationServerConfig(): AuthorizationServerConfig | null;
|
|
9284
|
+
/**
|
|
9285
|
+
* `localhost`, `127.0.0.1` and `[::1]` — the hosts a browser treats as a secure
|
|
9286
|
+
* context over plain http, which is why the issuer may be `http://` on them and
|
|
9287
|
+
* nowhere else. `URL.hostname` normalises every IPv6 spelling to `[::1]`.
|
|
9288
|
+
*/
|
|
9289
|
+
declare function isLoopbackHostname(hostname: string): boolean;
|
|
9290
|
+
/**
|
|
9291
|
+
* Refuse boot on an issuer no client could use.
|
|
9292
|
+
*
|
|
9293
|
+
* `.well-known/*` lives at an origin's root, so an issuer carrying a path has no
|
|
9294
|
+
* place to publish its metadata and every discovery request 404s. An issuer that
|
|
9295
|
+
* is neither https nor loopback http means tokens crossing the network in the
|
|
9296
|
+
* clear. Both are configuration drift between environments, so the deploy that
|
|
9297
|
+
* introduces them is where they have to surface — the posture, the place and the
|
|
9298
|
+
* voice of `assertOAuthRedirectUris`, one door down.
|
|
9299
|
+
*
|
|
9300
|
+
* This only asserts. `configureAuthorizationServer` reduced the value it reads
|
|
9301
|
+
* if it could, so anything reaching here that is not an origin is one the
|
|
9302
|
+
* reduction deliberately left alone.
|
|
9303
|
+
*
|
|
9304
|
+
* Silent when no authorization server is configured: an application that does
|
|
9305
|
+
* not run one must boot exactly as it did before this feature existed.
|
|
9306
|
+
*
|
|
9307
|
+
* @throws When the resolved issuer cannot be honoured. The message names the
|
|
9308
|
+
* variable or the option the value came from.
|
|
9309
|
+
*/
|
|
9310
|
+
declare function assertAuthorizationServerIssuer(): void;
|
|
9311
|
+
|
|
9312
|
+
/**
|
|
9313
|
+
* OAuth 2.1 redirect URI rules
|
|
9314
|
+
*
|
|
9315
|
+
* Two jobs, and they are not the same job. Registration decides whether a URI
|
|
9316
|
+
* may be written down at all; matching decides whether the URI on an authorize
|
|
9317
|
+
* request is one that was. Registration is where policy lives (no plain http off
|
|
9318
|
+
* loopback, https only on origins the application allows, no fragment ever), and
|
|
9319
|
+
* matching is deliberately dumb: exact, on everything except a loopback port.
|
|
9320
|
+
*
|
|
9321
|
+
* The loopback exception is the whole reason a CLI can use this flow. `claude`
|
|
9322
|
+
* opens a listener on whatever port the OS hands it and cannot know that port
|
|
9323
|
+
* when it registers, so RFC 8252 §7.3 lets the port vary — and nothing else.
|
|
9324
|
+
* `localhost`, `127.0.0.1` and `[::1]` are three different registrations that do
|
|
9325
|
+
* not stand in for one another: they resolve differently on a machine with a
|
|
9326
|
+
* split-horizon resolver, and a client that registered one and is answered on
|
|
9327
|
+
* another is a client something redirected.
|
|
9328
|
+
*
|
|
9329
|
+
* IPv6 arrives in as many spellings as there are ways to write zeroes, so both
|
|
9330
|
+
* sides are read through `new URL(...).hostname`, which answers `[::1]` for
|
|
9331
|
+
* every one of them. The registered value is stored verbatim — the registration
|
|
9332
|
+
* response echoes it back and must not answer a client with a URI it did not
|
|
9333
|
+
* write — so the normalisation happens here, on both sides, at every comparison.
|
|
9334
|
+
*/
|
|
9335
|
+
/** Why a redirect URI cannot be registered, in RFC 7591 §3.2.2 terms. */
|
|
9336
|
+
type RedirectUriRefusal = 'invalid_redirect_uri';
|
|
9337
|
+
/**
|
|
9338
|
+
* Whether a URI may be registered, given the https origins this application
|
|
9339
|
+
* allows.
|
|
9340
|
+
*
|
|
9341
|
+
* @param uri - The value exactly as the client wrote it
|
|
9342
|
+
* @param allowedRedirectOrigins - `https://` origins from the lifecycle config
|
|
9343
|
+
* @returns null when it may; the refusal detail when it may not
|
|
9344
|
+
*/
|
|
9345
|
+
declare function refuseRedirectUriRegistration(uri: string, allowedRedirectOrigins: string[]): string | null;
|
|
9346
|
+
/**
|
|
9347
|
+
* Whether a presented redirect URI is one of the registered ones.
|
|
9348
|
+
*
|
|
9349
|
+
* Host, path and query must be identical; the port may differ only when both
|
|
9350
|
+
* sides are loopback http. A presented URI carrying a fragment or a dot segment
|
|
9351
|
+
* matches nothing — registration already refuses both, so this is the request
|
|
9352
|
+
* side of the same two rules.
|
|
9353
|
+
*/
|
|
9354
|
+
declare function matchesRegisteredRedirectUri(presented: string, registered: string[]): boolean;
|
|
9355
|
+
/**
|
|
9356
|
+
* The host shown on the consent screen, so the person approving can see where
|
|
9357
|
+
* the code is about to be sent.
|
|
9358
|
+
*/
|
|
9359
|
+
declare function redirectHostOf(uri: string): string;
|
|
9360
|
+
|
|
9361
|
+
/**
|
|
9362
|
+
* OAuth 2.1 resource indicator (RFC 8707)
|
|
9363
|
+
*
|
|
9364
|
+
* The one string that says which API an access token is good against. It is
|
|
9365
|
+
* required at authorize, defaulted from the grant at token, and compared again
|
|
9366
|
+
* at verification — and the three comparisons have to agree, or a token minted
|
|
9367
|
+
* for one spelling of a URL is refused by another.
|
|
9368
|
+
*
|
|
9369
|
+
* So there is one rule and it is applied at every entry point: parse and
|
|
9370
|
+
* re-serialise with `new URL(...).toString()`, store that, and compare the
|
|
9371
|
+
* normalised strings exactly. That folds away the differences a URL parser is
|
|
9372
|
+
* allowed to fold — a default port written out, a percent-encoding case, an
|
|
9373
|
+
* empty path becoming `/` — and folds away nothing else. A trailing slash is
|
|
9374
|
+
* not noise: `https://api.example.com/mcp` and `https://api.example.com/mcp/`
|
|
9375
|
+
* are different paths and stay different resources.
|
|
9376
|
+
*
|
|
9377
|
+
* A fragment is refused rather than stripped. RFC 8707 §2 forbids one, and
|
|
9378
|
+
* stripping would quietly hand back a token for a target the client did not ask
|
|
9379
|
+
* for.
|
|
9380
|
+
*/
|
|
9381
|
+
/**
|
|
9382
|
+
* The canonical form of a resource indicator, or null when the value is not one.
|
|
9383
|
+
*
|
|
9384
|
+
* @param value - The `resource` parameter as it arrived
|
|
9385
|
+
*/
|
|
9386
|
+
declare function normalizeResource(value: string): string | null;
|
|
9387
|
+
/**
|
|
9388
|
+
* Whether a presented resource names the same target as a grant's.
|
|
9389
|
+
*
|
|
9390
|
+
* Both sides go through `normalizeResource`: the grant's value was normalised
|
|
9391
|
+
* when it was stored, and normalising it again costs one parse and removes the
|
|
9392
|
+
* chance that a row written by an older rule is compared raw.
|
|
9393
|
+
*/
|
|
9394
|
+
declare function sameResource(presented: string, granted: string): boolean;
|
|
9395
|
+
|
|
9396
|
+
/**
|
|
9397
|
+
* OAuth 2.1 token, code and clock helpers
|
|
9398
|
+
*
|
|
9399
|
+
* Every secret this server issues is generated, hashed and compared here, so
|
|
9400
|
+
* there is one answer to "how long is it, what does it start with, and how is it
|
|
9401
|
+
* checked" rather than one per call site.
|
|
9402
|
+
*
|
|
9403
|
+
* Lookup is by the hash and the hash column is unique, so the database finds at
|
|
9404
|
+
* most one row — but the equality that actually authorizes is done here, in
|
|
9405
|
+
* constant time, over the hex digests. It costs a string comparison of 64
|
|
9406
|
+
* characters and it means the decision never depends on how an index compared.
|
|
9407
|
+
*
|
|
9408
|
+
* The clock helpers are the other half. Three places express a moment and they
|
|
9409
|
+
* disagree about the unit — the row stores a timestamp, `verifyAccessToken`
|
|
9410
|
+
* answers seconds since the epoch, and a token response carries the seconds
|
|
9411
|
+
* remaining — so all three go through one function each rather than three
|
|
9412
|
+
* divisions by 1000 that can each be wrong on their own.
|
|
9413
|
+
*/
|
|
9414
|
+
/** Shape of an access token. Paired with `isAccessTokenShaped` below. */
|
|
9415
|
+
declare const OAUTH2_ACCESS_TOKEN_PREFIX = "spfn_at_";
|
|
9416
|
+
/** Shape of a refresh token. */
|
|
9417
|
+
declare const OAUTH2_REFRESH_TOKEN_PREFIX = "spfn_rt_";
|
|
9418
|
+
/** SHA-256 hex of a token or code. The only form either is ever stored in. */
|
|
9419
|
+
declare function hashOAuth2Secret(secret: string): string;
|
|
9420
|
+
/** Constant-time equality for two hex digests. */
|
|
9421
|
+
declare function sameOAuth2Hash(a: string, b: string): boolean;
|
|
9422
|
+
declare function generateAccessToken(): string;
|
|
9423
|
+
declare function generateRefreshToken(): string;
|
|
9424
|
+
/** 43 url-safe characters, which is 32 bytes of base64url with no padding. */
|
|
9425
|
+
declare function generateAuthorizationCode(): string;
|
|
9426
|
+
/**
|
|
9427
|
+
* Whether a presented bearer credential has the access-token shape.
|
|
9428
|
+
*
|
|
9429
|
+
* Shape only — the token may still be unknown, revoked or expired, which
|
|
9430
|
+
* `verifyAccessToken` decides. Callers read a raw header, so a missing or
|
|
9431
|
+
* non-string argument answers false rather than throwing, exactly as
|
|
9432
|
+
* `isOpsToken` does.
|
|
9433
|
+
*/
|
|
9434
|
+
declare function isAccessTokenShaped(bearer: string): boolean;
|
|
9435
|
+
/** The PKCE S256 transform: base64url of SHA-256 over the verifier's ASCII. */
|
|
9436
|
+
declare function pkceChallengeFor(codeVerifier: string): string;
|
|
9437
|
+
/**
|
|
9438
|
+
* Whether a presented verifier is one RFC 7636 describes.
|
|
9439
|
+
*
|
|
9440
|
+
* Conformance rather than defence — the S256 comparison is what authorizes, and
|
|
9441
|
+
* a verifier of any length still has to hash to the stored challenge. What this
|
|
9442
|
+
* catches is a client that built its verifier wrong: 22 characters of entropy
|
|
9443
|
+
* carries less than the transform promises, and an oversized one is a client
|
|
9444
|
+
* that will be refused by the next server it talks to for a reason this one
|
|
9445
|
+
* never told it.
|
|
9446
|
+
*/
|
|
9447
|
+
declare function isPkceVerifierShaped(codeVerifier: string): boolean;
|
|
9448
|
+
/**
|
|
9449
|
+
* Whether a presented challenge could have come out of the S256 transform.
|
|
9450
|
+
*
|
|
9451
|
+
* A challenge of any other shape is a client that sent something else in the
|
|
9452
|
+
* field — its verifier, most often, which is `plain` PKCE wearing the S256
|
|
9453
|
+
* label and is exactly what the method check exists to refuse.
|
|
9454
|
+
*/
|
|
9455
|
+
declare function isPkceS256ChallengeShaped(codeChallenge: string): boolean;
|
|
9456
|
+
/** A moment as seconds since the epoch — what `verifyAccessToken` answers with. */
|
|
9457
|
+
declare function toEpochSeconds(at: Date): number;
|
|
9458
|
+
/**
|
|
9459
|
+
* Whole seconds from now until a moment — what `expires_in` carries.
|
|
9460
|
+
*
|
|
9461
|
+
* Floored at zero: a token that expired while the response was being built is
|
|
9462
|
+
* answered as zero rather than as a negative number a client would read as an
|
|
9463
|
+
* enormous unsigned one.
|
|
9464
|
+
*/
|
|
9465
|
+
declare function secondsUntil(at: Date, from?: Date): number;
|
|
9466
|
+
|
|
8083
9467
|
/**
|
|
8084
9468
|
* One-Time Token Manager
|
|
8085
9469
|
*
|
|
@@ -8520,6 +9904,33 @@ interface AuthLifecycleOptions extends AuthInitOptions {
|
|
|
8520
9904
|
*/
|
|
8521
9905
|
intervalMs?: number;
|
|
8522
9906
|
};
|
|
9907
|
+
/**
|
|
9908
|
+
* OAuth 2.1 authorization server for MCP clients
|
|
9909
|
+
*
|
|
9910
|
+
* Opt-in, and the opt-in is this block. Without it `/_auth/oauth2/*` and
|
|
9911
|
+
* `/.well-known/oauth-authorization-server` answer 404, the boot check does
|
|
9912
|
+
* not run, and the application boots exactly as it did before this feature
|
|
9913
|
+
* existed. With it, Claude Code and Codex can register themselves, send the
|
|
9914
|
+
* account owner to a consent screen, and hold a token against `/mcp`.
|
|
9915
|
+
*
|
|
9916
|
+
* `scopes` is the one thing with no default: the names are the
|
|
9917
|
+
* application's own vocabulary, they are published in the metadata document
|
|
9918
|
+
* and shown on the consent screen, and there is nothing to derive them from.
|
|
9919
|
+
*
|
|
9920
|
+
* @example
|
|
9921
|
+
* ```typescript
|
|
9922
|
+
* createAuthLifecycle({
|
|
9923
|
+
* authorizationServer: {
|
|
9924
|
+
* scopes: {
|
|
9925
|
+
* 'mcp:read': 'Read your projects and tasks',
|
|
9926
|
+
* 'mcp:write': 'Create and edit your tasks',
|
|
9927
|
+
* },
|
|
9928
|
+
* defaultScopes: ['mcp:read'],
|
|
9929
|
+
* },
|
|
9930
|
+
* })
|
|
9931
|
+
* ```
|
|
9932
|
+
*/
|
|
9933
|
+
authorizationServer?: AuthorizationServerOptions;
|
|
8523
9934
|
}
|
|
8524
9935
|
declare function createAuthLifecycle(options?: AuthLifecycleOptions): AuthLifecycleConfig;
|
|
8525
9936
|
|
|
@@ -8582,8 +9993,8 @@ declare const linkMailJob: _spfn_core_job.JobDef<{
|
|
|
8582
9993
|
}, void>;
|
|
8583
9994
|
|
|
8584
9995
|
/**
|
|
8585
|
-
* Build the auth job router: the account-deletion purge sweep
|
|
8586
|
-
* sender.
|
|
9996
|
+
* Build the auth job router: the account-deletion purge sweep, the OAuth 2.1
|
|
9997
|
+
* stale-client sweep, and the link-mail sender.
|
|
8587
9998
|
*
|
|
8588
9999
|
* The cron is a parameter because `job(...).cron(expression)` bakes the string in
|
|
8589
10000
|
* at module-import time, which always happens before `createAuthLifecycle()` runs
|
|
@@ -8592,11 +10003,14 @@ declare const linkMailJob: _spfn_core_job.JobDef<{
|
|
|
8592
10003
|
* after that call, when the schedule is not the default.
|
|
8593
10004
|
*
|
|
8594
10005
|
* @param options.purgeCron - Deletion purge schedule; defaults to daily at 04:00
|
|
10006
|
+
* @param options.oauth2ClientPurgeCron - Stale OAuth client sweep; defaults to daily at 05:00
|
|
8595
10007
|
*/
|
|
8596
10008
|
declare function createAuthJobRouter(options?: {
|
|
8597
10009
|
purgeCron?: string;
|
|
10010
|
+
oauth2ClientPurgeCron?: string;
|
|
8598
10011
|
}): _spfn_core_job.JobRouter<{
|
|
8599
10012
|
deletionPurge: _spfn_core_job.JobDef<void, void>;
|
|
10013
|
+
oauth2ClientPurge: _spfn_core_job.JobDef<void, void>;
|
|
8600
10014
|
linkMail: _spfn_core_job.JobDef<{
|
|
8601
10015
|
kind: "signup-link";
|
|
8602
10016
|
rowId: number;
|
|
@@ -8615,6 +10029,7 @@ declare function createAuthJobRouter(options?: {
|
|
|
8615
10029
|
*/
|
|
8616
10030
|
declare const authJobRouter: _spfn_core_job.JobRouter<{
|
|
8617
10031
|
deletionPurge: _spfn_core_job.JobDef<void, void>;
|
|
10032
|
+
oauth2ClientPurge: _spfn_core_job.JobDef<void, void>;
|
|
8618
10033
|
linkMail: _spfn_core_job.JobDef<{
|
|
8619
10034
|
kind: "signup-link";
|
|
8620
10035
|
rowId: number;
|
|
@@ -8846,4 +10261,4 @@ type AuthDeletionCancelledPayload = typeof authDeletionCancelledEvent._payload;
|
|
|
8846
10261
|
type AuthDeletionCompletedPayload = typeof authDeletionCompletedEvent._payload;
|
|
8847
10262
|
type OAuthUnlinkedPayload = typeof oauthUnlinkedEvent._payload;
|
|
8848
10263
|
|
|
8849
|
-
export { type AccountDeletionPurgeUser, type AccountDeletionRequest, AccountDeletionRequestedBy, AccountDeletionRequestsRepository, type AuthConfig, AuthContext, type AuthCsrfConfig, type AuthDeletionCancelledPayload, type AuthDeletionCompletedPayload, type AuthDeletionConfig, type AuthDeletionRequestedPayload, type AuthDeviceAuthConfig, type AuthLifecycleConfig, type AuthLifecycleOptions, type AuthLoginPayload, type AuthMetadataEntity, AuthMetadataRepository, type AuthPasswordResetPayload, AuthProviderSchema, type AuthRegisterPayload, type BeforeRegisterContext, COOKIE_NAMES, CSRF_HEADER, type CancelAccountDeletionParams, type CancelAccountDeletionResult, type CreateOAuthStateParams, type CsrfMode, DEFAULT_DELETION_ALLOW_SELF_IMMEDIATE, DEFAULT_DELETION_GRACE_PERIOD_DAYS, DEFAULT_DELETION_PURGE_CRON, DEFAULT_DELETION_PURGE_STRATEGY, DEFAULT_DELETION_SEND_NOTIFICATIONS, DEFAULT_DEVICE_AUTH_INTERVAL_MS, DEFAULT_DEVICE_AUTH_TTL_MS, DEVICE_AUTH_STATUSES, type DecryptedOAuthToken, type DeviceAuthStatus, type DeviceAuthorization, DeviceAuthorizationsRepository, type EmailNormalizationResult, EnvironmentKeyringTokenCipher, type GoogleTokenResponse, type GoogleUserInfo, type Invitation, type InvitationAcceptedPayload, type InvitationCreatedPayload, InvitationStatus, InvitationsRepository, type IssuedOpsToken, KeyAlgorithmType, KeysRepository, type NewAccountDeletionRequest, type NewAuthMetadataEntity, type NewDeviceAuthorization, type NewInvitation, type NewOpsToken, NewPasskey, type NewPasswordResetToken, type NewPermission, type NewPermissionEntity, type NewRole, type NewRoleEntity, type NewRolePermission, type NewSignupLinkToken, type NewUser, type NewUserPermission, type NewUserProfile, type NewUserPublicKey, type NewUserSocialAccount, type NewVerificationCode, type NewWebAuthnChallenge, OAuthProvider, type OAuthState, type OAuthTokenCipher, type OAuthTokenContext, type OAuthTokenType, type OAuthUnlinkedPayload, OPS_TOKEN_PREFIX, type OpsOrUserConfig, type OpsToken, OpsTokensRepository, Passkey, type PasskeyConfig, type PasskeyUserVerification, PasskeysRepository, type PasswordResetToken, PasswordResetTokensRepository, type PendingDeletionInfo, type Permission, type PermissionEntity, PermissionsRepository, PurgeStrategy, type PurgeUserResult, type RegisterChannel, type RequestAccountDeletionParams, type RequestAccountDeletionResult, type Role, type RoleEntity, type RoleGuardOptions, type RolePermission, RolePermissionsRepository, RolesRepository, type SessionPayload, type SignupLinkToken, SignupLinkTokensRepository, SocialAccountsRepository, SocialProvider, type SweepDuePurgesResult, type TokenPayload, USER_CODE_ALPHABET, USER_CODE_LENGTH, type UpdateProfileParams, type User, type UserPermission, UserPermissionsRepository, type UserProfile, UserProfilesRepository, type UserPublicKey, type UserSocialAccount, UsersRepository, type VerificationCode, VerificationCodesRepository, VerificationPurpose, type VerifiedOpsToken, type VerifyIdTokenParams, WEBAUTHN_CHALLENGE_KINDS, type WebAuthnChallenge, type WebAuthnChallengeKind, WebAuthnChallengesRepository, acceptInvitation, accountDeletionRequests, accountDeletionRequestsRepository, addPermissionToRole, appleProvider, assertCanAssignRole, assertKeyMatchesAlgorithm, assertPasskeyConfig, authDeletionCancelledEvent, authDeletionCompletedEvent, authDeletionRequestedEvent, authJobRouter, authLogger, authLoginEvent, authMetadata, authMetadataRepository, authPasswordResetEvent, authRegisterEvent, authSchema, cancelAccountDeletionService, cancelInvitation, checkUsernameAvailableService, configureAuth, configureDeletion, configureDeviceAuth, configureOAuthTokenCipher, createAuthDeletionJobRouter, createAuthDeletionPurgeJob, createAuthJobRouter, createAuthLifecycle, createInvitation, createOAuthState, createRole, decodeToken, decryptToken, deleteInvitation, deleteRole, deriveCsrfToken, deviceAuthorizations, deviceAuthorizationsRepository, encryptToken, exchangeCodeForTokens, expireOldInvitations, formatUserCode, generateDeviceCode, generateOAuthNonce, generateToken, generateUserCode, getAllRoles, getAuth, getAuthConfig, getAuthSessionService, getCsrfExemptPaths, getCsrfMode, getDeletionConfig, getDeviceAuthConfig, getDummyPasswordHash, getGoogleAuthUrl, getGoogleOAuthConfig, getGoogleUserInfo, getInvitationByToken, getInvitationWithDetails, getKeyId, getLocale, getOneTimeTokenManager, getOpsToken, getOptionalAuth, getPasskeyConfig, getPendingDeletionInfo, getRole, getRoleByName, getRolePermissions, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, githubProvider, googleProvider, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashDeviceCode, hashPassword, initOneTimeTokenManager, initializeAuth, invitationAcceptedEvent, invitationCreatedEvent, invitationsRepository, isEncrypted, isGoogleOAuthEnabled, isOpsToken, issueOpsTokenService, kakaoProvider, keysRepository, linkMailJob, listInvitations, listOpsTokensService, matchOAuthCsrfCookies, matchesCsrfToken, naverProvider, normalizeEmail, normalizeOptionalEmail, normalizeStoredEmails, normalizeUserCode, oauthUnlinkedEvent, oneTimeTokenAuth, opsOrUser, opsTokenAuth, opsTokens, opsTokensRepository, parseDuration, passkeysRepository, passwordResetTokens, passwordResetTokensRepository, permissions, permissionsRepository, purgeUserService, refreshAccessToken, removePermissionFromRole, requestAccountDeletionService, requireAnyPermission, requireOpsScope, requirePermissions, requireRole, resendInvitation, revokeOpsTokenService, roleGuard, rolePermissions, rolePermissionsRepository, roles, rolesRepository, runBeforeRegister, setRolePermissions, signupLinkTokens, signupLinkTokensRepository, socialAccountsRepository, sweepDuePurges, updateLastLoginService, updateLocaleService, updateRole, updateUserProfileService, updateUserService, updateUsernameService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyClientToken, verifyIdToken, verifyKeyFingerprint, verifyOAuthState, verifyOpsTokenService, verifyPassword, verifyToken, webauthnChallenges, webauthnChallengesRepository };
|
|
10264
|
+
export { AUTHORIZE_PATH, type AccountDeletionPurgeUser, type AccountDeletionRequest, AccountDeletionRequestedBy, AccountDeletionRequestsRepository, type AuthConfig, AuthContext, type AuthCsrfConfig, type AuthDeletionCancelledPayload, type AuthDeletionCompletedPayload, type AuthDeletionConfig, type AuthDeletionRequestedPayload, type AuthDeviceAuthConfig, type AuthLifecycleConfig, type AuthLifecycleOptions, type AuthLoginPayload, type AuthMetadataEntity, AuthMetadataRepository, type AuthPasswordResetPayload, AuthProviderSchema, type AuthRegisterPayload, type AuthorizationServerConfig, type AuthorizationServerOptions, type BeforeRegisterContext, COOKIE_NAMES, CSRF_HEADER, type CancelAccountDeletionParams, type CancelAccountDeletionResult, type CreateOAuthStateParams, type CsrfMode, DEFAULT_ACCESS_TOKEN_TTL_MS, DEFAULT_CODE_TTL_MS, DEFAULT_DELETION_ALLOW_SELF_IMMEDIATE, DEFAULT_DELETION_GRACE_PERIOD_DAYS, DEFAULT_DELETION_PURGE_CRON, DEFAULT_DELETION_PURGE_STRATEGY, DEFAULT_DELETION_SEND_NOTIFICATIONS, DEFAULT_DEVICE_AUTH_INTERVAL_MS, DEFAULT_DEVICE_AUTH_TTL_MS, DEFAULT_REFRESH_TOKEN_TTL_MS, DEVICE_AUTH_STATUSES, type DecryptedOAuthToken, type DeviceAuthStatus, type DeviceAuthorization, DeviceAuthorizationsRepository, type EmailNormalizationResult, EnvironmentKeyringTokenCipher, type GoogleTokenResponse, type GoogleUserInfo, type Invitation, type InvitationAcceptedPayload, type InvitationCreatedPayload, InvitationStatus, InvitationsRepository, type IssuedOpsToken, KeyAlgorithmType, KeysRepository, MAX_UNGRANTED_CLIENTS_PER_IP, type NewAccountDeletionRequest, type NewAuthMetadataEntity, type NewDeviceAuthorization, type NewInvitation, type NewOAuth2AuthorizationCode, type NewOAuth2Client, type NewOAuth2Grant, type NewOAuth2Token, type NewOpsToken, NewPasskey, type NewPasswordResetToken, type NewPermission, type NewPermissionEntity, type NewRole, type NewRoleEntity, type NewRolePermission, type NewSignupLinkToken, type NewUser, type NewUserPermission, type NewUserProfile, type NewUserPublicKey, type NewUserSocialAccount, type NewVerificationCode, type NewWebAuthnChallenge, OAUTH2_ACCESS_TOKEN_PREFIX, OAUTH2_REFRESH_TOKEN_PREFIX, OAUTH2_TOKEN_KINDS, type OAuth2AuthorizationCode, OAuth2AuthorizationCodesRepository, type OAuth2Client, OAuth2ClientsRepository, type OAuth2Grant, type OAuth2GrantWithClient, OAuth2GrantsRepository, type OAuth2RegisterRefusal, type OAuth2RegisterRequest, type OAuth2RegisterResult, type OAuth2RegisteredClient, type OAuth2Token, type OAuth2TokenKind, type OAuth2TokenRefusal, type OAuth2TokenRequest, type OAuth2TokenResponse, type OAuth2TokenResult, OAuth2TokensRepository, OAuthProvider, type OAuthState, type OAuthTokenCipher, type OAuthTokenContext, type OAuthTokenType, type OAuthUnlinkedPayload, OPS_TOKEN_PREFIX, type OpsOrUserConfig, type OpsToken, OpsTokensRepository, Passkey, type PasskeyConfig, type PasskeyUserVerification, PasskeysRepository, type PasswordResetToken, PasswordResetTokensRepository, type PendingDeletionInfo, type Permission, type PermissionEntity, PermissionsRepository, PurgeStrategy, type PurgeUserResult, type RedirectUriRefusal, type RegisterChannel, type RequestAccountDeletionParams, type RequestAccountDeletionResult, type Role, type RoleEntity, type RoleGuardOptions, type RolePermission, RolePermissionsRepository, RolesRepository, STALE_CLIENT_MAX_AGE_MS, SUPPORTED_GRANT_TYPES, SUPPORTED_RESPONSE_TYPES, type SessionPayload, type SignupLinkToken, SignupLinkTokensRepository, SocialAccountsRepository, SocialProvider, type SweepDuePurgesResult, type TokenPayload, USER_CODE_ALPHABET, USER_CODE_LENGTH, type UpdateProfileParams, type User, type UserPermission, UserPermissionsRepository, type UserProfile, UserProfilesRepository, type UserPublicKey, type UserSocialAccount, UsersRepository, type VerificationCode, VerificationCodesRepository, VerificationPurpose, type VerifiedOAuth2AccessToken, type VerifiedOpsToken, type VerifyIdTokenParams, WEBAUTHN_CHALLENGE_KINDS, type WebAuthnChallenge, type WebAuthnChallengeKind, WebAuthnChallengesRepository, acceptInvitation, accountDeletionRequests, accountDeletionRequestsRepository, addPermissionToRole, appleProvider, assertAuthorizationServerIssuer, assertCanAssignRole, assertKeyMatchesAlgorithm, assertPasskeyConfig, authDeletionCancelledEvent, authDeletionCompletedEvent, authDeletionRequestedEvent, authJobRouter, authLogger, authLoginEvent, authMetadata, authMetadataRepository, authPasswordResetEvent, authRegisterEvent, authSchema, cancelAccountDeletionService, cancelInvitation, checkUsernameAvailableService, configureAuth, configureAuthorizationServer, configureDeletion, configureDeviceAuth, configureOAuthTokenCipher, createAuthDeletionJobRouter, createAuthDeletionPurgeJob, createAuthJobRouter, createAuthLifecycle, createInvitation, createOAuthState, createRole, decodeToken, decryptToken, deleteInvitation, deleteRole, deriveCsrfToken, deviceAuthorizations, deviceAuthorizationsRepository, encryptToken, exchangeCodeForTokens, expireOldInvitations, formatUserCode, generateAccessToken, generateAuthorizationCode, generateDeviceCode, generateOAuthNonce, generateRefreshToken, generateToken, generateUserCode, getAllRoles, getAuth, getAuthConfig, getAuthSessionService, getAuthorizationServerConfig, getCsrfExemptPaths, getCsrfMode, getDeletionConfig, getDeviceAuthConfig, getDummyPasswordHash, getGoogleAuthUrl, getGoogleOAuthConfig, getGoogleUserInfo, getInvitationByToken, getInvitationWithDetails, getKeyId, getLocale, getOneTimeTokenManager, getOpsToken, getOptionalAuth, getPasskeyConfig, getPendingDeletionInfo, getRole, getRoleByName, getRolePermissions, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, githubProvider, googleProvider, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashDeviceCode, hashOAuth2Secret, hashPassword, initOneTimeTokenManager, initializeAuth, invitationAcceptedEvent, invitationCreatedEvent, invitationsRepository, isAccessTokenShaped, isEncrypted, isGoogleOAuthEnabled, isLoopbackHostname, isOpsToken, isPkceS256ChallengeShaped, isPkceVerifierShaped, issueOpsTokenService, kakaoProvider, keysRepository, linkMailJob, listInvitations, listOpsTokensService, matchOAuthCsrfCookies, matchesCsrfToken, matchesRegisteredRedirectUri, naverProvider, normalizeEmail, normalizeOptionalEmail, normalizeResource, normalizeStoredEmails, normalizeUserCode, oauth2AuthorizationCodes, oauth2AuthorizationCodesRepository, oauth2Clients, oauth2ClientsRepository, oauth2Grants, oauth2GrantsRepository, oauth2TokenService, oauth2Tokens, oauth2TokensRepository, oauthUnlinkedEvent, oneTimeTokenAuth, opsOrUser, opsTokenAuth, opsTokens, opsTokensRepository, parseDuration, passkeysRepository, passwordResetTokens, passwordResetTokensRepository, permissions, permissionsRepository, pkceChallengeFor, purgeStaleOAuth2ClientsService, purgeUserService, redirectHostOf, refreshAccessToken, refuseRedirectUriRegistration, registerOAuth2ClientService, removePermissionFromRole, requestAccountDeletionService, requireAnyPermission, requireOpsScope, requirePermissions, requireRole, resendInvitation, resolveIssuerSource, revokeOAuth2TokenService, revokeOpsTokenService, roleGuard, rolePermissions, rolePermissionsRepository, roles, rolesRepository, runBeforeRegister, sameOAuth2Hash, sameResource, secondsUntil, setRolePermissions, signupLinkTokens, signupLinkTokensRepository, socialAccountsRepository, sweepDuePurges, toEpochSeconds, updateLastLoginService, updateLocaleService, updateRole, updateUserProfileService, updateUserService, updateUsernameService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyAccessToken, verifyClientToken, verifyIdToken, verifyKeyFingerprint, verifyOAuthState, verifyOpsTokenService, verifyPassword, verifyToken, webauthnChallenges, webauthnChallengesRepository };
|