Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
Added¶
JaduAuthProvidernow injects a<link rel="preconnect" crossorigin="use-credentials">for theapiUrlorigin on mount, warming the DNS + TCP + TLS handshake that the mount-timeGET /api/auth/sso/meprobe would otherwise pay cold. The probe is usually the only request on the page pointed at the auth origin, so it is the only one exposed to handshake packet loss — a single dropped SYN there costs seconds of kernel retransmit backoff. For the hint to buy real lead time it should also go in the app's HTML<head>, where the browser can start the handshake during HTML parse instead of at React mount; see the README.use-credentialsis required, since the probe sendscredentials: "include"and a socket opened in another credentials mode is not reused for it.
Fixed¶
- The mount-time
GET /api/auth/sso/meprobe now times out after 15s instead of 5s. On a lossy path a dropped TCP SYN (1-7s of kernel retransmit backoff) plus the CORS preflight round trip regularly pushed a healthy session past 5s, and the abort showed a signed-in user the "couldn't sign you in" screen. - Impersonation no longer ends on a page reload. It is carried by the access
token, never the session token, so the mount-time
GET /api/auth/sso/meprobe authenticates the real session and answers as the real user —initializeAuthwas adopting that response and overwriting the impersonated access token, spine token and cached user. It now keeps the impersonated set when a valid impersonation access token is stored, and restoresoriginalUserso the banner survives too. Consumers that reload fromonImpersonationStart(the documented way to refetch as the impersonated user) were losing impersonation every time. - An expired impersonation token now lapses back to the real user, clears the
stored original, and fires
onImpersonationEnd— restoring 1.5.x behaviour. - Redeeming a
?code(a brand-new session) drops any impersonation left over from the previous one instead of adopting it.
Removed¶
onSessionProbeprovider prop andSessionProbeResulttype, briefly published in 2.0.5. Probe telemetry will return as built-in SDK logging.
[2.0.0] - JaduSSO¶
BREAKING. The SDK is now JaduSSO-only. Tenants no longer own login UI; login lives on jadu-account, and the SDK handles the cookie-based session probe + impersonation + RBAC reads. Major version bump reflects the removed credential surface and the provider/option renames below.
Added¶
startJaduSSO(overrides?)onuseJaduAuth()— arg-less SSO redirect that readsjaduSSOUrl+authAppIdfrom the provider and defaultsreturnToto the current URL, then sends the browser tojaduSSOUrl/login?appId=…&returnTo=…. Tenants render a "Login using JaduAccount" button that callsstartJaduSSO().jaduSSOUrlprop onJaduAuthProvider— the jadu-account login host used bystartJaduSSO().buildJaduSSOUrl(opts)(@scenarix/jadu-authand@scenarix/jadu-auth/react) — lower-level URL builder for SSR, anchorhrefs, or tests where there's no hook context. Takes{ jaduSSOUrl, appId, returnTo }.JaduAuthProviderperforms a cookie-onlyGET /api/auth/sso/meon mount withx-auth-app-id. The BE verifies cookie + RBAC for the app in a single trip and returns{ user, accessToken, sessionToken, jaduSpineToken }. The SDK seeds local storage with the result soauthenticatedAxios,canUserDo, scheduled refresh, and impersonation all work without further round trips.autoSSORedirectprop onJaduAuthProvider(defaultfalse) — when enabled, the mount-time probe auto-redirects to JaduSSO login on a clean 401/403 instead of waiting for a button click. RequiresjaduSSOUrl. A per-tab loop guard (sessionStorage) caps consecutive auto-redirects so a non-returning session cookie can't cause an infinite redirect loop; transient/network failures and explicitlogout()never auto-redirect.ssoRedirectingandssoRedirectBlockedon theuseJaduAuth()surface — drive a "Signing you in…" placeholder vs. the manual fallback button.
Removed¶
JaduAuthModeand themodeprop onJaduAuthProvider. v2 is the only flow.- All credential-owning methods on
useJaduAuth():loginWithEmailPassword,signupWithEmailPassword,forgotPasswordInit,forgotPasswordVerify,sendVerificationEmail,verifyEmail,signupInitWithEmailOtp,signupVerifyWithEmailOtp,loginInitWithEmailOtp,loginVerifyWithEmailOtp,loginInitWithSmsOtp,loginVerifyWithSmsOtp,refreshToken,simulateAccessTokenExpiry. Login is jadu-account's job. - Strategy blocks on
AuthClient:emailPassword.*,emailOtp.*,smsOtp.*. Use jadu-account's BE directly if you need to drive credential flows server-side. AuthErrorCode.NOT_SUPPORTED_IN_V2(no longer reachable),AuthErrorCode.INVALID_CREDENTIALS,AuthErrorCode.USER_ALREADY_EXISTS.InvalidCredentialsError,UserAlreadyExistsError.- Type re-exports:
AuthStrategies,LoginRequest,SignupRequest,VerifyEmailRequest,SendVerificationEmailRequest,SignupResponse,isSignupResponse,JaduAuthMode,SignupResult.
Changed¶
- Renamed the
jaduAuthUrlprovider prop /JaduSSOOptionsfield →jaduSSOUrl(alsobuildJaduSSOUrl({ jaduSSOUrl, … })). Update call sites. - The provider's session probe moved from
GET /api/auth/meto the new cookie-onlyGET /api/auth/sso/me.
Backend (additive — no removals)¶
- New
GET /api/auth/sso/me(cookie-only, behindauthenticateSessionCookieOnly). Requiresx-auth-app-id(rejected with 400 if missing) and returns{ user, accessToken, jaduSpineToken, sessionToken }. Bearer-only requests are rejected at 401. - Legacy
GET /api/auth/meis unchanged (still cookie-or-Bearer, returns{ user }), so existing SDK versions keep working. v1 cleanup is deferred. logoutnow clears the session cookie with the full cookie options (path + domain) so it actually clears in production.- New optional
SESSION_COOKIE_DOMAINenv (e.g..studiojadu.comin prod) for cross-subdomain SSO; unset in dev.
Fixed¶
be/src/index.ts: wait for async error logging to flush before exiting onuncaughtException.useJaduAuth: preserve optimisticsetUser(cachedUser)for non-impersonation session restores while still keeping impersonation-safe cleanup.package/src/server/jaduAuth.ts: temporarily relax JWTauthAppIdenforcement (fall back to configuredappId) to unblock production token validation.
[1.5.0]¶
Removed¶
AuthClient.getSessions()andGET /api/auth/sessions— not implemented on jadu-auth serverAuthClient.changePassword()anduseJaduAuth().changePassword—POST /api/auth/change-passwordnot implemented on jadu-auth server
[0.1.0] - 2025-02-09¶
Added¶
- Initial release of
@scenarix/jadu-auth JaduAuthProvideranduseJaduAuthReact integrationAuthClientfor low-level auth API callscreateAuthenticatedAxioswith automatic token refreshJaduAuthserver SDK for JWT verification- Email verification, password reset, and forgot password flows
Fixed¶
- getMe response shape: Backend returns
{ data: { user: User } }; SDK now correctly extractsuserinstead of treating entiredataasUser - Error mapping: When backend omits
error.code, SDK now infers error type from HTTP status (400→VALIDATION_ERROR, 401→SESSION_EXPIRED, etc.) - EMAIL_NOT_VERIFIED: Added handling for backend
errorCode: 'EMAIL_NOT_VERIFIED'in error responses
Changed¶
- Replaced magic number
15 * 60 * 1000withDEFAULT_ACCESS_TOKEN_TTL_MSconstant - Unified debug log prefix to
[JaduAuth]across authClient and authenticatedAxios - Made
ApiErrorResponse.erroroptional to align with backend response shape - Added
appIdto provider init effect dependencies
Added (API)¶
changePassword(currentPassword, newPassword)onuseJaduAuthfor authenticated password changesVERSIONandSDK_NAMEexports from main package- Security note in TokenStorage JSDoc regarding localStorage and XSS
Removed¶
getAuthClientandinitAuthClient(unused singletons; usenew AuthClient(config)instead)