diff --git a/integration-tests/plugins/__tests__/customer/store/create-customer-addresses.ts b/integration-tests/plugins/__tests__/customer/store/create-customer-addresses.ts index f628406a4d399..cd93c6d9fa41a 100644 --- a/integration-tests/plugins/__tests__/customer/store/create-customer-addresses.ts +++ b/integration-tests/plugins/__tests__/customer/store/create-customer-addresses.ts @@ -1,11 +1,12 @@ -import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { initDb, useDb } from "../../../../environment-helpers/use-db" + import { ICustomerModuleService } from "@medusajs/types" +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" +import { getContainer } from "../../../../environment-helpers/use-container" import path from "path" import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" jest.setTimeout(50000) @@ -39,9 +40,11 @@ describe("POST /store/customers/me/addresses", () => { }) it("should create a customer address", async () => { + const { jwt_secret } = appContainer.resolve("configModule").projectConfig const { customer, jwt } = await createAuthenticatedCustomer( customerModuleService, - appContainer.resolve(ModuleRegistrationName.AUTH) + appContainer.resolve(ModuleRegistrationName.AUTH), + jwt_secret ) const api = useApi() as any diff --git a/integration-tests/plugins/__tests__/customer/store/create-customer.spec.ts b/integration-tests/plugins/__tests__/customer/store/create-customer.spec.ts index bae4ee4918c8d..7048092f9e46f 100644 --- a/integration-tests/plugins/__tests__/customer/store/create-customer.spec.ts +++ b/integration-tests/plugins/__tests__/customer/store/create-customer.spec.ts @@ -4,6 +4,7 @@ import { initDb, useDb } from "../../../../environment-helpers/use-db" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import adminSeeder from "../../../../helpers/admin-seeder" import { getContainer } from "../../../../environment-helpers/use-container" +import jwt from "jsonwebtoken" import path from "path" import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import { useApi } from "../../../../environment-helpers/use-api" @@ -47,12 +48,14 @@ describe("POST /store/customers", () => { const authService: IAuthModuleService = appContainer.resolve( ModuleRegistrationName.AUTH ) + const { jwt_secret } = appContainer.resolve("configModule").projectConfig const authUser = await authService.createAuthUser({ entity_id: "store_user", - provider_id: "test", + provider: "emailpass", scope: "store", }) - const jwt = await authService.generateJwtToken(authUser.id, "store") + + const token = jwt.sign(authUser, jwt_secret) const api = useApi() as any const response = await api.post( @@ -62,7 +65,7 @@ describe("POST /store/customers", () => { last_name: "Doe", email: "john@me.com", }, - { headers: { authorization: `Bearer ${jwt}` } } + { headers: { authorization: `Bearer ${token}` } } ) expect(response.status).toEqual(200) diff --git a/integration-tests/plugins/__tests__/customer/store/delete-customer-address.spec.ts b/integration-tests/plugins/__tests__/customer/store/delete-customer-address.spec.ts index d2476958ab6d5..c5af2699b535c 100644 --- a/integration-tests/plugins/__tests__/customer/store/delete-customer-address.spec.ts +++ b/integration-tests/plugins/__tests__/customer/store/delete-customer-address.spec.ts @@ -1,11 +1,12 @@ -import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { initDb, useDb } from "../../../../environment-helpers/use-db" + import { ICustomerModuleService } from "@medusajs/types" +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" +import { getContainer } from "../../../../environment-helpers/use-container" import path from "path" import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" const env = { MEDUSA_FF_MEDUSA_V2: true } @@ -25,6 +26,14 @@ describe("DELETE /store/customers/me/addresses/:address_id", () => { ) }) + // TODO: delete with removal of authProvider + beforeEach(async () => { + const onStart = + appContainer.resolve(ModuleRegistrationName.AUTH).__hooks + .onApplicationStart ?? (() => Promise.resolve()) + await onStart() + }) + afterAll(async () => { const db = useDb() await db.shutdown() @@ -37,9 +46,11 @@ describe("DELETE /store/customers/me/addresses/:address_id", () => { }) it("should delete a customer address", async () => { + const { jwt_secret } = appContainer.resolve("configModule").projectConfig const { customer, jwt } = await createAuthenticatedCustomer( customerModuleService, - appContainer.resolve(ModuleRegistrationName.AUTH) + appContainer.resolve(ModuleRegistrationName.AUTH), + jwt_secret ) const address = await customerModuleService.addAddresses({ @@ -65,9 +76,11 @@ describe("DELETE /store/customers/me/addresses/:address_id", () => { }) it("should fail to delete another customer's address", async () => { + const { jwt_secret } = appContainer.resolve("configModule").projectConfig const { jwt } = await createAuthenticatedCustomer( customerModuleService, - appContainer.resolve(ModuleRegistrationName.AUTH) + appContainer.resolve(ModuleRegistrationName.AUTH), + jwt_secret ) const otherCustomer = await customerModuleService.create({ diff --git a/integration-tests/plugins/__tests__/customer/store/get-me.spec.ts b/integration-tests/plugins/__tests__/customer/store/get-me.spec.ts index c5329a4c83d31..4600a0b2a9e51 100644 --- a/integration-tests/plugins/__tests__/customer/store/get-me.spec.ts +++ b/integration-tests/plugins/__tests__/customer/store/get-me.spec.ts @@ -1,12 +1,13 @@ -import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { initDb, useDb } from "../../../../environment-helpers/use-db" + import { ICustomerModuleService } from "@medusajs/types" +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" +import customer from "../../../../development/database/customer" +import { getContainer } from "../../../../environment-helpers/use-container" import path from "path" import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import adminSeeder from "../../../../helpers/admin-seeder" -import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" jest.setTimeout(50000) @@ -34,19 +35,17 @@ describe("GET /store/customers", () => { await shutdownServer() }) - beforeEach(async () => { - await adminSeeder(dbConnection) - }) - afterEach(async () => { const db = useDb() await db.teardown() }) it("should retrieve auth user's customer", async () => { + const { jwt_secret } = appContainer.resolve("configModule").projectConfig const { customer, jwt } = await createAuthenticatedCustomer( customerModuleService, - appContainer.resolve(ModuleRegistrationName.AUTH) + appContainer.resolve(ModuleRegistrationName.AUTH), + jwt_secret ) const api = useApi() as any diff --git a/integration-tests/plugins/__tests__/customer/store/list-customer-addresses.ts b/integration-tests/plugins/__tests__/customer/store/list-customer-addresses.ts index ca4753eac7b43..9881982fce74f 100644 --- a/integration-tests/plugins/__tests__/customer/store/list-customer-addresses.ts +++ b/integration-tests/plugins/__tests__/customer/store/list-customer-addresses.ts @@ -1,11 +1,12 @@ -import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { initDb, useDb } from "../../../../environment-helpers/use-db" + import { ICustomerModuleService } from "@medusajs/types" +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" +import { getContainer } from "../../../../environment-helpers/use-container" import path from "path" import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" const env = { MEDUSA_FF_MEDUSA_V2: true } @@ -43,9 +44,11 @@ describe("GET /store/customers/me/addresses", () => { }) it("should get all customer addresses and its count", async () => { + const { jwt_secret } = appContainer.resolve("configModule").projectConfig const { customer, jwt } = await createAuthenticatedCustomer( customerModuleService, - appContainer.resolve(ModuleRegistrationName.AUTH) + appContainer.resolve(ModuleRegistrationName.AUTH), + jwt_secret ) await customerModuleService.addAddresses([ diff --git a/integration-tests/plugins/__tests__/customer/store/update-customer-address.spec.ts b/integration-tests/plugins/__tests__/customer/store/update-customer-address.spec.ts index 258d7a19c525e..22850130ff6ed 100644 --- a/integration-tests/plugins/__tests__/customer/store/update-customer-address.spec.ts +++ b/integration-tests/plugins/__tests__/customer/store/update-customer-address.spec.ts @@ -1,11 +1,12 @@ -import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { initDb, useDb } from "../../../../environment-helpers/use-db" + import { ICustomerModuleService } from "@medusajs/types" +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" +import { getContainer } from "../../../../environment-helpers/use-container" import path from "path" import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" const env = { MEDUSA_FF_MEDUSA_V2: true } @@ -25,6 +26,14 @@ describe("POST /store/customers/:id/addresses/:address_id", () => { ) }) + // TODO: delete with removal of authProvider + beforeEach(async () => { + const onStart = + appContainer.resolve(ModuleRegistrationName.AUTH).__hooks + .onApplicationStart ?? (() => Promise.resolve()) + await onStart() + }) + afterAll(async () => { const db = useDb() await db.shutdown() @@ -37,9 +46,12 @@ describe("POST /store/customers/:id/addresses/:address_id", () => { }) it("should update a customer address", async () => { + const { jwt_secret } = appContainer.resolve("configModule").projectConfig + const { customer, jwt } = await createAuthenticatedCustomer( customerModuleService, - appContainer.resolve(ModuleRegistrationName.AUTH) + appContainer.resolve(ModuleRegistrationName.AUTH), + jwt_secret ) const address = await customerModuleService.addAddresses({ @@ -69,15 +81,19 @@ describe("POST /store/customers/:id/addresses/:address_id", () => { }) it("should fail to update another customer's address", async () => { + const { jwt_secret } = appContainer.resolve("configModule").projectConfig + const { jwt } = await createAuthenticatedCustomer( customerModuleService, - appContainer.resolve(ModuleRegistrationName.AUTH) + appContainer.resolve(ModuleRegistrationName.AUTH), + jwt_secret ) const otherCustomer = await customerModuleService.create({ first_name: "Jane", last_name: "Doe", }) + const address = await customerModuleService.addAddresses({ customer_id: otherCustomer.id, first_name: "John", diff --git a/integration-tests/plugins/helpers/create-authenticated-customer.ts b/integration-tests/plugins/helpers/create-authenticated-customer.ts index 3bb092d950d2a..903dd172aa215 100644 --- a/integration-tests/plugins/helpers/create-authenticated-customer.ts +++ b/integration-tests/plugins/helpers/create-authenticated-customer.ts @@ -1,8 +1,11 @@ -import { ICustomerModuleService, IAuthModuleService } from "@medusajs/types" +import { IAuthModuleService, ICustomerModuleService } from "@medusajs/types" + +import jwt from "jsonwebtoken" export const createAuthenticatedCustomer = async ( customerModuleService: ICustomerModuleService, - authService: IAuthModuleService + authService: IAuthModuleService, + jwtSecret: string ) => { const customer = await customerModuleService.create({ first_name: "John", @@ -12,12 +15,12 @@ export const createAuthenticatedCustomer = async ( const authUser = await authService.createAuthUser({ entity_id: "store_user", - provider_id: "test", + provider: "emailpass", scope: "store", app_metadata: { customer_id: customer.id }, }) - const jwt = await authService.generateJwtToken(authUser.id, "store") + const token = jwt.sign(authUser, jwtSecret) - return { customer, authUser, jwt } + return { customer, authUser, jwt: token } } diff --git a/integration-tests/plugins/medusa-config.js b/integration-tests/plugins/medusa-config.js index 5d4193b4a4d79..fdfad225dff1c 100644 --- a/integration-tests/plugins/medusa-config.js +++ b/integration-tests/plugins/medusa-config.js @@ -46,9 +46,6 @@ module.exports = { scope: "internal", resources: "shared", resolve: "@medusajs/auth", - options: { - jwt_secret: "test", - }, }, [Modules.STOCK_LOCATION]: { scope: "internal", diff --git a/packages/auth/src/providers/google.ts b/packages/auth/src/providers/google.ts index 77f7d9d8788eb..7cc0404a5f25e 100644 --- a/packages/auth/src/providers/google.ts +++ b/packages/auth/src/providers/google.ts @@ -1,8 +1,8 @@ import { AbstractAuthModuleProvider, MedusaError } from "@medusajs/utils" import { + AuthProviderScope, AuthenticationInput, AuthenticationResponse, - AuthProviderScope, ModulesSdkTypes, } from "@medusajs/types" import { AuthUserService } from "@services" @@ -82,9 +82,9 @@ class GoogleProvider extends AbstractAuthModuleProvider { // abstractable async verify_(refreshToken: string, scope: string) { - const jwtData = (await jwt.decode(refreshToken, { + const jwtData = jwt.decode(refreshToken, { complete: true, - })) as JwtPayload + }) as JwtPayload const entity_id = jwtData.payload.email let authUser diff --git a/packages/auth/src/services/auth-module.ts b/packages/auth/src/services/auth-module.ts index 995ec3b734dc4..6ac7dd2dc6266 100644 --- a/packages/auth/src/services/auth-module.ts +++ b/packages/auth/src/services/auth-module.ts @@ -1,5 +1,3 @@ -import jwt from "jsonwebtoken" - import { AuthenticationInput, AuthenticationResponse, @@ -11,7 +9,6 @@ import { CreateAuthUserDTO, DAL, InternalModuleDeclaration, - JWTGenerationOptions, ModuleJoinerConfig, ModulesSdkTypes, UpdateAuthUserDTO, @@ -31,15 +28,6 @@ import { } from "@medusajs/utils" import { ServiceTypes } from "@types" -type AuthModuleOptions = { - jwt_secret: string -} - -type AuthJWTPayload = { - id: string - scope: string -} - type InjectedDependencies = { baseRepository: DAL.RepositoryService authUserService: ModulesSdkTypes.InternalModuleService @@ -68,7 +56,6 @@ export default class AuthModuleService< protected baseRepository_: DAL.RepositoryService protected authUserService_: ModulesSdkTypes.InternalModuleService protected authProviderService_: ModulesSdkTypes.InternalModuleService - protected options_: AuthModuleOptions constructor( { @@ -76,7 +63,6 @@ export default class AuthModuleService< authProviderService, baseRepository, }: InjectedDependencies, - options: AuthModuleOptions, protected readonly moduleDeclaration: InternalModuleDeclaration ) { // @ts-ignore @@ -85,53 +71,12 @@ export default class AuthModuleService< this.baseRepository_ = baseRepository this.authUserService_ = authUserService this.authProviderService_ = authProviderService - this.options_ = options } __joinerConfig(): ModuleJoinerConfig { return joinerConfig } - async generateJwtToken( - authUserId: string, - scope: string, - options: JWTGenerationOptions = {} - ): Promise { - const authUser = await this.authUserService_.retrieve(authUserId) - return jwt.sign({ id: authUser.id, scope }, this.options_.jwt_secret, { - expiresIn: options.expiresIn || "1d", - }) - } - - async retrieveAuthUserFromJwtToken( - token: string, - scope: string - ): Promise { - let decoded: AuthJWTPayload - try { - const verifiedToken = jwt.verify(token, this.options_.jwt_secret) - decoded = verifiedToken as AuthJWTPayload - } catch (err) { - throw new MedusaError( - MedusaError.Types.UNAUTHORIZED, - "The provided JWT token is invalid" - ) - } - - if (decoded.scope !== scope) { - throw new MedusaError( - MedusaError.Types.UNAUTHORIZED, - "The provided JWT token is invalid" - ) - } - - const authUser = await this.authUserService_.retrieve(decoded.id) - return await this.baseRepository_.serialize( - authUser, - { populate: true } - ) - } - async createAuthProvider( data: CreateAuthProviderDTO[], sharedContext?: Context diff --git a/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/callback/route.ts b/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/callback/route.ts index 54066dce4f3fd..3327e307c934b 100644 --- a/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/callback/route.ts +++ b/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/callback/route.ts @@ -1,8 +1,8 @@ -import { AuthenticationInput, IAuthModuleService } from "@medusajs/types" -import { MedusaRequest, MedusaResponse } from "../../../../../types/routing" - +import jwt from "jsonwebtoken" import { MedusaError } from "@medusajs/utils" import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { AuthenticationInput, IAuthModuleService } from "@medusajs/types" +import { MedusaRequest, MedusaResponse } from "../../../../../types/routing" export const GET = async (req: MedusaRequest, res: MedusaResponse) => { const { scope, authProvider } = req.params @@ -29,10 +29,9 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => { } if (success) { - req.session.auth_user = authUser - req.session.scope = authUser.scope - - return res.status(200).json({ authUser }) + const { jwt_secret } = req.scope.resolve("configModule").projectConfig + const token = jwt.sign(authUser, jwt_secret) + return res.status(200).json({ token }) } throw new MedusaError( diff --git a/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/route.ts b/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/route.ts index 7d3873a320ccd..23f3ff87bd5c3 100644 --- a/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/route.ts +++ b/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/route.ts @@ -1,8 +1,8 @@ +import jwt from "jsonwebtoken" import { AuthenticationInput, IAuthModuleService } from "@medusajs/types" -import { MedusaRequest, MedusaResponse } from "../../../../types/routing" - import { MedusaError } from "@medusajs/utils" import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { MedusaRequest, MedusaResponse } from "../../../../types/routing" export const GET = async (req: MedusaRequest, res: MedusaResponse) => { const { scope, authProvider } = req.params @@ -29,10 +29,11 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => { } if (success) { - req.session.auth_user = authUser - req.session.scope = authUser.scope + const { jwt_secret } = req.scope.resolve("configModule").projectConfig + + const token = jwt.sign(authUser, jwt_secret) - return res.status(200).json({ authUser }) + return res.status(200).json({ token }) } throw new MedusaError( diff --git a/packages/medusa/src/api-v2/auth/middlewares.ts b/packages/medusa/src/api-v2/auth/middlewares.ts new file mode 100644 index 0000000000000..ee8b4eb5a3fa4 --- /dev/null +++ b/packages/medusa/src/api-v2/auth/middlewares.ts @@ -0,0 +1,10 @@ +import { MiddlewareRoute } from "../../types/middlewares" +import { authenticate } from "../../utils/authenticate-middleware" + +export const authRoutesMiddlewares: MiddlewareRoute[] = [ + { + method: ["POST"], + matcher: "/auth/session", + middlewares: [authenticate(/.*/, "bearer")], + }, +] diff --git a/packages/medusa/src/api-v2/auth/session/route.ts b/packages/medusa/src/api-v2/auth/session/route.ts new file mode 100644 index 0000000000000..3d1f249939660 --- /dev/null +++ b/packages/medusa/src/api-v2/auth/session/route.ts @@ -0,0 +1,7 @@ +import { MedusaRequest, MedusaResponse } from "../../../types/routing" + +export const POST = async (req: MedusaRequest, res: MedusaResponse) => { + req.session.auth_user = req.auth_user + + res.status(200).json({ user: req.auth_user }) +} diff --git a/packages/medusa/src/api-v2/middlewares.ts b/packages/medusa/src/api-v2/middlewares.ts index 40b80fa5ee3f2..e7e440d096351 100644 --- a/packages/medusa/src/api-v2/middlewares.ts +++ b/packages/medusa/src/api-v2/middlewares.ts @@ -5,6 +5,7 @@ import { storeCustomerRoutesMiddlewares } from "./store/customers/middlewares" import { adminCustomerRoutesMiddlewares } from "./admin/customers/middlewares" import { adminPromotionRoutesMiddlewares } from "./admin/promotions/middlewares" import { storeCartRoutesMiddlewares } from "./store/carts/middlewares" +import { authRoutesMiddlewares } from "./auth/middlewares" export const config: MiddlewaresConfig = { routes: [ @@ -14,5 +15,6 @@ export const config: MiddlewaresConfig = { ...adminCampaignRoutesMiddlewares, ...storeCustomerRoutesMiddlewares, ...storeCartRoutesMiddlewares, + ...authRoutesMiddlewares, ], } diff --git a/packages/medusa/src/services/invite.ts b/packages/medusa/src/services/invite.ts index b53d7964e883e..3cfb556aa4456 100644 --- a/packages/medusa/src/services/invite.ts +++ b/packages/medusa/src/services/invite.ts @@ -228,9 +228,11 @@ class InviteService extends TransactionBaseService { verifyToken(token): JwtPayload | string { const { jwt_secret } = this.configModule_.projectConfig + if (jwt_secret) { return jwt.verify(token, jwt_secret) } + throw new MedusaError( MedusaError.Types.INVALID_DATA, "Please configure jwt_secret" diff --git a/packages/medusa/src/types/routing.ts b/packages/medusa/src/types/routing.ts index d270d7adc87cc..c1a7027837505 100644 --- a/packages/medusa/src/types/routing.ts +++ b/packages/medusa/src/types/routing.ts @@ -1,7 +1,5 @@ import type { Customer, User } from "../models" import type { NextFunction, Request, Response } from "express" - -import { AuthUserDTO } from "@medusajs/types" import type { MedusaContainer } from "./global" export interface MedusaRequest extends Request { diff --git a/packages/medusa/src/utils/authenticate-middleware.ts b/packages/medusa/src/utils/authenticate-middleware.ts index ffc2326a09f53..6af3f6a93aa3e 100644 --- a/packages/medusa/src/utils/authenticate-middleware.ts +++ b/packages/medusa/src/utils/authenticate-middleware.ts @@ -1,8 +1,9 @@ -import { AuthUserDTO, IAuthModuleService } from "@medusajs/types" import { MedusaRequest, MedusaResponse } from "../types/routing" import { NextFunction, RequestHandler } from "express" +import jwt, { JwtPayload } from "jsonwebtoken" -import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { AuthUserDTO } from "@medusajs/types" +import { stringEqualsOrRegexMatch } from "@medusajs/utils" const SESSION_AUTH = "session" const BEARER_AUTH = "bearer" @@ -15,7 +16,7 @@ type MedusaSession = { type AuthType = "session" | "bearer" export const authenticate = ( - authScope: string, + authScope: string | RegExp, authType: AuthType | AuthType[], options: { allowUnauthenticated?: boolean } = {} ): RequestHandler => { @@ -25,22 +26,23 @@ export const authenticate = ( next: NextFunction ): Promise => { const authTypes = Array.isArray(authType) ? authType : [authType] - const authModule = req.scope.resolve( - ModuleRegistrationName.AUTH - ) // @ts-ignore const session: MedusaSession = req.session || {} let authUser: AuthUserDTO | null = null if (authTypes.includes(SESSION_AUTH)) { - if (session.auth_user && session.scope === authScope) { + if ( + session.auth_user && + stringEqualsOrRegexMatch(authScope, session.auth_user.scope) + ) { authUser = session.auth_user } } if (!authUser && authTypes.includes(BEARER_AUTH)) { const authHeader = req.headers.authorization + if (authHeader) { const re = /(\S+)\s+(\S+)/ const matches = authHeader.match(re) @@ -49,10 +51,17 @@ export const authenticate = ( if (matches) { const tokenType = matches[1] const token = matches[2] - if (tokenType.toLowerCase() === "bearer") { - authUser = await authModule - .retrieveAuthUserFromJwtToken(token, authScope) - .catch(() => null) + if (tokenType.toLowerCase() === BEARER_AUTH) { + // get config jwt secret + // verify token and set authUser + const { jwt_secret } = + req.scope.resolve("configModule").projectConfig + + const verified = jwt.verify(token, jwt_secret) as JwtPayload + + if (stringEqualsOrRegexMatch(authScope, verified.scope)) { + authUser = verified as AuthUserDTO + } } } } @@ -62,7 +71,7 @@ export const authenticate = ( req.auth_user = { id: authUser.id, app_metadata: authUser.app_metadata, - scope: authScope, + scope: authUser.scope, } return next() } diff --git a/packages/types/src/auth/service.ts b/packages/types/src/auth/service.ts index 1dd4c4ecc2cc2..06890dc151333 100644 --- a/packages/types/src/auth/service.ts +++ b/packages/types/src/auth/service.ts @@ -76,16 +76,6 @@ export interface IAuthModuleService extends IModuleService { sharedContext?: Context ): Promise - generateJwtToken( - authUserId: string, - scope: string, - options?: JWTGenerationOptions - ): Promise - retrieveAuthUserFromJwtToken( - token: string, - scope: string - ): Promise - listAuthUsers( filters?: FilterableAuthProviderProps, config?: FindConfig, diff --git a/packages/utils/src/common/index.ts b/packages/utils/src/common/index.ts index 4f47fcc1ea4d0..01066b41e7333 100644 --- a/packages/utils/src/common/index.ts +++ b/packages/utils/src/common/index.ts @@ -34,6 +34,7 @@ export * from "./remove-nullisih" export * from "./selector-constraints-to-string" export * from "./set-metadata" export * from "./simple-hash" +export * from "./string-or-regex-equals" export * from "./string-to-select-relation-object" export * from "./stringify-circular" export * from "./to-camel-case" @@ -42,4 +43,3 @@ export * from "./to-pascal-case" export * from "./transaction" export * from "./upper-case-first" export * from "./wrap-handler" - diff --git a/packages/utils/src/common/string-or-regex-equals.ts b/packages/utils/src/common/string-or-regex-equals.ts new file mode 100644 index 0000000000000..01608058e3719 --- /dev/null +++ b/packages/utils/src/common/string-or-regex-equals.ts @@ -0,0 +1,9 @@ +export const stringEqualsOrRegexMatch = ( + stringOrRegex: string | RegExp, + testString: string +) => { + if (stringOrRegex instanceof RegExp) { + return stringOrRegex.test(testString) + } + return stringOrRegex === testString +}