mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
fix(auth): require a hashed poll secret for desktop handoff (#2357)
This commit is contained in:
1 parent
b82681b77a
commit
f703969e80
45 files changed
+382
-188
No files matched your search
@@ -227,6 +227,7 @@ export type UsernameSuggestionsResponse = z.infer<typeof UsernameSuggestionsResp
|
||||
export const HandoffInitiateResponse = z.object({
|
||||
code: z.string().describe('Handoff code to share with the receiving device'),
|
||||
expires_at: z.iso.datetime().describe('ISO 8601 timestamp when the handoff code expires'),
|
||||
poll_secret: z.string().optional().describe('Secret the initiating device must present to retrieve the token'),
|
||||
});
|
||||
|
||||
export type HandoffInitiateResponse = z.infer<typeof HandoffInitiateResponse>;
|
||||
@@ -331,6 +332,18 @@ export const HandoffCodeParam = z.object({
|
||||
|
||||
export type HandoffCodeParam = z.infer<typeof HandoffCodeParam>;
|
||||
|
||||
export const HandoffStatusRequest = z.object({
|
||||
poll_secret: createStringType().describe('The poll secret issued when the handoff was initiated'),
|
||||
});
|
||||
|
||||
export type HandoffStatusRequest = z.infer<typeof HandoffStatusRequest>;
|
||||
|
||||
export const HandoffCancelRequest = z.object({
|
||||
poll_secret: createStringType().describe('The poll secret issued when the handoff was initiated'),
|
||||
});
|
||||
|
||||
export type HandoffCancelRequest = z.infer<typeof HandoffCancelRequest>;
|
||||
|
||||
export const EnableMfaTotpRequest = z
|
||||
.object({
|
||||
secret: createStringType(1, 256).describe('The TOTP secret key'),
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
export const DESKTOP_HANDOFF_CODE_ALPHABET = 'ABCDEFGHJKMNPQRSTUVWXYZ23456789';
|
||||
export const DESKTOP_HANDOFF_CODE_LENGTH = 12;
|
||||
|
||||
const DESKTOP_HANDOFF_CODE_GROUP_LENGTH = 6;
|
||||
const DESKTOP_HANDOFF_CODE_SEPARATOR = '-';
|
||||
const DESKTOP_HANDOFF_CODE_SEPARATOR_PATTERN = /[^A-Za-z0-9]/gu;
|
||||
|
||||
function normalizeDesktopHandoffCode(value: string): string {
|
||||
return value.replace(DESKTOP_HANDOFF_CODE_SEPARATOR_PATTERN, '').toUpperCase();
|
||||
}
|
||||
|
||||
export function isDesktopHandoffCode(value: string): boolean {
|
||||
if (value.length !== DESKTOP_HANDOFF_CODE_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
return Array.from(value).every((character) => DESKTOP_HANDOFF_CODE_ALPHABET.includes(character));
|
||||
}
|
||||
|
||||
export function parseDesktopHandoffCodeInput(value: string): string {
|
||||
return normalizeDesktopHandoffCode(value).slice(0, DESKTOP_HANDOFF_CODE_LENGTH);
|
||||
}
|
||||
|
||||
export function parseDesktopHandoffCode(value: string | null | undefined): string | null {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
const normalized = normalizeDesktopHandoffCode(value);
|
||||
if (!isDesktopHandoffCode(normalized)) {
|
||||
return null;
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function formatDesktopHandoffCode(value: string): string {
|
||||
const normalized = parseDesktopHandoffCodeInput(value);
|
||||
const groups: Array<string> = [];
|
||||
for (let index = 0; index < normalized.length; index += DESKTOP_HANDOFF_CODE_GROUP_LENGTH) {
|
||||
groups.push(normalized.slice(index, index + DESKTOP_HANDOFF_CODE_GROUP_LENGTH));
|
||||
}
|
||||
return groups.join(DESKTOP_HANDOFF_CODE_SEPARATOR);
|
||||
}
|
||||
Reference in new issue
Block a user