From dfcb06f5a921a81e93f536eb81f9a465589fa031 Mon Sep 17 00:00:00 2001 From: chenhang Date: Fri, 10 Jul 2026 16:33:29 +0800 Subject: [PATCH] feat(auth): add psid field to various login request DTOs and schemas --- scripts/tools/verify-meta-id-match-with-proof.js | 10 ++++------ .../dto/auth/request/facebook_login_request.ts | 1 + src/data/dto/auth/request/fb_id_login_request.ts | 1 + src/data/dto/auth/request/google_login_request.ts | 1 + src/data/dto/auth/request/login_request.ts | 1 + src/data/repositories/auth_repository.ts | 8 ++++++++ .../repositories/interfaces/iauth_repository.ts | 4 ++++ src/data/schemas/auth/facebook_login_request.ts | 1 + src/data/schemas/auth/fb_id_login_request.ts | 1 + src/data/schemas/auth/google_login_request.ts | 1 + src/data/schemas/auth/login_request.ts | 1 + src/stores/auth/auth-actors.ts | 14 ++++++++++++-- src/stores/auth/auth-helpers.ts | 9 +++++++++ 13 files changed, 45 insertions(+), 8 deletions(-) diff --git a/scripts/tools/verify-meta-id-match-with-proof.js b/scripts/tools/verify-meta-id-match-with-proof.js index fbec4927..3547d3fe 100755 --- a/scripts/tools/verify-meta-id-match-with-proof.js +++ b/scripts/tools/verify-meta-id-match-with-proof.js @@ -1,7 +1,5 @@ #!/usr/bin/env node -const crypto = require("node:crypto"); - const GRAPH_API_VERSION = "v25.0"; const PSID = "27511427698460020"; const EXPECTED_ASID = "122111097783118257"; @@ -15,9 +13,9 @@ function assertConfigured(name, value) { } } -function createAppSecretProof(accessToken, appSecret) { - return crypto - .createHmac("sha256", appSecret.trim()) +async function createAppSecretProof(accessToken, appSecret) { + const { createHmac } = await import("node:crypto"); + return createHmac("sha256", appSecret.trim()) .update(accessToken.trim()) .digest("hex"); } @@ -33,7 +31,7 @@ async function main() { url.searchParams.set("access_token", PAGE_ACCESS_TOKEN); url.searchParams.set( "appsecret_proof", - createAppSecretProof(PAGE_ACCESS_TOKEN, APP_SECRET), + await createAppSecretProof(PAGE_ACCESS_TOKEN, APP_SECRET), ); const response = await fetch(url); diff --git a/src/data/dto/auth/request/facebook_login_request.ts b/src/data/dto/auth/request/facebook_login_request.ts index fdff17ad..2c491b61 100644 --- a/src/data/dto/auth/request/facebook_login_request.ts +++ b/src/data/dto/auth/request/facebook_login_request.ts @@ -11,6 +11,7 @@ export class FacebookLoginRequest { declare readonly accessToken: string; declare readonly platform: string; declare readonly guestId: string; + declare readonly psid: string; declare readonly isTestAccount: boolean; private constructor(input: FacebookLoginRequestInput) { diff --git a/src/data/dto/auth/request/fb_id_login_request.ts b/src/data/dto/auth/request/fb_id_login_request.ts index 82642114..ee91fe6c 100644 --- a/src/data/dto/auth/request/fb_id_login_request.ts +++ b/src/data/dto/auth/request/fb_id_login_request.ts @@ -10,6 +10,7 @@ import { export class FbIdLoginRequest { declare readonly fbId: string; declare readonly avatarUrl: string; + declare readonly psid: string; declare readonly isTestAccount: boolean; private constructor(input: FbIdLoginRequestInput) { diff --git a/src/data/dto/auth/request/google_login_request.ts b/src/data/dto/auth/request/google_login_request.ts index 964f72a3..0841bfb1 100644 --- a/src/data/dto/auth/request/google_login_request.ts +++ b/src/data/dto/auth/request/google_login_request.ts @@ -11,6 +11,7 @@ export class GoogleLoginRequest { declare readonly idToken: string; declare readonly platform: string; declare readonly guestId: string; + declare readonly psid: string; declare readonly isTestAccount: boolean; private constructor(input: GoogleLoginRequestInput) { diff --git a/src/data/dto/auth/request/login_request.ts b/src/data/dto/auth/request/login_request.ts index a5f84a74..70836f59 100644 --- a/src/data/dto/auth/request/login_request.ts +++ b/src/data/dto/auth/request/login_request.ts @@ -13,6 +13,7 @@ export class LoginRequest { declare readonly password: string; declare readonly platform: string; declare readonly guestId: string; + declare readonly psid: string; declare readonly isTestAccount: boolean; private constructor(input: LoginRequestInput) { diff --git a/src/data/repositories/auth_repository.ts b/src/data/repositories/auth_repository.ts index a82b4bd8..e00a8732 100644 --- a/src/data/repositories/auth_repository.ts +++ b/src/data/repositories/auth_repository.ts @@ -73,6 +73,7 @@ export class AuthRepository implements IAuthRepository { username?: string; password: string; guestId?: string; + psid?: string; }): Promise> { return Result.wrap(async () => { const email = input.email?.trim() ?? ""; @@ -84,6 +85,7 @@ export class AuthRepository implements IAuthRepository { password: input.password, platform: getAuthPlatform(), guestId: input.guestId ?? "", + psid: input.psid ?? "", }), ), ); @@ -173,6 +175,7 @@ export class AuthRepository implements IAuthRepository { async googleLogin(input: { idToken: string; guestId?: string; + psid?: string; }): Promise> { return this._socialLogin(LoginStatus.Google, () => this.api.googleLogin( @@ -181,6 +184,7 @@ export class AuthRepository implements IAuthRepository { idToken: input.idToken, platform: getAuthPlatform(), guestId: input.guestId ?? "", + psid: input.psid ?? "", }), ), ), @@ -191,6 +195,7 @@ export class AuthRepository implements IAuthRepository { async facebookLogin(input: { accessToken: string; guestId?: string; + psid?: string; }): Promise> { return this._socialLogin(LoginStatus.Facebook, () => this.api.facebookLogin( @@ -199,6 +204,7 @@ export class AuthRepository implements IAuthRepository { accessToken: input.accessToken, platform: getAuthPlatform(), guestId: input.guestId ?? "", + psid: input.psid ?? "", }), ), ), @@ -209,6 +215,7 @@ export class AuthRepository implements IAuthRepository { async facebookIdLogin(input: { fbId: string; avatarUrl?: string; + psid?: string; }): Promise> { return this._socialLogin(LoginStatus.Facebook, () => this.api.facebookIdLogin( @@ -216,6 +223,7 @@ export class AuthRepository implements IAuthRepository { withTestAccountFlag({ fbId: input.fbId, avatarUrl: input.avatarUrl ?? "", + psid: input.psid ?? "", }), ), ), diff --git a/src/data/repositories/interfaces/iauth_repository.ts b/src/data/repositories/interfaces/iauth_repository.ts index 886cfdcb..817aa10d 100644 --- a/src/data/repositories/interfaces/iauth_repository.ts +++ b/src/data/repositories/interfaces/iauth_repository.ts @@ -36,6 +36,7 @@ export interface IAuthRepository { username?: string; password: string; guestId?: string; + psid?: string; }): Promise>; /** 退出真实用户登录并恢复游客态。 */ @@ -48,18 +49,21 @@ export interface IAuthRepository { googleLogin(input: { idToken: string; guestId?: string; + psid?: string; }): Promise>; /** Facebook 登录(accessToken 流程)。 */ facebookLogin(input: { accessToken: string; guestId?: string; + psid?: string; }): Promise>; /** Facebook ID 登录(v7.0 新增,fbId 流程)。 */ facebookIdLogin(input: { fbId: string; avatarUrl?: string; + psid?: string; }): Promise>; /** 刷新 token:先读本地的 refresh token,空则返回错误。 */ diff --git a/src/data/schemas/auth/facebook_login_request.ts b/src/data/schemas/auth/facebook_login_request.ts index 4f1e6cc5..ab257dfa 100644 --- a/src/data/schemas/auth/facebook_login_request.ts +++ b/src/data/schemas/auth/facebook_login_request.ts @@ -10,6 +10,7 @@ export const FacebookLoginRequestSchema = z.object({ accessToken: z.string(), platform: z.string(), guestId: stringOrEmpty, + psid: stringOrEmpty, isTestAccount: booleanOrFalse, }); diff --git a/src/data/schemas/auth/fb_id_login_request.ts b/src/data/schemas/auth/fb_id_login_request.ts index 631e3dd1..5ebf9e97 100644 --- a/src/data/schemas/auth/fb_id_login_request.ts +++ b/src/data/schemas/auth/fb_id_login_request.ts @@ -9,6 +9,7 @@ import { booleanOrFalse, stringOrEmpty } from "../nullable-defaults"; export const FbIdLoginRequestSchema = z.object({ fbId: z.string(), avatarUrl: stringOrEmpty, + psid: stringOrEmpty, isTestAccount: booleanOrFalse, }); diff --git a/src/data/schemas/auth/google_login_request.ts b/src/data/schemas/auth/google_login_request.ts index c33b84ee..789ea7c7 100644 --- a/src/data/schemas/auth/google_login_request.ts +++ b/src/data/schemas/auth/google_login_request.ts @@ -10,6 +10,7 @@ export const GoogleLoginRequestSchema = z.object({ idToken: z.string(), platform: z.string(), guestId: stringOrEmpty, + psid: stringOrEmpty, isTestAccount: booleanOrFalse, }); diff --git a/src/data/schemas/auth/login_request.ts b/src/data/schemas/auth/login_request.ts index 5dcb8649..f59a04d9 100644 --- a/src/data/schemas/auth/login_request.ts +++ b/src/data/schemas/auth/login_request.ts @@ -12,6 +12,7 @@ export const LoginRequestSchema = z.object({ password: z.string(), platform: z.string(), guestId: stringOrEmpty, + psid: stringOrEmpty, isTestAccount: booleanOrFalse, }); diff --git a/src/stores/auth/auth-actors.ts b/src/stores/auth/auth-actors.ts index 0483b78a..c92f7c93 100644 --- a/src/stores/auth/auth-actors.ts +++ b/src/stores/auth/auth-actors.ts @@ -12,7 +12,7 @@ import { UserStorage } from "@/data/storage/user/user_storage"; import { deviceIdentifier, Logger, Result } from "@/utils"; import { hasCompleteBusinessAuthSession } from "@/lib/auth/auth_session"; -import { readGuestId } from "./auth-helpers"; +import { readGuestId, readPsid } from "./auth-helpers"; const log = new Logger("AuthActors"); @@ -25,10 +25,12 @@ export const emailLoginActor = fromPromise { const authRepo = getAuthRepository(); const guestId = await readGuestId(); + const psid = await readPsid(); const result = await authRepo.googleLogin({ idToken: input.idToken, guestId, + psid, }); if (Result.isErr(result)) throw result.error; return "google" as LoginStatus; @@ -125,9 +131,11 @@ export const syncFacebookBackendActor = fromPromise< >(async ({ input }) => { const authRepo = getAuthRepository(); const guestId = await readGuestId(); + const psid = await readPsid(); const result = await authRepo.facebookLogin({ accessToken: input.accessToken, guestId, + psid, }); if (Result.isErr(result)) throw result.error; @@ -252,9 +260,11 @@ export const checkAuthStatusActor = fromPromise(async () => { if (asidR.success && asidR.data) { const authRepo = getAuthRepository(); const avatarUrlR = await UserStorage.getInstance().getAvatarUrl(); + const psid = await readPsid(); const result = await authRepo.facebookIdLogin({ fbId: asidR.data, avatarUrl: avatarUrlR.success ? avatarUrlR.data ?? undefined : undefined, + psid, }); if (Result.isErr(result)) { diff --git a/src/stores/auth/auth-helpers.ts b/src/stores/auth/auth-helpers.ts index a1f2cacc..4b3438a7 100644 --- a/src/stores/auth/auth-helpers.ts +++ b/src/stores/auth/auth-helpers.ts @@ -13,3 +13,12 @@ export async function readGuestId(): Promise { } return undefined; } + +/** 从本地存储读 PSID;读不到 / 失败时返回 undefined(不抛)。 */ +export async function readPsid(): Promise { + const r = await AuthStorage.getInstance().getPsid(); + if (r.success && r.data != null) { + return r.data; + } + return undefined; +}