docs: docs for next release (#14110)
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
export const metadata = {
|
||||
title: `Custom Order Display ID`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this guide, you'll learn how to customize the display ID of orders in Medusa.
|
||||
|
||||
<Note>
|
||||
|
||||
This feature is available since [Medusa v2.12.0](https://github.com/medusajs/medusa/releases/tag/v2.12.0).
|
||||
|
||||
</Note>
|
||||
|
||||
## Default Display ID
|
||||
|
||||
By default, Medusa stores the display ID of orders in the `display_id` property of the [Order data model](/references/order/models/Order). The display ID is a serial integer that starts at 1 and increments with each new order.
|
||||
|
||||
For example:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "order_123",
|
||||
"display_id": 1,
|
||||
// other properties...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Custom Display ID
|
||||
|
||||
In some cases, you might want to use a custom display ID for orders. This is useful for integrating with external systems or providing a more user-friendly order identifier.
|
||||
|
||||
The `Order` data model has a `custom_display_id` property that stores a custom display ID you generate.
|
||||
|
||||
You can define the logic for generating this ID in the `generateCustomDisplayId` module option set in `medusa-config.ts`.
|
||||
|
||||
For example:
|
||||
|
||||
```ts title="medusa-config.ts"
|
||||
// other imports...
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { OrderTypes, Context } from "@medusajs/framework/types"
|
||||
|
||||
module.exports = defineConfig({
|
||||
modules: [
|
||||
{
|
||||
key: Modules.ORDER,
|
||||
options: {
|
||||
generateCustomDisplayId: async function (
|
||||
order: OrderTypes.CreateOrderDTO,
|
||||
sharedContext: Context
|
||||
): Promise<string> {
|
||||
// Return your custom display ID
|
||||
return `${order.email}-${Date.now()}`
|
||||
},
|
||||
},
|
||||
},
|
||||
// other modules...
|
||||
],
|
||||
// other configurations...
|
||||
})
|
||||
```
|
||||
|
||||
In the example above, the `generateCustomDisplayId` function generates a custom display ID by combining the order's email with the current timestamp.
|
||||
|
||||
You can implement any logic to generate a unique and meaningful display ID for your orders.
|
||||
|
||||
---
|
||||
|
||||
## View Custom Display ID in Medusa Admin
|
||||
|
||||
By default, Medusa Admin displays the `display_id` in the table on the Orders page. To view the custom display ID in the table, you can enable the `view_configurations` experimental feature.
|
||||
|
||||
To enable this feature, add the following to `medusa-config.ts`:
|
||||
|
||||
```ts title="medusa-config.ts"
|
||||
module.exports = defineConfig({
|
||||
// other configurations...
|
||||
featureFlags: {
|
||||
view_configurations: true,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
This enables the feature's flag.
|
||||
|
||||
Next, run the necessary migrations:
|
||||
|
||||
```bash
|
||||
npx medusa db:migrate
|
||||
```
|
||||
|
||||
Then, start the Medusa application:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Finally, customize the Order view in Medusa Admin to display the `custom_display_id` property.
|
||||
@@ -187,6 +187,28 @@ STRIPE_API_KEY=<YOUR_STRIPE_API_KEY>
|
||||
|
||||
\-
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
`oxxoExpiresDays`
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
The number of days before an OXXO payment expires. Only applicable if you plan to use OXXO as a payment method.
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
No
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
`3`
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
@@ -303,6 +325,18 @@ Assuming you set the ID of the Stripe Module Provider to `stripe` in `medusa-con
|
||||
|
||||
`pp_stripe-promptpay_stripe`
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
OXXO Payments (Available since [Medusa v2.12.0](https://github.com/medusajs/medusa/releases/tag/v2.12.0))
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
`pp_stripe-oxxo_stripe`
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
@@ -413,6 +447,18 @@ The Stripe Module Provider supports the following payment types, and the webhook
|
||||
|
||||
`{server_url}/hooks/payment/stripe-promptpay_stripe`
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
OXXO Payments (Available since [Medusa v2.12.0](https://github.com/medusajs/medusa/releases/tag/v2.12.0))
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
`{server_url}/hooks/payment/stripe-oxxo_stripe`
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
|
||||
@@ -86,6 +86,28 @@ The Medusa Admin UI may not provide a way to create each of these promotion exam
|
||||
|
||||
---
|
||||
|
||||
## Promotion Limits
|
||||
|
||||
<Note>
|
||||
|
||||
The `limit` property is available since [Medusa v2.12.0](https://github.com/medusajs/medusa/releases/tag/v2.12.0).
|
||||
|
||||
</Note>
|
||||
|
||||
A promotion can have usage limits to restrict how many times it can be used.
|
||||
|
||||
There are three ways to limit a promotion's usage:
|
||||
|
||||
1. By setting its `limit` property: This limits the total number of times the promotion can be used across all orders.
|
||||
2. By setting the [global budget on the promotion's campaign](../campaign/page.mdx#global-budgets): This limits the total spend or usage across all promotions in the campaign.
|
||||
3. By setting the [attribute-based budget on the promotion's campaign](../campaign/page.mdx#attribute-based-budgets): This limits the total spend or usage for specific attributes across all promotions in the campaign. For example, limiting the budget for a specific customer group.
|
||||
|
||||
All budgets are applied on the promotion. Once a budget is exhausted, the promotion can no longer be applied.
|
||||
|
||||
For example, if a promotion has a `limit` of `10` and its campaign has a global budget of `$1000`, the promotion can only be used `10` times or until the total discount given reaches `$1000`, whichever comes first.
|
||||
|
||||
---
|
||||
|
||||
## Promotion Rules
|
||||
|
||||
A promotion can be restricted by a set of rules, each rule is represented by the [PromotionRule data model](/references/promotion/models/PromotionRule).
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
---
|
||||
tags:
|
||||
- auth
|
||||
- user
|
||||
- name: server
|
||||
label: Custom Admin Authentication
|
||||
products:
|
||||
- auth
|
||||
- user
|
||||
---
|
||||
|
||||
export const metadata = {
|
||||
title: `How to Add Custom Authentication in Medusa Admin`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this guide, you'll learn how to add custom authentication provider to the Medusa Admin.
|
||||
|
||||
<Note>
|
||||
|
||||
Authenticating into the Medusa Admin with third-party providers is supported from [Medusa v2.12.0](https://github.com/medusajs/medusa/releases/tag/v2.12.0).
|
||||
|
||||
</Note>
|
||||
|
||||
## Overview
|
||||
|
||||
By default, the Medusa Admin allows users to authenticate using their email and password. Medusa uses the [Emailpass Authentication Provider](../../../../commerce-modules/auth/auth-providers/emailpass/page.mdx) to handle this authentication method.
|
||||
|
||||
You can also integrate a custom or third-party authentication provider to allow users registered with that provider to log in to the Medusa Admin. This delegates the authentication process to the third-party provider, which is useful if your organization uses a centralized authentication system.
|
||||
|
||||
<Note type="warning">
|
||||
|
||||
Ensure the third-party authentication provider allows **only** your organization's users to log in to the Medusa Admin. For example, integrating a social login provider like Google or Facebook without restrictions will allow any user with an account on those platforms to access your Medusa Admin.
|
||||
|
||||
</Note>
|
||||
|
||||
### Summary of Custom Medusa Admin Authentication
|
||||
|
||||
To authenticate admin users through a third-party provider, you need to:
|
||||
|
||||
1. Create a [custom Authentication Module Provider](/references/auth/provider) that integrates the third-party provider. For example, you can create a provider that integrates with Okta.
|
||||
2. Change the authentication type in the Medusa Admin dashboard to use JWT authentication.
|
||||
3. Add an API route with a workflow that handles creating the admin user after they authenticate through the third-party provider.
|
||||
4. Add a widget on the login page that provides the option to log in through the third-party provider.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Step 1: Create a Custom Authentication Module Provider
|
||||
|
||||
The first step is to create a custom Authentication Module Provider that integrates with the third-party authentication provider you want to use.
|
||||
|
||||
For example, if your organization uses Okta for authentication, you can create an Okta Authentication Provider that uses the Okta SDK to authenticate users.
|
||||
|
||||
Refer to the [Create Custom Authentication Module Provider](/references/auth/provider) guide to learn how to create a custom Authentication Module Provider.
|
||||
|
||||
### Enable Custom Authentication Provider for Admin Users
|
||||
|
||||
By default, registered Authentication Module Providers can be used for all [actor types](../../../../commerce-modules/auth/auth-identity-and-actor-types/page.mdx). This means both admin users and customers can authenticate through the provider.
|
||||
|
||||
It's recommended to restrict the custom authentication provider to admin users only. To do this, set the `http.authMethodsPerActor` configuration in `medusa-config.ts` to enable the custom authentication provider only for the `user` actor type:
|
||||
|
||||
```ts title="medusa-config.ts"
|
||||
module.exports = defineConfig({
|
||||
projectConfig: {
|
||||
http: {
|
||||
// ...
|
||||
authMethodsPerActor: {
|
||||
user: ["emailpass", "custom"],
|
||||
customer: ["emailpass"],
|
||||
},
|
||||
},
|
||||
// ...
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Where `emailpass` is the identifier of the Emailpass Authentication Provider, and `custom` is the identifier of your custom Authentication Module Provider.
|
||||
|
||||
Refer to the [Authentication Module Providers](../../../../commerce-modules/auth/auth-providers/page.mdx#configure-allowed-auth-providers-of-actor-types) guide to learn more about configuring allowed authentication providers for actor types.
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Change Authentication Type in Medusa Admin
|
||||
|
||||
Next, you need to change the authentication type in the Medusa Admin dashboard to use JWT authentication.
|
||||
|
||||
To do this, set the `ADMIN_AUTH_TYPE` environment variable to `jwt` in your Medusa application's environment variables:
|
||||
|
||||
```bash
|
||||
ADMIN_AUTH_TYPE=jwt
|
||||
```
|
||||
|
||||
Make sure to also create a JS SDK instance in your Medusa Admin customizations with the `auth.type` option set to `jwt`. For example, create the file `src/lib/sdk.ts` with the following content:
|
||||
|
||||
```ts title="src/lib/sdk.ts"
|
||||
import Medusa from "@medusajs/js-sdk"
|
||||
|
||||
export const sdk = new Medusa({
|
||||
baseUrl: import.meta.env.VITE_BACKEND_URL || "/",
|
||||
debug: import.meta.env.DEV,
|
||||
auth: {
|
||||
type: "jwt",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Refer to the [JS SDK Authentication guide](../../../../js-sdk/auth/overview/page.mdx) to learn more about configuring authentication in the Medusa JS SDK.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Create User API Route
|
||||
|
||||
Next, you need to create an [API route](!docs!/learn/fundamentals/api-routes) with a [workflow](!docs!/learn/fundamentals/workflows) that handles creating the admin user after they authenticate through the third-party provider.
|
||||
|
||||
Note that this API route will allow any user with a valid authentication token to create an admin user. Therefore, ensure that only authorized users can obtain an authentication token from the third-party provider.
|
||||
|
||||
### Create User Workflow
|
||||
|
||||
First, you need to create the workflow that creates a user and associates it with the authenticated identity.
|
||||
|
||||
Create the file `src/workflows/create-user.ts` with the following content:
|
||||
|
||||
```ts title="src/workflows/create-user.ts"
|
||||
import { createWorkflow, transform, WorkflowResponse } from "@medusajs/framework/workflows-sdk"
|
||||
import { createUsersWorkflow, setAuthAppMetadataStep } from "@medusajs/medusa/core-flows"
|
||||
|
||||
type WorkflowInput = {
|
||||
email: string
|
||||
auth_identity_id: string
|
||||
}
|
||||
|
||||
export const createUserWorkflow = createWorkflow(
|
||||
"create-user",
|
||||
(input: WorkflowInput) => {
|
||||
const users = createUsersWorkflow.runAsStep({
|
||||
input: {
|
||||
users: [
|
||||
{
|
||||
email: input.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const authUserInput = transform({ input, users }, ({ input, users }) => {
|
||||
const createdUser = users[0]
|
||||
|
||||
return {
|
||||
authIdentityId: input.auth_identity_id,
|
||||
actorType: "user",
|
||||
value: createdUser.id,
|
||||
}
|
||||
})
|
||||
|
||||
setAuthAppMetadataStep(authUserInput)
|
||||
|
||||
return new WorkflowResponse({
|
||||
user: users[0],
|
||||
})
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
The workflow receives an object with the following properties:
|
||||
|
||||
- `email`: The email of the user being authenticated. You can modify this based on your third-party provider's identification method.
|
||||
- `auth_identity_id`: The ID of the auth identity created by the custom Authentication Module Provider. Refer to the [Auth Identities](../../../../commerce-modules/auth/auth-identity-and-actor-types/page.mdx) guide to learn more.
|
||||
|
||||
In the workflow, you:
|
||||
|
||||
1. Create a user with the provided email using `createUsersWorkflow`.
|
||||
2. Associate the created user with the authenticated identity using `setAuthAppMetadataStep`.
|
||||
|
||||
### Create User API Route
|
||||
|
||||
Next, you need to create the API route that calls the workflow to create the user.
|
||||
|
||||
Create the file `src/api/custom-auth/admin/users/route.ts` with the following content:
|
||||
|
||||
```ts title="src/api/custom-auth/admin/users/route.ts"
|
||||
import { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/framework"
|
||||
import { z } from "zod"
|
||||
import { createUserWorkflow } from "../../../../workflows/create-user"
|
||||
|
||||
export const CreateUserSchema = z.object({
|
||||
email: z.string(),
|
||||
})
|
||||
|
||||
type CreateUserBody = z.infer<typeof CreateUserSchema>
|
||||
|
||||
export const POST = async (req: AuthenticatedMedusaRequest<CreateUserBody>, res: MedusaResponse) => {
|
||||
const user = await createUserWorkflow(req.scope)
|
||||
.run({
|
||||
input: {
|
||||
email: req.body.email,
|
||||
auth_identity_id: req.auth_context!.auth_identity_id!,
|
||||
},
|
||||
})
|
||||
|
||||
return res.status(201).json({ user })
|
||||
}
|
||||
```
|
||||
|
||||
You expose a `POST` API route at `/custom-auth/admin/users` that receives the user's email in the request body. It executes `createUserWorkflow` to create the user and returns the created user in the response.
|
||||
|
||||
### Apply Authentication Middleware
|
||||
|
||||
Finally, you need to apply the authentication [middleware](!docs!/learn/fundamentals/api-routes/middlewares) to the API route to ensure that only authenticated users can access it.
|
||||
|
||||
To do this, create the file `src/api/middlewares.ts` with the following content:
|
||||
|
||||
```ts title="src/api/middlewares.ts"
|
||||
import { authenticate, defineMiddlewares } from "@medusajs/framework/http"
|
||||
|
||||
export default defineMiddlewares({
|
||||
routes: [
|
||||
{
|
||||
matcher: "/custom-auth/admin/users",
|
||||
methods: ["POST"],
|
||||
middlewares: [
|
||||
authenticate("user", "bearer", {
|
||||
allowUnregistered: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
This middleware applies the `authenticate` middleware to the `/custom-auth/admin/users` `POST` route, allowing only authenticated users to access it. By enabling the `allowUnregistered` option, users who are authenticated through the third-party provider but don't yet have an associated Medusa user can still access the route to create their user.
|
||||
|
||||
Refer to the [Protected Routes](!docs!/learn/fundamentals/api-routes/protected-routes) guide to learn more about protecting API routes with the `authentication` middleware.
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Add a Widget on the Login Page
|
||||
|
||||
Finally, you need to add a [widget](!docs!/learn/fundamentals/admin/widgets) to the Medusa Admin login page that provides the option to log in through the third-party provider.
|
||||
|
||||
The widget should display a button that authenticates or redirects the user to the third-party provider. The widget should also handle the redirection back to the Medusa Admin after successful authentication.
|
||||
|
||||
For example, the widget may look like this:
|
||||
|
||||
```tsx title="src/admin/widgets/custom-login.tsx"
|
||||
import { defineWidgetConfig } from "@medusajs/admin-sdk"
|
||||
import { Button, toast } from "@medusajs/ui"
|
||||
import { decodeToken } from "react-jwt"
|
||||
import { useSearchParams, useNavigate } from "react-router-dom"
|
||||
import { useMutation } from "@tanstack/react-query"
|
||||
import { sdk } from "../lib/sdk"
|
||||
import { useEffect } from "react"
|
||||
|
||||
// Replace with the identifier of your custom authentication provider
|
||||
const CUSTOM_AUTH_PROVIDER = "custom"
|
||||
|
||||
const CustomLogin = () => {
|
||||
// The third-party provider redirects back with query parameters
|
||||
// used to validate the authentication
|
||||
const [searchParams] = useSearchParams()
|
||||
const navigate = useNavigate()
|
||||
const { mutateAsync, isPending } = useMutation({
|
||||
mutationFn: async () => {
|
||||
if (isPending) {
|
||||
return
|
||||
}
|
||||
return await validateCallback()
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error("Custom authentication error:", error)
|
||||
},
|
||||
})
|
||||
|
||||
const sendCallback = async () => {
|
||||
try {
|
||||
return await sdk.auth.callback(
|
||||
"user",
|
||||
CUSTOM_AUTH_PROVIDER,
|
||||
Object.fromEntries(searchParams)
|
||||
)
|
||||
} catch (error) {
|
||||
toast.error("Authentication failed")
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the authentication callback
|
||||
const validateCallback = async () => {
|
||||
const token = await sendCallback()
|
||||
|
||||
const decodedToken = decodeToken(token) as { actor_id: string, user_metadata: Record<string, unknown> }
|
||||
|
||||
const userExists = decodedToken.actor_id !== ""
|
||||
|
||||
if (!userExists) {
|
||||
// Create user
|
||||
await sdk.client.fetch("/custom-auth/admin/users", {
|
||||
method: "POST",
|
||||
body: {
|
||||
email: decodedToken.user_metadata?.email as string,
|
||||
},
|
||||
})
|
||||
|
||||
const newToken = await sdk.auth.refresh()
|
||||
|
||||
if (!newToken) {
|
||||
toast.error("Authentication failed")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// User is authenticated
|
||||
navigate("/orders")
|
||||
}
|
||||
|
||||
// Handle custom login button click
|
||||
const customLogin = async () => {
|
||||
const result = await sdk.auth.login("user", CUSTOM_AUTH_PROVIDER, {})
|
||||
|
||||
if (typeof result === "object" && result.location) {
|
||||
// Redirect to custom provider for authentication
|
||||
window.location.href = result.location
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof result !== "string") {
|
||||
// Result failed, show an error
|
||||
toast.error("Authentication failed")
|
||||
return
|
||||
}
|
||||
|
||||
navigate("/app")
|
||||
}
|
||||
|
||||
// Handle the redirection back from the third-party provider
|
||||
useEffect(() => {
|
||||
// Check for provider-specific query parameters
|
||||
if (searchParams.get("code")) {
|
||||
mutateAsync()
|
||||
}
|
||||
}, [searchParams, mutateAsync])
|
||||
|
||||
return (
|
||||
<>
|
||||
<hr className="bg-ui-border-base my-4" />
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={customLogin}
|
||||
className="w-full"
|
||||
>
|
||||
Login with Custom Provider
|
||||
</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const config = defineWidgetConfig({
|
||||
zone: "login.after",
|
||||
})
|
||||
|
||||
export default CustomLogin
|
||||
```
|
||||
|
||||
You inject the widget into the `login.after` zone. This displays it below the default email and password login form.
|
||||
|
||||
<Note>
|
||||
|
||||
You can't remove the default email and password login form from the Medusa Admin. You can only add additional login options through widgets.
|
||||
|
||||
</Note>
|
||||
|
||||
In the widget, you:
|
||||
|
||||
1. Display a button that initiates login through the third-party provider using the `sdk.auth.login` method.
|
||||
- If the login method returns a `location` property, redirect the user to that location to authenticate through the third-party provider.
|
||||
- Otherwise, if the login method returns a token, the user is authenticated and you navigate to the Orders page of the admin dashboard.
|
||||
2. Add a `useEffect` hook that checks for provider-specific query parameters in the URL, such as `code`, to handle the redirection back from the third-party provider after successful authentication.
|
||||
3. Upon redirection back, you:
|
||||
- Call the `sdk.auth.callback` method to validate the authentication with the third-party provider.
|
||||
- If the user doesn't exist in Medusa, call the [custom API route you created](#step-3-create-user-api-route) to create the user, then refresh the authentication token.
|
||||
- Finally, if authentication is successful, navigate to the Orders page of the admin dashboard.
|
||||
|
||||
---
|
||||
|
||||
## Test Custom Authentication in Medusa Admin
|
||||
|
||||
To test the custom authentication in the Medusa Admin, run the following command to start your Medusa application:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Then, open the Medusa Admin at `http://localhost:9000/app`, which will redirect you to the login page.
|
||||
|
||||
On the login page, you should see the option to log in through the third-party provider you integrated. Click the button to log in through the provider and follow the authentication flow.
|
||||
|
||||
If authentication is successful, you'll have access to the Medusa Admin dashboard. Otherwise, you can troubleshoot the issue by checking your Medusa application's logs or the browser's console for errors.
|
||||
@@ -611,6 +611,7 @@ If you already set up the [Auth Module Provider](../../../commerce-modules/auth/
|
||||
- A token in a `token` property. In this case, the customer was previously logged in with the third-party service. No additional actions are required. You can use the token to send subsequent authenticated requests.
|
||||
2. Once authentication with the third-party service finishes, it redirects back to the storefront with query parameters such as `code` and `state`. Make sure your third-party service is configured to redirect to your storefront's callback page after successful authentication.
|
||||
3. In the storefront's callback page, send a request to the [Validate Authentication Callback API route](!api!/store#auth_postactor_typeauth_providercallback). Pass the query parameters (`code`, `state`, etc.) received from the third-party service.
|
||||
- Medusa validates the authentication with the third-party service.
|
||||
4. If the callback validation is successful, you'll receive the authentication token. Decode the received token in the storefront using tools like [react-jwt](https://www.npmjs.com/package/react-jwt).
|
||||
- If the decoded data has an `actor_id` property, the customer is already registered. Use this token for subsequent authenticated requests.
|
||||
- If not, follow the rest of the steps.
|
||||
|
||||
Reference in New Issue
Block a user