@spfn/auth 0.3.0-beta.16 → 0.3.0-beta.17
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 +10 -0
- package/dist/index.d.ts +2 -2
- package/dist/{machine-principals-Dn-7BqYZ.d.ts → machine-principals-nrpFSvvB.d.ts} +1 -10
- package/dist/nextjs/api.js +36 -0
- package/dist/nextjs/api.js.map +1 -1
- package/dist/nextjs/client.d.ts +28 -1
- package/dist/nextjs/client.js +24 -3
- package/dist/nextjs/client.js.map +1 -1
- package/dist/nextjs/server.d.ts +2 -1
- package/dist/nextjs/server.js +22 -1
- package/dist/nextjs/server.js.map +1 -1
- package/dist/server.d.ts +3 -3
- package/dist/server.js +17 -2
- package/dist/server.js.map +1 -1
- package/dist/{session-DTHahDQ9.d.ts → session-Dfwu5g2W.d.ts} +28 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -949,6 +949,16 @@ Both convenience URL APIs seal `metadata` into the encrypted OAuth state. On a n
|
|
|
949
949
|
signup, the callback passes it to `beforeRegister` and `authRegisterEvent`; existing-account
|
|
950
950
|
logins do not run the registration hook.
|
|
951
951
|
|
|
952
|
+
`returnUrl` must be a path inside your app — absolute URLs, `//host`, `..`, a backslash, and a
|
|
953
|
+
tab/CR/LF (which a URL parser strips, turning `/<tab>/host` into `//host`) are refused, so a
|
|
954
|
+
real login cannot become an open redirect. The start seams answer an unsafe value with a 400
|
|
955
|
+
`ValidationError`; the seams that already hold a logged-in user replace the destination instead
|
|
956
|
+
of failing the login — `OAuthCallback` navigates to `/` and `createOAuthCallbackHandler`
|
|
957
|
+
redirects to its `defaultRedirectUrl` (`/` unless you pass one). The rule is exported as
|
|
958
|
+
`isSafeReturnPath` from `@spfn/auth/server`, `@spfn/auth/nextjs/server`, and
|
|
959
|
+
`@spfn/auth/nextjs/client` for apps that validate a destination before calling
|
|
960
|
+
`getGoogleOAuthUrl`.
|
|
961
|
+
|
|
952
962
|
Built-in OAuth routes: `POST /_auth/oauth/google/url`, `GET /_auth/oauth/google` (redirect),
|
|
953
963
|
`GET /_auth/oauth/google/callback`, `POST /_auth/oauth/finalize`, `GET /_auth/oauth/providers`,
|
|
954
964
|
plus the provider-generic `POST /_auth/oauth/start`. `getGoogleAccessToken(userId)` returns a
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _spfn_core_nextjs from '@spfn/core/nextjs';
|
|
2
|
-
import { P as PermissionConfig, R as RoleConfig, m as mainAuthRouter, S as SendVerificationCodeResult, a as RegisterResult, b as RequestSignupLinkResult, C as ConfirmSignupLinkResult, c as RequestPasswordResetResult, d as ConfirmPasswordResetResult, L as LoginResult, e as StartDeviceAuthResult, D as DeviceAuthInfoResult, F as FinishPasskeyEnrollmentResult, f as PasskeySummary, g as RotateKeyResult, K as KeySummary, h as RevokeAllKeysResult, I as IssueOneTimeTokenResult, O as OAuthStartResult, i as OAuthNativeResult, U as UserProfile, j as ProfileInfo } from './machine-principals-
|
|
3
|
-
export { A as AuthInitOptions, k as AuthSession, l as PERMISSION_CATEGORIES, n as PermissionCategory, V as VERIFICATION_PURPOSES, o as VERIFICATION_TARGET_TYPES, p as VerificationPurpose, q as VerificationTargetType } from './machine-principals-
|
|
2
|
+
import { P as PermissionConfig, R as RoleConfig, m as mainAuthRouter, S as SendVerificationCodeResult, a as RegisterResult, b as RequestSignupLinkResult, C as ConfirmSignupLinkResult, c as RequestPasswordResetResult, d as ConfirmPasswordResetResult, L as LoginResult, e as StartDeviceAuthResult, D as DeviceAuthInfoResult, F as FinishPasskeyEnrollmentResult, f as PasskeySummary, g as RotateKeyResult, K as KeySummary, h as RevokeAllKeysResult, I as IssueOneTimeTokenResult, O as OAuthStartResult, i as OAuthNativeResult, U as UserProfile, j as ProfileInfo } from './machine-principals-nrpFSvvB.js';
|
|
3
|
+
export { A as AuthInitOptions, k as AuthSession, l as PERMISSION_CATEGORIES, n as PermissionCategory, V as VERIFICATION_PURPOSES, o as VERIFICATION_TARGET_TYPES, p as VerificationPurpose, q as VerificationTargetType } from './machine-principals-nrpFSvvB.js';
|
|
4
4
|
import * as _simplewebauthn_server from '@simplewebauthn/server';
|
|
5
5
|
import * as _spfn_core_route from '@spfn/core/route';
|
|
6
6
|
import { HttpMethod } from '@spfn/core/route';
|
|
@@ -300,15 +300,6 @@ declare function verifyCodeService(params: VerifyCodeParams): Promise<{
|
|
|
300
300
|
* is a second entry point to the same account creation, not a replacement.
|
|
301
301
|
*/
|
|
302
302
|
|
|
303
|
-
/**
|
|
304
|
-
* Whether a return path can be handed back to the browser.
|
|
305
|
-
*
|
|
306
|
-
* Only a path within the app is allowed. The rejected shapes are the ones that
|
|
307
|
-
* turn a return path into an open redirect: an absolute URL, a protocol-relative
|
|
308
|
-
* `//host` that a browser reads as another origin, a backslash that some
|
|
309
|
-
* browsers normalize into a slash, and any `..` traversal.
|
|
310
|
-
*/
|
|
311
|
-
declare function isSafeReturnPath(returnPath: string): boolean;
|
|
312
303
|
interface RequestSignupLinkParams {
|
|
313
304
|
email: string;
|
|
314
305
|
returnPath?: string;
|
|
@@ -2575,4 +2566,4 @@ declare const machineAuth: _spfn_core_route.NamedMiddleware<"machineAuth">;
|
|
|
2575
2566
|
*/
|
|
2576
2567
|
declare const requireMachineScope: _spfn_core_route.NamedMiddlewareFactory<"machineScope", string[]>;
|
|
2577
2568
|
|
|
2578
|
-
export { KeyIdSchema as $, type AuthInitOptions as A, type ConfirmPasswordResetParams as B, type ConfirmSignupLinkResult as C, type DeviceAuthInfoResult as D, type ConfirmSignupLinkParams as E, type FinishPasskeyEnrollmentResult as F, type DenyDeviceAuthParams as G, type DeviceAuthApprovedResult as H, type IssueOneTimeTokenResult as I, type DeviceAuthInfoParams as J, type KeySummary as K, type LoginResult as L, type DeviceAuthPendingResult as M, type NewPasskey as N, type OAuthStartResult as O, type PermissionConfig as P, DeviceAuthPollResponseSchema as Q, type RoleConfig as R, type SendVerificationCodeResult as S, DeviceNameSchema as T, type UserProfile as U, VERIFICATION_PURPOSES as V, EmailSchema as W, FingerprintSchema as X, type FinishPasskeyEnrollmentParams as Y, type FinishPasskeyLoginParams as Z, KEY_FINGERPRINT_PREFIX_LENGTH as _, type RegisterResult as a,
|
|
2569
|
+
export { KeyIdSchema as $, type AuthInitOptions as A, type ConfirmPasswordResetParams as B, type ConfirmSignupLinkResult as C, type DeviceAuthInfoResult as D, type ConfirmSignupLinkParams as E, type FinishPasskeyEnrollmentResult as F, type DenyDeviceAuthParams as G, type DeviceAuthApprovedResult as H, type IssueOneTimeTokenResult as I, type DeviceAuthInfoParams as J, type KeySummary as K, type LoginResult as L, type DeviceAuthPendingResult as M, type NewPasskey as N, type OAuthStartResult as O, type PermissionConfig as P, DeviceAuthPollResponseSchema as Q, type RoleConfig as R, type SendVerificationCodeResult as S, DeviceNameSchema as T, type UserProfile as U, VERIFICATION_PURPOSES as V, EmailSchema as W, FingerprintSchema as X, type FinishPasskeyEnrollmentParams as Y, type FinishPasskeyLoginParams as Z, KEY_FINGERPRINT_PREFIX_LENGTH as _, type RegisterResult as a, issueOneTimeTokenService as a$, type LoginParams as a0, type LogoutParams as a1, type MachinePrincipal as a2, type MachineVerifierRegistration as a3, type NativeVerifyOptions as a4, type NormalizedIdentity as a5, type OAuthCallbackParams as a6, type OAuthCallbackResult as a7, type OAuthCodeExchangeOptions as a8, type OAuthNativeParams as a9, UnlinkNotifyRejection as aA, type UnlinkNotifyRequest as aB, type UnlinkNotifyResult as aC, UserCodeSchema as aD, VerificationPurposeSchema as aE, type VerifyCodeParams as aF, type VerifyCodeResult as aG, approveDeviceAuthService as aH, assertNotLastRecoveryCredential as aI, assertRecentAuthentication as aJ, authenticate as aK, buildOAuthErrorUrl as aL, changePasswordService as aM, completePasswordResetService as aN, completeSignupService as aO, confirmPasswordResetService as aP, confirmSignupLinkService as aQ, denyDeviceAuthService as aR, finishPasskeyEnrollmentService as aS, finishPasskeyLoginService as aT, getDeviceAuthInfoService as aU, getEnabledOAuthProviders as aV, getGoogleAccessToken as aW, getMachinePrincipal as aX, getOAuthProvider as aY, getRegisteredProviders as aZ, isOAuthProviderEnabled as a_, type OAuthStartParams as aa, type OAuthTokens as ab, PASSKEY_DEVICE_TYPES as ac, PASSKEY_LABEL_MAX_LENGTH as ad, type PasskeyDeviceType as ae, PasswordSchema as af, PhoneSchema as ag, PlatformSchema as ah, type PollDeviceAuthParams as ai, type PollDeviceAuthResult as aj, PublicKeySchema as ak, type RecentAuthenticationParams as al, type RegisterParams as am, type RegisterPublicKeyParams as an, type RenamePasskeyParams as ao, type RequestPasswordResetParams as ap, type RequestSignupLinkParams as aq, type RevokeAllKeysParams as ar, type RevokeKeyParams as as, type RevokePasskeyParams as at, type RotateKeyParams as au, type SendVerificationCodeParams as av, type StartDeviceAuthParams as aw, type StartPasskeyEnrollmentParams as ax, TargetTypeSchema as ay, type UnlinkNotification as az, type RequestSignupLinkResult as b, listKeysService as b0, listPasskeysService as b1, loginService as b2, logoutService as b3, machineAuth as b4, oauthCallbackService as b5, oauthNativeService as b6, oauthStartService as b7, oauthUnlinkNotifyService as b8, optionalAuth as b9, passkeys as ba, pollDeviceAuthService as bb, registerAuthProfile as bc, registerMachineVerifier as bd, registerOAuthProvider as be, registerPublicKeyService as bf, registerService as bg, renamePasskeyService as bh, requestPasswordResetService as bi, requestSignupLinkService as bj, requireEnabledProvider as bk, requireMachineScope as bl, resolveAuthenticatedUser as bm, revokeAllKeysService as bn, revokeKeyService as bo, revokePasskeyService as bp, rotateKeyService as bq, runAuthProfile as br, selectAuthProfile as bs, sendVerificationCodeService as bt, startDeviceAuthService as bu, startPasskeyEnrollmentService as bv, startPasskeyLoginService as bw, verifyCodeService as bx, verifyOneTimeTokenService as by, 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 AuthSession as k, PERMISSION_CATEGORIES as l, mainAuthRouter as m, type PermissionCategory as n, VERIFICATION_TARGET_TYPES as o, type VerificationPurpose as p, type VerificationTargetType as q, type OAuthProvider as r, type Passkey as s, type AuthContext as t, type ApproveDeviceAuthParams as u, type AuthProfileOutcome as v, type AuthProfileVerifier as w, type ChangePasswordParams as x, type CompletePasswordResetParams as y, type CompleteSignupParams as z };
|
package/dist/nextjs/api.js
CHANGED
|
@@ -846,6 +846,21 @@ async function createOAuthState(params) {
|
|
|
846
846
|
return encodeURIComponent(jwe);
|
|
847
847
|
}
|
|
848
848
|
|
|
849
|
+
// src/lib/return-path.ts
|
|
850
|
+
var URL_STRIPPED_CHARACTER = /[\t\n\r]/;
|
|
851
|
+
function isSafeReturnPath(returnPath) {
|
|
852
|
+
if (!returnPath.startsWith("/")) {
|
|
853
|
+
return false;
|
|
854
|
+
}
|
|
855
|
+
if (returnPath.startsWith("//") || returnPath.includes("\\")) {
|
|
856
|
+
return false;
|
|
857
|
+
}
|
|
858
|
+
if (returnPath.includes("..") || URL_STRIPPED_CHARACTER.test(returnPath)) {
|
|
859
|
+
return false;
|
|
860
|
+
}
|
|
861
|
+
return !/^\/[^/?#]*:/.test(returnPath);
|
|
862
|
+
}
|
|
863
|
+
|
|
849
864
|
// src/nextjs/session-helpers.ts
|
|
850
865
|
import * as jose3 from "jose";
|
|
851
866
|
import { cookies } from "next/headers.js";
|
|
@@ -872,6 +887,20 @@ async function unsealPendingSession(jwt2) {
|
|
|
872
887
|
}
|
|
873
888
|
|
|
874
889
|
// src/nextjs/interceptors/oauth.ts
|
|
890
|
+
var UNSAFE_RETURN_URL_MESSAGE = "returnUrl must be a relative path within the app";
|
|
891
|
+
function refuseUnsafeReturnUrl() {
|
|
892
|
+
return {
|
|
893
|
+
status: 400,
|
|
894
|
+
body: {
|
|
895
|
+
__type: "ValidationError",
|
|
896
|
+
message: UNSAFE_RETURN_URL_MESSAGE,
|
|
897
|
+
error: {
|
|
898
|
+
code: "ValidationError",
|
|
899
|
+
message: UNSAFE_RETURN_URL_MESSAGE
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
}
|
|
875
904
|
var oauthUrlInterceptor = {
|
|
876
905
|
pathPattern: /^\/_auth\/oauth\/\w+\/url$/,
|
|
877
906
|
method: "POST",
|
|
@@ -879,6 +908,13 @@ var oauthUrlInterceptor = {
|
|
|
879
908
|
const provider = ctx.path.split("/")[3];
|
|
880
909
|
const returnUrl = ctx.body?.returnUrl || "/";
|
|
881
910
|
const metadata = ctx.body?.metadata;
|
|
911
|
+
if (typeof returnUrl !== "string" || !isSafeReturnPath(returnUrl)) {
|
|
912
|
+
authLogger.interceptor.oauth?.warn?.("OAuth start refused: returnUrl is not a path within the app", {
|
|
913
|
+
provider
|
|
914
|
+
});
|
|
915
|
+
ctx.abort = refuseUnsafeReturnUrl();
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
882
918
|
const keyPair = generateKeyPair("ES256");
|
|
883
919
|
const csrfNonce = generateOAuthNonce();
|
|
884
920
|
const state = await createOAuthState({
|