chore: reorganize docs apps (#7228)
* reorganize docs apps * add README * fix directory * add condition for old docs
This commit is contained in:
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>
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 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.
|
||||
|
||||

|
||||
|
||||
### 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: {
|
||||
// ...
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
@@ -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.
|
||||
|
||||

|
||||
|
||||
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,
|
||||
})
|
||||
}
|
||||
```
|
||||
Reference in new issue
Block a user