You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: mintlify/snippets/sandbox-global-account-magic.mdx
+16-8Lines changed: 16 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
-
The Grid sandbox accepts a small set of magic values for Global Account flows, so you can exercise the full request shape without standing up Turnkey, WebAuthn, or an OIDC provider. OTP, passkey, and wallet signatures use fixed sandbox-only values. OAuth uses JWT-shaped sandbox OIDC tokens: sandbox skips real IdP signature verification, but still validates the token claims, freshness, credential identity, and verify-time nonce binding.
1
+
The Grid sandbox lets you exercise Global Account auth flows without moving real money. Email OTP uses the fixed sandbox code `000000`. Passkey auth can use the same browser WebAuthn ceremony as production. Wallet signatures use fixed sandbox-only values. OAuth uses JWT-shaped sandbox OIDC tokens: sandbox skips real IdP signature verification, but still validates token claims, freshness, credential identity, and verify-time nonce binding.
2
2
3
-
A wrong magic value or sandbox OIDC authentication failure returns`401 UNAUTHORIZED` with a `reason` field that names the specific check that failed. A malformed OIDC JWT can return `400 INVALID_INPUT` before authentication starts.
3
+
Sandbox-only compatibility values are still available for some flows, but they do not exercise the production-shaped client implementation. Authentication failures return`401 UNAUTHORIZED` with a `reason` field that names the specific check that failed. A malformed OIDC JWT can return `400 INVALID_INPUT` before authentication starts.
4
4
5
5
### Email OTP code
6
6
@@ -20,11 +20,17 @@ curl -X POST https://api.lightspark.com/grid/2025-10-13/auth/credentials/AuthMet
20
20
21
21
Any other code returns `401 UNAUTHORIZED` with `reason: "Invalid OTP code"`.
22
22
23
-
### Passkey assertion signature
23
+
### Passkey WebAuthn ceremony
24
24
25
-
Pass `sandbox-valid-passkey-signature` as `assertion.signature` on `POST /auth/credentials/{id}/verify` when the credential type is `PASSKEY`. The sandbox accepts the rest of the assertion as-is and skips the WebAuthn signature check.
25
+
For new sandbox integrations, use the same WebAuthn calls you plan to use in production.
26
26
27
-
Passkey reauthentication is a two-step `/challenge` → `/verify` flow. The `clientPublicKey` is sent on `/challenge` (so Grid can seal the session signing key to your device) — the magic value bypasses the credential check, not the HPKE plumbing, so the public key is still required.
27
+
1. Generate your own WebAuthn registration challenge and call `navigator.credentials.create()`.
28
+
2. Register the passkey with `POST /auth/credentials`, passing the challenge and attestation returned by the browser.
29
+
3. Reauthenticate with `POST /auth/credentials/{id}/challenge`, passing the P-256 `clientPublicKey` that Grid should seal the session signing key to.
30
+
4. Pass the returned `challenge` into `navigator.credentials.get()` using the returned `credentialId` in `allowCredentials`.
31
+
5. Verify with `POST /auth/credentials/{id}/verify`, passing the browser assertion and echoing `Request-Id` from the challenge response.
32
+
33
+
The sandbox validates the registered credential ID, WebAuthn challenge, origin/RP binding, user-presence bit, assertion signature, and signature counter. A successful verify response includes `encryptedSessionSigningKey`, sealed to the `clientPublicKey`, just like production.
28
34
29
35
```bash
30
36
# 1. /challenge with clientPublicKey
@@ -35,7 +41,7 @@ curl -X POST https://api.lightspark.com/grid/2025-10-13/auth/credentials/AuthMet
35
41
"clientPublicKey": "04f45f2a..."
36
42
}'
37
43
38
-
# 2. /verify with the magic signature, no clientPublicKey
44
+
# 2. /verify with the browser assertion returned by navigator.credentials.get()
39
45
curl -X POST https://api.lightspark.com/grid/2025-10-13/auth/credentials/AuthMethod:abc123/verify \
40
46
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
41
47
-H "Content-Type: application/json" \
@@ -46,12 +52,14 @@ curl -X POST https://api.lightspark.com/grid/2025-10-13/auth/credentials/AuthMet
46
52
"credentialId": "...",
47
53
"clientDataJson": "...",
48
54
"authenticatorData": "...",
49
-
"signature": "sandbox-valid-passkey-signature"
55
+
"signature": "..."
50
56
}
51
57
}'
52
58
```
53
59
54
-
Any other signature returns `401 UNAUTHORIZED` with `reason: "Invalid passkey signature"`.
60
+
<Note>
61
+
The legacy sandbox-only assertion signature `sandbox-valid-passkey-signature` is still accepted for compatibility, but it skips WebAuthn verification and should not be used for production-shaped sandbox tests.
0 commit comments