# Custom Strategies

Source: https://payloadcms.com/docs/beta/authentication/custom-strategies

> **Warning**
>
> This is an advanced feature, so only attempt this if you are an experienced
> developer. Otherwise, just let Payload's built-in authentication handle user
> auth for you.
>
> **Development Note:** Changes to custom authentication strategies require a full server restart to take effect. Auth strategies are not hot-reloaded during development. Consider using tools like `nodemon` for auto-restart functionality.

### Creating a strategy

At the core, a strategy is a way to authenticate a user making a request. As of `3.0` we moved away from [Passport](https://www.passportjs.org) in favor of pulling back the curtain and putting you in full control.

A strategy is made up of the following:

| Parameter             | Description                                                               |
| --------------------- | ------------------------------------------------------------------------- |
| **`name`** \*         | The name of your strategy                                                 |
| **`authenticate`** \* | A function that takes in the parameters below and returns a user or null. |

The `authenticate` function is passed the following arguments:

| Argument               | Description                                                                                                         |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------- |
| **`canSetHeaders`** \* | Whether or not the strategy is being executed from a context where response headers can be set. Default is `false`. |
| **`headers`** \*       | The headers on the incoming request. Useful for retrieving identifiable information on a request.                   |
| **`payload`** \*       | The Payload class. Useful for authenticating the identifiable information against Payload.                          |
| **`isGraphQL`**        | Whether or not the strategy is being executed within the GraphQL endpoint. Default is `false`.                      |
| **`req`**              | The request that initiated authentication, when available.                                                          |

### Example Strategy

At its core a strategy simply takes information from the incoming request and returns a user. This is exactly how Payload's built-in strategies function.

The example below sets `disableLocalStrategy` to `true` because the custom strategy replaces local authentication. Set it to `false` or omit it to keep email and password authentication enabled alongside your custom strategy.

Your `authenticate` method should return an object containing a Payload user document and any optional headers that you'd like Payload to set for you when we return a response.

```ts
import type { CollectionConfig } from 'payload'

export const Users: CollectionConfig = {
  slug: 'users',
  auth: {
    disableLocalStrategy: true,
    // highlight-start
    strategies: [
      {
        name: 'custom-strategy',
        authenticate: async ({ payload, headers }) => {
          const usersQuery = await payload.find({
            collection: 'users',
            overrideAccess: true,
            where: {
              code: {
                equals: headers.get('code'),
              },
              secret: {
                equals: headers.get('secret'),
              },
            },
          })

          return {
            // Send the user with the collection slug back to authenticate,
            // or send null if no user should be authenticated
            user: usersQuery.docs[0]
              ? {
                  collection: 'users',
                  ...usersQuery.docs[0],
                }
              : null,

            // Optionally, you can return headers
            // that you'd like Payload to set here when
            // it returns the response
            responseHeaders: new Headers({
              'some-header': 'my header value',
            }),
          }
        },
      },
    ],
    // highlight-end
  },
  fields: [
    {
      name: 'code',
      type: 'text',
      index: true,
      unique: true,
    },
    {
      name: 'secret',
      type: 'text',
    },
  ],
}
```
