@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
|
@@ -1592,6 +1592,138 @@ interface OAuthNativeResult {
|
|
|
1592
1592
|
*/
|
|
1593
1593
|
declare function oauthNativeService(params: OAuthNativeParams): Promise<OAuthNativeResult>;
|
|
1594
1594
|
|
|
1595
|
+
/**
|
|
1596
|
+
* OAuth 2.1 Authorize Service
|
|
1597
|
+
*
|
|
1598
|
+
* The API half of the consent screen. The screen itself is a page on the web
|
|
1599
|
+
* app, because that is where the session cookie is; it has no database, so it
|
|
1600
|
+
* asks here what to draw (`describeOAuth2AuthorizeRequest`) and tells here what
|
|
1601
|
+
* the user decided (`approveOAuth2Authorize` / `denyOAuth2Authorize`). Both
|
|
1602
|
+
* calls validate the request from scratch — the second must never trust what the
|
|
1603
|
+
* first was shown, since a form can be edited between them.
|
|
1604
|
+
*
|
|
1605
|
+
* Refusals come in two kinds and the split is the security property, not a
|
|
1606
|
+
* presentation choice:
|
|
1607
|
+
*
|
|
1608
|
+
* - **Not redirectable.** An unknown `client_id`, or a `redirect_uri` the client
|
|
1609
|
+
* never registered. There is no vetted URI to send the error to, and sending
|
|
1610
|
+
* it to the one the request supplied is precisely the open redirect the
|
|
1611
|
+
* registration check exists to prevent. These are shown on the screen.
|
|
1612
|
+
* - **Redirectable.** Everything else — a missing PKCE challenge, a missing
|
|
1613
|
+
* `resource`, an unknown scope, and the user saying no. The client and its
|
|
1614
|
+
* URI are both vetted by then, so RFC 6749 §4.1.2.1 puts the error back on
|
|
1615
|
+
* that URI as query parameters, which is the only form the waiting CLI can
|
|
1616
|
+
* read.
|
|
1617
|
+
*/
|
|
1618
|
+
/** An authorize request as the web handler forwards it, before anything is trusted. */
|
|
1619
|
+
interface OAuth2AuthorizeParams {
|
|
1620
|
+
clientId: string;
|
|
1621
|
+
redirectUri: string;
|
|
1622
|
+
codeChallenge?: string;
|
|
1623
|
+
codeChallengeMethod?: string;
|
|
1624
|
+
resource?: string;
|
|
1625
|
+
scope?: string;
|
|
1626
|
+
state?: string;
|
|
1627
|
+
}
|
|
1628
|
+
/** One scope, with the sentence the consent screen shows for it. */
|
|
1629
|
+
interface OAuth2ScopeDescription {
|
|
1630
|
+
name: string;
|
|
1631
|
+
description: string;
|
|
1632
|
+
}
|
|
1633
|
+
/** Everything the consent screen needs, and nothing it does not. */
|
|
1634
|
+
interface OAuth2ConsentView {
|
|
1635
|
+
clientName: string;
|
|
1636
|
+
/** Host the code would be sent to — the one fact about the client that is checkable. */
|
|
1637
|
+
redirectHost: string;
|
|
1638
|
+
scopes: OAuth2ScopeDescription[];
|
|
1639
|
+
resource: string;
|
|
1640
|
+
}
|
|
1641
|
+
/** What the web handler turns into the success redirect. */
|
|
1642
|
+
interface OAuth2AuthorizationCodeIssued {
|
|
1643
|
+
code: string;
|
|
1644
|
+
/** The presented URI, which matched a registered one. Safe to redirect to. */
|
|
1645
|
+
redirectUri: string;
|
|
1646
|
+
/** Echoed back verbatim, or absent when the request carried none. */
|
|
1647
|
+
state?: string;
|
|
1648
|
+
}
|
|
1649
|
+
/**
|
|
1650
|
+
* What to draw on the consent screen for this request.
|
|
1651
|
+
*
|
|
1652
|
+
* Read-only: nothing is recorded by looking, so a user who closes the tab has
|
|
1653
|
+
* consented to nothing and left nothing behind.
|
|
1654
|
+
*/
|
|
1655
|
+
declare function describeOAuth2AuthorizeRequestService(params: OAuth2AuthorizeParams): Promise<OAuth2ConsentView>;
|
|
1656
|
+
/**
|
|
1657
|
+
* Record the consent and mint the code.
|
|
1658
|
+
*
|
|
1659
|
+
* The whole request is validated again rather than carried over from the GET:
|
|
1660
|
+
* the form between the two is in the user's browser, and a parameter changed
|
|
1661
|
+
* there must be caught here and not honoured because the screen once looked
|
|
1662
|
+
* right.
|
|
1663
|
+
*
|
|
1664
|
+
* `userId` comes from the approving session. Never from a request body — that
|
|
1665
|
+
* would be the entire authorization.
|
|
1666
|
+
*/
|
|
1667
|
+
declare function approveOAuth2AuthorizeService(params: OAuth2AuthorizeParams, userId: number): Promise<OAuth2AuthorizationCodeIssued>;
|
|
1668
|
+
/**
|
|
1669
|
+
* The user said no.
|
|
1670
|
+
*
|
|
1671
|
+
* Validated first, and validated in full — the same `validate` the approval
|
|
1672
|
+
* runs. `access_denied` goes back to the client on its redirect URI like any
|
|
1673
|
+
* other redirectable error, so the URI has to be one the client registered
|
|
1674
|
+
* before anybody is sent to it; and a request that was malformed was malformed
|
|
1675
|
+
* whichever button was pressed, so answering `access_denied` to it would tell
|
|
1676
|
+
* the waiting client the user refused when in fact it never asked properly.
|
|
1677
|
+
* Nothing is recorded — a refusal is not a grant with a flag on it.
|
|
1678
|
+
*/
|
|
1679
|
+
declare function denyOAuth2AuthorizeService(params: OAuth2AuthorizeParams): Promise<never>;
|
|
1680
|
+
|
|
1681
|
+
/**
|
|
1682
|
+
* OAuth 2.1 Grant Service
|
|
1683
|
+
*
|
|
1684
|
+
* The user's side of the authorization server: what is connected, and the button
|
|
1685
|
+
* that disconnects it. A grant is the unit because it is the thing a person can
|
|
1686
|
+
* recognise — "Claude Code, on this API, with these permissions" — and because
|
|
1687
|
+
* revoking it takes every code and token underneath with it.
|
|
1688
|
+
*
|
|
1689
|
+
* `revokeAllOAuth2GrantsForUser` is the same act performed on the user's behalf
|
|
1690
|
+
* rather than by them, and it sits at the four places that revoke everything:
|
|
1691
|
+
* revoke-all, a password change, a completed password reset, a deletion request.
|
|
1692
|
+
* A global revocation that left a grant alive would leave a refresh token alive,
|
|
1693
|
+
* and a CLI holding one would be signed in again within the hour — which is
|
|
1694
|
+
* exactly the device the user was cutting off.
|
|
1695
|
+
*/
|
|
1696
|
+
/** One connected client, as the account settings screen lists it. */
|
|
1697
|
+
interface OAuth2GrantSummary {
|
|
1698
|
+
id: number;
|
|
1699
|
+
clientId: string;
|
|
1700
|
+
clientName: string;
|
|
1701
|
+
resource: string;
|
|
1702
|
+
scopes: string[];
|
|
1703
|
+
createdAtMillis: number;
|
|
1704
|
+
lastUsedAtMillis?: number;
|
|
1705
|
+
}
|
|
1706
|
+
/** What a user has connected. Revoked grants are not listed — they are gone. */
|
|
1707
|
+
declare function listOAuth2GrantsService(userId: number): Promise<OAuth2GrantSummary[]>;
|
|
1708
|
+
/**
|
|
1709
|
+
* Disconnect one client.
|
|
1710
|
+
*
|
|
1711
|
+
* The user id is part of the statement's condition, not a check before it: the
|
|
1712
|
+
* id comes from a URL, and a grant belonging to somebody else must answer as if
|
|
1713
|
+
* it did not exist rather than as if it were merely not theirs.
|
|
1714
|
+
*/
|
|
1715
|
+
declare function revokeOAuth2GrantService(id: number, userId: number): Promise<void>;
|
|
1716
|
+
/**
|
|
1717
|
+
* Revoke every grant a user has — the authorization-server half of a global
|
|
1718
|
+
* revocation, called beside `deviceAuthorizationsRepository.denyAllActiveByUserId`.
|
|
1719
|
+
*
|
|
1720
|
+
* Tokens are revoked as well as the grants. Verification already refuses a token
|
|
1721
|
+
* whose grant is dead, so this changes no decision; it means a `SELECT` against
|
|
1722
|
+
* `oauth2_tokens` after a revoke-all does not show live-looking rows, which is
|
|
1723
|
+
* the sort of thing that gets read as a hole.
|
|
1724
|
+
*/
|
|
1725
|
+
declare function revokeAllOAuth2GrantsForUser(userId: number): Promise<void>;
|
|
1726
|
+
|
|
1595
1727
|
/**
|
|
1596
1728
|
* @spfn/auth - Main Router
|
|
1597
1729
|
*
|
|
@@ -1608,6 +1740,7 @@ declare function oauthNativeService(params: OAuthNativeParams): Promise<OAuthNat
|
|
|
1608
1740
|
* - Users: /_auth/users/*
|
|
1609
1741
|
* - Deletion: /_auth/deletion/request, /_auth/deletion/cancel
|
|
1610
1742
|
* - Admin: /_auth/admin/* (superadmin only)
|
|
1743
|
+
* - OAuth 2.1 authorization server: /_auth/oauth2/*, /.well-known/oauth-authorization-server
|
|
1611
1744
|
*/
|
|
1612
1745
|
declare const mainAuthRouter: _spfn_core_route.Router<{
|
|
1613
1746
|
sendVerificationCode: _spfn_core_route.RouteDef<{
|
|
@@ -2272,6 +2405,43 @@ declare const mainAuthRouter: _spfn_core_route.Router<{
|
|
|
2272
2405
|
createdAt: string | null;
|
|
2273
2406
|
};
|
|
2274
2407
|
}>;
|
|
2408
|
+
registerOAuth2Client: _spfn_core_route.RouteDef<{}, {}, Response>;
|
|
2409
|
+
getOAuth2Authorize: _spfn_core_route.RouteDef<{
|
|
2410
|
+
query: _sinclair_typebox.TObject<{
|
|
2411
|
+
client_id: _sinclair_typebox.TString;
|
|
2412
|
+
redirect_uri: _sinclair_typebox.TString;
|
|
2413
|
+
code_challenge: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
2414
|
+
code_challenge_method: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
2415
|
+
resource: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
2416
|
+
scope: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
2417
|
+
state: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
2418
|
+
}>;
|
|
2419
|
+
}, {}, OAuth2ConsentView>;
|
|
2420
|
+
createOAuth2AuthorizationCode: _spfn_core_route.RouteDef<{
|
|
2421
|
+
body: _sinclair_typebox.TObject<{
|
|
2422
|
+
approve: _sinclair_typebox.TBoolean;
|
|
2423
|
+
client_id: _sinclair_typebox.TString;
|
|
2424
|
+
redirect_uri: _sinclair_typebox.TString;
|
|
2425
|
+
code_challenge: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
2426
|
+
code_challenge_method: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
2427
|
+
resource: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
2428
|
+
scope: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
2429
|
+
state: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
2430
|
+
}>;
|
|
2431
|
+
}, {}, OAuth2AuthorizationCodeIssued>;
|
|
2432
|
+
oauth2Token: _spfn_core_route.RouteDef<{}, {}, Response>;
|
|
2433
|
+
oauth2Revoke: _spfn_core_route.RouteDef<{}, {}, Response>;
|
|
2434
|
+
listOAuth2Grants: _spfn_core_route.RouteDef<{}, {}, {
|
|
2435
|
+
grants: OAuth2GrantSummary[];
|
|
2436
|
+
}>;
|
|
2437
|
+
revokeOAuth2Grant: _spfn_core_route.RouteDef<{
|
|
2438
|
+
params: _sinclair_typebox.TObject<{
|
|
2439
|
+
id: _sinclair_typebox.TNumber;
|
|
2440
|
+
}>;
|
|
2441
|
+
}, {}, {
|
|
2442
|
+
revoked: boolean;
|
|
2443
|
+
}>;
|
|
2444
|
+
oauth2AuthorizationServerMetadata: _spfn_core_route.RouteDef<{}, {}, Response>;
|
|
2275
2445
|
}>;
|
|
2276
2446
|
|
|
2277
2447
|
/**
|
|
@@ -2566,4 +2736,4 @@ declare const machineAuth: _spfn_core_route.NamedMiddleware<"machineAuth">;
|
|
|
2566
2736
|
*/
|
|
2567
2737
|
declare const requireMachineScope: _spfn_core_route.NamedMiddlewareFactory<"machineScope", string[]>;
|
|
2568
2738
|
|
|
2569
|
-
export {
|
|
2739
|
+
export { type FinishPasskeyEnrollmentParams as $, type AuthInitOptions as A, type ChangePasswordParams as B, type ConfirmSignupLinkResult as C, type DeviceAuthInfoResult as D, type CompletePasswordResetParams as E, type FinishPasskeyEnrollmentResult as F, type CompleteSignupParams as G, type ConfirmPasswordResetParams as H, type IssueOneTimeTokenResult as I, type ConfirmSignupLinkParams as J, type KeySummary as K, type LoginResult as L, type DenyDeviceAuthParams as M, type NewPasskey as N, type OAuthStartResult as O, type PermissionConfig as P, type DeviceAuthApprovedResult as Q, type RoleConfig as R, type SendVerificationCodeResult as S, type DeviceAuthInfoParams as T, type UserProfile as U, VERIFICATION_PURPOSES as V, type DeviceAuthPendingResult as W, DeviceAuthPollResponseSchema as X, DeviceNameSchema as Y, EmailSchema as Z, FingerprintSchema as _, type RegisterResult as a, finishPasskeyLoginService as a$, type FinishPasskeyLoginParams as a0, KEY_FINGERPRINT_PREFIX_LENGTH as a1, KeyIdSchema as a2, type LoginParams as a3, type LogoutParams as a4, type MachinePrincipal as a5, type MachineVerifierRegistration as a6, type NativeVerifyOptions as a7, type NormalizedIdentity as a8, type OAuth2AuthorizeParams as a9, type SendVerificationCodeParams as aA, type StartDeviceAuthParams as aB, type StartPasskeyEnrollmentParams as aC, TargetTypeSchema as aD, type UnlinkNotification as aE, UnlinkNotifyRejection as aF, type UnlinkNotifyRequest as aG, type UnlinkNotifyResult as aH, UserCodeSchema as aI, VerificationPurposeSchema as aJ, type VerifyCodeParams as aK, type VerifyCodeResult as aL, approveDeviceAuthService as aM, approveOAuth2AuthorizeService as aN, assertNotLastRecoveryCredential as aO, assertRecentAuthentication as aP, authenticate as aQ, buildOAuthErrorUrl as aR, changePasswordService as aS, completePasswordResetService as aT, completeSignupService as aU, confirmPasswordResetService as aV, confirmSignupLinkService as aW, denyDeviceAuthService as aX, denyOAuth2AuthorizeService as aY, describeOAuth2AuthorizeRequestService as aZ, finishPasskeyEnrollmentService as a_, type OAuth2ScopeDescription as aa, type OAuthCallbackParams as ab, type OAuthCallbackResult as ac, type OAuthCodeExchangeOptions as ad, type OAuthNativeParams as ae, type OAuthStartParams as af, type OAuthTokens as ag, PASSKEY_DEVICE_TYPES as ah, PASSKEY_LABEL_MAX_LENGTH as ai, type PasskeyDeviceType as aj, PasswordSchema as ak, PhoneSchema as al, PlatformSchema as am, type PollDeviceAuthParams as an, type PollDeviceAuthResult as ao, PublicKeySchema as ap, type RecentAuthenticationParams as aq, type RegisterParams as ar, type RegisterPublicKeyParams as as, type RenamePasskeyParams as at, type RequestPasswordResetParams as au, type RequestSignupLinkParams as av, type RevokeAllKeysParams as aw, type RevokeKeyParams as ax, type RevokePasskeyParams as ay, type RotateKeyParams as az, type RequestSignupLinkResult as b, getDeviceAuthInfoService as b0, getEnabledOAuthProviders as b1, getGoogleAccessToken as b2, getMachinePrincipal as b3, getOAuthProvider as b4, getRegisteredProviders as b5, isOAuthProviderEnabled as b6, issueOneTimeTokenService as b7, listKeysService as b8, listOAuth2GrantsService as b9, revokePasskeyService as bA, rotateKeyService as bB, runAuthProfile as bC, selectAuthProfile as bD, sendVerificationCodeService as bE, startDeviceAuthService as bF, startPasskeyEnrollmentService as bG, startPasskeyLoginService as bH, verifyCodeService as bI, verifyOneTimeTokenService as bJ, listPasskeysService as ba, loginService as bb, logoutService as bc, machineAuth as bd, oauthCallbackService as be, oauthNativeService as bf, oauthStartService as bg, oauthUnlinkNotifyService as bh, optionalAuth as bi, passkeys as bj, pollDeviceAuthService as bk, registerAuthProfile as bl, registerMachineVerifier as bm, registerOAuthProvider as bn, registerPublicKeyService as bo, registerService as bp, renamePasskeyService as bq, requestPasswordResetService as br, requestSignupLinkService as bs, requireEnabledProvider as bt, requireMachineScope as bu, resolveAuthenticatedUser as bv, revokeAllKeysService as bw, revokeAllOAuth2GrantsForUser as bx, revokeKeyService as by, revokeOAuth2GrantService as bz, type RequestPasswordResetResult as c, type ConfirmPasswordResetResult as d, type StartDeviceAuthResult as e, type PasskeySummary as f, type RotateKeyResult as g, type RevokeAllKeysResult as h, type OAuthNativeResult as i, type ProfileInfo as j, type OAuth2ConsentView as k, type OAuth2AuthorizationCodeIssued as l, mainAuthRouter as m, type OAuth2GrantSummary as n, type AuthSession as o, PERMISSION_CATEGORIES as p, type PermissionCategory as q, VERIFICATION_TARGET_TYPES as r, type VerificationPurpose as s, type VerificationTargetType as t, type OAuthProvider as u, type Passkey as v, type AuthContext as w, type ApproveDeviceAuthParams as x, type AuthProfileOutcome as y, type AuthProfileVerifier as z };
|
package/dist/nextjs/api.js
CHANGED
|
@@ -285,8 +285,13 @@ function getCsrfMode() {
|
|
|
285
285
|
}
|
|
286
286
|
return normalized;
|
|
287
287
|
}
|
|
288
|
+
var PACKAGE_CSRF_EXEMPT_PATHS = [
|
|
289
|
+
"/_auth/oauth2/register",
|
|
290
|
+
"/_auth/oauth2/token",
|
|
291
|
+
"/_auth/oauth2/revoke"
|
|
292
|
+
];
|
|
288
293
|
function getCsrfExemptPaths() {
|
|
289
|
-
return globalConfig.csrf?.exemptPaths ?? [];
|
|
294
|
+
return [...PACKAGE_CSRF_EXEMPT_PATHS, ...globalConfig.csrf?.exemptPaths ?? []];
|
|
290
295
|
}
|
|
291
296
|
|
|
292
297
|
// src/nextjs/interceptors/cookie-options.ts
|