Release 0.11.0: trust device for 30 days
This commit is contained in:
+38
-4
@@ -40,11 +40,16 @@ export async function requestOtc(email) {
|
||||
return jsonOrThrow(res)
|
||||
}
|
||||
|
||||
export async function verifyOtc(email, code) {
|
||||
export async function verifyOtc(email, code, { trustDevice = false } = {}) {
|
||||
// v0.11.0 — `trustDevice` is the "trust this device for 30 days"
|
||||
// checkbox on the Login.jsx OTC step. When true, the server mints
|
||||
// a fresh device-trust row and sets the long-lived cookie; on
|
||||
// subsequent visits, the cookie skips the OTC roundtrip via
|
||||
// `startDeviceTrust()`.
|
||||
const res = await fetch('/auth/otc/verify', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, code }),
|
||||
body: JSON.stringify({ email, code, trust_device: !!trustDevice }),
|
||||
})
|
||||
return jsonOrThrow(res)
|
||||
}
|
||||
@@ -82,15 +87,44 @@ export async function checkPasscode(email) {
|
||||
return jsonOrThrow(res)
|
||||
}
|
||||
|
||||
export async function verifyPasscode(email, passcode) {
|
||||
export async function verifyPasscode(email, passcode, { trustDevice = false } = {}) {
|
||||
// v0.11.0 — same trust-device opt-in as `verifyOtc`.
|
||||
const res = await fetch('/auth/passcode/verify', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, passcode }),
|
||||
body: JSON.stringify({ email, passcode, trust_device: !!trustDevice }),
|
||||
})
|
||||
return jsonOrThrow(res)
|
||||
}
|
||||
|
||||
// ── v0.11.0: trust device for 30 days (§6.2, roadmap item #9) ─────────────
|
||||
//
|
||||
// On a returning visit with a valid device-trust cookie, `startDeviceTrust`
|
||||
// re-establishes the session without an OTC / passcode roundtrip. The
|
||||
// cookie is HttpOnly so the client cannot read it; the call is a pure POST
|
||||
// that the browser attaches the cookie to automatically.
|
||||
//
|
||||
// `listMyDevices`, `revokeMyDevice`, and `revokeAllMyDevices` drive the
|
||||
// /settings/devices revoke-device UI. The signed-in user is the implicit
|
||||
// subject; the cookie carries the session.
|
||||
|
||||
export async function startDeviceTrust() {
|
||||
const res = await fetch('/auth/device-trust/start', { method: 'POST' })
|
||||
return jsonOrThrow(res)
|
||||
}
|
||||
|
||||
export async function listMyDevices() {
|
||||
return jsonOrThrow(await fetch('/api/auth/me/devices'))
|
||||
}
|
||||
|
||||
export async function revokeMyDevice(deviceId) {
|
||||
return jsonOrThrow(await fetch(`/api/auth/me/devices/${deviceId}`, { method: 'DELETE' }))
|
||||
}
|
||||
|
||||
export async function revokeAllMyDevices() {
|
||||
return jsonOrThrow(await fetch('/api/auth/me/devices', { method: 'DELETE' }))
|
||||
}
|
||||
|
||||
export async function setPasscode(passcode) {
|
||||
// Requires an active session — the server returns 401 if not signed
|
||||
// in. The signed-in user is the implicit subject; the body carries
|
||||
|
||||
Reference in New Issue
Block a user