feat: Apply authentication middleware globally (#7396)
* feat: Apply auth middleware globally * feat: Remove local auth middleware where it makes sense
This commit is contained in:
1 parent
62ef82f497
commit
10ef32c5a3
52 files changed
+76
-276
No files matched your search
File renamed without changes.
File renamed without changes.
@@ -123,21 +123,31 @@ export const createServer = async (rootDir) => {
|
||||
if (opts.adminSession) {
|
||||
const token = jwt.sign(
|
||||
{
|
||||
user_id: opts.adminSession.userId || opts.adminSession.jwt?.userId,
|
||||
domain: "admin",
|
||||
actor_id: opts.adminSession.userId || opts.adminSession.jwt?.userId,
|
||||
actor_type: "user",
|
||||
app_metadata: {
|
||||
user_id:
|
||||
opts.adminSession.userId || opts.adminSession.jwt?.userId,
|
||||
},
|
||||
},
|
||||
config.projectConfig.http.jwtSecret!
|
||||
)
|
||||
|
||||
headers.Authorization = `Bearer ${token}`
|
||||
}
|
||||
|
||||
if (opts.clientSession) {
|
||||
const token = jwt.sign(
|
||||
{
|
||||
customer_id:
|
||||
actor_id:
|
||||
opts.clientSession.customer_id ||
|
||||
opts.clientSession.jwt?.customer_id,
|
||||
domain: "store",
|
||||
actor_type: "customer",
|
||||
app_metadata: {
|
||||
customer_id:
|
||||
opts.clientSession.customer_id ||
|
||||
opts.clientSession.jwt?.customer_id,
|
||||
},
|
||||
},
|
||||
config.projectConfig.http.jwtSecret!
|
||||
)
|
||||
|
||||
@@ -154,34 +154,6 @@ describe("RoutesLoader", function () {
|
||||
expect(res.text).toBe("GET /admin/unprotected")
|
||||
})
|
||||
|
||||
it("should return 200 when customer is authenticated", async () => {
|
||||
const res = await request("GET", "/store/me/protected", {
|
||||
clientSession: {
|
||||
jwt: {
|
||||
customer_id: "lebron",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
expect(res.text).toBe("GET /store/protected")
|
||||
})
|
||||
|
||||
// The authentication middleware has changed and is not automatically attached currently
|
||||
it.skip("should return 401 when customer is not authenticated", async () => {
|
||||
const res = await request("GET", "/store/me/protected")
|
||||
|
||||
expect(res.status).toBe(401)
|
||||
expect(res.text).toBe("Unauthorized")
|
||||
})
|
||||
|
||||
it("should return 200 when customer route is opted out of authentication", async () => {
|
||||
const res = await request("GET", "/store/me/unprotected")
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
expect(res.text).toBe("GET /store/unprotected")
|
||||
})
|
||||
|
||||
it("should return the error as JSON when an error is thrown with default error handling", async () => {
|
||||
const res = await request("GET", "/customers/error")
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { type Express, json, Router, text, urlencoded } from "express"
|
||||
import { readdir } from "fs/promises"
|
||||
import { extname, join, sep } from "path"
|
||||
import { MedusaRequest, MedusaResponse } from "../../../types/routing"
|
||||
import { errorHandler } from "../../../utils/middlewares"
|
||||
import { authenticate, errorHandler } from "../../../utils/middlewares"
|
||||
import logger from "../../logger"
|
||||
import {
|
||||
AsyncRouteHandler,
|
||||
@@ -298,10 +298,6 @@ export class RoutesLoader {
|
||||
|
||||
const config: RouteConfig = {
|
||||
routes: [],
|
||||
shouldRequireAdminAuth: false,
|
||||
shouldRequireCustomerAuth: false,
|
||||
shouldAppendCustomer: false,
|
||||
shouldAppendAuthCors: false,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,6 +309,7 @@ export class RoutesLoader {
|
||||
? (import_[AUTHTHENTICATE] as boolean)
|
||||
: true
|
||||
|
||||
config.optedOutOfAuth = !shouldRequireAuth
|
||||
/**
|
||||
* If the developer has not exported the
|
||||
* CORS flag we default to true.
|
||||
@@ -321,29 +318,24 @@ export class RoutesLoader {
|
||||
import_["CORS"] !== undefined ? (import_["CORS"] as boolean) : true
|
||||
|
||||
if (route.startsWith("/admin")) {
|
||||
config.routeType = "admin"
|
||||
if (shouldAddCors) {
|
||||
config.shouldAppendAdminCors = true
|
||||
}
|
||||
|
||||
if (shouldRequireAuth) {
|
||||
config.shouldRequireAdminAuth = true
|
||||
}
|
||||
}
|
||||
|
||||
if (route.startsWith("/store")) {
|
||||
config.shouldAppendCustomer = true
|
||||
|
||||
config.routeType = "store"
|
||||
if (shouldAddCors) {
|
||||
config.shouldAppendStoreCors = true
|
||||
}
|
||||
}
|
||||
|
||||
if (route.startsWith("/auth") && shouldAddCors) {
|
||||
config.shouldAppendAuthCors = true
|
||||
}
|
||||
|
||||
if (shouldRequireAuth && route.startsWith("/store/me")) {
|
||||
config.shouldRequireCustomerAuth = shouldRequireAuth
|
||||
config.routeType = "auth"
|
||||
if (shouldAddCors) {
|
||||
config.shouldAppendAuthCors = true
|
||||
}
|
||||
}
|
||||
|
||||
const handlers = Object.keys(import_).filter((key) => {
|
||||
@@ -587,6 +579,7 @@ export class RoutesLoader {
|
||||
continue
|
||||
}
|
||||
|
||||
const config = descriptor.config
|
||||
const routes = descriptor.config.routes
|
||||
|
||||
/**
|
||||
@@ -594,7 +587,7 @@ export class RoutesLoader {
|
||||
* not opted out of.
|
||||
*/
|
||||
|
||||
if (descriptor.config.shouldAppendAdminCors) {
|
||||
if (config.shouldAppendAdminCors) {
|
||||
/**
|
||||
* Apply the admin cors
|
||||
*/
|
||||
@@ -609,7 +602,7 @@ export class RoutesLoader {
|
||||
)
|
||||
}
|
||||
|
||||
if (descriptor.config.shouldAppendAuthCors) {
|
||||
if (config.shouldAppendAuthCors) {
|
||||
/**
|
||||
* Apply the auth cors
|
||||
*/
|
||||
@@ -624,7 +617,7 @@ export class RoutesLoader {
|
||||
)
|
||||
}
|
||||
|
||||
if (descriptor.config.shouldAppendStoreCors) {
|
||||
if (config.shouldAppendStoreCors) {
|
||||
/**
|
||||
* Apply the store cors
|
||||
*/
|
||||
@@ -639,6 +632,24 @@ export class RoutesLoader {
|
||||
)
|
||||
}
|
||||
|
||||
// We only apply the auth middleware to store routes to populate the auth context. For actual authentication, users can just reapply the middleware.
|
||||
if (!config.optedOutOfAuth && config.routeType === "store") {
|
||||
this.router.use(
|
||||
descriptor.route,
|
||||
authenticate("customer", ["bearer", "session"], {
|
||||
allowUnauthenticated: true,
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (!config.optedOutOfAuth && config.routeType === "admin") {
|
||||
// We probably don't want to allow access to all endpoints using an api key, but it will do until we revamp our routing.
|
||||
this.router.use(
|
||||
descriptor.route,
|
||||
authenticate("user", ["bearer", "session", "api-key"])
|
||||
)
|
||||
}
|
||||
|
||||
for (const route of routes) {
|
||||
/**
|
||||
* Apply the body parser middleware if the route
|
||||
|
||||
@@ -36,9 +36,8 @@ export type RouteImplementation = {
|
||||
}
|
||||
|
||||
export type RouteConfig = {
|
||||
shouldRequireAdminAuth?: boolean
|
||||
shouldRequireCustomerAuth?: boolean
|
||||
shouldAppendCustomer?: boolean
|
||||
optedOutOfAuth?: boolean
|
||||
routeType?: "admin" | "store" | "auth"
|
||||
shouldAppendAdminCors?: boolean
|
||||
shouldAppendStoreCors?: boolean
|
||||
shouldAppendAuthCors?: boolean
|
||||
|
||||
Reference in new issue
Block a user