> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/medusajs/medusa/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Learn how to authenticate requests to the Medusa API using JWT tokens, API keys, and session management.

## Overview

Medusa supports multiple authentication methods depending on the API and use case:

* **JWT Authentication**: For admin users and store customers
* **API Keys**: For server-to-server admin operations
* **Session Management**: For maintaining authenticated state

## Admin Authentication

### JWT Token Authentication

Admin users authenticate using JWT tokens obtained through the auth endpoints.

#### Step 1: Authenticate

Obtain a JWT token by authenticating with email and password:

```bash theme={null}
curl -X POST http://localhost:9000/auth/user/emailpass \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@example.com",
    "password": "supersecret"
  }'
```

Response:

```json theme={null}
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

<ResponseField name="token" type="string">
  The JWT token to use for authenticated requests.
</ResponseField>

#### Step 2: Make Authenticated Requests

Include the JWT token in the `Authorization` header:

```bash theme={null}
curl -X GET http://localhost:9000/admin/products \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

### API Key Authentication

API keys provide a secure way for server-to-server communication with the Admin API.

#### Creating an API Key

Create an API key through the Admin API:

```bash theme={null}
curl -X POST http://localhost:9000/admin/api-keys \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Integration API Key",
    "type": "secret"
  }'
```

<ParamField body="title" type="string" required>
  A descriptive name for the API key.
</ParamField>

<ParamField body="type" type="string" required>
  The type of API key. Use `"secret"` for server-to-server authentication.
</ParamField>

Response:

```json theme={null}
{
  "api_key": {
    "id": "apk_123",
    "token": "sk_...",
    "title": "Integration API Key",
    "type": "secret",
    "created_at": "2024-03-03T10:00:00.000Z"
  }
}
```

<Warning>
  The API key token is only shown once. Store it securely and never expose it in client-side code.
</Warning>

#### Using API Keys

Include the API key in the `x-medusa-access-token` header:

```bash theme={null}
curl -X GET http://localhost:9000/admin/products \
  -H "x-medusa-access-token: sk_..."
```

Or use it as a query parameter:

```bash theme={null}
curl -X GET "http://localhost:9000/admin/products?api_token=sk_..."
```

<Note>
  Header-based authentication is recommended for better security.
</Note>

#### Revoking API Keys

Revoke an API key when it's no longer needed:

```bash theme={null}
curl -X POST http://localhost:9000/admin/api-keys/{id}/revoke \
  -H "Authorization: Bearer {jwt_token}"
```

Source: `packages/medusa/src/api/admin/api-keys/[id]/revoke/route.ts`

## Store Authentication

### Customer Authentication

Store customers authenticate using JWT tokens.

#### Step 1: Register a Customer

Create a new customer account:

```bash theme={null}
curl -X POST http://localhost:9000/store/customers \
  -H "Content-Type: application/json" \
  -d '{
    "email": "customer@example.com",
    "password": "password123",
    "first_name": "John",
    "last_name": "Doe"
  }'
```

<ParamField body="email" type="string" required>
  The customer's email address.
</ParamField>

<ParamField body="password" type="string" required>
  The customer's password.
</ParamField>

<ParamField body="first_name" type="string">
  The customer's first name.
</ParamField>

<ParamField body="last_name" type="string">
  The customer's last name.
</ParamField>

Source: `packages/medusa/src/api/store/customers/route.ts:11`

#### Step 2: Authenticate

Obtain a JWT token:

```bash theme={null}
curl -X POST http://localhost:9000/auth/customer/emailpass \
  -H "Content-Type: application/json" \
  -d '{
    "email": "customer@example.com",
    "password": "password123"
  }'
```

Response:

```json theme={null}
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

#### Step 3: Make Authenticated Requests

Include the JWT token in authenticated store requests:

```bash theme={null}
curl -X GET http://localhost:9000/store/customers/me \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

## Session Management

### Session Context

Authenticated requests automatically create and maintain session context through the `req.auth_context` object:

```typescript theme={null}
req.auth_context = {
  actor_id: "user_123",           // The authenticated user/customer ID
  auth_identity_id: "authid_456", // The auth identity ID
  app_metadata: {}                // Additional metadata
}
```

Source: `packages/medusa/src/api/admin/customers/route.ts:53`

### Token Expiration

JWT tokens have an expiration time. When a token expires, clients must re-authenticate to obtain a new token.

### Logout

To logout, clients should discard the JWT token. Server-side session invalidation may be implemented through custom middleware.

## Security Best Practices

<AccordionGroup>
  <Accordion title="Secure Token Storage">
    * Store JWT tokens securely (e.g., httpOnly cookies, secure storage)
    * Never expose API keys in client-side code
    * Use environment variables for API keys in server environments
  </Accordion>

  <Accordion title="Token Rotation">
    * Implement token refresh mechanisms for long-lived sessions
    * Rotate API keys periodically
    * Revoke unused or compromised API keys immediately
  </Accordion>

  <Accordion title="HTTPS Only">
    * Always use HTTPS in production to prevent token interception
    * Configure secure cookie flags when using session cookies
  </Accordion>

  <Accordion title="Scope Limitations">
    * Create separate API keys for different integrations
    * Use role-based access control (RBAC) to limit permissions
    * Assign API keys to specific sales channels when applicable
  </Accordion>
</AccordionGroup>

## Error Handling

### Unauthorized (401)

Returned when authentication is required but not provided:

```json theme={null}
{
  "type": "unauthorized",
  "message": "Authentication required"
}
```

### Forbidden (403)

Returned when the authenticated user lacks permissions:

```json theme={null}
{
  "type": "not_allowed",
  "message": "Insufficient permissions"
}
```

### Invalid Credentials

Returned when authentication credentials are incorrect:

```json theme={null}
{
  "type": "invalid_data",
  "message": "Invalid email or password"
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Admin API" icon="shield" href="/api/admin/products">
    Start using the Admin API
  </Card>

  <Card title="Store API" icon="store" href="/api/store/products">
    Build your storefront with the Store API
  </Card>
</CardGroup>
