diff --git a/www/apps/api-reference/specs/admin/openapi.full.yaml b/www/apps/api-reference/specs/admin/openapi.full.yaml
index e2f616b8fe..5106375d8c 100644
--- a/www/apps/api-reference/specs/admin/openapi.full.yaml
+++ b/www/apps/api-reference/specs/admin/openapi.full.yaml
@@ -43374,9 +43374,7 @@ paths:
operationId: PostActor_typeAuth_providerCallback
summary: Validate Authentication Callback
description: |
- This API route is used by your dashboard or frontend application when a third-party provider redirects to it after authentication.
-
- It validates the authentication with the third-party provider and, if successful, returns an authentication token.
+ This API route is used by your dashboard or frontend application when a third-party provider redirects to it after authentication. It validates the authentication with the third-party provider and, if successful, returns an authentication token. All query parameters received from the third-party provider, such as `code`, `state`, and `error`, must be passed as query parameters to this route.
You can decode the JWT token using libraries like [react-jwt](https://www.npmjs.com/package/react-jwt) in the frontend. If the decoded data doesn't have an `actor_id` property, then you must create a user, typically using the Accept Invite route passing the token in the request's Authorization header.
externalDocs:
diff --git a/www/apps/api-reference/specs/admin/paths/auth_user_{auth_provider}_callback.yaml b/www/apps/api-reference/specs/admin/paths/auth_user_{auth_provider}_callback.yaml
index 68811d1b95..9ab9bc3db5 100644
--- a/www/apps/api-reference/specs/admin/paths/auth_user_{auth_provider}_callback.yaml
+++ b/www/apps/api-reference/specs/admin/paths/auth_user_{auth_provider}_callback.yaml
@@ -3,11 +3,11 @@ post:
summary: Validate Authentication Callback
description: >
This API route is used by your dashboard or frontend application when a
- third-party provider redirects to it after authentication.
-
-
- It validates the authentication with the third-party provider and, if
- successful, returns an authentication token.
+ third-party provider redirects to it after authentication. It validates the
+ authentication with the third-party provider and, if successful, returns an
+ authentication token. All query parameters received from the third-party
+ provider, such as `code`, `state`, and `error`, must be passed as query
+ parameters to this route.
You can decode the JWT token using libraries like
diff --git a/www/apps/api-reference/specs/store/openapi.full.yaml b/www/apps/api-reference/specs/store/openapi.full.yaml
index 254c07dfd3..4d2c388b6e 100644
--- a/www/apps/api-reference/specs/store/openapi.full.yaml
+++ b/www/apps/api-reference/specs/store/openapi.full.yaml
@@ -219,10 +219,7 @@ paths:
operationId: PostActor_typeAuth_providerCallback
summary: Validate Authentication Callback
description: |
- This API route is used by your storefront or frontend application when a third-party provider redirects to it after authentication.
-
- It validates the authentication with the third-party provider and, if successful, returns an authentication token.
-
+ This API route is used by your storefront or frontend application when a third-party provider redirects to it after authentication. It validates the authentication with the third-party provider and, if successful, returns an authentication token. All query parameters received from the third-party provider, such as `code`, `state`, and `error`, must be passed as query parameters to this route.
You can decode the JWT token using libraries like [react-jwt](https://www.npmjs.com/package/react-jwt) in the storefront. If the decoded data doesn't have an `actor_id` property, then you must register the customer using the Create Customer API route passing the token in the request's Authorization header.
externalDocs:
url: https://docs.medusajs.com/v2/storefront-development/customers/third-party-login
diff --git a/www/apps/api-reference/specs/store/paths/auth_customer_{auth_provider}_callback.yaml b/www/apps/api-reference/specs/store/paths/auth_customer_{auth_provider}_callback.yaml
index a5cc384770..fd375ec3b2 100644
--- a/www/apps/api-reference/specs/store/paths/auth_customer_{auth_provider}_callback.yaml
+++ b/www/apps/api-reference/specs/store/paths/auth_customer_{auth_provider}_callback.yaml
@@ -3,12 +3,11 @@ post:
summary: Validate Authentication Callback
description: >
This API route is used by your storefront or frontend application when a
- third-party provider redirects to it after authentication.
-
-
- It validates the authentication with the third-party provider and, if
- successful, returns an authentication token.
-
+ third-party provider redirects to it after authentication. It validates the
+ authentication with the third-party provider and, if successful, returns an
+ authentication token. All query parameters received from the third-party
+ provider, such as `code`, `state`, and `error`, must be passed as query
+ parameters to this route.
You can decode the JWT token using libraries like
[react-jwt](https://www.npmjs.com/package/react-jwt) in the storefront. If
diff --git a/www/apps/resources/app/commerce-modules/auth/auth-flows/page.mdx b/www/apps/resources/app/commerce-modules/auth/auth-flows/page.mdx
index 94c997ddaf..2701c008d0 100644
--- a/www/apps/resources/app/commerce-modules/auth/auth-flows/page.mdx
+++ b/www/apps/resources/app/commerce-modules/auth/auth-flows/page.mdx
@@ -144,7 +144,7 @@ const { success, authIdentity, location } = await authModuleService.authenticate
// passed to auth provider
{
// ...
- callback_url: "example.com"
+ callback_url: "example.com",
}
)
```
@@ -176,6 +176,12 @@ if (success) {
}
```
+
+
+For providers like Google, the `query` object contains the query parameters from the original callback URL, such as the `code` and `state` parameters.
+
+
+
If the returned `success` property is `true`, the authentication with the third-party provider was successful.

diff --git a/www/apps/resources/app/commerce-modules/auth/auth-providers/emailpass/page.mdx b/www/apps/resources/app/commerce-modules/auth/auth-providers/emailpass/page.mdx
index 5a867d5388..a3459cd88c 100644
--- a/www/apps/resources/app/commerce-modules/auth/auth-providers/emailpass/page.mdx
+++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/emailpass/page.mdx
@@ -41,7 +41,7 @@ module.exports = defineConfig({
},
],
},
- }
+ },
],
})
```
diff --git a/www/apps/resources/app/commerce-modules/auth/auth-providers/github/page.mdx b/www/apps/resources/app/commerce-modules/auth/auth-providers/github/page.mdx
index 49434d604c..85f34c95b3 100644
--- a/www/apps/resources/app/commerce-modules/auth/auth-providers/github/page.mdx
+++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/github/page.mdx
@@ -60,7 +60,7 @@ module.exports = defineConfig({
},
],
},
- }
+ },
],
})
```
diff --git a/www/apps/resources/app/commerce-modules/auth/auth-providers/google/page.mdx b/www/apps/resources/app/commerce-modules/auth/auth-providers/google/page.mdx
index d93583e8ab..9c67d796c2 100644
--- a/www/apps/resources/app/commerce-modules/auth/auth-providers/google/page.mdx
+++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/google/page.mdx
@@ -63,7 +63,7 @@ module.exports = defineConfig({
],
},
},
- }
+ },
],
})
```
diff --git a/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx b/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx
index 3f51e2dff5..7edc4f7328 100644
--- a/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx
+++ b/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx
@@ -59,7 +59,7 @@ It requires the following steps:
1. Authenticate the user with the [Auth Route](#login-route).
2. The auth route returns a URL to authenticate with third-party service, such as login with Google. The frontend (such as a storefront), when it receives a `location` property in the response, must redirect to the returned location.
3. Once the authentication with the third-party service finishes, it redirects back to the frontend with a `code` query parameter. So, make sure your third-party service is configured to redirect to your frontend page after successful authentication.
-4. The frontend sends a request to the [Callback Route](#callback-route) passing the `code` query parameter.
+4. The frontend sends a request to the [Validate Callback Route](#validate-callback-route) passing it the query parameters received from the third-party service, such as the `code` and `state` query parameters.
5. If the callback validation is successful, the frontend receives the authentication token.
6. Decode the received token in the frontend using tools like [react-jwt](https://www.npmjs.com/package/react-jwt).
- If the decoded data has an `actor_id` property, then the user is already registered. So, use this token for subsequent authenticated requests.
@@ -221,7 +221,7 @@ Redirect to that URL in the frontend to continue the authentication process with
The Medusa application defines an API route at `/auth/{actor_type}/{provider}/callback` that's useful for validating the authentication callback or redirect from third-party services like Google.
```bash
-curl -X POST http://localhost:9000/auth/{actor_type}/{providers}/callback?code=123
+curl -X POST http://localhost:9000/auth/{actor_type}/{providers}/callback?code=123&state=456
```
@@ -239,7 +239,7 @@ Its path parameters are:
### Query Parameters
-This route accepts a `code` query parameter, which is the code received from the third-party provider.
+This route accepts all the query parameters that the third-party service sends to the frontend after the user completes the authentication process, such as the `code` and `state` query parameters.
### Response Fields
diff --git a/www/apps/resources/app/commerce-modules/inventory/inventory-kit/page.mdx b/www/apps/resources/app/commerce-modules/inventory/inventory-kit/page.mdx
index ff7c657d3e..9bb7371075 100644
--- a/www/apps/resources/app/commerce-modules/inventory/inventory-kit/page.mdx
+++ b/www/apps/resources/app/commerce-modules/inventory/inventory-kit/page.mdx
@@ -54,7 +54,7 @@ export const multiPartsHighlights1 = [
```ts highlights={multiPartsHighlights1}
import {
createInventoryItemsWorkflow,
- useQueryGraphStep
+ useQueryGraphStep,
} from "@medusajs/medusa/core-flows"
import { createWorkflow } from "@medusajs/framework/workflows-sdk"
@@ -66,8 +66,8 @@ export const createMultiPartProductsWorkflow = createWorkflow(
entity: "stock_location",
fields: ["*"],
filters: {
- name: "European Warehouse"
- }
+ name: "European Warehouse",
+ },
})
const inventoryItems = createInventoryItemsWorkflow.runAsStep({
@@ -79,9 +79,9 @@ export const createMultiPartProductsWorkflow = createWorkflow(
location_levels: [
{
stocked_quantity: 100,
- location_id: stockLocations[0].id
- }
- ]
+ location_id: stockLocations[0].id,
+ },
+ ],
},
{
sku: "WHEEL",
@@ -89,9 +89,9 @@ export const createMultiPartProductsWorkflow = createWorkflow(
location_levels: [
{
stocked_quantity: 100,
- location_id: stockLocations[0].id
- }
- ]
+ location_id: stockLocations[0].id,
+ },
+ ],
},
{
sku: "SEAT",
@@ -99,12 +99,12 @@ export const createMultiPartProductsWorkflow = createWorkflow(
location_levels: [
{
stocked_quantity: 100,
- location_id: stockLocations[0].id
- }
- ]
- }
- ]
- }
+ location_id: stockLocations[0].id,
+ },
+ ],
+ },
+ ],
+ },
})
// TODO create the product
@@ -127,11 +127,11 @@ export const multiPartHighlights2 = [
```ts highlights={multiPartHighlights2}
import {
// ...
- transform
+ transform,
} from "@medusajs/framework/workflows-sdk"
import {
// ...
- createProductsWorkflow
+ createProductsWorkflow,
} from "@medusajs/medusa/core-flows"
export const createMultiPartProductsWorkflow = createWorkflow(
@@ -140,7 +140,7 @@ export const createMultiPartProductsWorkflow = createWorkflow(
// ...
const inventoryItemIds = transform({
- inventoryItems
+ inventoryItems,
}, (data) => {
return data.inventoryItems.map((inventoryItem) => {
return {
@@ -161,24 +161,24 @@ export const createMultiPartProductsWorkflow = createWorkflow(
prices: [
{
amount: 100,
- currency_code: "usd"
- }
+ currency_code: "usd",
+ },
],
options: {
- "Default Option": "Default Variant"
+ "Default Option": "Default Variant",
},
- inventory_items: inventoryItemIds
- }
+ inventory_items: inventoryItemIds,
+ },
],
options: [
{
title: "Default Option",
- values: ["Default Variant"]
- }
- ]
- }
- ]
- }
+ values: ["Default Variant"],
+ },
+ ],
+ },
+ ],
+ },
})
}
)
@@ -235,21 +235,21 @@ export const createBundledProducts = createWorkflow(
prices: [
{
amount: 10,
- currency_code: "usd"
- }
+ currency_code: "usd",
+ },
],
options: {
- "Default Option": "Default Variant"
+ "Default Option": "Default Variant",
},
- manage_inventory: true
- }
+ manage_inventory: true,
+ },
],
options: [
{
title: "Default Option",
- values: ["Default Variant"]
- }
- ]
+ values: ["Default Variant"],
+ },
+ ],
},
{
title: "Pants",
@@ -259,21 +259,21 @@ export const createBundledProducts = createWorkflow(
prices: [
{
amount: 10,
- currency_code: "usd"
- }
+ currency_code: "usd",
+ },
],
options: {
- "Default Option": "Default Variant"
+ "Default Option": "Default Variant",
},
- manage_inventory: true
- }
+ manage_inventory: true,
+ },
],
options: [
{
title: "Default Option",
- values: ["Default Variant"]
- }
- ]
+ values: ["Default Variant"],
+ },
+ ],
},
{
title: "Shoes",
@@ -283,24 +283,24 @@ export const createBundledProducts = createWorkflow(
prices: [
{
amount: 10,
- currency_code: "usd"
- }
+ currency_code: "usd",
+ },
],
options: {
- "Default Option": "Default Variant"
+ "Default Option": "Default Variant",
},
- manage_inventory: true
- }
+ manage_inventory: true,
+ },
],
options: [
{
title: "Default Option",
- values: ["Default Variant"]
- }
- ]
- }
- ]
- }
+ values: ["Default Variant"],
+ },
+ ],
+ },
+ ],
+ },
})
// TODO re-retrieve with inventory
@@ -321,10 +321,10 @@ export const bundledHighlights2 = [
```ts highlights={bundledHighlights2}
import {
// ...
- transform
+ transform,
} from "@medusajs/framework/workflows-sdk"
import {
- useQueryGraphStep
+ useQueryGraphStep,
} from "@medusajs/medusa/core-flows"
export const createBundledProducts = createWorkflow(
@@ -332,7 +332,7 @@ export const createBundledProducts = createWorkflow(
() => {
// ...
const productIds = transform({
- products
+ products,
}, (data) => data.products.map((product) => product.id))
// @ts-ignore
@@ -340,19 +340,19 @@ export const createBundledProducts = createWorkflow(
entity: "product",
fields: [
"variants.*",
- "variants.inventory_items.*"
+ "variants.inventory_items.*",
],
filters: {
- id: productIds
- }
+ id: productIds,
+ },
})
const inventoryItemIds = transform({
- productsWithInventory
+ productsWithInventory,
}, (data) => {
return data.productsWithInventory.map((product) => {
return {
- inventory_item_id: product.variants[0].inventory_items?.[0]?.inventory_item_id
+ inventory_item_id: product.variants[0].inventory_items?.[0]?.inventory_item_id,
}
})
})
@@ -387,24 +387,24 @@ export const createBundledProducts = createWorkflow(
prices: [
{
amount: 30,
- currency_code: "usd"
- }
+ currency_code: "usd",
+ },
],
options: {
- "Default Option": "Default Variant"
+ "Default Option": "Default Variant",
},
inventory_items: inventoryItemIds,
- }
+ },
],
options: [
{
title: "Default Option",
- values: ["Default Variant"]
- }
- ]
- }
- ]
- }
+ values: ["Default Variant"],
+ },
+ ],
+ },
+ ],
+ },
}).config({ name: "create-bundled-product" })
}
)
diff --git a/www/apps/resources/app/commerce-modules/payment/payment-flow/page.mdx b/www/apps/resources/app/commerce-modules/payment/payment-flow/page.mdx
index bc9adecf1c..cd3a8ea1ea 100644
--- a/www/apps/resources/app/commerce-modules/payment/payment-flow/page.mdx
+++ b/www/apps/resources/app/commerce-modules/payment/payment-flow/page.mdx
@@ -36,15 +36,15 @@ For example:
```ts
-import { createPaymentCollectionForCartWorkflow } from "@medusajs/medusa/core-flows";
+import { createPaymentCollectionForCartWorkflow } from "@medusajs/medusa/core-flows"
// ...
await createPaymentCollectionForCartWorkflow(req.scope)
.run({
input: {
- cart_id: "cart_123"
- }
+ cart_id: "cart_123",
+ },
})
```
@@ -77,7 +77,7 @@ For example:
```ts
-import { createPaymentSessionsWorkflow } from "@medusajs/medusa/core-flows";
+import { createPaymentSessionsWorkflow } from "@medusajs/medusa/core-flows"
// ...
@@ -86,7 +86,7 @@ const { result: paymentSesion } = await createPaymentSessionsWorkflow(req.scope)
input: {
payment_collection_id: "paycol_123",
provider_id: "stripe",
- }
+ },
})
```
@@ -124,13 +124,13 @@ For example:
```ts
-import { authorizePaymentSessionStep } from "@medusajs/medusa/core-flows";
+import { authorizePaymentSessionStep } from "@medusajs/medusa/core-flows"
// ...
authorizePaymentSessionStep({
id: "payses_123",
- context: {}
+ context: {},
})
```
@@ -140,7 +140,7 @@ authorizePaymentSessionStep({
```ts
const payment = authorizePaymentSessionStep({
id: "payses_123",
- context: {}
+ context: {},
})
```
diff --git a/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx b/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx
index 9702844fe6..99c5b5d492 100644
--- a/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx
+++ b/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx
@@ -273,7 +273,7 @@ import { defineLink } from "@medusajs/framework/utils"
export default defineLink(
{
linkable: DigitalProductModule.linkable.digitalProduct,
- deleteCascade: true
+ deleteCascade: true,
},
ProductModule.linkable.productVariant
)
@@ -1534,17 +1534,17 @@ export const retrieveDigitalProductsToDeleteStep = createStep(
const query = container.resolve("query")
const productVariants = await productService.listProductVariants({
- product_id: product_id
+ product_id: product_id,
}, {
- withDeleted: true
+ withDeleted: true,
})
const { data } = await query.graph({
entity: DigitalProductVariantLink.entryPoint,
fields: ["digital_product.*"],
filters: {
- product_variant_id: productVariants.map((v) => v.id)
- }
+ product_variant_id: productVariants.map((v) => v.id),
+ },
})
const digitalProductIds = data.map((d) => d.digital_product.id)
@@ -1612,9 +1612,9 @@ You can now create the workflow that executes those steps.
Create the file `src/workflows/delete-product-digital-products/index.ts` with the following content:
```ts title="src/workflows/delete-product-digital-products/index.ts"
-import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk";
-import { deleteDigitalProductsSteps } from "./steps/delete-digital-products";
-import { retrieveDigitalProductsToDeleteStep } from "./steps/retrieve-digital-products-to-delete";
+import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk"
+import { deleteDigitalProductsSteps } from "./steps/delete-digital-products"
+import { retrieveDigitalProductsToDeleteStep } from "./steps/retrieve-digital-products-to-delete"
type DeleteProductDigitalProductsInput = {
id: string
@@ -1624,11 +1624,11 @@ export const deleteProductDigitalProductsWorkflow = createWorkflow(
"delete-product-digital-products",
(input: DeleteProductDigitalProductsInput) => {
const digitalProductsToDelete = retrieveDigitalProductsToDeleteStep({
- product_id: input.id
+ product_id: input.id,
})
deleteDigitalProductsSteps({
- ids: digitalProductsToDelete
+ ids: digitalProductsToDelete,
})
return new WorkflowResponse({})
@@ -1656,10 +1656,10 @@ So, you'll listen to the `product.deleted` event in a subscriber, and execute th
Create the file `src/subscribers/handle-product-deleted.ts` with the following content:
```ts title="src/subscribers/handle-product-deleted.ts"
-import { SubscriberArgs, SubscriberConfig } from "@medusajs/framework";
+import { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
import {
- deleteProductDigitalProductsWorkflow
-} from "../workflows/delete-product-digital-products";
+ deleteProductDigitalProductsWorkflow,
+} from "../workflows/delete-product-digital-products"
export default async function handleProductDeleted({
event: { data },
@@ -1711,7 +1711,7 @@ import {
FulfillmentDTO,
FulfillmentItemDTO,
FulfillmentOption,
- FulfillmentOrderDTO
+ FulfillmentOrderDTO,
} from "@medusajs/framework/types"
class DigitalProductFulfillmentService extends AbstractFulfillmentProviderService {
@@ -1750,7 +1750,7 @@ class DigitalProductFulfillmentService extends AbstractFulfillmentProviderServic
// No data is being sent anywhere
return {
data,
- labels: []
+ labels: [],
}
}
@@ -2606,7 +2606,7 @@ In `src/types/global.ts`, add the following types that you’ll use in your cust
```ts title="src/types/global.ts"
import {
// other imports...
- StoreProductVariant
+ StoreProductVariant,
} from "@medusajs/types"
// ...
@@ -2668,7 +2668,7 @@ export const listProducts = async ({
query: {
// ...
fields: "*variants.calculated_price,+variants.inventory_quantity,+metadata,+tags,*variants.calculated_price,*variants.digital_product",
- }
+ },
}
)
// ...
@@ -2707,7 +2707,7 @@ export const getDigitalProductPreview = async function ({
{
headers,
next,
- cache: "force-cache"
+ cache: "force-cache",
}
)
diff --git a/www/apps/resources/app/storefront-development/checkout/shipping/page.mdx b/www/apps/resources/app/storefront-development/checkout/shipping/page.mdx
index c5ffa9ee90..318594d276 100644
--- a/www/apps/resources/app/storefront-development/checkout/shipping/page.mdx
+++ b/www/apps/resources/app/storefront-development/checkout/shipping/page.mdx
@@ -72,8 +72,8 @@ export const fetchHighlights = [
cart_id: cart.id,
data: {
// pass any data useful for calculation with third-party provider.
- }
- })
+ },
+ }),
})
.then((res) => res.json())
)
@@ -160,7 +160,7 @@ export const highlights = [
import { useCart } from "../../../providers/cart"
import { HttpTypes } from "@medusajs/types"
- export default function CheckoutShippingStep () {
+ export default function CheckoutShippingStep() {
const { cart, setCart } = useCart()
const [loading, setLoading] = useState(false)
const [shippingOptions, setShippingOptions] = useState<
@@ -171,7 +171,7 @@ export const highlights = [
>({})
const [
selectedShippingOption,
- setSelectedShippingOption
+ setSelectedShippingOption,
] = useState()
useEffect(() => {
@@ -211,8 +211,8 @@ export const highlights = [
cart_id: cart.id,
data: {
// pass any data useful for calculation with third-party provider.
- }
- })
+ },
+ }),
})
.then((res) => res.json())
)
@@ -253,8 +253,8 @@ export const highlights = [
data: {
// TODO add any data necessary for
// fulfillment provider
- }
- })
+ },
+ }),
})
.then((res) => res.json())
.then(({ cart: updatedCart }) => {
diff --git a/www/apps/resources/app/storefront-development/customers/register/page.mdx b/www/apps/resources/app/storefront-development/customers/register/page.mdx
index 6d937776e0..85bc9f26c9 100644
--- a/www/apps/resources/app/storefront-development/customers/register/page.mdx
+++ b/www/apps/resources/app/storefront-development/customers/register/page.mdx
@@ -50,12 +50,12 @@ export const fetchHighlights = [
credentials: "include",
method: "POST",
headers: {
- "Content-Type": "application/json"
+ "Content-Type": "application/json",
},
body: JSON.stringify({
email,
- password
- })
+ password,
+ }),
}
)
.then((res) => res.json())
@@ -72,12 +72,12 @@ export const fetchHighlights = [
credentials: "include",
method: "POST",
headers: {
- "Content-Type": "application/json"
+ "Content-Type": "application/json",
},
body: JSON.stringify({
email,
- password
- })
+ password,
+ }),
}
)
.then((res) => res.json())
@@ -166,12 +166,12 @@ export const highlights = [
credentials: "include",
method: "POST",
headers: {
- "Content-Type": "application/json"
+ "Content-Type": "application/json",
},
body: JSON.stringify({
email,
- password
- })
+ password,
+ }),
}
)
.then((res) => res.json())
@@ -188,12 +188,12 @@ export const highlights = [
credentials: "include",
method: "POST",
headers: {
- "Content-Type": "application/json"
+ "Content-Type": "application/json",
},
body: JSON.stringify({
email,
- password
- })
+ password,
+ }),
}
)
.then((res) => res.json())
@@ -218,13 +218,13 @@ export const highlights = [
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
- "x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp"
+ "x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
},
body: JSON.stringify({
first_name: firstName,
last_name: lastName,
- email
- })
+ email,
+ }),
}
)
.then((res) => res.json())
diff --git a/www/apps/resources/app/storefront-development/customers/third-party-login/page.mdx b/www/apps/resources/app/storefront-development/customers/third-party-login/page.mdx
index 87b173b0fe..fe6bbc9cff 100644
--- a/www/apps/resources/app/storefront-development/customers/third-party-login/page.mdx
+++ b/www/apps/resources/app/storefront-development/customers/third-party-login/page.mdx
@@ -21,8 +21,8 @@ To login a customer with a third-party service, such as Google or GitHub, you mu
1. Authenticate the customer with the [Authenticate Customer API route](!api!/store#auth_postactor_typeauth_provider).
2. The auth route returns a URL to authenticate with third-party service, such as login with Google. The storefront, when it receives a `location` property in the response, must redirect to the returned location.
-3. Once the authentication with the third-party service finishes, it redirects back to the storefront with a `code` query parameter. So, make sure your third-party service is configured to redirect to your storefront page after successful authentication.
-4. The storefront sends a request to the [Validate Authentication Callback API route](!api!/store#auth_postactor_typeauth_providercallback) passing the `code` query parameter.
+3. Once the authentication with the third-party service finishes, it redirects back to the storefront with query parameters such as `code` and `state`. So, make sure your third-party service is configured to redirect to your storefront page after successful authentication.
+4. The storefront sends a request to the [Validate Authentication Callback API route](!api!/store#auth_postactor_typeauth_providercallback) passing the query parameters received from the third-party service.
5. If the callback validation is successful, the storefront receives the authentication token.
6. Decode the received token in the frontend using tools like [react-jwt](https://www.npmjs.com/package/react-jwt).
- If the decoded data has an `actor_id` property, then the user is already registered. So, use this token for subsequent authenticated requests.
@@ -194,8 +194,7 @@ Then, in a new page in your storefront that will be used as the callback / redir
export const sendCallbackFetchHighlights = [
- ["6", "code", "The code received from Google as a query parameter."],
- ["7", "state", "The state received from Google as a query parameter."],
+ ["6", "queryParams", "The query parameters received from Google, such as `code` and `state`."],
["10", "fetch", "Send a request to the Validate Authentication Callback API route"],
["18", "!token", "If the token isn't returned, the authentication has failed."],
]
@@ -205,13 +204,12 @@ import { decodeToken } from "react-jwt"
// ...
-const queryParams = new URLSearchParams(window.location.search)
-const code = queryParams.get("code")
-const state = queryParams.get("state")
+const searchParams = new URLSearchParams(window.location.search)
+const queryParams = Object.fromEntries(searchParams.entries())
const sendCallback = async () => {
const { token } = await fetch(
- `http://localhost:9000/auth/customer/google/callback?code=${code}&state=${state}`,
+ `http://localhost:9000/auth/customer/google/callback?${new URLSearchParams(queryParams).toString()}`,
{
credentials: "include",
method: "POST",
@@ -250,17 +248,14 @@ export default function GoogleCallback() {
const [loading, setLoading] = useState(true)
const [customer, setCustomer] = useState()
// for other than Next.js
- const { code, state } = useMemo(() => {
- const queryParams = new URLSearchParams(window.location.search);
- return {
- code: queryParams.get("code"),
- state: queryParams.get("state"),
- };
- }, []);
+ const queryParams = useMemo(() => {
+ const searchParams = new URLSearchParams(window.location.search)
+ return Object.fromEntries(searchParams.entries())
+ }, [])
const sendCallback = async () => {
const { token } = await fetch(
- `http://localhost:9000/auth/customer/google/callback?code=${code}&state=${state}`,
+ `http://localhost:9000/auth/customer/google/callback?${new URLSearchParams(queryParams).toString()}`,
{
credentials: "include",
method: "POST",
@@ -289,7 +284,7 @@ export default function GoogleCallback() {
-This adds in the new page the function `sendCallback` which sends a request to the [Validate Callback API route](!api!/store#auth_postactor_typeauth_providercallback), passing it the `code` received from Google.
+This adds in the new page the function `sendCallback` which sends a request to the [Validate Callback API route](!api!/store#auth_postactor_typeauth_providercallback), passing it the query parameters received from Google.
Then, replace the `TODO` with the following:
@@ -566,12 +561,12 @@ export default function GoogleCallback() {
const [customer, setCustomer] = useState()
// for other than Next.js
const { code, state } = useMemo(() => {
- const queryParams = new URLSearchParams(window.location.search);
+ const queryParams = new URLSearchParams(window.location.search)
return {
code: queryParams.get("code"),
state: queryParams.get("state"),
- };
- }, []);
+ }
+ }, [])
const sendCallback = async () => {
const { token } = await fetch(
diff --git a/www/apps/resources/generated/edit-dates.mjs b/www/apps/resources/generated/edit-dates.mjs
index 3722d2398b..ee152a69dd 100644
--- a/www/apps/resources/generated/edit-dates.mjs
+++ b/www/apps/resources/generated/edit-dates.mjs
@@ -1,7 +1,7 @@
export const generatedEditDates = {
- "app/commerce-modules/auth/auth-providers/emailpass/page.mdx": "2025-01-07T12:47:24.380Z",
+ "app/commerce-modules/auth/auth-providers/emailpass/page.mdx": "2025-01-13T11:31:35.361Z",
"app/commerce-modules/auth/auth-providers/page.mdx": "2024-10-08T07:27:21.859Z",
- "app/commerce-modules/auth/authentication-route/page.mdx": "2025-01-07T09:26:27.809Z",
+ "app/commerce-modules/auth/authentication-route/page.mdx": "2025-01-13T11:31:17.572Z",
"app/commerce-modules/auth/examples/page.mdx": "2024-10-15T15:02:13.794Z",
"app/commerce-modules/auth/module-options/page.mdx": "2025-01-07T12:47:35.073Z",
"app/commerce-modules/auth/page.mdx": "2025-01-09T13:41:05.476Z",
@@ -47,7 +47,7 @@ export const generatedEditDates = {
"app/commerce-modules/payment/module-options/page.mdx": "2024-10-15T12:51:40.574Z",
"app/commerce-modules/payment/payment/page.mdx": "2024-10-09T10:59:08.463Z",
"app/commerce-modules/payment/payment-collection/page.mdx": "2024-10-09T10:56:49.510Z",
- "app/commerce-modules/payment/payment-flow/page.mdx": "2025-01-08T12:51:39.100Z",
+ "app/commerce-modules/payment/payment-flow/page.mdx": "2025-01-13T11:31:35.361Z",
"app/commerce-modules/payment/payment-provider/stripe/page.mdx": "2024-12-16T13:21:03.554Z",
"app/commerce-modules/payment/payment-provider/page.mdx": "2024-10-09T11:07:27.269Z",
"app/commerce-modules/payment/payment-session/page.mdx": "2024-10-09T10:58:00.960Z",
@@ -112,7 +112,7 @@ export const generatedEditDates = {
"app/nextjs-starter/page.mdx": "2025-01-06T12:19:31.143Z",
"app/recipes/b2b/page.mdx": "2024-10-03T13:07:44.153Z",
"app/recipes/commerce-automation/page.mdx": "2024-10-16T08:52:01.585Z",
- "app/recipes/digital-products/examples/standard/page.mdx": "2025-01-07T14:39:31.335Z",
+ "app/recipes/digital-products/examples/standard/page.mdx": "2025-01-13T11:31:35.362Z",
"app/recipes/digital-products/page.mdx": "2025-01-06T11:19:35.623Z",
"app/recipes/ecommerce/page.mdx": "2024-10-22T11:01:01.218Z",
"app/recipes/integrate-ecommerce-stack/page.mdx": "2024-12-09T13:03:35.846Z",
@@ -147,14 +147,14 @@ export const generatedEditDates = {
"app/storefront-development/checkout/email/page.mdx": "2024-12-19T16:30:40.122Z",
"app/storefront-development/checkout/payment/stripe/page.mdx": "2024-12-19T16:30:39.173Z",
"app/storefront-development/checkout/payment/page.mdx": "2025-01-02T08:47:20.531Z",
- "app/storefront-development/checkout/shipping/page.mdx": "2024-12-26T15:34:51.431Z",
+ "app/storefront-development/checkout/shipping/page.mdx": "2025-01-13T11:31:35.361Z",
"app/storefront-development/checkout/page.mdx": "2024-06-12T19:46:06+02:00",
"app/storefront-development/customers/addresses/page.mdx": "2025-01-06T16:59:53.878Z",
"app/storefront-development/customers/context/page.mdx": "2024-12-19T16:38:43.703Z",
"app/storefront-development/customers/log-out/page.mdx": "2024-12-19T16:31:28.347Z",
"app/storefront-development/customers/login/page.mdx": "2024-12-19T16:31:34.194Z",
"app/storefront-development/customers/profile/page.mdx": "2024-12-19T16:31:43.978Z",
- "app/storefront-development/customers/register/page.mdx": "2025-01-07T09:28:42.723Z",
+ "app/storefront-development/customers/register/page.mdx": "2025-01-13T11:31:35.362Z",
"app/storefront-development/customers/retrieve/page.mdx": "2025-01-06T16:07:12.542Z",
"app/storefront-development/customers/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/products/categories/list/page.mdx": "2024-12-19T16:33:06.547Z",
@@ -192,7 +192,7 @@ export const generatedEditDates = {
"app/usage/page.mdx": "2024-05-13T18:55:11+03:00",
"app/page.mdx": "2025-01-09T11:40:57.826Z",
"app/commerce-modules/auth/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00",
- "app/commerce-modules/auth/auth-flows/page.mdx": "2025-01-07T09:29:52.153Z",
+ "app/commerce-modules/auth/auth-flows/page.mdx": "2025-01-13T11:31:35.361Z",
"app/commerce-modules/auth/_events/page.mdx": "2024-07-03T19:27:13+03:00",
"app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx": "2025-01-07T09:02:27.235Z",
"app/commerce-modules/api-key/page.mdx": "2025-01-09T13:41:04.492Z",
@@ -861,9 +861,9 @@ export const generatedEditDates = {
"references/types/HttpTypes/interfaces/types.HttpTypes.AdminClaimPreviewResponse/page.mdx": "2025-01-07T12:54:21.225Z",
"references/types/HttpTypes/interfaces/types.HttpTypes.AdminOrderEditPreviewResponse/page.mdx": "2025-01-07T12:54:21.543Z",
"references/types/interfaces/types.BaseClaim/page.mdx": "2025-01-07T12:54:20.996Z",
- "app/commerce-modules/auth/auth-providers/github/page.mdx": "2025-01-07T12:47:30.196Z",
- "app/commerce-modules/auth/auth-providers/google/page.mdx": "2025-01-07T12:47:32.501Z",
- "app/storefront-development/customers/third-party-login/page.mdx": "2025-01-06T16:05:41.159Z",
+ "app/commerce-modules/auth/auth-providers/github/page.mdx": "2025-01-13T11:31:35.361Z",
+ "app/commerce-modules/auth/auth-providers/google/page.mdx": "2025-01-13T11:31:35.361Z",
+ "app/storefront-development/customers/third-party-login/page.mdx": "2025-01-13T11:31:35.362Z",
"references/types/HttpTypes/types/types.HttpTypes.AdminWorkflowRunResponse/page.mdx": "2024-12-09T13:21:34.761Z",
"references/types/HttpTypes/types/types.HttpTypes.BatchResponse/page.mdx": "2024-12-09T13:21:33.549Z",
"references/types/WorkflowsSdkTypes/types/types.WorkflowsSdkTypes.Acknowledgement/page.mdx": "2024-12-09T13:21:35.873Z",
@@ -5788,7 +5788,7 @@ export const generatedEditDates = {
"references/types/StockLocationTypes/interfaces/types.StockLocationTypes.FilterableStockLocationAddressProps/page.mdx": "2025-01-07T12:54:23.060Z",
"references/types/StockLocationTypes/types/types.StockLocationTypes.UpdateStockLocationAddressInput/page.mdx": "2025-01-07T12:54:23.057Z",
"references/types/StockLocationTypes/types/types.StockLocationTypes.UpsertStockLocationAddressInput/page.mdx": "2025-01-07T12:54:23.058Z",
- "app/commerce-modules/inventory/inventory-kit/page.mdx": "2025-01-09T09:39:50.221Z",
+ "app/commerce-modules/inventory/inventory-kit/page.mdx": "2025-01-13T11:31:35.362Z",
"app/commerce-modules/api-key/workflows/page.mdx": "2025-01-09T13:41:46.573Z",
"app/commerce-modules/api-key/js-sdk/page.mdx": "2025-01-09T12:04:39.787Z",
"app/commerce-modules/auth/js-sdk/page.mdx": "2025-01-09T13:27:54.016Z",
diff --git a/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider]_callback.ts b/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider]_callback.ts
index 62c384eb79..9b8bba7c5e 100644
--- a/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider]_callback.ts
+++ b/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider]_callback.ts
@@ -3,10 +3,8 @@
* operationId: PostActor_typeAuth_providerCallback
* summary: Validate Authentication Callback
* description: >
- * This API route is used by your dashboard or frontend application when a third-party provider redirects to it after authentication.
- *
- *
- * It validates the authentication with the third-party provider and, if successful, returns an authentication token.
+ * This API route is used by your dashboard or frontend application when a third-party provider redirects to it after authentication. It validates the authentication with the third-party provider and, if successful, returns an authentication token.
+ * All query parameters received from the third-party provider, such as `code`, `state`, and `error`, must be passed as query parameters to this route.
*
*
* You can decode the JWT token using libraries like [react-jwt](https://www.npmjs.com/package/react-jwt) in the frontend. If the decoded data doesn't
diff --git a/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider]_callback.ts b/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider]_callback.ts
index e01171bcc6..cef1aebc6f 100644
--- a/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider]_callback.ts
+++ b/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider]_callback.ts
@@ -3,11 +3,8 @@
* operationId: PostActor_typeAuth_providerCallback
* summary: Validate Authentication Callback
* description: >
- * This API route is used by your storefront or frontend application when a third-party provider redirects to it after authentication.
- *
- *
- * It validates the authentication with the third-party provider and, if successful, returns an authentication token.
- *
+ * This API route is used by your storefront or frontend application when a third-party provider redirects to it after authentication. It validates the authentication with the third-party provider and, if successful, returns an authentication token.
+ * All query parameters received from the third-party provider, such as `code`, `state`, and `error`, must be passed as query parameters to this route.
*
* You can decode the JWT token using libraries like [react-jwt](https://www.npmjs.com/package/react-jwt) in the storefront. If the decoded data doesn't
* have an `actor_id` property, then you must register the customer using the Create Customer API route passing the token in the request's Authorization header.