diff --git a/.github/workflows/generate-resources-reference.yml b/.github/workflows/generate-resources-reference.yml index 289b65d449..2d60fd93fd 100644 --- a/.github/workflows/generate-resources-reference.yml +++ b/.github/workflows/generate-resources-reference.yml @@ -46,11 +46,15 @@ jobs: working-directory: www run: yarn install + - name: Build Docs packages + working-directory: www + run: yarn build:packages + - name: Install Workspace dependencies run: yarn install working-directory: www/utils - - name: Build Workspace dependencies + - name: Build Workspace packages run: yarn build working-directory: www/utils @@ -64,6 +68,10 @@ jobs: run: "yarn start generate all --merge" working-directory: www/utils/packages/typedoc-generate-references + - name: Generate Sidebar and File Map + run: "yarn prep" + working-directory: www/apps/resources + - name: Generate Changeset run: "yarn generate:changeset" working-directory: www/utils/packages/scripts 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 935ff58f4e..5eeed30e00 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 @@ -12,7 +12,7 @@ In this document, you'll learn about how the Auth Provider is used in an authent ## How to Authenticate a User -To authenticate a user, you use the [authenticate method of the Auth Module's main service](/references/auth/authenticate) (`IAuthModuleService`). For example: +To authenticate a user, you use the [authenticate method of the Auth Module's main service](/references/auth/authenticate). For example: ```ts const data = await authModuleService.authenticate( 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 new file mode 100644 index 0000000000..82b4e2f4be --- /dev/null +++ b/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/page.mdx @@ -0,0 +1,58 @@ +export const metadata = { + title: `Auth Identity and Actor Types`, +} + +# {metadata.title} + +In this document, you’ll learn about concepts related to identity and actors in the Auth Module. + +## What is an Auth Identity? + +The [AuthIdentity data model](/references/auth/model/AuthIdentity) represents a previously-authenticated 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. + +--- + +## Actor Types + +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. + +### Protect Routes by Actor Type + +When you protect routes with the `authenticate` middleware, you specify in its first parameter the actor type that must be authenticated to access the specified API routes. + +For example: + +export const highlights = [ + ["8", `"user"`, "The actor type that must be authenticated to access the specified routes."] +] + +```ts title="src/api/middlewares.ts" highlights={highlights} +import { MiddlewaresConfig, authenticate } from "@medusajs/medusa" + +export const config: MiddlewaresConfig = { + routes: [ + { + matcher: "/custom/admin*", + middlewares: [ + authenticate("user", ["session", "bearer", "api-key"]), + ], + }, + ], +} +``` + +By specifying `user` as the first parameter of `authenticate`, only authenticated users of actor type `user` can access API routes starting with `/custom/admin`. + +--- + +## Custom Actor Types + +You can define custom actor types that point to the data model of your module. + +For example, if you have a custom module with a `Manager` data model, you can authenticate managers with the `manager` actor type. + +Learn how to create a custom actor type in [this guide](../create-actor-type/page.mdx). \ No newline at end of file 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 0000000000..defecac973 --- /dev/null +++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/_google/page.mdx @@ -0,0 +1,189 @@ +import { Table } from "docs-ui" + +export const metadata = { + title: `Google Auth Provider Module`, +} + +# {metadata.title} + +In this document, you’ll learn about the Google auth provider module and how to install and use it in the Auth Module. + +## Features + +The Google auth provider module 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 Provider Module + + + +- [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 provider module, 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" +const { Modules } = require("@medusajs/modules-sdk") + +// ... + +const modules = { + // ... + [Modules.AUTH]: { + resolve: "@medusajs/auth", + options: { + providers: [ + { + resolve: "@medusajs/auth-google", + options: { + config: { + google: { + 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 new file mode 100644 index 0000000000..51319e56b7 --- /dev/null +++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/emailpass/page.mdx @@ -0,0 +1,95 @@ +import { Table } from "docs-ui" + +export const metadata = { + title: `Emailpass Auth Provider Module`, +} + +# {metadata.title} + +In this document, you’ll learn about the Emailpass auth provider module and how to install and use it in the Auth Module. + +## Features + +Using the Emailpass auth provider module, you allow users to register and login with an email and password. + +--- + +## Install the Emailpass Auth Provider Module + +The Emailpass auth provider is registered by default with the Auth Module. + +If you want to pass options to the provider, add the provider to the `providers` option of the Auth Module: + +```js title="medusa-config.js" +const { Modules } = require("@medusajs/modules-sdk") + +// ... + +const modules = { + // ... + [Modules.AUTH]: { + resolve: "@medusajs/auth", + options: { + providers: [ + { + resolve: "@medusajs/auth-emailpass", + config: { + emailpass: { + // options... + } + } + }, + ], + }, + }, +} +``` + +### Module Options + + + + + Configuration + Description + Required + Default + + + + + + + `hashConfig` + + + + + An object of configurations to use when hashing the user's + password. Refer to [scrypt-kdf](https://www.npmjs.com/package/scrypt-kdf#-hash)'s + documentation for accepted options. + + + + + No + + + + + ```ts noCopy noReport noLineNumbers + const hashConfig = { + logN: 15, + r: 8, + p: 1 + } + ``` + + + + +
+ +## Related Guides + +- [How to register a customer using email and password](../../../customer/register-customer-email/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 920c738b30..a7a964a22e 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 @@ -12,7 +12,7 @@ An auth provider module handles authenticating customers and users, either using For example, the EmailPass Auth Provider Module authenticates a user using their email and password, whereas the Google Auth Provider Module authenticates users using their Google account. - + Support for the Google Auth Provider Module is coming soon. @@ -20,11 +20,11 @@ Support for the Google Auth Provider Module is coming soon. --- -## Configure Auth Provider Modules +## Configure Allowed Auth Providers of Actor Types -By default, admin users and customers can login with all installed auth provider moduless. +By default, users of all actor types can authenticate with all installed auth provider moduless. -To limit the auth providers that used for admin users and customers, use the [authMethodsPerActor option](/references/medusa-config#http-authMethodsPerActor-1-3) in Medusa's configurations: +To restrict the auth providers used for actor types, use the [authMethodsPerActor option](/references/medusa-config#http-authMethodsPerActor-1-3) in Medusa's configurations: ```js title="medusa-config.js" module.exports = defineConfig({ @@ -41,6 +41,12 @@ module.exports = defineConfig({ }) ``` + + +When you specify the `authMethodsPerActor` configuration, it overrides the default. So, if you don't specify any providers for an actor type, users of that actor type can't authenticate with any provider. + + + --- ## How to Create an Auth Provider Module 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 new file mode 100644 index 0000000000..694400d53d --- /dev/null +++ b/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx @@ -0,0 +1,37 @@ +export const metadata = { + title: `Authentication Route`, +} + +# {metadata.title} + +In this document, you'll learn about the `/auth` route and how to use it to create or log-in users. + +## `/auth` Route + +The Medusa application defines an API route at `/auth/{actor_type}/{provider}` used to obtain a token used later for authentication purposes. + +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, `emailpass`. + +This route accepts in the request body the data that the specified authentication provider requires to handle authentication. + +For example, the EmailPass provider requires an `email` and `password` fields in the request body. + +If the authentication is successful, you'll receive a `token` field in the response body. + +--- + +## How to Use the Authentication Token + +There are two ways the returned authentication token is useful: + +1. Send authenticated requests to restricted routes. For example, if the token is of an admin user, you use it in the bearer header of subsequent requests to the admin API routes. +2. Before creating a user of an actor type, such as a `customer` or a custom actor type. You use it in the bearer header of the request to the API route that creates the user. + + + +[How to register Customers using the authentication route](../../customer/register-customer-email/page.mdx). + + 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 new file mode 100644 index 0000000000..bee1234490 --- /dev/null +++ b/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx @@ -0,0 +1,316 @@ +export const metadata = { + title: `How to Create an Actor Type`, +} + +# {metadata.title} + +In this document, learn how to create an actor type and authenticate its associated data model. + +## 0. Create Module with Data Model + +Before creating an actor type, you must define a data model the actor type belongs to. The data model is defined in a custom module. + +The rest of this guide uses this `Manager` data model as an example: + +```ts title="src/modules/manager/models/manager.ts" +import { BaseEntity } from "@medusajs/utils" +import { + Entity, + PrimaryKey, + Property, +} from "@mikro-orm/core" + +@Entity() +export class Manager extends BaseEntity { + @PrimaryKey({ columnType: "text" }) + id!: string + + @Property({ columnType: "text" }) + first_name: string + + @Property({ columnType: "text" }) + last_name: string + + @Property({ columnType: "text" }) + email: string +} +``` + +The module’s main service must also have a `create` method to create a record of the `Manager` data model. + +--- + +## 1. Create Workflow + +Start by creating a workflow that does two things: + +- Create a record of the `Manager` data model. +- Sets the `app_metadata` field of the associated `AuthIdentity` record based on the new actor type. + +For example, create the file `src/workflows/create-manager.ts`. with the following content: + +export const workflowHighlights = [ + ["27", "createManagerStep", "Thi step creates a manager."], + ["44", "createManagerWorkflow", "The workflow used to create a manager and set its auth identity's actor type."], + ["53", "setAuthAppMetadataStep", "Set the actor type of the manager's associated auth identity."], + ["55", '"manager"', "The actor type of the manager."] +] + +```ts title="src/workflows/create-manager.ts" highlights={workflowHighlights} +import { + createWorkflow, + createStep, + StepResponse +} from "@medusajs/workflows-sdk" +import { + setAuthAppMetadataStep +} from "@medusajs/core-flows" +import ManagerModuleService from "../modules/manager/service" + +type CreateManagerWorkflowInput = { + manager: { + first_name: string + last_name: string + email: string + } + authIdentityId: string +} + +type CreateManagerWorkflowOutput = { + id: string + first_name: string + last_name: string + email: string +} + +const createManagerStep = createStep( + "create-manager-step", + async ({ + manager: managerData + }: Pick, + { container }) => { + const managerModuleService: ManagerModuleService = + container.resolve("managerModuleService") + + const manager = await managerModuleService.create( + managerData + ) + + return new StepResponse(manager) + } +) + +const createManagerWorkflow = createWorkflow< + CreateManagerWorkflowInput, CreateManagerWorkflowOutput +>( + "create-manager", + function (input) { + const manager = createManagerStep({ + manager: input.manager + }) + + setAuthAppMetadataStep({ + authIdentityId: input.authIdentityId, + actorType: "manager", + value: manager.id + }) + + return manager + } +) + +export default createManagerWorkflow +``` + +This workflow accepts the manager’s data and the associated auth identity’s ID as inputs. The next sections explain how the auth identity ID is retrieved. + +The workflow has two steps: + +1. Create the manager using the `createManagerStep`. +2. Set the `app_metadata` field of the associated auth identity using the `setAuthAppMetadataStep` step imported from `@medusajs/core-flows`. You specify the actor type `manager` in the `actorType` property of the step’s input. + +--- + +## 2. Define the Create API Route + +Next, you’ll use the workflow defined in the previous section in an API route that creates a manager. + +So, create the file `src/api/manager/route.ts` with the following content: + +export const createRouteHighlights = [ + ["15", "AuthenticatedMedusaRequest", "The request must be authenticated to associate the manager with an auth identity."], + ["27", "createManagerWorkflow", "Use the workflow created previously to create the manager."], + ["31", "auth_identity_id", "Access the associated auth identity's ID in `req.auth_context.auth_identity_id`."] +] + +```ts title="src/api/manager/route.ts" highlights={createRouteHighlights} +import type { + AuthenticatedMedusaRequest, + MedusaResponse +} from "@medusajs/medusa" +import { MedusaError } from "@medusajs/utils" +import createManagerWorkflow from "../../workflows/create-manager" + +type RequestBody = { + first_name: string + last_name: string + email: string +} + +export async function POST( + req: AuthenticatedMedusaRequest, + res: MedusaResponse +) { + // If `actor_id` is present, the request carries + // authentication for an existing manager + if (req.auth_context.actor_id) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + "Request already authenticated as a manager." + ) + } + + const { result } = await createManagerWorkflow(req.scope) + .run({ + input: { + manager: req.body, + authIdentityId: req.auth_context.auth_identity_id + } + }) + + res.status(200).json({ manager: result }) +} +``` + +Since the manager must be associated with an `AuthIdentity` record, the request is expected to be authenticated, even if the manager isn’t created yet. This can be achieved by: + +1. Obtaining a token usng the [/auth route](../authentication-route/page.mdx). +2. Passing the token in the bearer header of the request to this route. + +In the API route, you create the manager using the workflow from the previous section and return it in the response. + +--- + +## 3. Apply the `authenticate` Middleware + +The last step is to apply the `authenticate` middleware on the API routes that require a manager’s authentication. + +To do that, create the file `src/api/middlewares.ts` with the following content: + +export const middlewareHighlights = [ + ["9", "authenticate", "Require the user to be authenticated to access the `/manager` API route when sending a `POST` request."], + ["10", "allowUnregistered", "The user doesn't need to be registered to access the API route."], + ["17", "authenticate", "Require the user to be authenticated as a manager when accessing `/manager/me` API routes."] +] + +```ts title="src/api/middlewares.ts" highlights={middlewareHighlights} +import { MiddlewaresConfig, authenticate } from "@medusajs/medusa" + +export const config: MiddlewaresConfig = { + routes: [ + { + matcher: "/manager", + method: "POST", + middlewares: [ + authenticate("manager", ["session", "bearer"], { + allowUnregistered: true + }), + ], + }, + { + matcher: "/manager/me*", + middlewares: [ + authenticate("manager", ["session", "bearer"]), + ], + }, + ], +} +``` + +This applies middlewares on two route patterns: + +1. The `authenticate` middleware is applied on the `/manager` API route for `POST` requests while allowing unregistered managers. This requires that a bearer token be passed in the request to access the manager’s auth identity but doesn’t require the manager to be registered. +2. The `authenticate` middleware is applied on all routes starting with `/manager/me`, restricting these routes to authenticated managers only. + +### Retrieve Manager API Route + +For example, create the file `src/api/manager/me/route.ts` with the following content: + +```ts title="src/api/manager/me/route.ts" +import { + AuthenticatedMedusaRequest, + MedusaResponse +} from "@medusajs/medusa"; +import ManagerModuleService from "../../../modules/manager/service"; + +export async function GET( + req: AuthenticatedMedusaRequest, + res: MedusaResponse +): Promise { + const managerModuleService: ManagerModuleService = + req.scope.resolve("managerModuleService") + + const manager = await managerModuleService.retrieve( + req.auth_context.actor_id + ) + + res.json({ manager }) +} + +``` + +This route is only accessible by authenticated managers. You access the manager’s ID using `req.auth_context.actor_id`. + +--- + +## Test Custom Actor Type Authentication Flow + +To authenticate managers: + +1. Send a `POST` request to `/auth/manager/emailpass` to create an auth identity for the manager: + +```bash +curl -X POST 'http://localhost:9000/auth/manager/emailpass' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "email": "manager@gmail.com", + "password": "supersecret" +}' +``` + +Copy the returned token to use it in the next request. + +2. Send a `POST` request to `/manager` to create a manager: + +```bash +curl -X POST 'http://localhost:9000/manager' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer {token}' \ +--data-raw '{ + "first_name": "John", + "last_name": "Doe", + "email": "manager@gmail.com" +}' +``` + +Replace `{token}` with the token returned in the previous step. + +3. Send a `POST` request to `/auth/manager/emailpass` again to retrieve an authenticated token for the manager: + +```bash +curl -X POST 'http://localhost:9000/auth/manager/emailpass' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "email": "manager@gmail.com", + "password": "supersecret" +}' +``` + +4. You can now send authenticated requests as a manager. For example, send a `GET` request to `/manager/me` to retrieve the authenticated manager’s details: + +```bash +curl 'http://localhost:9000/manager/me' \ +-H 'Authorization: Bearer {token}' +``` + +Whenever you want to log in as a manager, use the `/auth/manager/emailpass` API route, as explained in step 3. diff --git a/www/apps/resources/app/commerce-modules/auth/module-options/page.mdx b/www/apps/resources/app/commerce-modules/auth/module-options/page.mdx index 8bf7cf033e..a04d8afc5e 100644 --- a/www/apps/resources/app/commerce-modules/auth/module-options/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/module-options/page.mdx @@ -14,6 +14,12 @@ In this document, you'll learn about the options of the Auth Module. ## providers +The `providers` option is an array of auth provider modules. + +When the Medusa application starts, these providers are registered and can be used to handle authentication. + +For example: + ```js title="medusa-config.js" const { Modules } = require("@medusajs/modules-sdk") @@ -22,212 +28,30 @@ const { Modules } = require("@medusajs/modules-sdk") module.exports = defineConfig({ // ... modules: { - [Modules.AUTH]: { - resolve: "@medusajs/auth", - options: { - providers: [ - { - name: "emailpass", - scopes: { - store: {}, - admin: {}, - }, + resolve: "@medusajs/auth", + options: { + providers: [ + { + resolve: "@medusajs/auth-google", + options: { + config: { + google: { + // provider options... + } + } }, - { - name: "google", - scopes: { - admin: { - 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, - }, - }, - }, - ], - }, - } - } + }, + ], + }, + }, }) ``` -The `providers` option is an array of objects indicating the auth providers to register, their scopes, and configurations. +The `providers` option is an array of objects that accept the following properties: -Each object accepts the following properties: - -- `name`: The provider's name, which is set in the auth provider class's `PROVIDER` field. For example, `emailpass` or `google`. -- `scopes`: An object of scopes. The keys are a scope's name, which in the Medusa application would be either `admin` or `store`. The value is an object of configurations for that scope. Each provider accepts different scope configurations as detailed below. - -### emailpass Scope Configurations - - - - - Configuration - Description - Required - Default - - - - - - - `hashConfig` - - - - - An object of configurations to use when hashing the user's - password. Refer to [scrypt-kdf](https://www.npmjs.com/package/scrypt-kdf#-hash)'s - documentation for accepted options. - - - - - No - - - - - ```ts noCopy noReport noLineNumbers - const hashConfig = { - logN: 15, - r: 8, - p: 1 - } - ``` - - - - -
- -### google Scope Configurations - - - -Follow [this Google documentation](https://developers.google.com/identity/protocols/oauth2/web-server#prerequisites) to enable Google's APIs and retrieve the necessary credentials. - - - - - - - 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 - - - - - \- - - - - -
- -### 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= -``` +- `resolve`: A string indicating the package name of the auth provider module or the path to it. +- `options`: An optional object of the auth provider module's options. The object must have the following property: + - `config`: An object whose key is the ID of the auth provider, and its value is an object of options to pass to the provider module. --- @@ -236,3 +60,11 @@ GOOGLE_SUCCESS_REDIRECT_URL= The Medusa application's authentication API routes are defined under the `/auth` prefix that requires setting the `authCors` property of the `http` configuration. So, before using these routes, make sure to set that configuration. Refer to [Medusa's configuration guide](/references/medusa-config#authCors) for more details. + +--- + +## authMethodsPerActor Configuration + +The Medusa application's configuration accept an `authMethodsPerActor` configuration which restricts the allowed auth providers used with an actor type. + +Learn more about the `authMethodsPerActor` configuration in [this guide](../auth-providers/page.mdx#configure-allowed-auth-providers-of-actor-types). \ No newline at end of file diff --git a/www/apps/resources/app/commerce-modules/auth/page.mdx b/www/apps/resources/app/commerce-modules/auth/page.mdx index 8905afdf80..fa9b7175bf 100644 --- a/www/apps/resources/app/commerce-modules/auth/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/page.mdx @@ -26,10 +26,9 @@ const { success, authIdentity, error } = } as AuthenticationInput) if (!success) { + // incorrect authentication details throw new Error(error) } - -// user is authenticated ``` ### Third-Party and Social Authentication diff --git a/www/apps/resources/app/commerce-modules/auth/user-creation/page.mdx b/www/apps/resources/app/commerce-modules/auth/user-creation/page.mdx deleted file mode 100644 index e3c89125bd..0000000000 --- a/www/apps/resources/app/commerce-modules/auth/user-creation/page.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -sidebar_label: "User Creation" ---- - -export const metadata = { - title: `User Creation`, -} - -# {metadata.title} - -In this document, you’ll learn about creating a user with the User Module after authentication. - -## Creating a User using the User Module - -The User Module provides user and invite management functionalities. However, it doesn’t provide authentication functionalities or store any related data. - -By combining the User and Auth Modules, you can use the Auth Module for authenticating users, and the User Module to manage those users. - -So, when a user is authenticated, and you receive the `AuthIdentity` object, you can use it to create a user if it doesn’t exist: - -```ts -const { success, authIdentity } = - await authModuleService.authenticate("emailpass", { - // ... - }) - -// assuming authIdentity is defined -const [, count] = await userModuleService.listAndCount({ - email: authIdentity.entity_id, -}) - -if (!count) { - const user = await userModuleService.create({ - email: authIdentity.entity_id, - }) -} -``` diff --git a/www/apps/resources/app/commerce-modules/customer/register-customer-email/page.mdx b/www/apps/resources/app/commerce-modules/customer/register-customer-email/page.mdx new file mode 100644 index 0000000000..57786bf241 --- /dev/null +++ b/www/apps/resources/app/commerce-modules/customer/register-customer-email/page.mdx @@ -0,0 +1,74 @@ +export const metadata = { + title: `How to Register a Customer with Email and Password`, +} + +# {metadata.title} + +In this guide, you'll learn the steps to register and authenticate a customer. + + + +1. Send a `POST` request to `/auth/customer/emailpass`. +2. Send a request to the [Create Customer API route](!api!/store#customers_postcustomers) passing the token obtained from the first step as a bearer token. +3. Send a `POST` request to `/auth/customer/emailpass` to log-in. + + + +## 1. Obtain Authentication Token + +Before registering and creating the customer, you must create an authentication identity that's associated with that customer. + +To do that, use the `/auth/customer/{provider}` API route, where `{provider}` is the auth provider to use to handle authentication. + + + +Learn more about the `/auth` route in [this document](../../auth/authentication-route/page.mdx) + + + +For example, send a `POST` request to `/auth/customer/emailpass`: + +```bash +curl -X POST 'http://localhost:9000/auth/customer/emailpass' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "email": "customer@gmail.com", + "password": "supersecret" +}' +``` + +--- + +## 2. Register Customer + +Then, use the returned token in the header of the [Create Customer API route](!api!/store#customers_postcustomers): + +```bash +curl -X POST 'http://localhost:9000/store/customers' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer {token}' \ +--data-raw '{ + "email": "customer@gmail.com", + "first_name": "John", + "last_name": "Doe" +}' +``` + +This creates and returns the customer. + +--- + +## 3. Login Customer + +Finally, to log-in the customer, send a `POST` request again to `/auth/customer/emailpass`: + +```bash +curl -X POST 'http://localhost:9000/auth/customer/emailpass' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "email": "customer@gmail.com", + "password": "supersecret" +}' +``` + +You can now use the returned token to send authenticated requests as a customer. diff --git a/www/apps/resources/app/commerce-modules/payment/module-options/page.mdx b/www/apps/resources/app/commerce-modules/payment/module-options/page.mdx index c47234c301..447b551869 100644 --- a/www/apps/resources/app/commerce-modules/payment/module-options/page.mdx +++ b/www/apps/resources/app/commerce-modules/payment/module-options/page.mdx @@ -97,7 +97,7 @@ In this document, you'll learn about the options of the Payment Module. ## providers -The `providers` option is an array of either payment provider modules, payment plugins, or path to a file that holds a payment provider. +The `providers` option is an array of payment provider modules. When the Medusa application starts, these providers are registered and can be used to process payments. diff --git a/www/apps/resources/app/commerce-modules/user/user-creation-flows/page.mdx b/www/apps/resources/app/commerce-modules/user/user-creation-flows/page.mdx index 77c3f41bf6..0778e1af70 100644 --- a/www/apps/resources/app/commerce-modules/user/user-creation-flows/page.mdx +++ b/www/apps/resources/app/commerce-modules/user/user-creation-flows/page.mdx @@ -6,14 +6,6 @@ export const metadata = { This document provides flows to create a user. -## Using the Auth Module - -The Auth Module allows you to create a user with different providers, such as creating a user with an email and password or creating a user using their Google account. - -Learn more about this creation flow in [this Auth Module guide](../../auth/user-creation/page.mdx). - ---- - ## Invite Users Another possible flow to create a user is by sending them an invite. Then, once they accept it, you create a new user for them: @@ -58,4 +50,26 @@ const user = await userModuleService.create({ }) ``` -However, the User Module doesn’t handle authentication methods or store a user’s password. For that, you’d need to use the [Auth Module](../../auth/page.mdx). +### With the Auth Module + +By combining the User and Auth Modules, you can use the Auth Module for authenticating users, and the User Module to manage those users. + +So, when a user is authenticated, and you receive the `AuthIdentity` object, you can use it to create a user if it doesn’t exist: + +```ts +const { success, authIdentity } = + await authModuleService.authenticate("emailpass", { + // ... + }) + +// assuming authIdentity is defined +const [, count] = await userModuleService.listAndCount({ + email: authIdentity.entity_id, +}) + +if (!count) { + const user = await userModuleService.create({ + email: authIdentity.entity_id, + }) +} +``` diff --git a/www/apps/resources/generated/files-map.mjs b/www/apps/resources/generated/files-map.mjs index 7cbdcec1ef..b8763e4fee 100644 --- a/www/apps/resources/generated/files-map.mjs +++ b/www/apps/resources/generated/files-map.mjs @@ -255,10 +255,30 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/commerce-modules/auth/auth-flows/page.mdx", "pathname": "/commerce-modules/auth/auth-flows" }, + { + "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/page.mdx", "pathname": "/commerce-modules/auth/auth-providers" }, + { + "filePath": "/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx", + "pathname": "/commerce-modules/auth/authentication-route" + }, + { + "filePath": "/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx", + "pathname": "/commerce-modules/auth/create-actor-type" + }, { "filePath": "/www/apps/resources/app/commerce-modules/auth/events/_events-table/page.mdx", "pathname": "/commerce-modules/auth/events/_events-table" @@ -279,10 +299,6 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/commerce-modules/auth/page.mdx", "pathname": "/commerce-modules/auth" }, - { - "filePath": "/www/apps/resources/app/commerce-modules/auth/user-creation/page.mdx", - "pathname": "/commerce-modules/auth/user-creation" - }, { "filePath": "/www/apps/resources/app/commerce-modules/cart/concepts/page.mdx", "pathname": "/commerce-modules/cart/concepts" @@ -355,6 +371,10 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/commerce-modules/customer/page.mdx", "pathname": "/commerce-modules/customer" }, + { + "filePath": "/www/apps/resources/app/commerce-modules/customer/register-customer-email/page.mdx", + "pathname": "/commerce-modules/customer/register-customer-email" + }, { "filePath": "/www/apps/resources/app/commerce-modules/customer/relations-to-other-modules/page.mdx", "pathname": "/commerce-modules/customer/relations-to-other-modules" diff --git a/www/apps/resources/generated/sidebar.mjs b/www/apps/resources/generated/sidebar.mjs index 9fac9bdb6d..4cf9971c31 100644 --- a/www/apps/resources/generated/sidebar.mjs +++ b/www/apps/resources/generated/sidebar.mjs @@ -181,6 +181,13 @@ export const generatedSidebar = [ "title": "Auth Module", "hasTitleStyling": true, "children": [ + { + "loaded": true, + "isPathHref": true, + "path": "/commerce-modules/auth/module-options", + "title": "Module Options", + "children": [] + }, { "loaded": true, "isPathHref": true, @@ -193,11 +200,33 @@ export const generatedSidebar = [ "isPathHref": true, "title": "Concepts", "children": [ + { + "loaded": true, + "isPathHref": true, + "path": "/commerce-modules/auth/auth-identity-and-actor-types", + "title": "Identity and Actor Types", + "children": [] + }, { "loaded": true, "isPathHref": true, "path": "/commerce-modules/auth/auth-providers", "title": "Auth Providers", + "children": [ + { + "loaded": true, + "isPathHref": true, + "path": "/commerce-modules/auth/auth-providers/emailpass", + "title": "Emailpass Auth Provider Module", + "children": [] + } + ] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/commerce-modules/auth/authentication-route", + "title": "Authentication Route", "children": [] }, { @@ -206,12 +235,19 @@ export const generatedSidebar = [ "path": "/commerce-modules/auth/auth-flows", "title": "Auth Flows", "children": [] - }, + } + ] + }, + { + "loaded": true, + "isPathHref": true, + "title": "Guides", + "children": [ { "loaded": true, "isPathHref": true, - "path": "/commerce-modules/auth/user-creation", - "title": "User Creation", + "path": "/commerce-modules/auth/create-actor-type", + "title": "Create an Actor Type", "children": [] } ] @@ -994,6 +1030,20 @@ export const generatedSidebar = [ } ] }, + { + "loaded": true, + "isPathHref": true, + "title": "Guides", + "children": [ + { + "loaded": true, + "isPathHref": true, + "path": "/commerce-modules/customer/register-customer-email", + "title": "Register a Customer with Email", + "children": [] + } + ] + }, { "loaded": true, "isPathHref": true, diff --git a/www/apps/resources/sidebar.mjs b/www/apps/resources/sidebar.mjs index b02d915747..2b2db6fe7b 100644 --- a/www/apps/resources/sidebar.mjs +++ b/www/apps/resources/sidebar.mjs @@ -78,6 +78,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([ title: "Auth Module", hasTitleStyling: true, children: [ + { + path: "/commerce-modules/auth/module-options", + title: "Module Options", + }, { path: "/commerce-modules/auth/examples", title: "Examples", @@ -85,17 +89,36 @@ export const sidebar = sidebarAttachHrefCommonOptions([ { title: "Concepts", children: [ + { + path: "/commerce-modules/auth/auth-identity-and-actor-types", + title: "Identity and Actor Types", + }, { path: "/commerce-modules/auth/auth-providers", title: "Auth Providers", + children: [ + { + path: "/commerce-modules/auth/auth-providers/emailpass", + title: "Emailpass Auth Provider Module", + }, + ], + }, + { + path: "/commerce-modules/auth/authentication-route", + title: "Authentication Route", }, { path: "/commerce-modules/auth/auth-flows", title: "Auth Flows", }, + ], + }, + { + title: "Guides", + children: [ { - path: "/commerce-modules/auth/user-creation", - title: "User Creation", + path: "/commerce-modules/auth/create-actor-type", + title: "Create an Actor Type", }, ], }, @@ -287,6 +310,15 @@ export const sidebar = sidebarAttachHrefCommonOptions([ }, ], }, + { + title: "Guides", + children: [ + { + path: "/commerce-modules/customer/register-customer-email", + title: "Register a Customer with Email", + }, + ], + }, { title: "References", children: [