feat(auth): Revamp authentication setup (#7387)

* chore: Clean up authentication middlewares

* chore: Rename AuthUser to AuthIdentity

* feat: Define link between user, customer, and auth identity

* feat: Use links for auth, update auth context content

* fix: Adjust user create command with new auth setup

* fix: Make auth login more dynamic, review fixes

* fix: Change test assertions for created by
This commit is contained in:
Stevche Radevski
2024-05-22 10:27:32 +02:00
committed by GitHub
parent b7df447682
commit 5ede560f70
88 changed files with 887 additions and 1014 deletions
@@ -1,12 +1,18 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { AuthenticationInput, IAuthModuleService } from "@medusajs/types"
import { MedusaError } from "@medusajs/utils"
import jwt from "jsonwebtoken"
import {
ContainerRegistrationKeys,
MedusaError,
remoteQueryObjectFromString,
} from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../../types/routing"
import { generateJwtToken } from "../../../../utils/auth/token"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const { scope, auth_provider } = req.params
const actorType = scope === "admin" ? "user" : "customer"
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const service: IAuthModuleService = req.scope.resolve(
ModuleRegistrationName.AUTH
)
@@ -20,16 +26,37 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
protocol: req.protocol,
} as AuthenticationInput
const authResult = await service.validateCallback(auth_provider, authData)
const { success, error, authIdentity, successRedirectUrl } =
await service.validateCallback(auth_provider, authData)
const { success, error, authUser, successRedirectUrl } = authResult
const queryObject = remoteQueryObjectFromString({
entryPoint: "auth_identity",
fields: [`${actorType}.id`],
variables: { id: authIdentity.id },
})
const [actorData] = await remoteQuery(queryObject)
const entityId = actorData?.[actorType]?.id
if (success) {
const { http } = req.scope.resolve("configModule").projectConfig
const { http } = req.scope.resolve(
ContainerRegistrationKeys.CONFIG_MODULE
).projectConfig
const { jwtSecret, jwtExpiresIn } = http
const token = jwt.sign(authUser, jwtSecret, { expiresIn: jwtExpiresIn })
// TODO: Clean up mapping between scope and actor type
const token = generateJwtToken(
{
actor_id: entityId,
actor_type: actorType,
auth_identity_id: authIdentity.id,
app_metadata: {},
scope,
},
{
secret: jwtSecret,
expiresIn: jwtExpiresIn,
}
)
if (successRedirectUrl) {
const url = new URL(successRedirectUrl!)
@@ -1,11 +1,17 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { AuthenticationInput, IAuthModuleService } from "@medusajs/types"
import { MedusaError } from "@medusajs/utils"
import jwt from "jsonwebtoken"
import {
ContainerRegistrationKeys,
MedusaError,
remoteQueryObjectFromString,
} from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
import { generateJwtToken } from "../../../utils/auth/token"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const { scope, auth_provider } = req.params
const actorType = scope === "admin" ? "user" : "customer"
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const service: IAuthModuleService = req.scope.resolve(
ModuleRegistrationName.AUTH
@@ -20,9 +26,10 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
protocol: req.protocol,
} as AuthenticationInput
const authResult = await service.authenticate(auth_provider, authData)
const { success, error, authUser, location } = authResult
const { success, error, authIdentity, location } = await service.authenticate(
auth_provider,
authData
)
if (location) {
res.redirect(location)
@@ -30,11 +37,33 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
}
if (success) {
const { http } = req.scope.resolve("configModule").projectConfig
const { http } = req.scope.resolve(
ContainerRegistrationKeys.CONFIG_MODULE
).projectConfig
const token = jwt.sign(authUser, http.jwtSecret, {
expiresIn: http.jwtExpiresIn,
const queryObject = remoteQueryObjectFromString({
entryPoint: "auth_identity",
fields: [`${actorType}.id`],
variables: { id: authIdentity.id },
})
const [actorData] = await remoteQuery(queryObject)
const entityId = actorData?.[actorType]?.id
const { jwtSecret, jwtExpiresIn } = http
// TODO: Clean up mapping between scope and actor type
const token = generateJwtToken(
{
actor_id: entityId,
actor_type: actorType,
auth_identity_id: authIdentity.id,
app_metadata: {},
scope,
},
{
secret: jwtSecret,
expiresIn: jwtExpiresIn,
}
)
return res.status(200).json({ token })
}
+2 -2
View File
@@ -5,12 +5,12 @@ export const authRoutesMiddlewares: MiddlewareRoute[] = [
{
method: ["POST"],
matcher: "/auth/session",
middlewares: [authenticate(/.*/, "bearer")],
middlewares: [authenticate("*", "bearer")],
},
{
method: ["DELETE"],
matcher: "/auth/session",
middlewares: [authenticate(/.*/, ["session"])],
middlewares: [authenticate("*", ["session"])],
},
{
method: ["POST"],
@@ -7,9 +7,9 @@ export const POST = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
req.session.auth_user = req.auth
req.session.auth_context = req.auth_context
res.status(200).json({ user: req.auth })
res.status(200).json({ user: req.auth_context })
}
export const DELETE = async (