From 3ed6271cdf27d51673164a31bd4eb0ddb3063014 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 5 Sep 2024 17:47:08 +0300 Subject: [PATCH 01/10] docs: update auth docs + add new storefront guides --- .../commerce-modules/auth/auth-flows/page.mdx | 97 ++- .../auth-identity-and-actor-types/page.mdx | 8 +- .../auth/auth-providers/_google/page.mdx | 186 ----- .../auth/auth-providers/emailpass/page.mdx | 3 +- .../auth/auth-providers/github/page.mdx | 152 ++++ .../auth/auth-providers/google/page.mdx | 152 ++++ .../auth/auth-providers/page.mdx | 23 +- .../auth/authentication-route/page.mdx | 128 +++- .../auth/create-actor-type/page.mdx | 2 +- .../commerce-modules/auth/examples/page.mdx | 5 +- .../app/commerce-modules/auth/page.mdx | 5 +- .../customers/third-party-login/page.mdx | 650 ++++++++++++++++++ www/apps/resources/generated/edit-dates.mjs | 22 +- www/apps/resources/generated/files-map.mjs | 16 +- www/apps/resources/generated/sidebar.mjs | 51 +- www/apps/resources/sidebar.mjs | 33 +- .../post_auth_[actor_type]_[auth_provider].ts | 35 +- ...h_[actor_type]_[auth_provider]_callback.ts | 21 +- ...h_[actor_type]_[auth_provider]_register.ts | 21 +- .../admin/post_auth_token_refresh.ts | 38 + .../post_auth_[actor_type]_[auth_provider].ts | 35 +- ...h_[actor_type]_[auth_provider]_callback.ts | 21 +- ...h_[actor_type]_[auth_provider]_register.ts | 21 +- .../store/post_auth_token_refresh.ts | 38 + 24 files changed, 1454 insertions(+), 309 deletions(-) delete mode 100644 www/apps/resources/app/commerce-modules/auth/auth-providers/_google/page.mdx create mode 100644 www/apps/resources/app/commerce-modules/auth/auth-providers/github/page.mdx create mode 100644 www/apps/resources/app/commerce-modules/auth/auth-providers/google/page.mdx create mode 100644 www/apps/resources/app/storefront-development/customers/third-party-login/page.mdx create mode 100644 www/utils/generated/oas-output/operations/admin/post_auth_token_refresh.ts create mode 100644 www/utils/generated/oas-output/operations/store/post_auth_token_refresh.ts 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 5762321e03a5f..7c95cf36ee0ed 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 @@ -50,24 +50,38 @@ This method calls the `authenticate` method of the provider specified in the fir ## Auth Flow 1: Basic Authentication -The basic authentication flow requires first using the `register` method, then the `authenticate` method. - -If the `authenticate` method returns the following object: +The basic authentication flow requires first using the `register` method, then the `authenticate` method: ```ts -data = { - success: true, - authIdentity: { +const { success, authIdentity } = await authModuleService.register( + "emailpass", + // passed to auth provider + { // ... - }, + } +) + +// later (can be another route for log-in) +const { success, authIdentity, location } = await authModuleService.authenticate( + "emailpass", + // passed to auth provider + { + // ... + } +) + +if (success && !location) { + // user is authenticated } ``` -Then, the user is authenticated successfully, and their authentication details are available within the `authIdentity` object. +If `success` is true and `location` isn't set, the user is authenticated successfully, and their authentication details are available within the `authIdentity` object. + +The next section explains the flow if `location` is set. -Check out the [AuthIdentity](/references/auth/models/AuthIdentity) reference for the expected properties in `authIdentity`. +Check out the [AuthIdentity](/references/auth/models/AuthIdentity) reference for the received properties in `authIdentity`. @@ -77,18 +91,33 @@ Check out the [AuthIdentity](/references/auth/models/AuthIdentity) reference for ## Auth Flow 2: Third-Party Service Authentication -The third-party service authentication method requires using the `authenticate` method first. - -If the `authenticate` method returns the following object: +The third-party service authentication method requires using the `authenticate` method first: ```ts -data = { - success: true, - location: "https://....", +const { success, authIdentity, location } = await authModuleService.authenticate( + "emailpass", + // passed to auth provider + { + // ... + } +) + +if (location) { + // return the location for the front-end to redirect to +} + +if (!success) { + // authentication failed } + +// authentication successful ``` -It means the authentication process requires the user to perform an action with a third-party service. For example, when using the `google` provider, the user goes to the URL specified in the `location`'s value to log in with their Google account. +If the `authenticate` method returns a `location` property, the authentication process requires the user to perform an action with a third-party service. So, you return the `location` to the front-end or client to redirect to that URL. + +For example, when using the `google` provider, the `location` is the URL that the user is navigated to login. + +If the `authenticate` method doesn't return a `location` property and the returned `success` property, the user is successfully authenticated. This happens after the user logs-in with the provider, such as google, the first time. ![Diagram showcasing the first part of the third-party authentication flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1711374847/Medusa%20Resources/third-party-auth-1_enyedy.jpg) @@ -96,27 +125,29 @@ It means the authentication process requires the user to perform an action with Providers handling this authentication flow must implement the `validateCallback` method. It implements the logic to validate the authentication with the third-party service. -So, once the user performs the required action, the third-party service must redirect to an API route that uses the [validateCallback method of the Auth Module's main service](/references/auth/validateCallback). The method calls the specified provider’s `validateCallback` method passing it the authentication details it received in the second parameter: +So, once the user performs the required action with the third-party service (for example, log-in with Google), the frontend must redirect to an API route that uses the [validateCallback method of the Auth Module's main service](/references/auth/validateCallback). -```ts -const data = await authModuleService.validateCallback( - "google", - // passed to auth provider - { - // ... - } - ) -``` - -If the authentication is successful, the `validateCallback` method returns the same data as the basic authentication: +The method calls the specified provider’s `validateCallback` method passing it the authentication details it received in the second parameter: ```ts -data = { - success: true, - authIdentity: { - // ... - }, +const { success, authIdentity } = await authModuleService.validateCallback( + "google", + // passed to auth provider + { + // request data, such as + url, + headers, + query, + body, + protocol + } +) + +if (success) { + // authentication succeeded } ``` +If the returned `success` property is `true`, the authentication with the third-party provider was successful. Subsequent authentication attempts can use the `authenticate` method only. + ![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-identity-and-actor-types/page.mdx b/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx index 96e7a49a9175a..bd38ca01d2231 100644 --- a/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx @@ -8,9 +8,9 @@ In this document, you’ll learn about concepts related to identity and actors i ## What is an Auth Identity? -The [AuthIdentity data model](/references/auth/model/AuthIdentity) represents a previously-authenticated user. +The [AuthIdentity data model](/references/auth/model/AuthIdentity) represents a registered user. -When a user is authenticated, a record of `AuthIdentity` is created. This record is used to validate the user’s authentication in future requests. +When a user is registered, a record of `AuthIdentity` is created. This record is used to validate the user’s authentication in future requests. --- @@ -18,7 +18,7 @@ When a user is authenticated, a record of `AuthIdentity` is created. This record An actor type is a type of user that can be authenticated. This user is a record of a data model defined by a module. -For example, the `customer` belongs to the Customer Module’s `Customer` data model. Similarly, the `user` belongs to the User Module’s `User` data model. +For example, the `customer` actor type belongs to the Customer Module’s `Customer` data model. Similarly, the `user` actor type belongs to the User Module’s `User` data model. ### Protect Routes by Actor Type @@ -48,7 +48,7 @@ export default defineMiddlewares({ }) ``` -By specifying `user` as the first parameter of `authenticate`, only authenticated users of actor type `user` can access API routes starting with `/custom/admin`. +By specifying `user` as the first parameter of `authenticate`, only authenticated users of actor type `user` (i.e. admin users) can access API routes starting with `/custom/admin`. --- 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 deleted file mode 100644 index fbc166db6eaa4..0000000000000 --- a/www/apps/resources/app/commerce-modules/auth/auth-providers/_google/page.mdx +++ /dev/null @@ -1,186 +0,0 @@ -import { Table } from "docs-ui" - -export const metadata = { - title: `Google Auth Module Provider`, -} - -# {metadata.title} - -In this document, you’ll learn about the Google auth module provider and how to install and use it in the Auth Module. - -## Features - -The Google auth module provider handles authenticating users with their Google accounts. - -By integrating the Google auth provider, you provide your users and customers with the ability to login with their Google account. - ---- - -## Install the Google Auth Module Provider - - - -- [Create a project in Google Cloud.](https://cloud.google.com/resource-manager/docs/creating-managing-projects). -- [Create authorization credentials](https://developers.google.com/identity/protocols/oauth2/web-server#creatingcred). - - Set the Redirect Uri of your Oauth Client ID to `{medusa_url}/auth/{actor_type}/google/callback`, where: - - `{medusa_url}` is the URL of your Medusa backend. - - `{actor_type}` is the actor type that the Google auth provider can authenticate. For example, `customer`. - - - -To install the Google auth module provider, run the following command in the directory of your Medusa application: - -```bash npm2yarn -npm install @medusajs/auth-google -``` - -Next, add the module to the array of providers passed to the Auth Module: - -```js title="medusa-config.js" -import { Modules } from "@medusajs/utils" - -// ... - -const modules = { - // ... - [Modules.AUTH]: { - resolve: "@medusajs/auth", - options: { - providers: [ - { - resolve: "@medusajs/auth-google", - id: "google", - options: { - clientID: process.env.GOOGLE_CLIENT_ID, - clientSecret: process.env.GOOGLE_CLIENT_SECRET, - callbackURL: process.env.GOOGLE_CALLBACK_URL, - successRedirectUrl: - process.env.GOOGLE_SUCCESS_REDIRECT_URL, - }, - }, - ], - }, - }, -} -``` - -### Environment Variables - -Make sure to add the necessary environment variables for the above options in `.env`: - -```bash -GOOGLE_CLIENT_ID= -GOOGLE_CLIENT_SECRET= -GOOGLE_CALLBACK_URL= -GOOGLE_SUCCESS_REDIRECT_URL= -``` - -### Module Options - - - - - Configuration - Description - Required - Default - - - - - - - `clientID` - - - - - A string indicating the [Google API Client ID](https://developers.google.com/identity/oauth2/web/guides/get-google-api-clientid). - - - - - Yes - - - - - \- - - - - - - - `clientSecret` - - - - - A string indicating the [Google Client Secret](https://support.google.com/cloud/answer/6158849?hl=en#zippy=%2Cstep-create-a-new-client-secret). - - - - - Yes - - - - - \- - - - - - - - `callbackURL` - - - - - A string indicating the URL to redirect to in your app after the user completes their authentication in Google. - - The Medusa application provides the API route `/auth/[scope]/google/callback` that you can use, where `[scope]` is the scope this config belongs to. - For example, `/auth/store/google/callback`. - - - - - Yes - - - - - \- - - - - - - - `successRedirectUrl` - - - - - A string indicating the URL to redirect to in your app after the authentication has been successful. - - If not provided, the Medusa application's callback route just returns a JSON with the JWT token of the auth identity. - - - - - No - - - - - \- - - - - -
- -{/* TODO add how to implement authentication flow with google */} \ No newline at end of file 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 a62c363cbccea..eac100af4ef9e 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 @@ -8,8 +8,6 @@ export const metadata = { In this document, you’ll learn about the Emailpass auth module provider and how to install and use it in the Auth Module. -## Features - Using the Emailpass auth module provider, you allow users to register and login with an email and password. --- @@ -31,6 +29,7 @@ const modules = { resolve: "@medusajs/auth", options: { providers: [ + // other providers... { resolve: "@medusajs/auth-emailpass", id: "emailpass", 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 new file mode 100644 index 0000000000000..ac935c68f85e7 --- /dev/null +++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/github/page.mdx @@ -0,0 +1,152 @@ +import { Table, Prerequisites } from "docs-ui" + +export const metadata = { + title: `GitHub Auth Module Provider`, +} + +# {metadata.title} + +In this document, you’ll learn about the GitHub Auth Module Provider and how to install and use it in the Auth Module. + +The Google Auth Module Provider handles authenticating users with their GitHub account. + + + +Learn about the authentication flow in [this guide](../../authentication-route/page.mdx). + + + +--- + +## Install the Google Auth Module Provider + + + +To install the Google auth module provider, run the following command in the directory of your Medusa application: + +```bash npm2yarn +npm install @medusajs/auth-github@preview +``` + +Next, add the module to the array of providers passed to the Auth Module: + +```js title="medusa-config.js" +import { Modules } from "@medusajs/utils" + +// ... + +const modules = { + // ... + [Modules.AUTH]: { + resolve: "@medusajs/auth", + options: { + providers: [ + // other providers... + { + resolve: "@medusajs/auth-github", + id: "google", + options: { + clientId: process.env.GITHUB_CLIENT_ID, + clientSecret: process.env.GITHUB_CLIENT_SECRET, + callbackUrl: process.env.GITHUB_CALLBACK_URL, + }, + }, + ], + }, + }, +} +``` + +### Environment Variables + +Make sure to add the necessary environment variables for the above options in `.env`: + +```plain +GITHUB_CLIENT_ID= +GITHUB_CLIENT_SECRET= +GITHUB_CALLBACK_URL= +``` + +### Module Options + + + + + Configuration + Description + Required + + + + + + + `clientId` + + + + + A string indicating the client ID of your GitHub app. + + + + + Yes + + + + + + + `clientSecret` + + + + + A string indicating the client secret of your GitHub app. + + + + + Yes + + + + + + + `callbackUrl` + + + + + A string indicating the URL to redirect to in your frontend after the user completes their authentication in GitHub. + + At this URL, the frontend will receive a `code` query parameter. It then sends that `code` query parameter to the Medusa application's `/auth/{actor_type}/github/callback` route. + + + + + Yes + + + + +
+ +--- + +## Examples + +- [How to implement third-party / social login in the storefront.](../../../../storefront-development/customers/third-party-login/page.mdx). 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 new file mode 100644 index 0000000000000..80fb147bbeef8 --- /dev/null +++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/google/page.mdx @@ -0,0 +1,152 @@ +import { Table, Prerequisites } from "docs-ui" + +export const metadata = { + title: `Google Auth Module Provider`, +} + +# {metadata.title} + +In this document, you’ll learn about the Google Auth Module Provider and how to install and use it in the Auth Module. + +The Google Auth Module Provider handles authenticating users with their Google account. + + + +Learn about the authentication flow in [this guide](../../authentication-route/page.mdx). + + + +--- + +## Install the Google Auth Module Provider + + + +To install the Google auth module provider, run the following command in the directory of your Medusa application: + +```bash npm2yarn +npm install @medusajs/auth-google@preview +``` + +Next, add the module to the array of providers passed to the Auth Module: + +```js title="medusa-config.js" +import { Modules } from "@medusajs/utils" + +// ... + +const modules = { + // ... + [Modules.AUTH]: { + resolve: "@medusajs/auth", + options: { + providers: [ + // other providers... + { + resolve: "@medusajs/auth-google", + id: "google", + options: { + clientId: process.env.GOOGLE_CLIENT_ID, + clientSecret: process.env.GOOGLE_CLIENT_SECRET, + callbackUrl: process.env.GOOGLE_CALLBACK_URL, + }, + }, + ], + }, + }, +} +``` + +### Environment Variables + +Make sure to add the necessary environment variables for the above options in `.env`: + +```plain +GOOGLE_CLIENT_ID= +GOOGLE_CLIENT_SECRET= +GOOGLE_CALLBACK_URL= +``` + +### Module Options + + + + + Configuration + Description + Required + + + + + + + `clientId` + + + + + A string indicating the [Google API Client ID](https://developers.google.com/identity/oauth2/web/guides/get-google-api-clientid). + + + + + Yes + + + + + + + `clientSecret` + + + + + A string indicating the [Google Client Secret](https://support.google.com/cloud/answer/6158849?hl=en#zippy=%2Cstep-create-a-new-client-secret). + + + + + Yes + + + + + + + `callbackUrl` + + + + + A string indicating the URL to redirect to in your frontend after the user completes their authentication in Google. + + At this URL, the frontend will receive a `code` query parameter. It then sends that `code` query parameter to the Medusa application's `/auth/{actor_type}/google/callback` route. + + + + + Yes + + + + +
+ +--- + +## Examples + +- [How to implement Google social login in the storefront.](../../../../storefront-development/customers/third-party-login/page.mdx). diff --git a/www/apps/resources/app/commerce-modules/auth/auth-providers/page.mdx b/www/apps/resources/app/commerce-modules/auth/auth-providers/page.mdx index 7e144c435071e..ebde6f8c41eef 100644 --- a/www/apps/resources/app/commerce-modules/auth/auth-providers/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/page.mdx @@ -1,3 +1,5 @@ +import { CardList } from "docs-ui" + export const metadata = { title: `Auth Providers`, } @@ -12,11 +14,24 @@ An auth module provider handles authenticating customers and users, either using For example, the EmailPass Auth Module Provider authenticates a user using their email and password, whereas the Google Auth Module Provider authenticates users using their Google account. - - -Support for the Google Auth Module Provider is coming soon. +### Auth Providers List - + --- 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 288995623e484..70c96f3fd696b 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 @@ -18,24 +18,52 @@ These routes are added by Medusa's application layer, not the Auth Module. This authentication flow doesn't require validation with third-party services. -It requires the following steps: + + +[How to register customer in storefront using basic authentication flow](../../../storefront-development/customers/register/page.mdx). + + + +The steps are: + +![Diagram showcasing the basic authentication flow between the frontend and the Medusa application](https://res.cloudinary.com/dza7lstvk/image/upload/v1725539370/Medusa%20Resources/basic-auth-routes_pgpjch.jpg) -1. Registering the user with the [Register Route](#register-route). -2. Authenticating the user with the [Auth Route](#auth-route). +1. Register the user with the [Register Route](#register-route). +5. Use the authentication token to create the user with their respective API route. + - For example, for customers you would use the [Create Customer API route](!api!/store#customers_postcustomers). + - For admin users, you accept an invite using the [Accept Invite API route](!api!/admin#invites_postinvitesaccept) +2. Authenticate the user with the [Auth Route](#auth-route). + +After registration, you only use the [Auth Route](#auth-route) for subsequent authentication. ### 2. Third-Party Service Authenticate Flow This authentication flow authenticates the user with a third-party service, such as Google. + + +[How to authenticate customer with a third-party provider in the storefront.](../../../storefront-development/customers/third-party-login/page.mdx). + + + It requires the following steps: -1. Authenticate the user with the [Auth Route](#auth-route). -2. If the authentication requires more action with the third-party service: - 1. The auth route redirects to the third-party service's authentication portal. The URL is returned by the Auth Module Provider. - 2. Once the authentication with the third-party service finishes, it redirects back to the [Callback Route](#callback-route). So, make sure your third-party service is configured to redirect to the [Callback Route](#callback-route). - 3. If the callback validation is successful, you'll receive the authentication token. +![Diagram showcasing the authentication flow between the frontend, Medusa application, and third-party service](https://res.cloudinary.com/dza7lstvk/image/upload/v1725528159/Medusa%20Resources/Third_Party_Auth_tvf4ng.jpg) -You may then use the [Auth Route](#auth-route) for subsequent authentication. +1. Authenticate the user with the [Auth Route](#auth-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. +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. + - If not, follow the rest of the steps. +7. The frontend uses the authentication token to create the user with their respective API route. + - For example, for customers you would use the [Create Customer API route](!api!/store#customers_postcustomers). + - For admin users, you accept an invite using the [Accept Invite API route](!api!/admin#invites_postinvitesaccept) +8. The frontend sends a request to the [Refresh Token Route](#refresh-token-route) to retrieve a new token for the user. + +After the first registration, you only use the [Auth Route](#auth-route) for subsequent authentication. --- @@ -43,6 +71,15 @@ You may then use the [Auth Route](#auth-route) for subsequent authentication. The Medusa application defines an API route at `/auth/{actor_type}/{provider}/register` that creates an auth identity for an actor type, such as a `customer`. It returns a JWT token that you pass to an API route that creates the user. +```bash +curl -X POST http://localhost:9000/auth/{actor_type}/{providers}/register +-H 'Content-Type: application/json' \ +--data-raw '{ + "email": "Whitney_Schultz@gmail.com" + // ... +}' +``` + This API route is useful for providers like `emailpass` that uses custom logic to authenticate a user. For authentication providers that authenticate with third-party services, such as Google, use the [Auth Route](#auth-route) instead. @@ -77,11 +114,7 @@ If the authentication is successful, you'll receive a `token` field in the respo } ``` - - -[How to register Customers using the authentication route](../../../storefront-development/customers/register/page.mdx). - - +Use that token in the header of subsequent requests to send authenticated requests. --- @@ -89,6 +122,15 @@ If the authentication is successful, you'll receive a `token` field in the respo The Medusa application defines an API route at `/auth/{actor_type}/{provider}` that authenticates a user of an actor type. It returns a JWT token that can be passed in [the header of subsequent requests](!api!/store#authentication) to send authenticated requests. +```bash +curl -X POST http://localhost:9000/auth/{actor_type}/{providers} +-H 'Content-Type: application/json' \ +--data-raw '{ + "email": "Whitney_Schultz@gmail.com" + // ... +}' +``` + For example, if you're authenticating a customer, you send a request to `/auth/customer/emailpass`. ### Path Parameters @@ -114,6 +156,18 @@ If the authentication is successful, you'll receive a `token` field in the respo } ``` +Use that token in the header of subsequent requests to send authenticated requests. + +If the authentication requires more action with a third-party service, you'll receive a `location` property: + +```json +{ + "location": "https://..." +} +``` + +Redirect to that URL in the frontend to continue the authentication process with the third-party service. + [How to login Customers using the authentication route](../../../storefront-development/customers/login/page.mdx). @@ -124,18 +178,18 @@ If the authentication is successful, you'll receive a `token` field in the respo ## Validate Callback Route -The Medusa application defines an API route at `/auth/{actor_type}/{provider}/callback` that's useful for authenticating users with third-party services, such as Google. +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. -When integrating with a third-party service, you use [Auth Route](#auth-route) first to authenticate the user. If the authentication requires more action with the third-party provider, the request redirects to the authentication provider's authentication portal. +```bash +curl -X POST http://localhost:9000/auth/{actor_type}/{providers}/callback?code=123 +``` -The URL of the authentication portal is received from the Auth Module Provider. +Refer to the [third-party authentication flow](#2-third-party-service-authenticate-flow) section to see how this route fits into the authentication flow. -Once the authentication with the third-party provider finishes, it should redirect back to this API route. So, make sure to add the necessary configuration in your provider to ensure this flow. - ### Path Parameters Its path parameters are: @@ -143,9 +197,9 @@ Its path parameters are: - `{actor_type}`: the actor type of the user you're authenticating. For example, `customer`. - `{provider}`: the auth provider to handle the authentication. For example, `google`. -### Request Body Parameters +### Query Parameters -This route accepts in the request body the data from the third-party service, and passes it along to the authentication provider to validate whether the customer was authenticated. +This route accepts a `code` query parameter, which is the code received from the third-party provider. ### Response Fields @@ -155,4 +209,34 @@ If the authentication is successful, you'll receive a `token` field in the respo { "token": "..." } -``` \ No newline at end of file +``` + +In your frontend, decode the token using tools like [react-jwt](https://www.npmjs.com/package/react-jwt): + +- If the decoded data has an `actor_id` property, the user is already registered. So, use this token for subsequent authenticated requests. +- If not, use the token in the header of a request that creates the user, such as the [Create Customer API route](!api!/store#customers_postcustomers). + +--- + +## Refresh Token Route + +The Medusa application defines an API route at `/auth/token/refresh` that's useful after authenticating a user with a third-party service. + +It requires the user's JWT token that they received from the authentication or callback routes. + +```bash +curl -X POST http://localhost:9000/auth/token/refresh \ +-H 'Authorization: Bearer {token}' +``` + +### Response Fields + +If the token was refreshed successfully, you'll receive a `token` field in the response body object: + +```json +{ + "token": "..." +} +``` + +Use that token in the header of subsequent requests to send authenticated requests. \ No newline at end of file diff --git a/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx b/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx index 5ad2ff5b50ea8..770338bd918cb 100644 --- a/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx @@ -251,7 +251,7 @@ To authenticate managers: 1. Send a `POST` request to `/auth/manager/emailpass/register` to create an auth identity for the manager: ```bash -curl -X POST 'http://localhost:9000/auth/manager/emailpass' \ +curl -X POST 'http://localhost:9000/auth/manager/emailpass/register' \ -H 'Content-Type: application/json' \ --data-raw '{ "email": "manager@gmail.com", diff --git a/www/apps/resources/app/commerce-modules/auth/examples/page.mdx b/www/apps/resources/app/commerce-modules/auth/examples/page.mdx index b621197792900..f039a13b9ebbf 100644 --- a/www/apps/resources/app/commerce-modules/auth/examples/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/examples/page.mdx @@ -52,7 +52,7 @@ export async function POST( } if (location) { - res.redirect(location) + res.json({ location }) return } @@ -90,8 +90,7 @@ export async function POST(request: Request) { } if (location) { - return NextResponse.redirect(location) - return + return NextResponse.json({ location }) } const token = jwt.sign(authIdentity, "supersecret") diff --git a/www/apps/resources/app/commerce-modules/auth/page.mdx b/www/apps/resources/app/commerce-modules/auth/page.mdx index 56e0a4637ed90..01f3833e4fcc7 100644 --- a/www/apps/resources/app/commerce-modules/auth/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/page.mdx @@ -49,9 +49,8 @@ const { success, authIdentity, location } = protocol: req.protocol, } as AuthenticationInput) -if (!authIdentity && location) { - res.redirect(location) - return +if (location) { + return res.json({ location }) } // in callback API route 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 new file mode 100644 index 0000000000000..b2e63fba7808d --- /dev/null +++ b/www/apps/resources/app/storefront-development/customers/third-party-login/page.mdx @@ -0,0 +1,650 @@ +import { Prerequisites, CodeTabs, CodeTab, Details } from "docs-ui" + +export const metadata = { + title: `Third-Party or Social Login in Storefront`, +} + +# {metadata.title} + +To login a customer with a third-party service, such as Google or GitHub, you must follow the following flow: + +![Diagram illustrating the authentication flow between the storefront, Medusa application, and the third-party service.](https://res.cloudinary.com/dza7lstvk/image/upload/v1725531068/Medusa%20Resources/Social_Media_Graphics_third-party-auth-customer_kfn3k3.jpg) + +
+ +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. +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. + - If not, follow the rest of the steps. +7. The storefront uses the authentication token to create the customer using the [Create Customer API route](!api!/store#customers_postcustomers). +8. The storefront sends a request to the [Refresh Token Route](#refresh-token-route) to retrieve a new token for the customer. + +
+ +You'll implement the flow in this guide using Google as an example. + + + +## Step 1: Authenticate Customer in Medusa + +When the customer clicks on a "Login with Google" button, send a request to the [Authenticate Customer API route](!api!/store#auth_postactor_typeauth_provider). + +For example: + + + + +export const fetchHighlights = [ + ["2", "fetch", "Send a request to the Authenticate Customer API route"], + ["10", "result.location", "If the request returns a location, redirect to that location to continue the authentication."], + ["17", "!result.token", "If the token isn't returned, the authentication has failed."], + ["26", "fetch", "Send a request as an authenticated customer."] +] + +```ts highlights={fetchHighlights} +const loginWithGoogle = async () => { + const result = await fetch( + `http://localhost:9000/auth/customer/google`, + { + credentials: "include", + method: "POST", + } + ).then((res) => res.json()) + + if (result.location) { + // redirect to Google for authentication + window.location.href = result.location + + return + } + + if (!result.token) { + // result failed, show an error + alert("Authentication failed") + return + } + + // authentication successful + // use token in the authorization header of + // all follow up requests. For example: + const { customer } = await fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${result.token}`, + }, + } + ) + .then((res) => res.json()) +} +``` + + + + +export const reactHighlights = [ + ["5", "fetch", "Send a request to the Authenticate Customer API route"], + ["13", "result.location", "If the request returns a location, redirect to that location to continue the authentication."], + ["20", "!result.token", "If the token isn't returned, the authentication has failed."], + ["29", "fetch", "Send a request as an authenticated customer."] +] + +```tsx highlights={reactHighlights} +"use client" // include with Next.js 13+ + +export default function Login() { + const loginWithGoogle = async () => { + const result = await fetch( + `http://localhost:9000/auth/customer/google`, + { + credentials: "include", + method: "POST", + } + ).then((res) => res.json()) + + if (result.location) { + // redirect to Google for authentication + window.location.href = result.location + + return + } + + if (!result.token) { + // result failed, show an error + alert("Authentication failed") + return + } + + // authentication successful + // use token in the authorization header of + // all follow up requests. For example: + const { customer } = await fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${result.token}`, + }, + } + ) + .then((res) => res.json()) + } + + return ( +
+ +
+ ) +} +``` + +
+
+ +If the Authenticate Customer API route returns a `location`, then you redirect to the returned page for authentication with the third-party service. + +If the route returns a `token`, then the customer has been authenticated before. You can use the token for subsequent authenticated request. + + + +If you're using a provider other than Google, or if you've configured the Google provider with an ID other than `google`, replace `google` in the URL `http://localhost:9000/auth/customer/google` with your provider ID. + + + +--- + +## Step 2: Callback Page in Storefront + +The next step is to create a page in your storefront that the customer is redirected to after they authenticate with Google. + +You'll use this page's URL as the Redirect Uri in your Google settings, and set it in the `callbackUrl` of your Google provider's configurations. + +First, install the [react-jwt library](https://www.npmjs.com/package/react-jwt) in your storefront to use it for decoding the token: + +```bash npm2yarn +npm install react-jwt +``` + +Then, in a new page in your storefront that will be used as the callback / redirect uri destination, add the following: + + + + +export const sendCallbackFetchHighlights = [ + ["6", "code", "The code received from Google as a query parameter."], + ["9", "fetch", "Send a request to the Validate Authentication Callback API route"], + ["17", "!token", "If the token isn't returned, the authentication has failed."], +] + +```ts highlights={sendCallbackFetchHighlights} +import { decodeToken } from "react-jwt" + +// ... + +const queryParams = new URLSearchParams(window.location.search) +const code = queryParams.get("code") + +const sendCallback = async () => { + let { token } = await fetch( + `http://localhost:9000/auth/customer/google/callback?code=${code}`, + { + credentials: "include", + method: "POST", + } + ).then((res) => res.json()) + + if (!token) { + alert("Authentication Failed") + return + } + + return token +} + +// TODO add more functions... +``` + + + + +export const sendCallbackReactHighlights = [ + ["11", "code", "The code received from Google as a query parameter."], + ["18", "fetch", "Send a request to the Validate Authentication Callback API route"], + ["26", "!token", "If the token isn't returned, the authentication has failed."], +] + +```tsx highlights={sendCallbackReactHighlights} +"use client" // include with Next.js 13+ + +import { HttpTypes } from "@medusajs/types" +import { useEffect, useMemo, useState } from "react" +import { decodeToken } from "react-jwt" + +export default function GoogleCallback () { + const [loading, setLoading] = useState(true) + const [customer, setCustomer] = useState() + // for other than Next.js + const code = useMemo(() => { + const queryParams = new URLSearchParams(window.location.search) + + return queryParams.get("code") + }, []) + + const sendCallback = async () => { + let { token } = await fetch( + `http://localhost:9000/auth/customer/google/callback?code=${code}`, + { + credentials: "include", + method: "POST", + } + ).then((res) => res.json()) + + if (!token) { + alert("Authentication Failed") + return + } + + return token + } + + // TODO add more functions + + return ( +
+ {loading && Loading...} + {customer && Created customer {customer.email} with 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 `code` received from Google. + +Then, replace the `TODO` with the following: + +export const createCustomerHighlights = [ + ["1", "token", "The token received from the Validate Callback API route."], + ["2", "fetch", "Create a customer"] +] + +```ts highlights={createCustomerHighlights} title="Fetch API / React Applicable" +const createCustomer = async (token: string) => { + await fetch(`http://localhost:9000/store/customers`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + body: JSON.stringify({ + // TODO show form to retrieve email from customer + email: "example@medusajs.com", + }), + }).then((res) => res.json()) +} + +// TODO add more functions... +``` + +This adds to the page the function `createCustomer` which, if the customer is new, it uses the token received from the Validate Callback API route to create a new customer. + +Next, replace the new `TODO` with the following: + +export const refreshTokenHighlights = [ + ["1", "token", "The token received from the Validate Callback API route."], + ["2", "fetch", "Fetch a new token for the created customer."] +] + +```ts highlights={refreshTokenHighlights} title="Fetch API / React Applicable" +const refreshToken = async (token: string) => { + const result = await fetch(`http://localhost:9000/auth/token/refresh`, { + credentials: "include", + method: "POST", + headers: { + "Authorization": `Bearer ${token}`, + }, + }).then((res) => res.json()) + + return result.token +} + +// TODO add more functions... +``` + +This adds to the page the function `refreshToken` which is used after the new customer is created to refresh their authentication token. + +Finally, add in the place of the new `TODO` the `validateCallback` function that runs when the page first loads to validate the authentication: + + + + +export const validateFetchHighlights = [ + ["2", "sendCallback", "Validate the callback in Medusa and retrieve the authentication token"], + ["4", "shouldCreateCustomer", "Check if the decoded token has an `actor_id` property to decide whether a customer to be created."], + ["7", "createCustomer", "Create a customer if the decoded token doesn't have `actor_id`."], + ["9", "refreshToken", "Fetch a new token for the created customer."], + ["13", "fetch", "Send an authenticated request using the token."] +] + +```ts highlights={validateFetchHighlights} +const validateCallback = async () => { + let { token } = await sendCallback() + + const shouldCreateCustomer = (decodeToken(token) as { actor_id: string }).actor_id === "" + + if (shouldCreateCustomer) { + await createCustomer(token) + + token = await refreshToken(token) + } + + // use token to send authenticated requests + const { customer } = await fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + method: "GET", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + body: JSON.stringify({ + // TODO show form to retrieve email from customer + email: "example@medusajs.com", + }), + } + ).then((res) => res.json()) +} +``` + + + + +export const validateReactHighlights = [ + ["2", "sendCallback", "Validate the callback in Medusa and retrieve the authentication token"], + ["4", "shouldCreateCustomer", "Check if the decoded token has an `actor_id` property to decide whether a customer to be created."], + ["7", "createCustomer", "Create a customer if the decoded token doesn't have `actor_id`."], + ["9", "refetchToken", "Fetch a new token for the created customer."], + ["13", "fetch", "Send an authenticated request using the token."] +] + +```tsx highlights={validateReactHighlights} +const validateCallback = async () => { + let { token } = await sendCallback() + + const shouldCreateCustomer = (decodeToken(token) as { actor_id: string }).actor_id === "" + + if (shouldCreateCustomer) { + await createCustomer(token) + + token = await refreshToken(token) + } + + // use token to send authenticated requests + const { customer: customerData } = await fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + method: "GET", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + body: JSON.stringify({ + // TODO show form to retrieve email from customer + email: "example@medusajs.com", + }), + } + ).then((res) => res.json()) + + setCustomer(customerData) + setLoading(false) +} + + +useEffect(() => { + if (!loading) { + return + } + + validateCallback() +}, [loading]) +``` + + + + +The `validateCallback` function uses the functions added earlier to: + +1. Send a request to the Validate Callback API route, which returns an authentication token. +2. Decodes the token to check if it has an `actor_id` property. + - If so, then the customer is previously registered, and the authentication token can be used for subsequent authenticated requests. + - If not: + 1. Create a customer using the Create Customer API route. + 2. Refetch the customer's token after it's created using the Refresh Token API route. + 3. Use the token for subsequent authenticated requests. + +### Full Code Example for Callback Page + +
+ + + + +```ts +import { decodeToken } from "react-jwt" + +// ... + +const queryParams = new URLSearchParams(window.location.search) +const code = queryParams.get("code") + + +const sendCallback = async () => { + let { token } = await fetch( + `http://localhost:9000/auth/customer/google/callback?code=${code}`, + { + credentials: "include", + method: "POST", + } + ).then((res) => res.json()) + + if (!token) { + alert("Authentication Failed") + return + } + + return token +} + +const createCustomer = async (token: string) => { + await fetch(`http://localhost:9000/store/customers`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + body: JSON.stringify({ + // TODO show form to retrieve email from customer + email: "example@medusajs.com", + }), + }).then((res) => res.json()) +} + +const refreshToken = async (token: string) => { + const result = await fetch(`http://localhost:9000/auth/token/refresh`, { + credentials: "include", + method: "POST", + headers: { + "Authorization": `Bearer ${token}`, + }, + }).then((res) => res.json()) + + return result.token +} + +const validateCallback = async () => { + let { token } = await sendCallback() + + const shouldCreateCustomer = (decodeToken(token) as { actor_id: string }).actor_id === "" + + if (shouldCreateCustomer) { + await createCustomer(token) + + token = await refreshToken(token) + } + + // use token to send authenticated requests + const { customer } = await fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + method: "GET", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + body: JSON.stringify({ + // TODO show form to retrieve email from customer + email: "example@medusajs.com", + }), + } + ).then((res) => res.json()) +} +``` + + + + +```tsx +"use client" // include with Next.js 13+ + +import { HttpTypes } from "@medusajs/types" +import { useEffect, useMemo, useState } from "react" +import { decodeToken } from "react-jwt" + +export default function GoogleCallback () { + const [loading, setLoading] = useState(true) + const [customer, setCustomer] = useState() + // for other than Next.js + const code = useMemo(() => { + const queryParams = new URLSearchParams(window.location.search) + + return queryParams.get("code") + }, []) + + const sendCallback = async () => { + let { token } = await fetch( + `http://localhost:9000/auth/customer/google/callback?code=${code}`, + { + credentials: "include", + method: "POST", + } + ).then((res) => res.json()) + + if (!token) { + alert("Authentication Failed") + return + } + + return token + } + + const createCustomer = async (token: string) => { + await fetch(`http://localhost:9000/store/customers`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + body: JSON.stringify({ + // TODO show form to retrieve email from customer + email: "example@medusajs.com", + }), + }).then((res) => res.json()) + } + + const refreshToken = async (token: string) => { + const result = await fetch(`http://localhost:9000/auth/token/refresh`, { + credentials: "include", + method: "POST", + headers: { + "Authorization": `Bearer ${token}`, + }, + }).then((res) => res.json()) + + return result.token + } + + const validateCallback = async () => { + let { token } = await sendCallback() + + const shouldCreateCustomer = (decodeToken(token) as { actor_id: string }).actor_id === "" + + if (shouldCreateCustomer) { + await createCustomer(token) + + token = await refreshToken(token) + } + + // use token to send authenticated requests + const { customer: customerData } = await fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + method: "GET", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + body: JSON.stringify({ + // TODO show form to retrieve email from customer + email: "example@medusajs.com", + }), + } + ).then((res) => res.json()) + + setCustomer(customerData) + setLoading(false) + } + + useEffect(() => { + if (!loading) { + return + } + + validateCallback() + }, [loading]) + + return ( +
+ {loading && Loading...} + {customer && Created customer {customer.email} with Google.} +
+ ) +} +``` + +
+
+ +
diff --git a/www/apps/resources/generated/edit-dates.mjs b/www/apps/resources/generated/edit-dates.mjs index 0ec032dead470..779f45a1006fe 100644 --- a/www/apps/resources/generated/edit-dates.mjs +++ b/www/apps/resources/generated/edit-dates.mjs @@ -1,10 +1,10 @@ export const generatedEditDates = { - "app/commerce-modules/auth/auth-providers/emailpass/page.mdx": "2024-07-04T17:26:03+03:00", - "app/commerce-modules/auth/auth-providers/page.mdx": "2024-07-01T10:21:19+03:00", - "app/commerce-modules/auth/authentication-route/page.mdx": "2024-08-30T12:23:50.176Z", - "app/commerce-modules/auth/examples/page.mdx": "2024-07-04T17:26:03+03:00", + "app/commerce-modules/auth/auth-providers/emailpass/page.mdx": "2024-09-05T12:08:19.945Z", + "app/commerce-modules/auth/auth-providers/page.mdx": "2024-09-05T12:15:19.491Z", + "app/commerce-modules/auth/authentication-route/page.mdx": "2024-09-05T12:06:38.155Z", + "app/commerce-modules/auth/examples/page.mdx": "2024-09-05T08:09:32.466Z", "app/commerce-modules/auth/module-options/page.mdx": "2024-07-04T17:26:03+03:00", - "app/commerce-modules/auth/page.mdx": "2024-08-05T07:24:27+00:00", + "app/commerce-modules/auth/page.mdx": "2024-09-05T08:08:28.782Z", "app/commerce-modules/cart/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00", "app/commerce-modules/cart/_events/page.mdx": "2024-07-03T19:27:13+03:00", "app/commerce-modules/cart/concepts/page.mdx": "2024-06-26T07:55:59+00:00", @@ -222,13 +222,12 @@ export const generatedEditDates = { "app/upgrade-guides/page.mdx": "2024-07-18T08:57:11+02:00", "app/usage/page.mdx": "2024-05-13T18:55:11+03:00", "app/page.mdx": "2024-08-13T08:51:20+02:00", - "app/commerce-modules/auth/auth-providers/_google/page.mdx": "2024-07-04T17:26:03+03:00", "app/commerce-modules/auth/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00", - "app/commerce-modules/auth/auth-flows/page.mdx": "2024-08-30T12:27:07.160Z", + "app/commerce-modules/auth/auth-flows/page.mdx": "2024-09-05T08:50:11.671Z", "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": "2024-07-31T17:01:33+03:00", + "app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx": "2024-09-05T08:11:28.936Z", "app/commerce-modules/api-key/page.mdx": "2024-08-05T07:24:27+00:00", - "app/commerce-modules/auth/create-actor-type/page.mdx": "2024-07-31T17:01:33+03:00", + "app/commerce-modules/auth/create-actor-type/page.mdx": "2024-09-05T09:24:48.099Z", "app/architectural-modules/page.mdx": "2024-05-28T13:25:03+03:00", "app/commerce-modules/api-key/relations-to-other-modules/page.mdx": "2024-05-29T11:08:06+00:00", "app/architectural-modules/workflow-engine/redis/page.mdx": "2024-07-18T13:04:29+02:00", @@ -914,5 +913,8 @@ export const generatedEditDates = { "references/types/HttpTypes/interfaces/types.HttpTypes.AdminClaimOrderResponse/page.mdx": "2024-09-04T00:11:02.625Z", "references/types/HttpTypes/interfaces/types.HttpTypes.AdminClaimPreviewResponse/page.mdx": "2024-09-04T00:11:02.637Z", "references/types/HttpTypes/interfaces/types.HttpTypes.AdminOrderEditPreviewResponse/page.mdx": "2024-09-04T00:11:02.897Z", - "references/types/interfaces/types.BaseClaim/page.mdx": "2024-09-04T00:11:02.485Z" + "references/types/interfaces/types.BaseClaim/page.mdx": "2024-09-04T00:11:02.485Z", + "app/commerce-modules/auth/auth-providers/github/page.mdx": "2024-09-05T12:13:04.991Z", + "app/commerce-modules/auth/auth-providers/google/page.mdx": "2024-09-05T12:12:59.196Z", + "app/storefront-development/customers/third-party-login/page.mdx": "2024-09-05T11:35:24.269Z" } \ No newline at end of file diff --git a/www/apps/resources/generated/files-map.mjs b/www/apps/resources/generated/files-map.mjs index 5a4292867888e..5f92e2b2cc051 100644 --- a/www/apps/resources/generated/files-map.mjs +++ b/www/apps/resources/generated/files-map.mjs @@ -123,14 +123,18 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx", "pathname": "/commerce-modules/auth/auth-identity-and-actor-types" }, - { - "filePath": "/www/apps/resources/app/commerce-modules/auth/auth-providers/_google/page.mdx", - "pathname": "/commerce-modules/auth/auth-providers/_google" - }, { "filePath": "/www/apps/resources/app/commerce-modules/auth/auth-providers/emailpass/page.mdx", "pathname": "/commerce-modules/auth/auth-providers/emailpass" }, + { + "filePath": "/www/apps/resources/app/commerce-modules/auth/auth-providers/github/page.mdx", + "pathname": "/commerce-modules/auth/auth-providers/github" + }, + { + "filePath": "/www/apps/resources/app/commerce-modules/auth/auth-providers/google/page.mdx", + "pathname": "/commerce-modules/auth/auth-providers/google" + }, { "filePath": "/www/apps/resources/app/commerce-modules/auth/auth-providers/page.mdx", "pathname": "/commerce-modules/auth/auth-providers" @@ -919,6 +923,10 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/storefront-development/customers/retrieve/page.mdx", "pathname": "/storefront-development/customers/retrieve" }, + { + "filePath": "/www/apps/resources/app/storefront-development/customers/third-party-login/page.mdx", + "pathname": "/storefront-development/customers/third-party-login" + }, { "filePath": "/www/apps/resources/app/storefront-development/page.mdx", "pathname": "/storefront-development" diff --git a/www/apps/resources/generated/sidebar.mjs b/www/apps/resources/generated/sidebar.mjs index 759cbd0f23d82..49c10175591d7 100644 --- a/www/apps/resources/generated/sidebar.mjs +++ b/www/apps/resources/generated/sidebar.mjs @@ -245,16 +245,7 @@ export const generatedSidebar = [ "type": "link", "path": "/commerce-modules/auth/auth-providers", "title": "Auth Providers", - "children": [ - { - "loaded": true, - "isPathHref": true, - "type": "link", - "path": "/commerce-modules/auth/auth-providers/emailpass", - "title": "Emailpass Auth Provider Module", - "children": [] - } - ] + "children": [] }, { "loaded": true, @@ -290,6 +281,38 @@ export const generatedSidebar = [ } ] }, + { + "loaded": true, + "isPathHref": true, + "type": "sub-category", + "title": "Providers", + "children": [ + { + "loaded": true, + "isPathHref": true, + "type": "link", + "path": "/commerce-modules/auth/auth-providers/emailpass", + "title": "Emailpass Provider", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "type": "link", + "path": "/commerce-modules/auth/auth-providers/google", + "title": "Google Provider", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "type": "link", + "path": "/commerce-modules/auth/auth-providers/github", + "title": "GitHub Provider", + "children": [] + } + ] + }, { "loaded": true, "isPathHref": true, @@ -8328,6 +8351,14 @@ export const generatedSidebar = [ "title": "Login Customer", "children": [] }, + { + "loaded": true, + "isPathHref": true, + "type": "link", + "path": "/storefront-development/customers/third-party-login", + "title": "Third-Party (Social) Login", + "children": [] + }, { "loaded": true, "isPathHref": true, diff --git a/www/apps/resources/sidebar.mjs b/www/apps/resources/sidebar.mjs index dd5ed53d1158d..2636746127cb4 100644 --- a/www/apps/resources/sidebar.mjs +++ b/www/apps/resources/sidebar.mjs @@ -120,13 +120,6 @@ export const sidebar = sidebarAttachHrefCommonOptions([ type: "link", path: "/commerce-modules/auth/auth-providers", title: "Auth Providers", - children: [ - { - type: "link", - path: "/commerce-modules/auth/auth-providers/emailpass", - title: "Emailpass Auth Provider Module", - }, - ], }, { type: "link", @@ -151,6 +144,27 @@ export const sidebar = sidebarAttachHrefCommonOptions([ }, ], }, + { + type: "sub-category", + title: "Providers", + children: [ + { + type: "link", + path: "/commerce-modules/auth/auth-providers/emailpass", + title: "Emailpass Provider", + }, + { + type: "link", + path: "/commerce-modules/auth/auth-providers/google", + title: "Google Provider", + }, + { + type: "link", + path: "/commerce-modules/auth/auth-providers/github", + title: "GitHub Provider", + }, + ], + }, { type: "sub-category", title: "References", @@ -2065,6 +2079,11 @@ export const sidebar = sidebarAttachHrefCommonOptions([ path: "/storefront-development/customers/login", title: "Login Customer", }, + { + type: "link", + path: "/storefront-development/customers/third-party-login", + title: "Third-Party (Social) Login", + }, { type: "link", path: "/storefront-development/customers/retrieve", diff --git a/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider].ts b/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider].ts index ec41bd4bba538..ff7c6d177fe49 100644 --- a/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider].ts +++ b/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider].ts @@ -2,7 +2,15 @@ * @oas [post] /auth/user/{auth_provider} * operationId: PostActor_typeAuth_provider * summary: Authenticate User - * description: Authenticate an admin user and receive the JWT token to be used in the header of subsequent requests. + * description: > + * Authenticate a user and receive the JWT token to be used in the header of subsequent requests. + * + * + * When used with a third-party provider, such as Google, the request returns a `location` property. You redirect to the + * specified URL in your frontend to continue authentication with the third-party service. + * externalDocs: + * url: https://docs.medusajs.com/v2/resources/commerce-modules/auth/authentication-route#types-of-authentication-flows + * description: Learn about different authentication flows. * x-authenticated: false * parameters: * - name: auth_provider @@ -12,10 +20,31 @@ * schema: * type: string * example: "emailpass" + * requestBody: + * content: + * application/json: + * schema: + * type: object + * title: input + * description: The input data necessary for authentication. For example, for email-pass authentication, pass `email` and `password` properties. * x-codeSamples: * - lang: Shell - * label: cURL - * source: curl -X POST '{backend_url}/auth/user/{auth_provider}' + * label: EmailPass Provider + * source: |- + * curl -X POST '{backend_url}/auth/user/emailpass' \ + * -H 'Content-Type: application/json' \ + * --data-raw '{ + * "email": "admin@medusa-test.com", + * "password": "supersecret" + * }' + * - lang: Shell + * label: Google Provider + * source: |- + * curl -X POST '{backend_url}/auth/user/google' + * - lang: Shell + * label: GitHub Provider + * source: |- + * curl -X POST '{backend_url}/auth/user/github' * tags: * - Auth * responses: 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 3938e90b99be1..7ddf9ecb3dfaf 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 @@ -2,8 +2,18 @@ * @oas [post] /auth/user/{auth_provider}/callback * operationId: PostActor_typeAuth_providerCallback * summary: Validate Authentication Callback - * description: Third-party authentication providers, such as Google, require an API route to call once authentication with the third-party provider is finished. - * This API route validates callback for admin users logged-in with third-party providers. + * 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. + * + * + * 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: + * url: https://docs.medusajs.com/v2/resources/commerce-modules/auth/authentication-route#2-third-party-service-authenticate-flow + * description: Learn about third-party authentication flow. * x-authenticated: false * parameters: * - name: auth_provider @@ -15,8 +25,11 @@ * example: "google" * x-codeSamples: * - lang: Shell - * label: cURL - * source: curl -X POST '{backend_url}/auth/user/{auth_provider}/callback' + * label: Google Provider + * source: curl -X POST '{backend_url}/auth/user/google/callback?code=123' + * - lang: Shell + * label: GitHub Provider + * source: curl -X POST '{backend_url}/auth/user/github/callback?code=123' * tags: * - Auth * responses: diff --git a/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider]_register.ts b/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider]_register.ts index 144005a82f6ac..9e215f122013a 100644 --- a/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider]_register.ts +++ b/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider]_register.ts @@ -2,8 +2,10 @@ * @oas [post] /auth/user/{auth_provider}/register * operationId: PostActor_typeAuth_provider_register * summary: Retrieve Registration JWT Token - * description: A registration JWT token is used in the header of requests that create a user, such as the accept invitation request. - * This API route retrieves the JWT token of a user that hasn't been registered yet. + * description: This API route retrieves a registration JWT token of a user that hasn't been registered yet. The token is used in the header of requests that create a user, such as the Accept Invite API route. + * externalDocs: + * url: https://docs.medusajs.com/v2/resources/commerce-modules/auth/authentication-route#1-basic-authentication-flow + * description: Learn about the basic authentication flow. * x-authenticated: false * parameters: * - name: auth_provider @@ -13,10 +15,23 @@ * schema: * type: string * example: "emailpass" + * requestBody: + * content: + * application/json: + * schema: + * type: object + * title: input + * description: The input data necessary for authentication. For example, for email-pass authentication, pass `email` and `password` properties. * x-codeSamples: * - lang: Shell * label: cURL - * source: curl -X POST '{backend_url}/auth/user/{auth_provider}/register' + * source: |- + * curl -X POST '{backend_url}/auth/user/emailpass/register' \ + * -H 'Content-Type: application/json' \ + * --data-raw '{ + * "email": "admin@medusa-test.com", + * "password": "supersecret" + * }' * tags: * - Auth * responses: diff --git a/www/utils/generated/oas-output/operations/admin/post_auth_token_refresh.ts b/www/utils/generated/oas-output/operations/admin/post_auth_token_refresh.ts new file mode 100644 index 0000000000000..fcfeaeb9e1838 --- /dev/null +++ b/www/utils/generated/oas-output/operations/admin/post_auth_token_refresh.ts @@ -0,0 +1,38 @@ +/** + * @oas [post] /auth/token/refresh + * operationId: PostAdminAuthTokenRefresh + * summary: Refresh Authentication Token + * description: Refresh the authentication token of a user. This is useful after authenticating a user with a third-party service, or when you don't want users to re-login every day. + * externalDocs: + * url: https://docs.medusajs.com/v2/resources/commerce-modules/auth/authentication-route#2-third-party-service-authenticate-flow + * description: Learn about third-party authentication flow. + * x-authenticated: true + * x-codeSamples: + * - lang: Shell + * label: cURL + * source: curl -X POST '{backend_url}/auth/token/refresh' \ + * -H 'Authorization: Bearer {token}' + * tags: + * - Auth + * responses: + * "200": + * description: OK + * content: + * application/json: + * schema: + * $ref: "#/components/schemas/AuthResponse" + * "400": + * $ref: "#/components/responses/400_error" + * "401": + * $ref: "#/components/responses/unauthorized" + * "404": + * $ref: "#/components/responses/not_found_error" + * "409": + * $ref: "#/components/responses/invalid_state_error" + * "422": + * $ref: "#/components/responses/invalid_request_error" + * "500": + * $ref: "#/components/responses/500_error" + * +*/ + diff --git a/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider].ts b/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider].ts index a9729c7869fd7..2e467d5f94b16 100644 --- a/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider].ts +++ b/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider].ts @@ -2,7 +2,15 @@ * @oas [post] /auth/customer/{auth_provider} * operationId: PostActor_typeAuth_provider * summary: Authenticate Customer - * description: Authenticate a customer and receive the JWT token to be used in the header of subsequent requests. + * description: > + * Authenticate a customer and receive the JWT token to be used in the header of subsequent requests. + * + * + * When used with a third-party provider, such as Google, the request returns a `location` property. You redirect to the + * specified URL in your storefront to continue authentication with the third-party service. + * externalDocs: + * url: https://docs.medusajs.com/v2/resources/commerce-modules/auth/authentication-route#types-of-authentication-flows + * description: Learn about different authentication flows. * x-authenticated: false * parameters: * - name: auth_provider @@ -12,10 +20,31 @@ * schema: * type: string * example: "emailpass" + * requestBody: + * content: + * application/json: + * schema: + * type: object + * title: input + * description: The input data necessary for authentication. For example, for email-pass authentication, pass `email` and `password` properties. * x-codeSamples: * - lang: Shell - * label: cURL - * source: curl -X POST '{backend_url}/auth/customer/{auth_provider}' + * label: EmailPass Provider + * source: |- + * curl -X POST '{backend_url}/auth/customer/emailpass' \ + * -H 'Content-Type: application/json' \ + * --data-raw '{ + * "email": "customer@gmail.com", + * "password": "supersecret" + * }' + * - lang: Shell + * label: Google Provider + * source: |- + * curl -X POST '{backend_url}/auth/customer/google' + * - lang: Shell + * label: GitHub Provider + * source: |- + * curl -X POST '{backend_url}/auth/customer/github' * tags: * - Auth * responses: 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 d6e3881329da7..eceb646de1c1f 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 @@ -2,8 +2,18 @@ * @oas [post] /auth/customer/{auth_provider}/callback * operationId: PostActor_typeAuth_providerCallback * summary: Validate Authentication Callback - * description: Third-party authentication providers, such as Google, require an API route to call once authentication with the third-party provider is finished. - * This API route validates callback for customers logged-in with third-party providers. + * 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. + * + * + * 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/resources/commerce-modules/auth/authentication-route#2-third-party-service-authenticate-flow + * description: Learn about third-party authentication flow. * x-authenticated: false * parameters: * - name: auth_provider @@ -15,8 +25,11 @@ * example: "google" * x-codeSamples: * - lang: Shell - * label: cURL - * source: curl -X POST '{backend_url}/auth/customer/{auth_provider}/callback' + * label: Google Provider + * source: curl -X POST '{backend_url}/auth/customer/google/callback?code=123' + * - lang: Shell + * label: GitHub Provider + * source: curl -X POST '{backend_url}/auth/customer/github/callback?code=123' * tags: * - Auth * responses: diff --git a/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider]_register.ts b/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider]_register.ts index 9681b084b1be9..d94c59d5fef2c 100644 --- a/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider]_register.ts +++ b/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider]_register.ts @@ -2,8 +2,10 @@ * @oas [post] /auth/customer/{auth_provider}/register * operationId: PostActor_typeAuth_provider_register * summary: Retrieve Registration JWT Token - * description: A registration JWT token is used in the header of requests that create a customer. - * This API route retrieves the JWT token of a customer that hasn't been registered yet. + * description: This API route retrieves a registration JWT token of a customer that hasn't been registered yet. The token is used in the header of requests that create a customer. + * externalDocs: + * url: https://docs.medusajs.com/v2/resources/commerce-modules/auth/authentication-route#1-basic-authentication-flow + * description: Learn about the basic authentication flow. * x-authenticated: false * parameters: * - name: auth_provider @@ -13,10 +15,23 @@ * schema: * type: string * example: "emailpass" + * requestBody: + * content: + * application/json: + * schema: + * type: object + * title: input + * description: The input data necessary for authentication. For example, for email-pass authentication, pass `email` and `password` properties. * x-codeSamples: * - lang: Shell * label: cURL - * source: curl -X POST '{backend_url}/auth/customer/{auth_provider}/register' + * source: |- + * curl -X POST '{backend_url}/auth/customer/emailpass/register' \ + * -H 'Content-Type: application/json' \ + * --data-raw '{ + * "email": "customer@gmail.com", + * "password": "supersecret" + * }' * tags: * - Auth * responses: diff --git a/www/utils/generated/oas-output/operations/store/post_auth_token_refresh.ts b/www/utils/generated/oas-output/operations/store/post_auth_token_refresh.ts new file mode 100644 index 0000000000000..d319c9d2a3cf9 --- /dev/null +++ b/www/utils/generated/oas-output/operations/store/post_auth_token_refresh.ts @@ -0,0 +1,38 @@ +/** + * @oas [post] /auth/token/refresh + * operationId: PostAdminAuthTokenRefresh + * summary: Refresh Authentication Token + * description: Refresh the authentication token of a customer. This is useful after authenticating a customer with a third-party service, or when you don't want customers to re-login every day. + * externalDocs: + * url: https://docs.medusajs.com/v2/resources/commerce-modules/auth/authentication-route#2-third-party-service-authenticate-flow + * description: Learn about third-party authentication flow. + * x-authenticated: true + * x-codeSamples: + * - lang: Shell + * label: cURL + * source: curl -X POST '{backend_url}/auth/token/refresh' \ + * -H 'Authorization: Bearer {token}' + * tags: + * - Auth + * responses: + * "200": + * description: OK + * content: + * application/json: + * schema: + * $ref: "#/components/schemas/AuthResponse" + * "400": + * $ref: "#/components/responses/400_error" + * "401": + * $ref: "#/components/responses/unauthorized" + * "404": + * $ref: "#/components/responses/not_found_error" + * "409": + * $ref: "#/components/responses/invalid_state_error" + * "422": + * $ref: "#/components/responses/invalid_request_error" + * "500": + * $ref: "#/components/responses/500_error" + * +*/ + From 8ea5eb6724be6c1e73ae5c74f77903575ed39850 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 5 Sep 2024 18:10:01 +0300 Subject: [PATCH 02/10] lint content --- .../notification/sendgrid/page.mdx | 2 +- .../app/commerce-modules/auth/auth-flows/page.mdx | 2 +- .../customers/third-party-login/page.mdx | 12 ++++++------ .../medusaIntegrationTestRunner/page.mdx | 2 +- .../moduleIntegrationTestRunner/page.mdx | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/www/apps/resources/app/architectural-modules/notification/sendgrid/page.mdx b/www/apps/resources/app/architectural-modules/notification/sendgrid/page.mdx index 0c1b77a1171b7..ead7eb9234533 100644 --- a/www/apps/resources/app/architectural-modules/notification/sendgrid/page.mdx +++ b/www/apps/resources/app/architectural-modules/notification/sendgrid/page.mdx @@ -168,7 +168,7 @@ export default async function productCreateHandler({ disposition: "attachment or inline attachment", id: "id", // only needed for inline attachment }, - ] + ], }) } 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 7c95cf36ee0ed..49ba7df03480d 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 @@ -139,7 +139,7 @@ const { success, authIdentity } = await authModuleService.validateCallback( headers, query, body, - protocol + protocol, } ) 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 b2e63fba7808d..e67de4964b274 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 @@ -199,7 +199,7 @@ const queryParams = new URLSearchParams(window.location.search) const code = queryParams.get("code") const sendCallback = async () => { - let { token } = await fetch( + const { token } = await fetch( `http://localhost:9000/auth/customer/google/callback?code=${code}`, { credentials: "include", @@ -234,7 +234,7 @@ import { HttpTypes } from "@medusajs/types" import { useEffect, useMemo, useState } from "react" import { decodeToken } from "react-jwt" -export default function GoogleCallback () { +export default function GoogleCallback() { const [loading, setLoading] = useState(true) const [customer, setCustomer] = useState() // for other than Next.js @@ -245,7 +245,7 @@ export default function GoogleCallback () { }, []) const sendCallback = async () => { - let { token } = await fetch( + const { token } = await fetch( `http://localhost:9000/auth/customer/google/callback?code=${code}`, { credentials: "include", @@ -458,7 +458,7 @@ const code = queryParams.get("code") const sendCallback = async () => { - let { token } = await fetch( + const { token } = await fetch( `http://localhost:9000/auth/customer/google/callback?code=${code}`, { credentials: "include", @@ -541,7 +541,7 @@ import { HttpTypes } from "@medusajs/types" import { useEffect, useMemo, useState } from "react" import { decodeToken } from "react-jwt" -export default function GoogleCallback () { +export default function GoogleCallback() { const [loading, setLoading] = useState(true) const [customer, setCustomer] = useState() // for other than Next.js @@ -552,7 +552,7 @@ export default function GoogleCallback () { }, []) const sendCallback = async () => { - let { token } = await fetch( + const { token } = await fetch( `http://localhost:9000/auth/customer/google/callback?code=${code}`, { credentials: "include", diff --git a/www/apps/resources/app/test-tools-reference/medusaIntegrationTestRunner/page.mdx b/www/apps/resources/app/test-tools-reference/medusaIntegrationTestRunner/page.mdx index d074f76be6a07..84e0d6dbf67b9 100644 --- a/www/apps/resources/app/test-tools-reference/medusaIntegrationTestRunner/page.mdx +++ b/www/apps/resources/app/test-tools-reference/medusaIntegrationTestRunner/page.mdx @@ -16,7 +16,7 @@ import { medusaIntegrationTestRunner } from "medusa-test-utils" medusaIntegrationTestRunner({ testSuite: ({ api, getContainer }) => { // TODO write tests... - } + }, }) ``` diff --git a/www/apps/resources/app/test-tools-reference/moduleIntegrationTestRunner/page.mdx b/www/apps/resources/app/test-tools-reference/moduleIntegrationTestRunner/page.mdx index cd3afb3d06d56..739c4d5f2dbde 100644 --- a/www/apps/resources/app/test-tools-reference/moduleIntegrationTestRunner/page.mdx +++ b/www/apps/resources/app/test-tools-reference/moduleIntegrationTestRunner/page.mdx @@ -22,7 +22,7 @@ moduleIntegrationTestRunner({ resolve: "./modules/hello", testSuite: ({ service }) => { // TODO write tests - } + }, }) ``` From c32eeafa34900b8674326f8c99690f59d23d8313 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 5 Sep 2024 18:52:40 +0300 Subject: [PATCH 03/10] fix vale error --- .../auth/auth-identity-and-actor-types/page.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx b/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx index bd38ca01d2231..40c8d6f0251a0 100644 --- a/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx @@ -48,7 +48,7 @@ export default defineMiddlewares({ }) ``` -By specifying `user` as the first parameter of `authenticate`, only authenticated users of actor type `user` (i.e. admin users) can access API routes starting with `/custom/admin`. +By specifying `user` as the first parameter of `authenticate`, only authenticated users of actor type `user` (admin users) can access API routes starting with `/custom/admin`. --- From 969280e913243d613a2192e3a712e3a1f9be8c20 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 5 Sep 2024 19:05:31 +0300 Subject: [PATCH 04/10] add callback response schema --- .../post_auth_[actor_type]_[auth_provider].ts | 4 +++- .../post_auth_[actor_type]_[auth_provider].ts | 4 +++- .../oas-output/schemas/AuthCallbackResponse.ts | 14 ++++++++++++++ .../docs-generator/src/commands/clean-oas.ts | 7 ++++--- 4 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 www/utils/generated/oas-output/schemas/AuthCallbackResponse.ts diff --git a/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider].ts b/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider].ts index ff7c6d177fe49..26b88c19ba7ec 100644 --- a/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider].ts +++ b/www/utils/generated/oas-output/operations/admin/post_auth_[actor_type]_[auth_provider].ts @@ -53,7 +53,9 @@ * content: * application/json: * schema: - * $ref: "#/components/schemas/AuthResponse" + * oneOf: + * - $ref: "#/components/schemas/AuthResponse" + * - $ref: "#/components/schemas/AuthCallbackResponse" * "400": * $ref: "#/components/responses/400_error" * "401": diff --git a/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider].ts b/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider].ts index 2e467d5f94b16..af4159ef25703 100644 --- a/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider].ts +++ b/www/utils/generated/oas-output/operations/store/post_auth_[actor_type]_[auth_provider].ts @@ -53,7 +53,9 @@ * content: * application/json: * schema: - * $ref: "#/components/schemas/AuthResponse" + * oneOf: + * - $ref: "#/components/schemas/AuthResponse" + * - $ref: "#/components/schemas/AuthCallbackResponse" * "400": * $ref: "#/components/responses/400_error" * "401": diff --git a/www/utils/generated/oas-output/schemas/AuthCallbackResponse.ts b/www/utils/generated/oas-output/schemas/AuthCallbackResponse.ts new file mode 100644 index 0000000000000..7fc135dcea802 --- /dev/null +++ b/www/utils/generated/oas-output/schemas/AuthCallbackResponse.ts @@ -0,0 +1,14 @@ +/** + * @schema AuthCallbackResponse + * type: object + * description: The authentication's details. + * x-schemaName: AuthCallbackResponse + * required: + * - location + * properties: + * token: + * type: string + * title: location + * description: The location to redirect the user to for further authentication with the third-party provider. +*/ + diff --git a/www/utils/packages/docs-generator/src/commands/clean-oas.ts b/www/utils/packages/docs-generator/src/commands/clean-oas.ts index 1854614fb24ad..e5ed643b81c56 100644 --- a/www/utils/packages/docs-generator/src/commands/clean-oas.ts +++ b/www/utils/packages/docs-generator/src/commands/clean-oas.ts @@ -22,13 +22,14 @@ const OAS_PREFIX_REGEX = /@oas \[(?(get|post|delete))\] (?.+)/ const ignoreSchemas = [ "AuthResponse", + "AuthCallbackResponse", "AuthAdminSessionResponse", "AuthStoreSessionResponse", ] const ignoreTags = { admin: ["Auth"], - store: ["Auth"] + store: ["Auth"], } export default async function () { @@ -229,8 +230,8 @@ export default async function () { } const lengthBefore = parsedBaseYaml.tags?.length || 0 - parsedBaseYaml.tags = parsedBaseYaml.tags?.filter((tag) => - areaTags.has(tag.name) || ignoreTags[area].includes(tag.name) + parsedBaseYaml.tags = parsedBaseYaml.tags?.filter( + (tag) => areaTags.has(tag.name) || ignoreTags[area].includes(tag.name) ) if (lengthBefore !== (parsedBaseYaml.tags?.length || 0)) { From e83c5ba0528da24e08b714e403253b53734bfd77 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 5 Sep 2024 19:09:16 +0300 Subject: [PATCH 05/10] Update www/apps/resources/app/commerce-modules/auth/auth-providers/github/page.mdx Co-authored-by: Stevche Radevski --- .../app/commerce-modules/auth/auth-providers/github/page.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ac935c68f85e7..a24d20cae96ed 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 @@ -18,7 +18,7 @@ Learn about the authentication flow in [this guide](../../authentication-route/p --- -## Install the Google Auth Module Provider +## Install the Github Auth Module Provider Date: Thu, 5 Sep 2024 19:09:30 +0300 Subject: [PATCH 06/10] Update www/apps/resources/app/commerce-modules/auth/auth-providers/github/page.mdx Co-authored-by: Stevche Radevski --- .../app/commerce-modules/auth/auth-providers/github/page.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a24d20cae96ed..7519ed32d71d9 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 @@ -8,7 +8,7 @@ export const metadata = { In this document, you’ll learn about the GitHub Auth Module Provider and how to install and use it in the Auth Module. -The Google Auth Module Provider handles authenticating users with their GitHub account. +The Github Auth Module Provider handles authenticating users with their GitHub account. From 28377be18d9a572aa6b41d1512fde42b412faa74 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 5 Sep 2024 19:11:20 +0300 Subject: [PATCH 07/10] Update www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx Co-authored-by: Stevche Radevski --- .../app/commerce-modules/auth/authentication-route/page.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 70c96f3fd696b..4c6ecacd69c36 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 @@ -61,7 +61,7 @@ It requires the following steps: 7. The frontend uses the authentication token to create the user with their respective API route. - For example, for customers you would use the [Create Customer API route](!api!/store#customers_postcustomers). - For admin users, you accept an invite using the [Accept Invite API route](!api!/admin#invites_postinvitesaccept) -8. The frontend sends a request to the [Refresh Token Route](#refresh-token-route) to retrieve a new token for the user. +8. The frontend sends a request to the [Refresh Token Route](#refresh-token-route) to retrieve a new token with the user information populated. After the first registration, you only use the [Auth Route](#auth-route) for subsequent authentication. From ae755aba641d0766c4820a8e0b21b41f0f1610c3 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 5 Sep 2024 19:12:19 +0300 Subject: [PATCH 08/10] address PR comments --- .../resources/app/commerce-modules/auth/auth-flows/page.mdx | 4 +--- .../app/commerce-modules/auth/authentication-route/page.mdx | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) 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 49ba7df03480d..ba1820b584a21 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 @@ -117,8 +117,6 @@ If the `authenticate` method returns a `location` property, the authentication p For example, when using the `google` provider, the `location` is the URL that the user is navigated to login. -If the `authenticate` method doesn't return a `location` property and the returned `success` property, the user is successfully authenticated. This happens after the user logs-in with the provider, such as google, the first time. - ![Diagram showcasing the first part of the third-party authentication flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1711374847/Medusa%20Resources/third-party-auth-1_enyedy.jpg) ### validateCallback @@ -148,6 +146,6 @@ if (success) { } ``` -If the returned `success` property is `true`, the authentication with the third-party provider was successful. Subsequent authentication attempts can use the `authenticate` method only. +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/authentication-route/page.mdx b/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx index 4c6ecacd69c36..4ed63c2caa7e9 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 @@ -63,7 +63,6 @@ It requires the following steps: - For admin users, you accept an invite using the [Accept Invite API route](!api!/admin#invites_postinvitesaccept) 8. The frontend sends a request to the [Refresh Token Route](#refresh-token-route) to retrieve a new token with the user information populated. -After the first registration, you only use the [Auth Route](#auth-route) for subsequent authentication. --- From 2e45e6ed340eb22de5fe750fe56459ab19b3aa55 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 5 Sep 2024 19:14:28 +0300 Subject: [PATCH 09/10] replace google -> github --- .../app/commerce-modules/auth/auth-providers/github/page.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 7519ed32d71d9..8e49749e1b86c 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 @@ -33,7 +33,7 @@ Learn about the authentication flow in [this guide](../../authentication-route/p ]} /> -To install the Google auth module provider, run the following command in the directory of your Medusa application: +To install the GitHub auth module provider, run the following command in the directory of your Medusa application: ```bash npm2yarn npm install @medusajs/auth-github@preview @@ -55,7 +55,7 @@ const modules = { // other providers... { resolve: "@medusajs/auth-github", - id: "google", + id: "github", options: { clientId: process.env.GITHUB_CLIENT_ID, clientSecret: process.env.GITHUB_CLIENT_SECRET, From fb3a9dc5eb1f0e44ca63b6abbd42c1540de81204 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 5 Sep 2024 19:17:55 +0300 Subject: [PATCH 10/10] better explanation for refresh token --- .../app/commerce-modules/auth/authentication-route/page.mdx | 2 +- .../storefront-development/customers/third-party-login/page.mdx | 2 +- .../oas-output/operations/admin/post_auth_token_refresh.ts | 2 +- .../oas-output/operations/store/post_auth_token_refresh.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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 4ed63c2caa7e9..590f0310f90db 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 @@ -219,7 +219,7 @@ In your frontend, decode the token using tools like [react-jwt](https://www.npmj ## Refresh Token Route -The Medusa application defines an API route at `/auth/token/refresh` that's useful after authenticating a user with a third-party service. +The Medusa application defines an API route at `/auth/token/refresh` that's useful after authenticating a user with a third-party service to populate the user's token with their new information. It requires the user's JWT token that they received from the authentication or callback routes. 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 e67de4964b274..2abd30a742c5d 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 @@ -328,7 +328,7 @@ const refreshToken = async (token: string) => { // TODO add more functions... ``` -This adds to the page the function `refreshToken` which is used after the new customer is created to refresh their authentication token. +This adds to the page the function `refreshToken` which is used after the new customer is created to refresh their authentication token. This ensures that the authentication token includes the details of the created customer. Finally, add in the place of the new `TODO` the `validateCallback` function that runs when the page first loads to validate the authentication: diff --git a/www/utils/generated/oas-output/operations/admin/post_auth_token_refresh.ts b/www/utils/generated/oas-output/operations/admin/post_auth_token_refresh.ts index fcfeaeb9e1838..85050ee5c1208 100644 --- a/www/utils/generated/oas-output/operations/admin/post_auth_token_refresh.ts +++ b/www/utils/generated/oas-output/operations/admin/post_auth_token_refresh.ts @@ -2,7 +2,7 @@ * @oas [post] /auth/token/refresh * operationId: PostAdminAuthTokenRefresh * summary: Refresh Authentication Token - * description: Refresh the authentication token of a user. This is useful after authenticating a user with a third-party service, or when you don't want users to re-login every day. + * description: Refresh the authentication token of a user. This is useful after authenticating a user with a third-party service to ensure the token holds the new user's details, or when you don't want users to re-login every day. * externalDocs: * url: https://docs.medusajs.com/v2/resources/commerce-modules/auth/authentication-route#2-third-party-service-authenticate-flow * description: Learn about third-party authentication flow. diff --git a/www/utils/generated/oas-output/operations/store/post_auth_token_refresh.ts b/www/utils/generated/oas-output/operations/store/post_auth_token_refresh.ts index d319c9d2a3cf9..7e05a56a99c4d 100644 --- a/www/utils/generated/oas-output/operations/store/post_auth_token_refresh.ts +++ b/www/utils/generated/oas-output/operations/store/post_auth_token_refresh.ts @@ -2,7 +2,7 @@ * @oas [post] /auth/token/refresh * operationId: PostAdminAuthTokenRefresh * summary: Refresh Authentication Token - * description: Refresh the authentication token of a customer. This is useful after authenticating a customer with a third-party service, or when you don't want customers to re-login every day. + * description: Refresh the authentication token of a customer. This is useful after authenticating a customer with a third-party service to ensure the token holds the new user's details, or when you don't want customers to re-login every day. * externalDocs: * url: https://docs.medusajs.com/v2/resources/commerce-modules/auth/authentication-route#2-third-party-service-authenticate-flow * description: Learn about third-party authentication flow.