@spfn/auth 0.3.0-beta.8 → 0.3.0-beta.9

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 CHANGED
@@ -140,14 +140,15 @@ real secret values out of band, never commit them.
140
140
  | `SPFN_AUTH_ADMIN_*` | `.env.server` | — | admin seeding (see below) |
141
141
  | `SPFN_AUTH_GOOGLE_CLIENT_ID` / `_CLIENT_SECRET` | `.env.server` | — | enables Google OAuth when both set |
142
142
  | `SPFN_AUTH_GOOGLE_SCOPES` | `.env.server` | — | comma-separated; default `email,profile` |
143
- | `SPFN_AUTH_GOOGLE_REDIRECT_URI` | `.env.server` | — | default `{NEXT_PUBLIC_SPFN_APP_URL\|\|SPFN_APP_URL}/_auth/oauth/google/callback` — see [OAuth callback origin](#oauth-callback-origin-web-app-host--rewrite) |
143
+ | `SPFN_AUTH_GOOGLE_REDIRECT_URI` | `.env.server` | — | default `{NEXT_PUBLIC_SPFN_APP_URL\|\|SPFN_APP_URL}/_auth/oauth/google/callback`; an override must stay on the web app origin at that path and is **checked at boot** — see [OAuth callback origin](#oauth-callback-origin-web-app-host--rewrite) |
144
144
  | `SPFN_AUTH_KAKAO_CLIENT_ID` / `_CLIENT_SECRET` | `.env.server` | — | REST API key enables Kakao Login; secret is included when configured |
145
145
  | `SPFN_AUTH_KAKAO_ADMIN_KEY` | `.env.server` | — | app admin key; required to verify the Kakao User Unlinked webhook |
146
- | `SPFN_AUTH_KAKAO_SCOPES` / `_REDIRECT_URI` | `.env.server` | — | default scope `account_email`; callback `/_auth/oauth/kakao/callback` |
146
+ | `SPFN_AUTH_KAKAO_SCOPES` / `_REDIRECT_URI` | `.env.server` | — | default scope `account_email`; callback `/_auth/oauth/kakao/callback` on the web app origin, **checked at boot** — see [OAuth callback origin](#oauth-callback-origin-web-app-host--rewrite) |
147
147
  | `SPFN_AUTH_NAVER_CLIENT_ID` / `_CLIENT_SECRET` | `.env.server` | — | both values enable Naver Login |
148
- | `SPFN_AUTH_NAVER_REDIRECT_URI` | `.env.server` | — | default `{NEXT_PUBLIC_SPFN_APP_URL\|\|SPFN_APP_URL}/_auth/oauth/naver/callback` |
148
+ | `SPFN_AUTH_NAVER_REDIRECT_URI` | `.env.server` | — | default `{NEXT_PUBLIC_SPFN_APP_URL\|\|SPFN_APP_URL}/_auth/oauth/naver/callback`; an override must stay on the web app origin at that path and is **checked at boot** — see [OAuth callback origin](#oauth-callback-origin-web-app-host--rewrite) |
149
149
  | `SPFN_AUTH_GITHUB_CLIENT_ID` / `_CLIENT_SECRET` | `.env.server` | — | both values enable GitHub OAuth |
150
- | `SPFN_AUTH_GITHUB_SCOPES` / `_REDIRECT_URI` | `.env.server` | — | default scopes `read:user,user:email`; callback `/_auth/oauth/github/callback` |
150
+ | `SPFN_AUTH_GITHUB_SCOPES` / `_REDIRECT_URI` | `.env.server` | — | default scopes `read:user,user:email`; callback `/_auth/oauth/github/callback` on the web app origin, **checked at boot** — see [OAuth callback origin](#oauth-callback-origin-web-app-host--rewrite) |
151
+ | `SPFN_AUTH_OAUTH_CALLBACK_ORIGIN_CHECK` | `.env.server` | — | `off` disables the boot check of the four `_REDIRECT_URI` overrides; any other value (unset included) runs it — see [OAuth callback origin](#oauth-callback-origin-web-app-host--rewrite) |
151
152
  | `SPFN_AUTH_GOOGLE_NATIVE_CLIENT_IDS` | `.env.server` | — | comma-separated client IDs accepted as native id_token audience (iOS/Android/web); enables Google native sign-in |
152
153
  | `SPFN_AUTH_APPLE_CLIENT_IDS` | `.env.server` | — | comma-separated Apple client IDs (bundle ID / Services ID); enables Apple native sign-in |
153
154
  | `SPFN_AUTH_KAKAO_NATIVE_CLIENT_IDS` | `.env.server` | — | comma-separated Kakao app keys accepted as native id_token audience (native app key); `SPFN_AUTH_KAKAO_CLIENT_ID` is also accepted, so either one enables Kakao native sign-in |
@@ -426,6 +427,11 @@ await authApi.revokeAllKeys.call({ body: { includeCurrent: true } }); // every
426
427
  > naming the cause. Proof-bearing auth operations are shaped this way; the unproven,
427
428
  > bodyless `core.time` synchronization prerequisite is the explicit exception.
428
429
 
430
+ - **A key must be the type its algorithm names.** A P-256 SPKI declared `RS256`, an RSA key
431
+ declared `ES256`, and a curve other than P-256 declared `ES256` are each refused 400 with
432
+ `KeyAlgorithmMismatchError` on register, login, rotate and device start — the algorithm is
433
+ stored beside the key and read back at proof verification, so a mismatch accepted at
434
+ enrollment would surface only once the device already believed it was enrolled.
429
435
  - **The public key never leaves the server**, and the fingerprint is truncated to 8 characters.
430
436
  The list exists to recognise a device and point at it; the full fingerprint is what a native
431
437
  sign-in sends as its nonce, not a label.
@@ -633,9 +639,25 @@ process), which differs from the API process in a split deployment — the callb
633
639
  matches every `spfn_oauth_csrf*` cookie candidate against the state nonce, so no PORT
634
640
  coordination is needed.
635
641
 
642
+ An explicit `SPFN_AUTH_<PROVIDER>_REDIRECT_URI` is checked when the server boots, because the
643
+ value used to be read lazily on the first OAuth request and a wrong one surfaced much later as
644
+ a CSRF refusal nobody traced back to it. A value that does not parse, or whose origin is not the
645
+ web app origin, or whose path is not `/_auth/oauth/<provider>/callback`, refuses to start — one
646
+ error naming every offending variable:
647
+
648
+ ```
649
+ SPFN_AUTH_GOOGLE_REDIRECT_URI must be on the web app origin (http://localhost:3790) at
650
+ /_auth/oauth/google/callback: the callback's CSRF cookie is host-only and /_auth/* is forwarded
651
+ to the API by the app's rewrite. Unset it to use the default, fix the origin, or set
652
+ SPFN_AUTH_OAUTH_CALLBACK_ORIGIN_CHECK=off for a deployment that deliberately terminates the
653
+ callback elsewhere.
654
+ ```
655
+
636
656
  One caveat: the direct `POST /_auth/oauth/start` flow (no Next.js interceptor) sets its CSRF
637
- cookie on the **API host**. If you use that flow in a split deployment, set
638
- the corresponding provider redirect URI explicitly to the API host callback instead.
657
+ cookie on the **API host**. If you use that flow in a split deployment, set the corresponding
658
+ provider redirect URI explicitly to the API host callback **and**
659
+ `SPFN_AUTH_OAUTH_CALLBACK_ORIGIN_CHECK=off` — that is the one deployment the check is wrong
660
+ about, and `off` is the only value that disables it.
639
661
 
640
662
  ### Native social sign-in (mobile / web id_token)
641
663
 
@@ -1733,7 +1755,9 @@ deploy.
1733
1755
  Almost always the callback origin. The CSRF check is a double-submit against a host-only
1734
1756
  cookie set on your **web app** host, so the provider must return to the web app origin, and
1735
1757
  the app must forward `/_auth/*` to the API with a Next.js rewrite. Without that rewrite the
1736
- callback 404s — including in local dev. Details in
1758
+ callback 404s — including in local dev. An explicit `SPFN_AUTH_<PROVIDER>_REDIRECT_URI` on the
1759
+ wrong origin or path no longer gets that far: it fails at boot with a message naming the
1760
+ variable. Details in
1737
1761
  [OAuth callback origin](#oauth-callback-origin-web-app-host--rewrite).
1738
1762
 
1739
1763
  **Does the server hold my users' private keys?**
@@ -1397,7 +1397,7 @@ function isAppKind(kind) {
1397
1397
  }
1398
1398
 
1399
1399
  // src/server/client-proof/contract-bundle.ts
1400
- var CONTRACT_VERSION = "0.10.0";
1400
+ var CONTRACT_VERSION = "0.10.1";
1401
1401
  var CONTRACT_MAJOR = 0;
1402
1402
  var CONTRACT_SUPPORTED_RANGE = ">=0.10.0 <0.11.0";
1403
1403
  function required(name, type) {