From 73812dc795a105053e3735d6c0f21a1aa925ef9a Mon Sep 17 00:00:00 2001 From: adrien2p Date: Tue, 29 Nov 2022 12:16:01 +0100 Subject: [PATCH] fix: Wrong user property used in store auth strategies --- .../src/auth-strategies/facebook/admin.ts | 23 ++++++------ .../src/auth-strategies/facebook/store.ts | 30 +++++++++------- .../src/auth-strategies/google/admin.ts | 25 +++++++------ .../src/auth-strategies/google/store.ts | 34 +++++++++++------- .../src/auth-strategies/linkedin/admin.ts | 26 +++++++------- .../src/auth-strategies/linkedin/store.ts | 36 +++++++++++-------- .../src/utils/build-callback-handler.ts | 11 ++++++ .../src/utils/get-cookie-options.ts | 4 ++- 8 files changed, 110 insertions(+), 79 deletions(-) create mode 100644 packages/medusa-plugin-auth/src/utils/build-callback-handler.ts diff --git a/packages/medusa-plugin-auth/src/auth-strategies/facebook/admin.ts b/packages/medusa-plugin-auth/src/auth-strategies/facebook/admin.ts index 7d573d9..495e30a 100644 --- a/packages/medusa-plugin-auth/src/auth-strategies/facebook/admin.ts +++ b/packages/medusa-plugin-auth/src/auth-strategies/facebook/admin.ts @@ -1,15 +1,14 @@ import passport from 'passport'; import { Strategy as FacebookStrategy } from 'passport-facebook'; -import jwt from 'jsonwebtoken'; import { ConfigModule, MedusaContainer } from '@medusajs/medusa/dist/types/global'; import { ADMIN_AUTH_TOKEN_COOKIE_NAME, TWENTY_FOUR_HOURS_IN_MS } from '../../types'; import { UserService } from '@medusajs/medusa'; import { MedusaError } from 'medusa-core-utils'; import { Router } from 'express'; import cors from 'cors'; -import { getCookieOptions } from '../../utils/get-cookie-options'; import { FACEBOOK_ADMIN_STRATEGY_NAME, FacebookAuthOptions, Profile } from './types'; import { PassportStrategy } from '../../core/Strategy'; +import { buildCallbackHandler } from '../../utils/build-callback-handler'; export class FacebookAdminStrategy extends PassportStrategy(FacebookStrategy, FACEBOOK_ADMIN_STRATEGY_NAME) { constructor( @@ -80,7 +79,7 @@ export function getFacebookAdminAuthRouter(facebook: FacebookAuthOptions, config credentials: true, }; - const authPath = facebook.admin.authPath ?? "/admin/auth/facebook" + const authPath = facebook.admin.authPath ?? '/admin/auth/facebook'; router.get(authPath, cors(adminCorsOptions)); router.get( @@ -91,21 +90,21 @@ export function getFacebookAdminAuthRouter(facebook: FacebookAuthOptions, config }) ); - const callbackHandler = (req, res) => { - const token = jwt.sign({ userId: req.user.id }, configModule.projectConfig.jwt_secret, { - expiresIn: facebook.admin.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS, - }); - res.cookie(ADMIN_AUTH_TOKEN_COOKIE_NAME, token, getCookieOptions()).redirect(facebook.admin.successRedirect); - }; - - const authPathCb = facebook.admin.authCallbackPath ?? "/admin/auth/facebook/cb" + const expiresIn = facebook.admin.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS; + const callbackHandler = buildCallbackHandler( + ADMIN_AUTH_TOKEN_COOKIE_NAME, + configModule.projectConfig.jwt_secret, + expiresIn, + facebook.admin.successRedirect + ); + const authPathCb = facebook.admin.authCallbackPath ?? '/admin/auth/facebook/cb'; router.get(authPathCb, cors(adminCorsOptions)); router.get( authPathCb, (req, res, next) => { if (req.user) { - callbackHandler(req, res); + return callbackHandler(req, res); } next(); diff --git a/packages/medusa-plugin-auth/src/auth-strategies/facebook/store.ts b/packages/medusa-plugin-auth/src/auth-strategies/facebook/store.ts index 940824c..be1ca97 100644 --- a/packages/medusa-plugin-auth/src/auth-strategies/facebook/store.ts +++ b/packages/medusa-plugin-auth/src/auth-strategies/facebook/store.ts @@ -2,16 +2,15 @@ import passport from 'passport'; import { Router } from 'express'; import cors from 'cors'; import { ConfigModule, MedusaContainer } from '@medusajs/medusa/dist/types/global'; -import jwt from 'jsonwebtoken'; import { Strategy as FacebookStrategy } from 'passport-facebook'; import { CustomerService } from '@medusajs/medusa'; import { MedusaError } from 'medusa-core-utils'; import { EntityManager } from 'typeorm'; import { CUSTOMER_METADATA_KEY, STORE_AUTH_TOKEN_COOKIE_NAME, TWENTY_FOUR_HOURS_IN_MS } from '../../types'; -import { getCookieOptions } from '../../utils/get-cookie-options'; import { FACEBOOK_STORE_STRATEGY_NAME, FacebookAuthOptions, Profile } from './types'; import { PassportStrategy } from '../../core/Strategy'; +import { buildCallbackHandler } from '../../utils/build-callback-handler'; export class FacebookStoreStrategy extends PassportStrategy(FacebookStrategy, FACEBOOK_STORE_STRATEGY_NAME) { constructor( @@ -106,7 +105,7 @@ export function getFacebookStoreAuthRouter(facebook: FacebookAuthOptions, config credentials: true, }; - const authPath = facebook.store.authPath ?? "/store/auth/facebook" + const authPath = facebook.store.authPath ?? '/store/auth/facebook'; router.get(authPath, cors(storeCorsOptions)); router.get( @@ -117,23 +116,30 @@ export function getFacebookStoreAuthRouter(facebook: FacebookAuthOptions, config }) ); - const authPathCb = facebook.store.authCallbackPath ?? "/store/auth/facebook/cb" + const expiresIn = facebook.store.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS; + const callbackHandler = buildCallbackHandler( + STORE_AUTH_TOKEN_COOKIE_NAME, + configModule.projectConfig.jwt_secret, + expiresIn, + facebook.store.successRedirect + ); + const authPathCb = facebook.store.authCallbackPath ?? '/store/auth/facebook/cb'; router.get(authPathCb, cors(storeCorsOptions)); router.get( authPathCb, + (req, res, next) => { + if (req.user) { + return callbackHandler(req, res); + } + + next(); + }, passport.authenticate(FACEBOOK_STORE_STRATEGY_NAME, { failureRedirect: facebook.store.failureRedirect, session: false, }), - (req, res) => { - const token = jwt.sign({ customer_id: req.user.customer_id }, configModule.projectConfig.jwt_secret, { - expiresIn: facebook.store.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS, - }); - res.cookie(STORE_AUTH_TOKEN_COOKIE_NAME, token, getCookieOptions()).redirect( - facebook.store.successRedirect - ); - } + callbackHandler ); return router; diff --git a/packages/medusa-plugin-auth/src/auth-strategies/google/admin.ts b/packages/medusa-plugin-auth/src/auth-strategies/google/admin.ts index f3aaeac..953bd5b 100644 --- a/packages/medusa-plugin-auth/src/auth-strategies/google/admin.ts +++ b/packages/medusa-plugin-auth/src/auth-strategies/google/admin.ts @@ -1,15 +1,14 @@ import passport from 'passport'; import { Strategy as GoogleStrategy } from 'passport-google-oauth2'; -import jwt from 'jsonwebtoken'; import { ConfigModule, MedusaContainer } from '@medusajs/medusa/dist/types/global'; import { ADMIN_AUTH_TOKEN_COOKIE_NAME, TWENTY_FOUR_HOURS_IN_MS } from '../../types'; import { UserService } from '@medusajs/medusa'; import { MedusaError } from 'medusa-core-utils'; import { Router } from 'express'; import cors from 'cors'; -import { getCookieOptions } from '../../utils/get-cookie-options'; import { GOOGLE_ADMIN_STRATEGY_NAME, GoogleAuthOptions, Profile } from './types'; import { PassportStrategy } from '../../core/Strategy'; +import { buildCallbackHandler } from '../../utils/build-callback-handler'; export class GoogleAdminStrategy extends PassportStrategy(GoogleStrategy, GOOGLE_ADMIN_STRATEGY_NAME) { constructor( @@ -78,8 +77,8 @@ export function getGoogleAdminAuthRouter(google: GoogleAuthOptions, configModule origin: configModule.projectConfig.admin_cors.split(','), credentials: true, }; - - const authPath = google.admin.authPath ?? "/admin/auth/google" + + const authPath = google.admin.authPath ?? '/admin/auth/google'; router.get(authPath, cors(adminCorsOptions)); router.get( @@ -93,21 +92,21 @@ export function getGoogleAdminAuthRouter(google: GoogleAuthOptions, configModule }) ); - const callbackHandler = (req, res) => { - const token = jwt.sign({ userId: req.user.id }, configModule.projectConfig.jwt_secret, { - expiresIn: google.admin.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS, - }); - res.cookie(ADMIN_AUTH_TOKEN_COOKIE_NAME, token, getCookieOptions()).redirect(google.admin.successRedirect); - }; + const expiresIn = google.admin.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS; + const callbackHandler = buildCallbackHandler( + ADMIN_AUTH_TOKEN_COOKIE_NAME, + configModule.projectConfig.jwt_secret, + expiresIn, + google.admin.successRedirect + ); + const authPathCb = google.admin.authCallbackPath ?? '/admin/auth/google/cb'; - const authPathCb = google.admin.authCallbackPath ?? "/admin/auth/google/cb" - router.get(authPathCb, cors(adminCorsOptions)); router.get( authPathCb, (req, res, next) => { if (req.user) { - callbackHandler(req, res); + return callbackHandler(req, res); } next(); diff --git a/packages/medusa-plugin-auth/src/auth-strategies/google/store.ts b/packages/medusa-plugin-auth/src/auth-strategies/google/store.ts index 570ad77..8b6e578 100644 --- a/packages/medusa-plugin-auth/src/auth-strategies/google/store.ts +++ b/packages/medusa-plugin-auth/src/auth-strategies/google/store.ts @@ -2,16 +2,15 @@ import passport from 'passport'; import { Router } from 'express'; import cors from 'cors'; import { ConfigModule, MedusaContainer } from '@medusajs/medusa/dist/types/global'; -import jwt from 'jsonwebtoken'; import { Strategy as GoogleStrategy } from 'passport-google-oauth2'; import { CustomerService } from '@medusajs/medusa'; import { MedusaError } from 'medusa-core-utils'; import { EntityManager } from 'typeorm'; import { CUSTOMER_METADATA_KEY, STORE_AUTH_TOKEN_COOKIE_NAME, TWENTY_FOUR_HOURS_IN_MS } from '../../types'; -import { getCookieOptions } from '../../utils/get-cookie-options'; import { PassportStrategy } from '../../core/Strategy'; -import { GOOGLE_STORE_STRATEGY_NAME, GoogleAuthOptions, Profile } from "./types"; +import { GOOGLE_STORE_STRATEGY_NAME, GoogleAuthOptions, Profile } from './types'; +import { buildCallbackHandler } from '../../utils/build-callback-handler'; export class GoogleStoreStrategy extends PassportStrategy(GoogleStrategy, GOOGLE_STORE_STRATEGY_NAME) { constructor( @@ -104,8 +103,8 @@ export function getGoogleStoreAuthRouter(google: GoogleAuthOptions, configModule origin: configModule.projectConfig.store_cors.split(','), credentials: true, }; - - const authPath = google.store.authPath ?? "/store/auth/google" + + const authPath = google.store.authPath ?? '/store/auth/google'; router.get(authPath, cors(storeCorsOptions)); router.get( @@ -118,22 +117,31 @@ export function getGoogleStoreAuthRouter(google: GoogleAuthOptions, configModule session: false, }) ); - - const authPathCb = google.store.authCallbackPath ?? "/store/auth/google/cb" + + const expiresIn = google.store.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS; + const callbackHandler = buildCallbackHandler( + STORE_AUTH_TOKEN_COOKIE_NAME, + configModule.projectConfig.jwt_secret, + expiresIn, + google.store.successRedirect + ); + const authPathCb = google.store.authCallbackPath ?? '/store/auth/google/cb'; router.get(authPathCb, cors(storeCorsOptions)); router.get( authPathCb, + (req, res, next) => { + if (req.user) { + return callbackHandler(req, res); + } + + next(); + }, passport.authenticate(GOOGLE_STORE_STRATEGY_NAME, { failureRedirect: google.store.failureRedirect, session: false, }), - (req, res) => { - const token = jwt.sign({ customer_id: req.user.customer_id }, configModule.projectConfig.jwt_secret, { - expiresIn: google.store.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS, - }); - res.cookie(STORE_AUTH_TOKEN_COOKIE_NAME, token, getCookieOptions()).redirect(google.store.successRedirect); - } + callbackHandler ); return router; diff --git a/packages/medusa-plugin-auth/src/auth-strategies/linkedin/admin.ts b/packages/medusa-plugin-auth/src/auth-strategies/linkedin/admin.ts index aa0e399..e9c1e80 100644 --- a/packages/medusa-plugin-auth/src/auth-strategies/linkedin/admin.ts +++ b/packages/medusa-plugin-auth/src/auth-strategies/linkedin/admin.ts @@ -1,15 +1,14 @@ import passport from 'passport'; import { Strategy as LinkedinStrategy } from 'passport-linkedin-oauth2'; -import jwt from 'jsonwebtoken'; import { ConfigModule, MedusaContainer } from '@medusajs/medusa/dist/types/global'; import { ADMIN_AUTH_TOKEN_COOKIE_NAME, TWENTY_FOUR_HOURS_IN_MS } from '../../types'; import { UserService } from '@medusajs/medusa'; import { MedusaError } from 'medusa-core-utils'; import { Router } from 'express'; import cors from 'cors'; -import { getCookieOptions } from '../../utils/get-cookie-options'; import { LINKEDIN_ADMIN_STRATEGY_NAME, LinkedinAuthOptions, Profile } from './types'; import { PassportStrategy } from '../../core/Strategy'; +import { buildCallbackHandler } from '../../utils/build-callback-handler'; export class LinkedinAdminStrategy extends PassportStrategy(LinkedinStrategy, LINKEDIN_ADMIN_STRATEGY_NAME) { constructor( @@ -80,8 +79,8 @@ export function getLinkedinAdminAuthRouter(linkedin: LinkedinAuthOptions, config origin: configModule.projectConfig.admin_cors.split(','), credentials: true, }; - - const authPath = linkedin.admin.authPath ?? "/admin/auth/linkedin" + + const authPath = linkedin.admin.authPath ?? '/admin/auth/linkedin'; router.get(authPath, cors(adminCorsOptions)); router.get( @@ -95,21 +94,22 @@ export function getLinkedinAdminAuthRouter(linkedin: LinkedinAuthOptions, config }) ); - const callbackHandler = (req, res) => { - const token = jwt.sign({ userId: req.user.id }, configModule.projectConfig.jwt_secret, { - expiresIn: linkedin.admin.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS, - }); - res.cookie(ADMIN_AUTH_TOKEN_COOKIE_NAME, token, getCookieOptions()).redirect(linkedin.admin.successRedirect); - }; - - const authPathCb = linkedin.admin.authCallbackPath ?? "/admin/auth/linkedin/cb" + const expiresIn = linkedin.admin.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS; + + const callbackHandler = buildCallbackHandler( + ADMIN_AUTH_TOKEN_COOKIE_NAME, + configModule.projectConfig.jwt_secret, + expiresIn, + linkedin.admin.successRedirect + ); + const authPathCb = linkedin.admin.authCallbackPath ?? '/admin/auth/linkedin/cb'; router.get(authPathCb, cors(adminCorsOptions)); router.get( authPathCb, (req, res, next) => { if (req.user) { - callbackHandler(req, res); + return callbackHandler(req, res); } next(); diff --git a/packages/medusa-plugin-auth/src/auth-strategies/linkedin/store.ts b/packages/medusa-plugin-auth/src/auth-strategies/linkedin/store.ts index 4906467..2606a5c 100644 --- a/packages/medusa-plugin-auth/src/auth-strategies/linkedin/store.ts +++ b/packages/medusa-plugin-auth/src/auth-strategies/linkedin/store.ts @@ -2,16 +2,15 @@ import passport from 'passport'; import { Router } from 'express'; import cors from 'cors'; import { ConfigModule, MedusaContainer } from '@medusajs/medusa/dist/types/global'; -import jwt from 'jsonwebtoken'; import { Strategy as LinkedinStrategy } from 'passport-linkedin-oauth2'; import { CustomerService } from '@medusajs/medusa'; import { MedusaError } from 'medusa-core-utils'; import { EntityManager } from 'typeorm'; import { CUSTOMER_METADATA_KEY, STORE_AUTH_TOKEN_COOKIE_NAME, TWENTY_FOUR_HOURS_IN_MS } from '../../types'; -import { getCookieOptions } from '../../utils/get-cookie-options'; import { PassportStrategy } from '../../core/Strategy'; -import { LINKEDIN_STORE_STRATEGY_NAME, LinkedinAuthOptions, Profile } from "./types"; +import { LINKEDIN_STORE_STRATEGY_NAME, LinkedinAuthOptions, Profile } from './types'; +import { buildCallbackHandler } from '../../utils/build-callback-handler'; export class LinkedinStoreStrategy extends PassportStrategy(LinkedinStrategy, LINKEDIN_STORE_STRATEGY_NAME) { constructor( @@ -106,8 +105,8 @@ export function getLinkedinStoreAuthRouter(linkedin: LinkedinAuthOptions, config origin: configModule.projectConfig.store_cors.split(','), credentials: true, }; - - const authPath = linkedin.store.authPath ?? "/store/auth/linkedin" + + const authPath = linkedin.store.authPath ?? '/store/auth/linkedin'; router.get(authPath, cors(storeCorsOptions)); router.get( @@ -121,23 +120,30 @@ export function getLinkedinStoreAuthRouter(linkedin: LinkedinAuthOptions, config }) ); - const authPathCb = linkedin.store.authCallbackPath ?? "/store/auth/linkedin/cb" - + const expiresIn = linkedin.store.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS; + const callbackHandler = buildCallbackHandler( + STORE_AUTH_TOKEN_COOKIE_NAME, + configModule.projectConfig.jwt_secret, + expiresIn, + linkedin.store.successRedirect + ); + const authPathCb = linkedin.store.authCallbackPath ?? '/store/auth/linkedin/cb'; + router.get(authPathCb, cors(storeCorsOptions)); router.get( authPathCb, + (req, res, next) => { + if (req.user) { + callbackHandler(req, res); + } + + next(); + }, passport.authenticate(LINKEDIN_STORE_STRATEGY_NAME, { failureRedirect: linkedin.store.failureRedirect, session: false, }), - (req, res) => { - const token = jwt.sign({ customer_id: req.user.customer_id }, configModule.projectConfig.jwt_secret, { - expiresIn: linkedin.store.expiresIn ?? TWENTY_FOUR_HOURS_IN_MS, - }); - res.cookie(STORE_AUTH_TOKEN_COOKIE_NAME, token, getCookieOptions()).redirect( - linkedin.store.successRedirect - ); - } + callbackHandler ); return router; diff --git a/packages/medusa-plugin-auth/src/utils/build-callback-handler.ts b/packages/medusa-plugin-auth/src/utils/build-callback-handler.ts new file mode 100644 index 0000000..30d3cdb --- /dev/null +++ b/packages/medusa-plugin-auth/src/utils/build-callback-handler.ts @@ -0,0 +1,11 @@ +import jwt from 'jsonwebtoken'; +import { getCookieOptions } from './get-cookie-options'; + +export function buildCallbackHandler(tokenName: string, secret: string, expiresIn: number, successRedirect: string) { + return (req, res) => { + const token = jwt.sign({ customer_id: req.user.id }, secret, { + expiresIn, + }); + res.cookie(tokenName, token, getCookieOptions(expiresIn)).redirect(successRedirect); + }; +} diff --git a/packages/medusa-plugin-auth/src/utils/get-cookie-options.ts b/packages/medusa-plugin-auth/src/utils/get-cookie-options.ts index f1e1be4..dd82c33 100644 --- a/packages/medusa-plugin-auth/src/utils/get-cookie-options.ts +++ b/packages/medusa-plugin-auth/src/utils/get-cookie-options.ts @@ -1,6 +1,6 @@ import { CookieOptions } from 'express-serve-static-core'; -export function getCookieOptions(): CookieOptions { +export function getCookieOptions(maxAge: number): CookieOptions { let secure = false; let sameSite: CookieOptions['sameSite'] = false; @@ -12,5 +12,7 @@ export function getCookieOptions(): CookieOptions { return { sameSite, secure, + httpOnly: true, + maxAge, }; }