mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
feat(api): hand desktop sign-in back with a deep link grant (#3278)
This commit is contained in:
1 parent
f8505d19f7
commit
e0d7625c39
7 files changed
+462
-32
No files matched your search
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {ThemeTypes} from '@fluxer/constants/src/UserConstants';
|
||||
import {ValidationErrorCodes} from '@fluxer/constants/src/ValidationErrorCodes';
|
||||
import {
|
||||
WebAuthnAuthenticationOptions,
|
||||
WebAuthnAuthenticationResponse,
|
||||
@@ -288,10 +289,30 @@ export const UsernameAvailabilityResponse = z.object({
|
||||
|
||||
export type UsernameAvailabilityResponse = z.infer<typeof UsernameAvailabilityResponse>;
|
||||
|
||||
export const DESKTOP_HANDOFF_RETURN_URI_PATTERN = /^fluxer(?:-canary|-development)?:\/\/handoff$/u;
|
||||
|
||||
export const DesktopHandoffReturnMethod = z.enum(['deep_link', 'code']);
|
||||
|
||||
export type DesktopHandoffReturnMethod = z.infer<typeof DesktopHandoffReturnMethod>;
|
||||
|
||||
export const HandoffInitiateRequest = z
|
||||
.object({
|
||||
return_uri: createStringType(1, 64)
|
||||
.refine((value) => DESKTOP_HANDOFF_RETURN_URI_PATTERN.test(value), ValidationErrorCodes.INVALID_FORMAT)
|
||||
.optional()
|
||||
.describe('Deep link the approving browser opens to return the sign-in to the initiating desktop app'),
|
||||
})
|
||||
.nullish();
|
||||
|
||||
export type HandoffInitiateRequest = z.infer<typeof HandoffInitiateRequest>;
|
||||
|
||||
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'),
|
||||
return_method: DesktopHandoffReturnMethod.optional().describe(
|
||||
'deep_link when the approving browser will hand the sign-in back through the return deep link, code otherwise',
|
||||
),
|
||||
});
|
||||
|
||||
export type HandoffInitiateResponse = z.infer<typeof HandoffInitiateResponse>;
|
||||
@@ -306,12 +327,15 @@ const HandoffInfoClientInfo = z.object({
|
||||
export const HandoffInfoResponse = z.object({
|
||||
status: z.string().describe('Current status of the handoff (pending, expired)'),
|
||||
client_info: HandoffInfoClientInfo.nullish().describe('Client information of the initiating device'),
|
||||
return_method: DesktopHandoffReturnMethod.optional().describe(
|
||||
'How the approving browser hands the sign-in back. deep_link opens the initiating app, code relies on the user comparing the code',
|
||||
),
|
||||
});
|
||||
|
||||
export type HandoffInfoResponse = z.infer<typeof HandoffInfoResponse>;
|
||||
|
||||
export const HandoffStatusResponse = z.object({
|
||||
status: z.string().describe('Current status of the handoff (pending, completed, expired)'),
|
||||
status: z.string().describe('Current status of the handoff (pending, completed, denied, expired)'),
|
||||
token: z.string().nullish().describe('Authentication token if handoff is complete'),
|
||||
user_id: SnowflakeStringType.nullish().describe('User ID if handoff is complete'),
|
||||
user: UserPartialResponse.nullish().describe('Partial user data if handoff is complete'),
|
||||
@@ -386,6 +410,9 @@ export const HandoffCompleteRequest = z.object({
|
||||
code: createStringType().describe('The handoff code from the initiating session'),
|
||||
token: createStringType().optional().describe('The authentication token to transfer'),
|
||||
user_id: createStringType().describe('The user ID associated with the authenticated session'),
|
||||
return_method: DesktopHandoffReturnMethod.optional().describe(
|
||||
'deep_link returns a one-time grant the initiating app must present, code releases the token to the poll secret alone',
|
||||
),
|
||||
});
|
||||
|
||||
export type HandoffCompleteRequest = z.infer<typeof HandoffCompleteRequest>;
|
||||
@@ -396,8 +423,15 @@ export const HandoffCodeParam = z.object({
|
||||
|
||||
export type HandoffCodeParam = z.infer<typeof HandoffCodeParam>;
|
||||
|
||||
export const HandoffCompleteResponse = z.object({
|
||||
return_url: z.string().describe('Deep link that returns the sign-in to the initiating app, with its one-time grant'),
|
||||
});
|
||||
|
||||
export type HandoffCompleteResponse = z.infer<typeof HandoffCompleteResponse>;
|
||||
|
||||
export const HandoffStatusRequest = z.object({
|
||||
poll_secret: createStringType().describe('The poll secret issued when the handoff was initiated'),
|
||||
grant: createStringType(1, 128).optional().describe('The one-time grant delivered to the app through the deep link'),
|
||||
});
|
||||
|
||||
export type HandoffStatusRequest = z.infer<typeof HandoffStatusRequest>;
|
||||
|
||||
Reference in new issue
Block a user