feat(auth): Make token auth default (#6305)
**What** - make token auth the default being returned from authentication endpoints in api-v2 - Add `auth/session` to convert token to session based auth - add regex-scopes to authenticate middleware Co-authored-by: Sebastian Rindom <7554214+srindom@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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([
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -46,9 +46,6 @@ module.exports = {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
resolve: "@medusajs/auth",
|
||||
options: {
|
||||
jwt_secret: "test",
|
||||
},
|
||||
},
|
||||
[Modules.STOCK_LOCATION]: {
|
||||
scope: "internal",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<any>
|
||||
@@ -68,7 +56,6 @@ export default class AuthModuleService<
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
protected authUserService_: ModulesSdkTypes.InternalModuleService<TAuthUser>
|
||||
protected authProviderService_: ModulesSdkTypes.InternalModuleService<TAuthProvider>
|
||||
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<string> {
|
||||
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<AuthUserDTO> {
|
||||
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<AuthTypes.AuthUserDTO>(
|
||||
authUser,
|
||||
{ populate: true }
|
||||
)
|
||||
}
|
||||
|
||||
async createAuthProvider(
|
||||
data: CreateAuthProviderDTO[],
|
||||
sharedContext?: Context
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
return res.status(200).json({ authUser })
|
||||
const token = jwt.sign(authUser, jwt_secret)
|
||||
|
||||
return res.status(200).json({ token })
|
||||
}
|
||||
|
||||
throw new MedusaError(
|
||||
|
||||
10
packages/medusa/src/api-v2/auth/middlewares.ts
Normal file
10
packages/medusa/src/api-v2/auth/middlewares.ts
Normal file
@@ -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")],
|
||||
},
|
||||
]
|
||||
7
packages/medusa/src/api-v2/auth/session/route.ts
Normal file
7
packages/medusa/src/api-v2/auth/session/route.ts
Normal file
@@ -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 })
|
||||
}
|
||||
@@ -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,
|
||||
],
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<void> => {
|
||||
const authTypes = Array.isArray(authType) ? authType : [authType]
|
||||
const authModule = req.scope.resolve<IAuthModuleService>(
|
||||
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()
|
||||
}
|
||||
|
||||
@@ -76,16 +76,6 @@ export interface IAuthModuleService extends IModuleService {
|
||||
sharedContext?: Context
|
||||
): Promise<AuthUserDTO>
|
||||
|
||||
generateJwtToken(
|
||||
authUserId: string,
|
||||
scope: string,
|
||||
options?: JWTGenerationOptions
|
||||
): Promise<string>
|
||||
retrieveAuthUserFromJwtToken(
|
||||
token: string,
|
||||
scope: string
|
||||
): Promise<AuthUserDTO>
|
||||
|
||||
listAuthUsers(
|
||||
filters?: FilterableAuthProviderProps,
|
||||
config?: FindConfig<AuthUserDTO>,
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
9
packages/utils/src/common/string-or-regex-equals.ts
Normal file
9
packages/utils/src/common/string-or-regex-equals.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export const stringEqualsOrRegexMatch = (
|
||||
stringOrRegex: string | RegExp,
|
||||
testString: string
|
||||
) => {
|
||||
if (stringOrRegex instanceof RegExp) {
|
||||
return stringOrRegex.test(testString)
|
||||
}
|
||||
return stringOrRegex === testString
|
||||
}
|
||||
Reference in New Issue
Block a user