# Email Login

> Learn about user registration, login with standard/session tokens, refresh, logout, and resetting passwords.

It is most common to authenticate users with an email and password either receiving and storing a standard token or using a session token cookie.

<callout color="primary" icon="i-lucide-book-open" to="/guides/auth/tokens-cookies">

Read more about tokens in Directus.

</callout>

## Registration

Before being able to log in, a user with an `email` and `password` must exist. This user can be created manually in the Data Studio, via an invite, or via the [Users API](/api/users).

<callout color="primary" icon="i-lucide-book-open" to="/guides/auth/creating-users">

Read more about creating users.

</callout>

## Login

You can authenticate as a user to receive a standard token.

## Logging In

<code-group>

```bash [Terminal]
curl \
    --request POST \
    --header 'Content-Type: application/json' \
    --data '{ "email": "hello@example.com", "password": "d1r3ctu5" }' \
    --url 'https://directus.example.com/auth/login'
```

```graphql [GraphQL]
mutation {
    auth_login(email: "hello@example.com", password: "d1r3ctu5") {
        access_token
        refresh_token
    }
}
```

```js [SDK]
import { createDirectus, authentication } from '@directus/sdk';

const email = "hello@example.com";
const password = "d1r3ctu5";

const client = createDirectus('http://directus.example.com').with(authentication());

const token = await client.login({ email, password });
```

</code-group>

If the user has [two-factor authentication](/guides/auth/2fa) enabled, an `otp` (one-time password) can be passed as an additional property. The response will contain a standard token.

<partial content="snippet-auth-token">



</partial>

### Setting a Cookie

If you wish to receive and store a session cookie, add a `mode` property when logging in.

<code-group>

```json [REST]
// POST /auth/login

{
  "email": "hello@example.com",
  "password": "d1r3ctu5",
  "mode": "session"
}

// The token won't be returned in JSON response.
```

```graphql [GraphQL]
mutation {
    auth_login(email: "hello@example.com", password: "d1r3ctu5", mode: "session") {
        access_token
        refresh_token
    }
}
```

```js [SDK]
import { createDirectus, authentication } from '@directus/sdk';

const email = "hello@example.com";
const password = "d1r3ctu5";

const client = createDirectus('http://directus.example.com').with(authentication());

const token = await client.login({ email, password }, { mode: "session" });
```

</code-group>

## Refresh

Retrieve a new access token by refreshing it. The refresh token will be returned in the JSON response or in a `httpOnly` cookie if [the `mode` parameter is set to `json` or `cookie`, respectively](/api/authentication).

<code-group>

```json [REST]
// POST /auth/refresh

{
  "refresh_token": "Xp2tTNAdLYfnaAOOjt3oetyCWtobKKUIeEXj..."
}
```

```graphql [GraphQL]
mutation {
    auth_refresh(refresh_token: "refresh_token") {
        access_token
        refresh_token
    }
}
```

```js [SDK]
import { createDirectus, authentication, rest, refresh } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(authentication()).with(rest());

// refresh http request using json
const result = await client.request(refresh({ mode: 'json', refresh_token }));
```

</code-group>

### Refreshing a Cookie

You do not need to provide the `refresh_token`, but you must specify the `mode`.

<code-group>

```json [REST]
// POST /auth/refresh

{
  "mode": "session"
}
```

```graphql [GraphQL]
mutation {
    auth_refresh(refresh_token: "refresh_token") {
        access_token
        refresh_token
    }
}
```

```js [SDK]
import { createDirectus, authentication, rest, refresh } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(authentication()).with(rest());

// refresh http request using a cookie
const result = await client.request(refresh({ mode: 'cookie' }));
```

</code-group>

## Logout

Invalidate the refresh token and destroy the user's session.

<code-group>

```json [REST]
// POST /auth/logout
{
  "refresh_token": "Xp2tTNAdLYfnaAOOjt3oetyCWtobKKUIeEXj..."
}
```

```graphql [GraphQL]
mutation {
    auth_logout(refresh_token: "Xp2tTNAdLYfnaAOOjt3oetyCWtobKKUIeEXj...")
}
```

```js [SDK]
import { createDirectus, authentication, rest, logout } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(authentication()).with(rest());

const result = await client.logout();
```

</code-group>

You can also log out using the http request mechanism:

```js
import { createDirectus, authentication, rest, logout } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(authentication()).with(rest());

const result = await client.request(logout({ refresh_token }));
```

### Invalidating a Cookie

You do not need to provide the `refresh_token`, but you must specify the `mode`. This will immediately invalidate and delete the cookie.

<code-group>

```json [REST]
// POST /auth/refresh

{
  "mode": "session"
}
```

```graphql [GraphQL]
mutation {
    auth_logout(mode: "session")
}
```

```js [SDK]
import { createDirectus, authentication, rest, logout } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(authentication()).with(rest());

const result = await client.logout({ mode: "session" });
```

</code-group>

## Password Reset

Requesting a password reset will send an email to the user with a URL to the Data Studio to reset their password. Password reset is only available for users using the default authentication provider. Users authenticated through external providers (OAuth, SAML, LDAP, etc.) will not receive a reset email.

```json [REST]
// POST /auth/password/request

{
  "email": "hello@example.com"
}
```

<callout color="primary" icon="i-lucide-book-open" to="/configuration/email">

An email service must be configured to send password reset requests.

</callout>

### Seamless Password Reset

You can use the password reset system within your own application ensuring users do not need to access the Data Studio.

When using the request reset password endpoint, add a `reset_url` property. The email will use this URL instead of your Directus project, appending the reset token in the URL as a `token` parameter.

Your application must extract this value, collect the new user's password, and send both to the reset password endpoint.

<code-group>

```json [REST]
// POST /auth/password/reset
{
  "token": "Xp2tTNAdLYfnaAOOjt3oetyCWtobKKUIeEXj",
  "password": "d1r3ctu5!"
}
```

```graphql [GraphQL]
mutation {
    auth_password_reset(token: "Xp2tTNAdLYfnaAOOjt3oetyCWtobKKUIeEXj", password: "d1r3ctu5!")
}
```

```js [SDK]
import { createDirectus, rest, passwordReset } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const reset_token = "Xp2tTNAdLYfnaAOOjt3oetyCWtobKKUIeEXj";
const new_password = "d1r3ctu5!";

const result = await client.request(passwordReset(reset_token, new_password));
```

</code-group>

<callout color="primary" icon="i-lucide-book-open" to="/configuration/security-limits">

The `PASSWORD_RESET_URL_ALLOW_LIST` environment variable must be configured.

</callout>
