WebAuthn platform passkeys: opt-in enrollment after a password login, a password-less sign-in that mints the same 14-day campaign-token, and revocation from the profile. The session is minted through Payload's public pieces (checkLoginPermission, addSessionToUser, getFieldsToSign, jwtSign) inside a transaction with an advisory lock, so a passkey login neither bypasses a lockout nor evicts the account's other sessions. The rpID is derived from NEXT_PUBLIC_SITE_URL and resolves to null when the request host disagrees, so previews never offer a ceremony the browser would refuse.
30 lines
1.1 KiB
TypeScript
30 lines
1.1 KiB
TypeScript
/**
|
|
* A short, human name for the device behind a user-agent string, used to
|
|
* pre-fill the passkey label so enrolling is one tap and no typing (B40).
|
|
*
|
|
* Deliberately coarse: this is a suggestion the person can overwrite, and it
|
|
* has to read like something they would say out loud ("iPhone", "Android"),
|
|
* not like a fingerprint of their browser. It is resolved on the server from
|
|
* the request header so the input has its value on first paint.
|
|
*/
|
|
|
|
const PATTERNS: ReadonlyArray<[RegExp, string]> = [
|
|
[/iPhone/i, 'iPhone'],
|
|
[/iPad/i, 'iPad'],
|
|
[/Android/i, 'Android'],
|
|
[/Macintosh|Mac OS X/i, 'Mac'],
|
|
[/Windows/i, 'Windows'],
|
|
[/CrOS/i, 'Chromebook'],
|
|
[/Linux/i, 'Linux'],
|
|
]
|
|
|
|
const FALLBACK_DEVICE_LABEL = 'Este aparelho'
|
|
|
|
export const deviceLabelFromUserAgent = (userAgent: string | null | undefined): string => {
|
|
if (!userAgent) return FALLBACK_DEVICE_LABEL
|
|
|
|
// iPadOS reports itself as a Macintosh with touch points, which the header
|
|
// alone cannot distinguish — "Mac" is the honest answer from here.
|
|
const match = PATTERNS.find(([pattern]) => pattern.test(userAgent))
|
|
return match ? match[1] : FALLBACK_DEVICE_LABEL
|
|
}
|