feat: Add support for refreshing JWT tokens (#9013)
* feat: Add support for refreshing JWT tokens * feat: Add refresh method to the auth SDK
This commit is contained in:
@@ -1,15 +1,22 @@
|
||||
import { AuthenticationInput, IAuthModuleService } from "@medusajs/types"
|
||||
import {
|
||||
AuthenticationInput,
|
||||
ConfigModule,
|
||||
IAuthModuleService,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
MedusaError,
|
||||
ModuleRegistrationName,
|
||||
generateJwtToken,
|
||||
} from "@medusajs/utils"
|
||||
import { MedusaRequest, MedusaResponse } from "../../../../../types/routing"
|
||||
import { generateJwtTokenForAuthIdentity } from "../../../utils/generate-jwt-token"
|
||||
|
||||
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
|
||||
const { actor_type, auth_provider } = req.params
|
||||
|
||||
const config: ConfigModule = req.scope.resolve(
|
||||
ContainerRegistrationKeys.CONFIG_MODULE
|
||||
)
|
||||
const service: IAuthModuleService = req.scope.resolve(
|
||||
ModuleRegistrationName.AUTH
|
||||
)
|
||||
@@ -27,30 +34,14 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
|
||||
authData
|
||||
)
|
||||
|
||||
const entityIdKey = `${actor_type}_id`
|
||||
const entityId = authIdentity?.app_metadata?.[entityIdKey] as
|
||||
| string
|
||||
| undefined
|
||||
if (success) {
|
||||
const { http } = req.scope.resolve(
|
||||
ContainerRegistrationKeys.CONFIG_MODULE
|
||||
).projectConfig
|
||||
if (success && authIdentity) {
|
||||
const { http } = config.projectConfig
|
||||
|
||||
const { jwtSecret, jwtExpiresIn } = http
|
||||
const token = generateJwtToken(
|
||||
const token = generateJwtTokenForAuthIdentity(
|
||||
{ authIdentity, actorType: actor_type },
|
||||
{
|
||||
actor_id: entityId ?? "",
|
||||
actor_type,
|
||||
auth_identity_id: authIdentity?.id ?? "",
|
||||
app_metadata: {
|
||||
[entityIdKey]: entityId,
|
||||
},
|
||||
},
|
||||
{
|
||||
// @ts-expect-error
|
||||
secret: jwtSecret,
|
||||
// @ts-expect-error
|
||||
expiresIn: jwtExpiresIn,
|
||||
secret: http.jwtSecret,
|
||||
expiresIn: http.jwtExpiresIn,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
|
||||
authData
|
||||
)
|
||||
|
||||
if (success) {
|
||||
if (success && authIdentity) {
|
||||
const { http } = config.projectConfig
|
||||
|
||||
const token = generateJwtTokenForAuthIdentity(
|
||||
|
||||
@@ -38,7 +38,7 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
|
||||
return res.status(200).json({ location })
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (success && authIdentity) {
|
||||
const { http } = config.projectConfig
|
||||
|
||||
const token = generateJwtTokenForAuthIdentity(
|
||||
|
||||
@@ -14,6 +14,11 @@ export const authRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
matcher: "/auth/session",
|
||||
middlewares: [authenticate("*", ["session"])],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/auth/token/refresh",
|
||||
middlewares: [authenticate("*", "bearer", { allowUnregistered: true })],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/auth/:actor_type/:auth_provider/callback",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { IAuthModuleService } from "@medusajs/types"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../types/routing"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
ModuleRegistrationName,
|
||||
} from "@medusajs/utils"
|
||||
import { generateJwtTokenForAuthIdentity } from "../../utils/generate-jwt-token"
|
||||
|
||||
// Retrieve a newly generated JWT token. All checks that the existing token is valid already happen in the auth middleware.
|
||||
// The token will include the actor ID, even if the token used to refresh didn't have one.
|
||||
// Note: We probably want to disallow refreshes if the password changes, and require reauth.
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const service: IAuthModuleService = req.scope.resolve(
|
||||
ModuleRegistrationName.AUTH
|
||||
)
|
||||
|
||||
const authIdentity = await service.retrieveAuthIdentity(
|
||||
req.auth_context.auth_identity_id
|
||||
)
|
||||
|
||||
const { http } = req.scope.resolve(
|
||||
ContainerRegistrationKeys.CONFIG_MODULE
|
||||
).projectConfig
|
||||
|
||||
const token = generateJwtTokenForAuthIdentity(
|
||||
{ authIdentity, actorType: req.auth_context.actor_type },
|
||||
{
|
||||
secret: http.jwtSecret,
|
||||
expiresIn: http.jwtExpiresIn,
|
||||
}
|
||||
)
|
||||
|
||||
return res.json({ token })
|
||||
}
|
||||
@@ -1,8 +1,15 @@
|
||||
import { AuthIdentityDTO } from "@medusajs/types"
|
||||
import { generateJwtToken } from "@medusajs/utils"
|
||||
|
||||
export function generateJwtTokenForAuthIdentity(
|
||||
{ authIdentity, actorType },
|
||||
{ secret, expiresIn }
|
||||
{
|
||||
authIdentity,
|
||||
actorType,
|
||||
}: { authIdentity: AuthIdentityDTO; actorType: string },
|
||||
{
|
||||
secret,
|
||||
expiresIn,
|
||||
}: { secret: string | undefined; expiresIn: string | undefined }
|
||||
) {
|
||||
const entityIdKey = `${actorType}_id`
|
||||
const entityId = authIdentity?.app_metadata?.[entityIdKey] as
|
||||
|
||||
Reference in New Issue
Block a user