# Authentication

> Learn to implement the three authentication modes.

There are three authentication modes in Directus Realtime.

<table>
<thead>
  <tr>
    <th>
      Mode
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <strong>
        <code>
          public
        </code>
      </strong>
    </td>
    
    <td>
      No authentication is required.
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        <code>
          handshake
        </code>
      </strong>
    </td>
    
    <td>
      No authentication required to connect. First message must be an authentication request sent before the timeout.
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        <code>
          strict
        </code>
      </strong>
    </td>
    
    <td>
      Authentication is required as a URL parameter on the initial connection.
    </td>
  </tr>
</tbody>
</table>

`handshake` is the default authentication mode.

## Changing Authentication Modes

You can only use one authentication mode at a time in a single project.

If self-hosting your project, you can set authentication modes by setting the `WEBSOCKETS_REST_AUTH`, `WEBSOCKETS_GRAPHQL_AUTH` and `WEBSOCKETS_LOGS_AUTH` environment variables to one of these modes. By default, they are set to the `handshake` mode.

## Public Mode

### Websockets

You do not need to authenticate if using a public authentication mode, but you are limited to the public role exclusively.

In order to change roles, follow the flow for the `handshake` authentication mode.

### GraphQL

```js
import { createClient } from "graphql-ws";

const client = createClient({
    url: "ws://your-directus-url/graphql",
    keepAlive: 30000,
});
```

## Handshake Mode

### Websockets

Your first message must include authentication details and be sent before the timeout. There are three options:

**Access Token**

```json
{
    "type": "auth",
    "access_token": "your-access-token"
}
```

**Email and Password**

```json
{
    "type": "auth",
    "email": "user@email.com",
    "password": "your-password"
}
```

**Refresh Token**

```json
{
    "type": "auth",
    "refresh_token": "token"
}
```

On successful authentication you’ll receive a confirmation message. This message includes a `refresh_token` when using
email/password and refresh_token credentials.

```json
{
    "type": "auth",
    "status": "ok",
    "refresh_token": "a-token-to-use-later"
}
```

When the client receives an auth expired error, a new authentication request is expected within the set timeout or the
connection will be closed.

### GraphQL

```js
import { createClient } from "graphql-ws";

const client = createClient({
    url: "ws://your-directus-url/graphql",
    keepAlive: 30000,
    connectionParams: async () => {
        return { access_token: "MY_TOKEN" };
    },
});
```

## Strict Mode

### Websockets

When initially opening your connection, add a `access_token` query parameter to your request.

Once initially authenticated, all 3 authentication are available.

GraphQL puts more responsibility on the client for handling the re-authentication flow and has no supported way for us
to implement it without breaking compatibility with existing clients. Because of this, you may only use an
`access_token` for authentication at this time.

When a token expires, the connection will be closed with a `Forbidden` message, signaling to the client to refresh their
`access_token` and reconnect.

### GraphQL

```js
import { createClient } from "graphql-ws";

const client = createClient({
    url: "ws://your-directus-url/graphql?access_token=your-access-token",
    keepAlive: 30000,
});
```

## Authentication with GraphQL

GraphQL puts more responsibility on the client for handling the re-authentication flow and has no supported way for us
to implement it without breaking compatibility with existing clients. Because of this, you may only use an
`access_token` for authentication at this time.

When a token expires, the connection will be closed with a `Forbidden` message, signaling to the client to refresh their
`access_token` and reconnect.
