From 4250c292eba886ddc88aa5621431392550eac0d3 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Mon, 13 Jan 2025 15:12:06 +0200 Subject: [PATCH] docs: fix authentication callback descriptions to include all query parameters (#10932) --- .../specs/admin/openapi.full.yaml | 4 +- .../auth_user_{auth_provider}_callback.yaml | 10 +- .../specs/store/openapi.full.yaml | 5 +- ...uth_customer_{auth_provider}_callback.yaml | 11 +- .../commerce-modules/auth/auth-flows/page.mdx | 8 +- .../auth/auth-providers/emailpass/page.mdx | 2 +- .../auth/auth-providers/github/page.mdx | 2 +- .../auth/auth-providers/google/page.mdx | 2 +- .../auth/authentication-route/page.mdx | 6 +- .../inventory/inventory-kit/page.mdx | 148 +++++++++--------- .../payment/payment-flow/page.mdx | 16 +- .../examples/standard/page.mdx | 36 ++--- .../checkout/shipping/page.mdx | 16 +- .../customers/register/page.mdx | 30 ++-- .../customers/third-party-login/page.mdx | 35 ++--- www/apps/resources/generated/edit-dates.mjs | 22 +-- ...h_[actor_type]_[auth_provider]_callback.ts | 6 +- ...h_[actor_type]_[auth_provider]_callback.ts | 7 +- 18 files changed, 178 insertions(+), 188 deletions(-) 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. ![Diagram showcasing the second part of the third-party authentication flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1711375123/Medusa%20Resources/third-party-auth-2_kmjxju.jpg) 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.