chore: Move token from params to headers (#11281)
* chore: Move token from params to body * chore: Add type * wip * chore: clean up * clean ip
This commit is contained in:
1 parent
4ec5219a72
commit
54a6ef91ac
7 files changed
+96
-75
No files matched your search
@@ -150,6 +150,9 @@ medusaIntegrationTestRunner({
|
|||||||
.post("/auth/user/emailpass/reset-password", {})
|
.post("/auth/user/emailpass/reset-password", {})
|
||||||
.catch((e) => e)
|
.catch((e) => e)
|
||||||
|
|
||||||
|
expect(errResponse.response.data.message).toEqual(
|
||||||
|
"Invalid request: Field 'identifier' is required"
|
||||||
|
)
|
||||||
expect(errResponse.response.status).toEqual(400)
|
expect(errResponse.response.status).toEqual(400)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -170,15 +173,6 @@ medusaIntegrationTestRunner({
|
|||||||
expect(response.status).toEqual(201)
|
expect(response.status).toEqual(201)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should fail to generate token for existing user but no provider, but still respond with 201", async () => {
|
|
||||||
const response = await api.post(
|
|
||||||
"/auth/user/non-existing-provider/reset-password",
|
|
||||||
{ identifier: "admin@medusa.js" }
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(response.status).toEqual(201)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should successfully reset password", async () => {
|
it("should successfully reset password", async () => {
|
||||||
// Register user
|
// Register user
|
||||||
await api.post("/auth/user/emailpass/register", {
|
await api.post("/auth/user/emailpass/register", {
|
||||||
@@ -199,10 +193,14 @@ medusaIntegrationTestRunner({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const response = await api.post(
|
const response = await api.post(
|
||||||
`/auth/user/emailpass/update?token=${result}`,
|
`/auth/user/emailpass/update`,
|
||||||
{
|
{
|
||||||
email: "test@medusa-commerce.com",
|
|
||||||
password: "new_password",
|
password: "new_password",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${result}`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -250,10 +248,15 @@ medusaIntegrationTestRunner({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const response = await api.post(
|
const response = await api.post(
|
||||||
`/auth/user/emailpass/update?token=${result}`,
|
`/auth/user/emailpass/update`,
|
||||||
{
|
{
|
||||||
email: "test+new@medusa-commerce.com",
|
email: "test+new@medusa-commerce.com",
|
||||||
password: "new_password",
|
password: "new_password",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${result}`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -306,10 +309,17 @@ medusaIntegrationTestRunner({
|
|||||||
jest.advanceTimersByTime(15 * 60 * 1000)
|
jest.advanceTimersByTime(15 * 60 * 1000)
|
||||||
|
|
||||||
const response = await api
|
const response = await api
|
||||||
.post(`/auth/user/emailpass/update?token=${result}`, {
|
.post(
|
||||||
email: "test@medusa-commerce.com",
|
`/auth/user/emailpass/update`,
|
||||||
password: "new_password",
|
{
|
||||||
})
|
password: "new_password",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${result}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
.catch((e) => e)
|
.catch((e) => e)
|
||||||
|
|
||||||
expect(response.response.status).toEqual(401)
|
expect(response.response.status).toEqual(401)
|
||||||
@@ -363,10 +373,17 @@ medusaIntegrationTestRunner({
|
|||||||
jest.advanceTimersByTime(15 * 60 * 1000)
|
jest.advanceTimersByTime(15 * 60 * 1000)
|
||||||
|
|
||||||
const response = await api
|
const response = await api
|
||||||
.post(`/auth/customer/emailpass/update?token=${result}`, {
|
.post(
|
||||||
email: "test@medusa-commerce.com",
|
`/auth/customer/emailpass/update`,
|
||||||
password: "new_password",
|
{
|
||||||
})
|
password: "new_password",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${result}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
.catch((e) => e)
|
.catch((e) => e)
|
||||||
|
|
||||||
expect(response.response.status).toEqual(401)
|
expect(response.response.status).toEqual(401)
|
||||||
@@ -398,10 +415,17 @@ medusaIntegrationTestRunner({
|
|||||||
jest.advanceTimersByTime(15 * 60 * 1000)
|
jest.advanceTimersByTime(15 * 60 * 1000)
|
||||||
|
|
||||||
const response = await api
|
const response = await api
|
||||||
.post(`/auth/user/emailpass/update?token=${result}`, {
|
.post(
|
||||||
email: "test@medusa-commerce.com",
|
`/auth/user/emailpass/update`,
|
||||||
password: "new_password",
|
{
|
||||||
})
|
password: "new_password",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${result}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
.catch((e) => e)
|
.catch((e) => e)
|
||||||
|
|
||||||
expect(response.response.status).toEqual(401)
|
expect(response.response.status).toEqual(401)
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export const useLogout = (options?: UseMutationOptions<void, FetchError>) => {
|
|||||||
|
|
||||||
export const useUpdateProviderForEmailPass = (
|
export const useUpdateProviderForEmailPass = (
|
||||||
token: string,
|
token: string,
|
||||||
options?: UseMutationOptions<void, FetchError, { password: string }>
|
options?: UseMutationOptions<void, FetchError, HttpTypes.AdminUpdateProvider>
|
||||||
) => {
|
) => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (payload) =>
|
mutationFn: (payload) =>
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ import { emitEventStep, useRemoteQueryStep } from "../../common"
|
|||||||
* [Generate Reset Password Token for Admin](https://docs.medusajs.com/api/admin#auth_postactor_typeauth_providerresetpassword)
|
* [Generate Reset Password Token for Admin](https://docs.medusajs.com/api/admin#auth_postactor_typeauth_providerresetpassword)
|
||||||
* and [Generate Reset Password Token for Customer](https://docs.medusajs.com/api/store#auth_postactor_typeauth_providerresetpassword)
|
* and [Generate Reset Password Token for Customer](https://docs.medusajs.com/api/store#auth_postactor_typeauth_providerresetpassword)
|
||||||
* API Routes.
|
* API Routes.
|
||||||
*
|
*
|
||||||
* The workflow emits the `auth.password_reset` event, which you can listen to in
|
* The workflow emits the `auth.password_reset` event, which you can listen to in
|
||||||
* a [subscriber](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers). Follow
|
* a [subscriber](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers). Follow
|
||||||
* [this guide](https://docs.medusajs.com/resources/commerce-modules/auth/reset-password) to learn
|
* [this guide](https://docs.medusajs.com/resources/commerce-modules/auth/reset-password) to learn
|
||||||
* how to handle this event.
|
* how to handle this event.
|
||||||
*
|
*
|
||||||
* You can use this workflow within your customizations or your own custom workflows, allowing you to
|
* You can use this workflow within your customizations or your own custom workflows, allowing you to
|
||||||
* generate reset password tokens within your custom flows.
|
* generate reset password tokens within your custom flows.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const { result } = await generateResetPasswordTokenWorkflow(container)
|
* const { result } = await generateResetPasswordTokenWorkflow(container)
|
||||||
* .run({
|
* .run({
|
||||||
@@ -34,9 +34,9 @@ import { emitEventStep, useRemoteQueryStep } from "../../common"
|
|||||||
* secret: "jwt_123" // jwt secret
|
* secret: "jwt_123" // jwt secret
|
||||||
* }
|
* }
|
||||||
* })
|
* })
|
||||||
*
|
*
|
||||||
* @summary
|
* @summary
|
||||||
*
|
*
|
||||||
* Generate a reset password token for a user or customer.
|
* Generate a reset password token for a user or customer.
|
||||||
*/
|
*/
|
||||||
export const generateResetPasswordTokenWorkflow = createWorkflow(
|
export const generateResetPasswordTokenWorkflow = createWorkflow(
|
||||||
@@ -90,11 +90,6 @@ export const generateResetPasswordTokenWorkflow = createWorkflow(
|
|||||||
eventName: AuthWorkflowEvents.PASSWORD_RESET,
|
eventName: AuthWorkflowEvents.PASSWORD_RESET,
|
||||||
data: {
|
data: {
|
||||||
entity_id: input.entityId,
|
entity_id: input.entityId,
|
||||||
/**
|
|
||||||
* Use `actor_type` instead. Will be removed in a future version.
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
actorType: input.actorType,
|
|
||||||
actor_type: input.actorType,
|
actor_type: input.actorType,
|
||||||
token,
|
token,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ const getAuthContextFromSession = (
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAuthContextFromJwtToken = (
|
export const getAuthContextFromJwtToken = (
|
||||||
authHeader: string | undefined,
|
authHeader: string | undefined,
|
||||||
jwtSecret: string,
|
jwtSecret: string,
|
||||||
authTypes: AuthType[],
|
authTypes: AuthType[],
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class Auth {
|
|||||||
* @param payload - The data to pass in the request's body for authentication. When using the `emailpass` provider,
|
* @param payload - The data to pass in the request's body for authentication. When using the `emailpass` provider,
|
||||||
* you pass the email and password.
|
* you pass the email and password.
|
||||||
* @returns The JWT token used for registration later.
|
* @returns The JWT token used for registration later.
|
||||||
*
|
*
|
||||||
* @tags auth
|
* @tags auth
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -68,7 +68,7 @@ export class Auth {
|
|||||||
* @param payload - The data to pass in the request's body for authentication. When using the `emailpass` provider,
|
* @param payload - The data to pass in the request's body for authentication. When using the `emailpass` provider,
|
||||||
* you pass the email and password.
|
* you pass the email and password.
|
||||||
* @returns The authentication JWT token
|
* @returns The authentication JWT token
|
||||||
*
|
*
|
||||||
* @tags auth
|
* @tags auth
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -116,7 +116,7 @@ export class Auth {
|
|||||||
* @param query - The query parameters from the Oauth callback, which should be passed to the API route. This includes query parameters like
|
* @param query - The query parameters from the Oauth callback, which should be passed to the API route. This includes query parameters like
|
||||||
* `code` and `state`.
|
* `code` and `state`.
|
||||||
* @returns The authentication JWT token
|
* @returns The authentication JWT token
|
||||||
*
|
*
|
||||||
* @tags auth
|
* @tags auth
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -125,7 +125,7 @@ export class Auth {
|
|||||||
* "google",
|
* "google",
|
||||||
* {
|
* {
|
||||||
* code: "123",
|
* code: "123",
|
||||||
* state: "456"
|
* state: "456"
|
||||||
* }
|
* }
|
||||||
* ).then((token) => {
|
* ).then((token) => {
|
||||||
* console.log(token)
|
* console.log(token)
|
||||||
@@ -158,7 +158,7 @@ export class Auth {
|
|||||||
* with {@link callback}. It sends a request to the [Refresh Authentication Token API route](https://docs.medusajs.com/api/admin#auth_postadminauthtokenrefresh).
|
* with {@link callback}. It sends a request to the [Refresh Authentication Token API route](https://docs.medusajs.com/api/admin#auth_postadminauthtokenrefresh).
|
||||||
*
|
*
|
||||||
* @returns The refreshed JWT authentication token.
|
* @returns The refreshed JWT authentication token.
|
||||||
*
|
*
|
||||||
* @tags auth
|
* @tags auth
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -184,7 +184,7 @@ export class Auth {
|
|||||||
/**
|
/**
|
||||||
* This method deletes the authentication session of the currently logged-in user to log them out.
|
* This method deletes the authentication session of the currently logged-in user to log them out.
|
||||||
* It sends a request to the [Delete Authentication Session API route](https://docs.medusajs.com/api/admin#auth_deletesession).
|
* It sends a request to the [Delete Authentication Session API route](https://docs.medusajs.com/api/admin#auth_deletesession).
|
||||||
*
|
*
|
||||||
* @tags auth
|
* @tags auth
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -214,7 +214,7 @@ export class Auth {
|
|||||||
* @param actor - The actor type. For example, `user` for admin user, or `customer` for customer.
|
* @param actor - The actor type. For example, `user` for admin user, or `customer` for customer.
|
||||||
* @param provider - The authentication provider to use. For example, `emailpass`.
|
* @param provider - The authentication provider to use. For example, `emailpass`.
|
||||||
* @param body - The data required to identify the user.
|
* @param body - The data required to identify the user.
|
||||||
*
|
*
|
||||||
* @tags auth
|
* @tags auth
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -261,7 +261,7 @@ export class Auth {
|
|||||||
* @param provider - The authentication provider to use. For example, `emailpass`.
|
* @param provider - The authentication provider to use. For example, `emailpass`.
|
||||||
* @param body - The data necessary to update the user's authentication data. When resetting the user's password,
|
* @param body - The data necessary to update the user's authentication data. When resetting the user's password,
|
||||||
* send the `password` property.
|
* send the `password` property.
|
||||||
*
|
*
|
||||||
* @tags auth
|
* @tags auth
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -280,16 +280,14 @@ export class Auth {
|
|||||||
updateProvider = async (
|
updateProvider = async (
|
||||||
actor: string,
|
actor: string,
|
||||||
provider: string,
|
provider: string,
|
||||||
body: Record<string, unknown>,
|
body: HttpTypes.AdminUpdateProvider,
|
||||||
token: string
|
token: string
|
||||||
) => {
|
) => {
|
||||||
await this.client.fetch(
|
await this.client.fetch(`/auth/${actor}/${provider}/update`, {
|
||||||
`/auth/${actor}/${provider}/update?token=${token}`,
|
method: "POST",
|
||||||
{
|
body,
|
||||||
method: "POST",
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
body,
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,3 +5,7 @@ export interface AdminSignUpWithEmailPassword {
|
|||||||
|
|
||||||
export interface AdminSignInWithEmailPassword
|
export interface AdminSignInWithEmailPassword
|
||||||
extends AdminSignUpWithEmailPassword {}
|
extends AdminSignUpWithEmailPassword {}
|
||||||
|
|
||||||
|
export interface AdminUpdateProvider {
|
||||||
|
[key: string]: unknown // Allow for any additional fields, this will vary depending on the provider
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
AuthenticatedMedusaRequest,
|
AuthenticatedMedusaRequest,
|
||||||
|
getAuthContextFromJwtToken,
|
||||||
MedusaNextFunction,
|
MedusaNextFunction,
|
||||||
MedusaRequest,
|
MedusaRequest,
|
||||||
MedusaResponse,
|
MedusaResponse,
|
||||||
@@ -10,20 +11,37 @@ import {
|
|||||||
MedusaError,
|
MedusaError,
|
||||||
Modules,
|
Modules,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { decode, JwtPayload, verify } from "jsonwebtoken"
|
import { HttpTypes } from "@medusajs/types"
|
||||||
|
|
||||||
|
export interface UpdateProviderJwtPayload {
|
||||||
|
entity_id: string
|
||||||
|
actor_type: string
|
||||||
|
provider: string
|
||||||
|
}
|
||||||
|
|
||||||
// Middleware to validate that a token is valid
|
// Middleware to validate that a token is valid
|
||||||
export const validateToken = () => {
|
export const validateToken = () => {
|
||||||
return async (
|
return async (
|
||||||
req: MedusaRequest,
|
req: MedusaRequest<HttpTypes.AdminUpdateProvider>,
|
||||||
res: MedusaResponse,
|
res: MedusaResponse,
|
||||||
next: MedusaNextFunction
|
next: MedusaNextFunction
|
||||||
) => {
|
) => {
|
||||||
const { actor_type, auth_provider } = req.params
|
const { actor_type, auth_provider } = req.params
|
||||||
const { token } = req.query
|
|
||||||
|
|
||||||
const req_ = req as AuthenticatedMedusaRequest
|
const req_ = req as AuthenticatedMedusaRequest
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const { http } = req_.scope.resolve<ConfigModule>(
|
||||||
|
ContainerRegistrationKeys.CONFIG_MODULE
|
||||||
|
).projectConfig
|
||||||
|
|
||||||
|
const token = getAuthContextFromJwtToken(
|
||||||
|
req.headers.authorization,
|
||||||
|
http.jwtSecret as string,
|
||||||
|
["bearer"],
|
||||||
|
[actor_type]
|
||||||
|
) as UpdateProviderJwtPayload | null
|
||||||
|
|
||||||
const errorObject = new MedusaError(
|
const errorObject = new MedusaError(
|
||||||
MedusaError.Types.UNAUTHORIZED,
|
MedusaError.Types.UNAUTHORIZED,
|
||||||
`Invalid token`
|
`Invalid token`
|
||||||
@@ -33,27 +51,15 @@ export const validateToken = () => {
|
|||||||
return next(errorObject)
|
return next(errorObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
const { http } = req_.scope.resolve<ConfigModule>(
|
|
||||||
ContainerRegistrationKeys.CONFIG_MODULE
|
|
||||||
).projectConfig
|
|
||||||
|
|
||||||
const authModule = req.scope.resolve<IAuthModuleService>(Modules.AUTH)
|
const authModule = req.scope.resolve<IAuthModuleService>(Modules.AUTH)
|
||||||
|
|
||||||
const decoded = decode(token as string) as JwtPayload
|
if (!token?.entity_id) {
|
||||||
|
|
||||||
if (!decoded?.entity_id) {
|
|
||||||
return next(errorObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
// E.g. token was requested for a customer, but attempted used for a user
|
|
||||||
if (decoded?.actor_type !== actor_type) {
|
|
||||||
return next(errorObject)
|
return next(errorObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
const [providerIdentity] = await authModule.listProviderIdentities(
|
const [providerIdentity] = await authModule.listProviderIdentities(
|
||||||
{
|
{
|
||||||
entity_id: decoded.entity_id,
|
entity_id: token.entity_id,
|
||||||
provider: auth_provider,
|
provider: auth_provider,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -65,12 +71,6 @@ export const validateToken = () => {
|
|||||||
return next(errorObject)
|
return next(errorObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
verify(token as string, http.jwtSecret as string) as JwtPayload
|
|
||||||
} catch (error) {
|
|
||||||
return next(errorObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
req_.auth_context = {
|
req_.auth_context = {
|
||||||
actor_type,
|
actor_type,
|
||||||
auth_identity_id: providerIdentity.auth_identity_id!,
|
auth_identity_id: providerIdentity.auth_identity_id!,
|
||||||
|
|||||||
Reference in new issue
Block a user