chore: reorganize docs apps (#7228)

* reorganize docs apps

* add README

* fix directory

* add condition for old docs
This commit is contained in:
Shahed Nasser authored and GitHub committed 2024-05-03 17:36:38 +03:00
1 parent 224ebb2154
commit 4fe28f5a95
6187 files changed
+601447 -598226

No files matched your search

@@ -0,0 +1,110 @@
---
sidebar_label: "Authentication Flows"
---
export const metadata = {
title: `Authentication Flows with the Auth Provider`,
}
# {metadata.title}
In this document, you'll learn about how the Auth Provider is used in an authentication flow.
## How to Authenticate a User
To authenticate a user, you use the `authenticate` method of the Auth Module's main service (`IAuthModuleService`). For example:
```ts
const data = await authModuleService.authenticate(
"emailpass",
// passed to auth provider
{
// ...
}
)
```
This method calls the `authenticate` method of the specified provider and returns its data.
<Note>
Learn about the parameters and return type of the `IAuthModuleService`'s `authenticate` method in [this reference](/references/auth/authenticate).
</Note>
---
## Basic Authentication Flow
If the `authenticate` method returns the following object:
```ts
data = {
success: true,
authUser: {
// ...
},
}
```
Then, the user is authenticated successfully, and their authentication details are available within the `authUser` object.
<Note>
Learn more about the `authUser` in [this guide](../persisting-auth-user/page.mdx#what-is-an-authuser).
</Note>
![Diagram showcasing the basic authentication flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1711373749/Medusa%20Resources/basic-auth_lgpqsj.jpg)
---
## Authentication with Third-Party Service Flow
If the `authenticate` method returns the following object:
```ts
data = {
success: true,
location: "https://....",
}
```
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.
![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
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 `IAuthModuleService`. The method calls the specified provider’s `validateCallback` method passing it the authentication details it received in the second parameter:
```ts
const data = await authModuleService.validateCallback(
"google",
// passed to auth provider
{
// ...
}
)
```
<Note>
Learn more about the parameters and return type of the `IAuthModuleService`'s `validateCallback` method in [this reference](/references/auth/validateCallback).
</Note>
If the authentication is successful, the auth provider’s `validateCallback` method returns the same data as the basic authentication:
```ts
data = {
success: true,
authUser: {
// ...
},
}
```
![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)
@@ -0,0 +1,39 @@
export const metadata = {
title: `Auth Providers`,
}
# {metadata.title}
In this document, you’ll learn how the Auth Module handles authentication using providers.
## What's an Auth Provider?
An auth provider is a TypeScript or JavaScript class used to authenticate customers and users. Each provider implements the authentication logic based on its purpose.
For example, the `emailpass` provider authenticates a user using their email and password, whereas the `google` provider authenticates users using their Google account.
---
## The Auth Provider Class
An auth provider implements the `AbstractAuthModuleProvider` class imported from the `@medusajs/utils` package. The provider must implement the `authenticate` method that authenticates a user.
When you call the `authenticate` method of the Auth Module's main service (`IAuthModuleService`), the method resolves the specified provider and calls its `authenticate` method passing it the second parameter it received:
```ts
const data = await authModuleService.authenticate(
"emailpass",
// passed to auth provider
{
// ...
}
)
```
It also returns the same data returned by the auth provider.
<Note>
Learn about the parameters and return type of the `IAuthModuleService`'s `authenticate` method in [this reference](/references/auth/authenticate).
</Note>
@@ -0,0 +1,451 @@
import { CodeTabs, CodeTab } from "docs-ui"
export const metadata = {
title: `Examples of the Auth Module`,
}
# {metadata.title}
In this guide, you’ll find common examples of how you can use the Auth Module in your application.
## Authenticate User
<Note>
This example uses the [jsonwebtoken NPM package](https://www.npmjs.com/package/jsonwebtoken) to create the authentication token.
</Note>
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import {
IAuthModuleService,
AuthenticationInput,
} from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { MedusaError } from "@medusajs/utils"
import jwt from "jsonwebtoken"
export async function POST(
req: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const authModuleService: IAuthModuleService =
req.scope.resolve(ModuleRegistrationName.AUTH)
const { success, authUser, location, error } =
await authModuleService.authenticate("emailpass", {
url: req.url,
headers: req.headers,
query: req.query,
body: req.body,
authScope: "admin",
protocol: req.protocol,
} as AuthenticationInput)
if (!success) {
throw new MedusaError(MedusaError.Types.UNAUTHORIZED, error)
}
if (location) {
res.redirect(location)
return
}
const { jwt_secret } =
req.scope.resolve("configModule").projectConfig
const token = jwt.sign(authUser, jwt_secret)
res.status(200).json({ token })
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import {
initialize as initializeAuthModule,
} from "@medusajs/auth"
export async function POST(request: Request) {
const authModuleService = await initializeAuthModule()
const url = new URL(request.url)
const { success, authUser, location, error } =
await authModuleService.authenticate("emailpass", {
url: request.url,
headers: Object.fromEntries(request.headers),
query: Object.fromEntries(url.searchParams),
body: await request.json(),
authScope: "admin",
protocol: url.protocol,
} as AuthenticationInput)
if (!success) {
throw new Error(error)
}
if (location) {
return NextResponse.redirect(location)
return
}
const token = jwt.sign(authUser, "supersecret")
return NextResponse.json({
token,
}, {
status: 200,
})
}
```
</CodeTab>
</CodeTabs>
---
## Validate Callback
<Note>
This example uses the [jsonwebtoken NPM package](https://www.npmjs.com/package/jsonwebtoken) to create the authentication token.
</Note>
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import {
IAuthModuleService,
AuthenticationInput,
} from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { MedusaError } from "@medusajs/utils"
import jwt from "jsonwebtoken"
export async function POST(
req: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const authModuleService: IAuthModuleService =
req.scope.resolve(ModuleRegistrationName.AUTH)
const { success, authUser, error, successRedirectUrl } =
await authModuleService.validateCallback("google", {
url: req.url,
headers: req.headers,
query: req.query,
body: req.body,
authScope: "admin",
protocol: req.protocol,
} as AuthenticationInput)
if (!success) {
throw new MedusaError(MedusaError.Types.UNAUTHORIZED, error)
}
const { jwt_secret } =
req.scope.resolve("configModule").projectConfig
const token = jwt.sign(authUser, jwt_secret)
if (successRedirectUrl) {
const url = new URL(successRedirectUrl!)
url.searchParams.append("auth_token", token)
return res.redirect(url.toString())
}
res.status(200).json({ token })
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import {
initialize as initializeAuthModule,
} from "@medusajs/auth"
export async function POST(request: Request) {
const authModuleService = await initializeAuthModule()
const url = new URL(request.url)
const { success, authUser, location, error } =
await authModuleService.authenticate("google", {
url: request.url,
headers: Object.fromEntries(request.headers),
query: Object.fromEntries(url.searchParams),
body: await request.json(),
authScope: "admin",
protocol: url.protocol,
} as AuthenticationInput)
if (!success) {
throw new Error(error)
}
const token = jwt.sign(authUser, "supersecret")
if (successRedirectUrl) {
const url = new URL(successRedirectUrl!)
url.searchParams.append("auth_token", token)
return NextResponse.redirect(url.toString())
}
return NextResponse.json({
token,
}, {
status: 200,
})
}
```
</CodeTab>
</CodeTabs>
---
## Create Auth User
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { IAuthModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export async function POST(
req: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const authModuleService: IAuthModuleService =
req.scope.resolve(ModuleRegistrationName.AUTH)
const authUser = await authModuleService.create({
provider: "emailpass",
entity_id: "user@example.com",
scope: "admin",
})
res.json({ auth_user: authUser })
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import {
initialize as initializeAuthModule,
} from "@medusajs/auth"
export async function POST(request: Request) {
const authModuleService = await initializeAuthModule()
const authUser = await authModuleService.create({
provider: "emailpass",
entity_id: "user@example.com",
scope: "admin",
})
return NextResponse.json({
auth_user: authUser,
})
}
```
</CodeTab>
</CodeTabs>
---
## List Auth Users
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { IAuthModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export async function GET(
req: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const authModuleService: IAuthModuleService =
req.scope.resolve(ModuleRegistrationName.AUTH)
res.json({
auth_users: await authModuleService.list(),
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import {
initialize as initializeAuthModule,
} from "@medusajs/auth"
export async function GET(request: Request) {
const authModuleService = await initializeAuthModule()
return NextResponse.json({
auth_users: await authModuleService.list(),
})
}
```
</CodeTab>
</CodeTabs>
---
## Update an Auth User
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { IAuthModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export async function POST(
req: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const authModuleService: IAuthModuleService =
req.scope.resolve(ModuleRegistrationName.AUTH)
const authUser = await authModuleService.update({
id: "authusr_123",
provider_metadata: {
test: true,
},
})
res.json({
auth_user: authUser,
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import {
initialize as initializeAuthModule,
} from "@medusajs/auth"
type ContextType = {
params: {
id: string
}
}
export async function POST(
request: Request,
{ params }: ContextType
) {
const authModuleService = await initializeAuthModule()
const authUser = await authModuleService.update({
id: "authusr_123",
provider_metadata: {
test: true,
},
})
return NextResponse.json({
auth_users: await authModuleService.list(),
})
}
```
</CodeTab>
</CodeTabs>
---
## Delete an Auth User
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { IAuthModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export async function DELETE(
req: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const authModuleService: IAuthModuleService =
req.scope.resolve(ModuleRegistrationName.AUTH)
await authModuleService.delete(["authusr_123"])
res.status(200)
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import {
initialize as initializeAuthModule,
} from "@medusajs/auth"
type ContextType = {
params: {
id: string
}
}
export async function DELETE(
request: Request,
{ params }: ContextType
) {
const authModuleService = await initializeAuthModule()
await authModuleService.delete(["authusr_123"])
}
```
</CodeTab>
</CodeTabs>
---
## More Examples
The [module interface reference](/references/auth) provides a reference to all the methods available for use with examples for each.
@@ -0,0 +1,232 @@
---
sidebar_label: "Module Options"
---
import { Table } from "docs-ui"
export const metadata = {
title: `Auth Module Options`,
}
# {metadata.title}
In this document, you'll learn about the options of the Auth Module.
## providers
```js title="medusa-config.js"
const modules = {
// ...
auth: {
resolve: "@medusajs/auth",
options: {
providers: [
{
name: "emailpass",
scopes: {
store: {},
admin: {},
},
},
{
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.
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
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Configuration</Table.HeaderCell>
<Table.HeaderCell>Description</Table.HeaderCell>
<Table.HeaderCell>Required</Table.HeaderCell>
<Table.HeaderCell>Default</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>
`hashConfig`
</Table.Cell>
<Table.Cell>
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.
</Table.Cell>
<Table.Cell>
No
</Table.Cell>
<Table.Cell>
```ts noCopy noReport noLineNumbers
const hashConfig = {
logN: 15,
r: 8,
p: 1
}
```
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
### google Scope Configurations
<Note type="check">
Follow [this Google documentation](https://developers.google.com/identity/protocols/oauth2/web-server#prerequisites) to enable Google's APIs and retrieve the necessary credentials.
</Note>
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Configuration</Table.HeaderCell>
<Table.HeaderCell>Description</Table.HeaderCell>
<Table.HeaderCell>Required</Table.HeaderCell>
<Table.HeaderCell>Default</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>
`clientID`
</Table.Cell>
<Table.Cell>
A string indicating the [Google API Client ID](https://developers.google.com/identity/oauth2/web/guides/get-google-api-clientid).
</Table.Cell>
<Table.Cell>
Yes
</Table.Cell>
<Table.Cell>
\-
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`clientSecret`
</Table.Cell>
<Table.Cell>
A string indicating the [Google Client Secret](https://support.google.com/cloud/answer/6158849?hl=en#zippy=%2Cstep-create-a-new-client-secret).
</Table.Cell>
<Table.Cell>
Yes
</Table.Cell>
<Table.Cell>
\-
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`callbackURL`
</Table.Cell>
<Table.Cell>
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`.
</Table.Cell>
<Table.Cell>
Yes
</Table.Cell>
<Table.Cell>
\-
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`successRedirectUrl`
</Table.Cell>
<Table.Cell>
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 user.
</Table.Cell>
<Table.Cell>
No
</Table.Cell>
<Table.Cell>
\-
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
### Environment Variables
Make sure to add the necessary environment variables for the above options in `.env`:
```bash
GOOGLE_CLIENT_ID=<YOUR_GOOGLE_CLIENT_ID>
GOOGLE_CLIENT_SECRET=<YOUR_GOOGLE_CLIENT_SECRET>
GOOGLE_CALLBACK_URL=<YOUR_GOOGLE_CALLBACK_URL>
GOOGLE_SUCCESS_REDIRECT_URL=<YOUR_GOOGLE_SUCCESS_REDIRECT_URL>
```
---
## Auth CORS
The Medusa application's authentication API routes are defined under the `/auth` prefix that requires setting the `auth_cors` configuration. So, before using these routes, make sure to set that configuration.
Refer to [Medusa's configuration guide](/references/medusa-config#auth_cors) for more details.
@@ -0,0 +1,159 @@
import { CodeTabs, CodeTab } from "docs-ui"
export const metadata = {
title: `Auth Module`,
}
# {metadata.title}
The Auth Module is the `@medusajs/auth` NPM package that provides authentication-related features in your Medusa and Node.js applications.
---
## Features
### Authenticate Users
With the Auth Module, authenticate users using their credentials.
```ts
const { success, authUser, error } =
await authModuleService.authenticate("emailpass", {
url: req.url,
headers: req.headers,
query: req.query,
body: req.body,
authScope: "admin",
protocol: req.protocol,
} as AuthenticationInput)
if (!success) {
throw new Error(error)
}
// user is authenticated
```
### Third-Party and Social Authentication
The Auth Module supports a variety of authentication methods, such as authenticating with third-party services and social platforms.
```ts
// in authentication API route
const { success, authUser, location } =
await authModuleService.authenticate("google", {
url: req.url,
headers: req.headers,
query: req.query,
body: req.body,
authScope: "admin",
protocol: req.protocol,
} as AuthenticationInput)
if (!authUser && location) {
res.redirect(location)
return
}
// in callback API route
const { success, authUser } =
await authModuleService.validateCallback("google", {
url: req.url,
headers: req.headers,
query: req.query,
body: req.body,
authScope: "admin",
protocol: req.protocol,
} as AuthenticationInput)
```
---
## Configure Auth Module
After installing the `@medusajs/auth` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const modules = {
// ...
auth: {
resolve: "@medusajs/auth",
options: {
providers: [
// ...
],
},
},
}
```
### Module Options
Refer to [this documentation](./module-options/page.mdx) for details on the module's options.
---
## How to Use Auth Module's Service
You can use the Auth Module's main service by resolving from the Medusa container the resource `ModuleRegistrationName.AUTH` imported from `@medusajs/modules-sdk`.
For example:
<CodeTabs groupId="resource-type">
<CodeTab label="API Route" value="api-route">
```ts title="src/api/store/custom/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { IAuthModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export async function GET(
req: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const authModuleService: IAuthModuleService =
req.scope.resolve(ModuleRegistrationName.AUTH)
res.json({
authUsers: authModuleService.list(),
})
}
```
</CodeTab>
<CodeTab label="Subscriber" value="subscribers">
```ts title="src/subscribers/custom-handler.ts"
import { SubscriberArgs } from "@medusajs/medusa"
import { IAuthModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export default async function subscriberHandler({
container,
}: SubscriberArgs) {
const authModuleService: IAuthModuleService =
container.resolve(ModuleRegistrationName.AUTH)
const authUsers = await authModuleService.list()
}
```
</CodeTab>
<CodeTab label="Workflow Step" value="workflow-step">
```ts title="src/workflows/hello-world/step1.ts"
import { createStep } from "@medusajs/workflows-sdk"
import { IAuthModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const authModuleService: IAuthModuleService =
context.container.resolve(
ModuleRegistrationName.AUTH
)
const authUsers = await authModuleService.list()
})
```
</CodeTab>
</CodeTabs>
@@ -0,0 +1,58 @@
---
sidebar_label: "Persisting Auth User"
---
export const metadata = {
title: `Persisting Auth User Authentication`,
}
# {metadata.title}
In this document, you’ll learn what the `AuthUser` is and how to persist its authentication.
## What is an AuthUser?
As explained in the [Auth Provider](../auth-providers/page.mdx) guide, when a user or customer is authenticated, you receive an `authUser` object:
```ts
const { success, authUser } =
await authModuleService.authenticate("emailpass", {
// ...
})
```
The `authUser` object is a record of the `AuthUser` data model. It has details about the authenticated user or customer, such as their ID, email, and other details.
<Note>
Learn more about the `AuthUser`'s fields in [this reference](/references/auth/models/AuthUser).
</Note>
---
## Persisting Authentication
While the Auth Module provides the authentication functionality, it doesn’t provide the functionality to persist the authentication, as that depends on your application’s requirements.
For example, the Medusa application’s authentication route signs the `authUser` object into a JSON Web Token (JWT):
```ts
const {
success,
authUser,
} = await service.authenticate(auth_provider, authData)
// ...
const {
jwt_secret,
} = req.scope.resolve("configModule").projectConfig
const token = jwt.sign(authUser, jwt_secret)
```
Then, the token is passed in the header of subsequent requests in the Authorization Bearer header.
An authentication middleware verifies the token and attaches the associated `authUser`'s details to the `auth` property of the request object passed to the subsequent middlewares and route.
If the authentication middleware can’t verify the token, the user isn’t authenticated and they’re asked to login again.
@@ -0,0 +1,55 @@
---
sidebar_label: "User Creation"
---
export const metadata = {
title: `User Creation with Auth Module`,
}
# {metadata.title}
In this document, you’ll learn about the user-creation flow and how to use it with the User Module.
## Auth User Creation in Authentication Flow
In the [Auth Provider](../auth-providers/page.mdx) documentation, you learned about the authentication flows supported by the Auth Module. These flows are used when an `AuthUser` is already available for the specified authentication data, such as email/password credentials.
However, the `emailpass` and `google` providers support creating an `AuthUser` if none exists. If an email is provided that doesn’t have an `AuthUser` associated with it (checked via its `entity_id` field) for the specified provider (checked via its `provider` field), a new `AuthUser` is created for that email and provider.
![Diagram showcasing the AuthUser creation part of the authentication flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1711441638/Medusa%20Resources/auth-user-creation_gmahvl.jpg)
So, by default, your authentication flow supports both sign-in and sign-up flows.
<Note title="Tip">
This step actually occurs at different points of the authentication flow for each of the providers. For the `emailpass` provider, it occurs before checking that the password is correct. For the `google` provider, you must go through the full authentication flow to retrieve the user details, such as email, from Google.
</Note>
---
## Creating a User in 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 `AuthUser` object, you can use it to create a user if it doesn’t exist:
```ts
const { success, authUser } =
await authModuleService.authenticate("emailpass", {
// ...
})
// assuming authUser is defined
const [, count] = await userModuleService.listAndCount({
email: authUser.entity_id,
})
if (!count) {
const user = await userModuleService.create({
email: authUser.entity_id,
})
}
```