From 859adb79da75d2010e8c0f46042e4e44953399c3 Mon Sep 17 00:00:00 2001 From: "Siegfred B. Pagador" Date: Thu, 28 Mar 2024 18:34:31 +0400 Subject: [PATCH] Feat: Custom userProfile for Oauth2 to support login with Keycloak; Include phone to customer when logging in store (#155) --- docs/pages/authentication/oauth2.mdx | 32 ++++++++++++++++++- .../src/auth-strategies/oauth2/admin.ts | 17 ++++++++++ .../src/auth-strategies/oauth2/store.ts | 17 ++++++++++ .../src/auth-strategies/oauth2/types.ts | 1 + .../src/core/validate-callback.ts | 2 ++ 5 files changed, 68 insertions(+), 1 deletion(-) diff --git a/docs/pages/authentication/oauth2.mdx b/docs/pages/authentication/oauth2.mdx index 0ef483b..b9443c7 100644 --- a/docs/pages/authentication/oauth2.mdx +++ b/docs/pages/authentication/oauth2.mdx @@ -73,7 +73,37 @@ newly added plugins. To do so here are the steps // verifyCallback: (container, req, accessToken, refreshToken, profile, strict) => { // // implement your custom verify callback here if you need it // } - } + }, + // parseProfile: (json) => { + // const profile = { + // provider: "keycloak", + // id: json.sub, + // username: json.preferred_username, + // displayName: json.name, + // email: json.email, + // name: { + // familyName: json.family_name, + // givenName: json.given_name, + // }, + // emails: json.email + // ? [ + // { + // value: json.email, + // }, + // ] + // : [], + // _json: json, + // phoneNumbers: json.phone_number + // ? [ + // { + // value: json.phone_number ?? "", + // }, + // ] + // : [], + // }; + + // return profile; + // }, } ] } diff --git a/packages/medusa-plugin-auth/src/auth-strategies/oauth2/admin.ts b/packages/medusa-plugin-auth/src/auth-strategies/oauth2/admin.ts index ff7b255..c9fd751 100644 --- a/packages/medusa-plugin-auth/src/auth-strategies/oauth2/admin.ts +++ b/packages/medusa-plugin-auth/src/auth-strategies/oauth2/admin.ts @@ -51,6 +51,23 @@ export function getOAuth2AdminStrategy(id: string): StrategyFactory void) { + if (this.strategyOptions.parseProfile !== undefined) { + let json; + + try { + json = JSON.parse(Buffer.from(accessToken.split('.')[1], 'base64').toString()); + } catch (ex) { + return done(new Error('Failed to parse access token')); + } + + const profile = this.strategyOptions.parseProfile(json); + done(null, profile); + } else { + super.userProfile(accessToken, done); + } + } }; } diff --git a/packages/medusa-plugin-auth/src/auth-strategies/oauth2/store.ts b/packages/medusa-plugin-auth/src/auth-strategies/oauth2/store.ts index b28f398..d922553 100644 --- a/packages/medusa-plugin-auth/src/auth-strategies/oauth2/store.ts +++ b/packages/medusa-plugin-auth/src/auth-strategies/oauth2/store.ts @@ -51,6 +51,23 @@ export function getOAuth2StoreStrategy(id: string): StrategyFactory void) { + if (this.strategyOptions.parseProfile !== undefined) { + let json; + + try { + json = JSON.parse(Buffer.from(accessToken.split('.')[1], 'base64').toString()); + } catch (ex) { + return done(new Error('Failed to parse access token')); + } + + const profile = this.strategyOptions.parseProfile(json); + done(null, profile); + } else { + super.userProfile(accessToken, done); + } + } }; } diff --git a/packages/medusa-plugin-auth/src/auth-strategies/oauth2/types.ts b/packages/medusa-plugin-auth/src/auth-strategies/oauth2/types.ts index fffeb31..5298389 100644 --- a/packages/medusa-plugin-auth/src/auth-strategies/oauth2/types.ts +++ b/packages/medusa-plugin-auth/src/auth-strategies/oauth2/types.ts @@ -65,4 +65,5 @@ export type OAuth2AuthOptions = { expiresIn?: number; }; scope?: string[]; + parseProfile?: (profile: any) => any; }; diff --git a/packages/medusa-plugin-auth/src/core/validate-callback.ts b/packages/medusa-plugin-auth/src/core/validate-callback.ts index a05dba6..4ddecd1 100644 --- a/packages/medusa-plugin-auth/src/core/validate-callback.ts +++ b/packages/medusa-plugin-auth/src/core/validate-callback.ts @@ -81,6 +81,7 @@ export async function validateStoreCallback< email_verified?: boolean; }; emails?: { value: string }[]; + phoneNumbers?: { value: string }[]; } = { emails?: { value: string }[]; } @@ -173,6 +174,7 @@ export async function validateStoreCallback< last_name: profile.name?.familyName ?? '', has_account: true, password: generatePassword(), + phone: profile.phoneNumbers?.[0]?.value ?? '', }); return { id: customer.id };