Authentication
Keystone allows you to extend your Keystone system to support authentication against a password
field using the createAuth()
function in the @keystone-6/auth
package. Additional options to this function provide support for creating an initial item in your database, sending password reset tokens, and sending one-time authentication tokens.
For examples of how to use authentication in your system please see the authentication guide.
import { config, list } from '@keystone-6/core'import { text, password, checkbox } from '@keystone-6/core/fields'import { createAuth } from '@keystone-6/auth'const { withAuth } = createAuth({// Required optionslistKey: 'User',identityField: 'email',secretField: 'password',// Additional optionssessionData: 'id name email',initFirstItem: {fields: ['email', 'password'],itemData: { isAdmin: true },skipKeystoneWelcome: false,},})export default withAuth(config({lists: {User: list({fields: {email: text({ isIndexed: 'unique' }),password: password(),isAdmin: checkbox(),},}),session: { /* ... */ },},}))
The function createAuth
returns a function withAuth
which should be used to wrap your config()
. This wrapper function will modify the config object to inject extra fields, extra GraphQL queries and mutations, and custom Admin UI functionality into the system. The createAuth
function must be used in conjunction with a session configuration.
Required options
The core functionality of the authentication system provides a GraphQL mutation to authenticate a user and then start a session, and a sign in page in the Admin UI.
listKey
: The name of the list to authenticate against.identityField
: The name of the field to use as an identity field. This field must have{ isIndexed: 'unique' }
set.secretField
: The name of the field to use as a secret. This field must be apassword()
field type.
import { createAuth } from '@keystone-6/auth'const { withAuth } = createAuth({listKey: 'User',identityField: 'email',secretField: 'password',})
GraphQL API
The following elements will be added to the GraphQL API.
type Mutation {authenticateUserWithPassword(email: String!, password: String!): UserAuthenticationWithPasswordResult!endSession: Boolean!}type Query {authenticatedItem: AuthenticatedItem}union AuthenticatedItem = Userunion UserAuthenticationWithPasswordResult = UserAuthenticationWithPasswordSuccess | UserAuthenticationWithPasswordFailuretype UserAuthenticationWithPasswordSuccess {sessionToken: String!item: User!}type UserAuthenticationWithPasswordFailure {message: String!}
authenticateUserWithPassword
This mutation will check the supplied credentials and start a new session if the credentials are valid. The argument names for this function are the values of identityField
and secretField
.
mutation {authenticateUserWithPassword(email: "username@example.com",password: "password") {... on UserAuthenticationWithPasswordSuccess {item {id}}... on UserAuthenticationWithPasswordFailure {message}}}
On success the session handler will start a new session and return the encoded session cookie data as sessionToken
. The authenticated item will be returned as item
.
On failure the values { code: FAILURE, message: "Authentication failed." }
will be returned.
authenticatedItem
This query will return the currently logged in user, based on the session
data.
Admin UI
A sign in page at the path /signin
will be added to the Admin UI. If a user tries to access the Admin UI without having logged in they will be redirected back to /signin
. This page uses the authenticateUserWithPassword
mutation to let users sign in to the Admin UI.
Additional options
The following options add extra functionality to your Keystone authentication system. By default they are disabled.
sessionData
This option adds support for setting a custom session.data
value based on the authenticated user.
The authentication mutations will set the values { listKey, itemId }
on the context.session
object. You will often need to know more than just the itemId
of the authenticated user, such as when performing access-control or using hooks. Configuring sessionData
will add an session.data
based on the itemId
, populated by the fields given in sessionData.query
.
The value is a GraphQL query string which indicates which fields should be populated on the session.data
object
import { createAuth } from '@keystone-6/auth'const { withAuth } = createAuth({listKey: 'User',identityField: 'email',secretField: 'password',sessionData: 'id name isAdmin',})
initFirstItem
This option adds support for bootstrapping the first user into the system via the Admin UI. If this option is enabled and there are no users in the system, the Admin UI will present a form to create an initial user in the system. Once the user is created, they will be presented with a Keystone Welcome screen, and prompted to sign up to the Keystone mailing list to receive updates about the project.
Options
fields
(required): A list of fields to include in the initial user form.itemData
(default:{}
): An object containing extra data to add to the initial user.skipKeystoneWelcome
(default:false
): A flag to skip display of the Keystone Welcome screen.
import { createAuth } from '@keystone-6/auth';const { withAuth } = createAuth({listKey: 'User',identityField: 'email',secretField: 'password',initFirstItem: {fields: ['email', 'password'],itemData: { isAdmin: true },skipKeystoneWelcome: false,},});
GraphQL API
Enabling initFirstItem
will add the following elements to the GraphQL API.
type Mutation {createInitialUser(data: CreateInitialUserInput!): UserAuthenticationWithPasswordSuccess!}input CreateInitialUserInput {name: Stringemail: Stringpassword: String}
createInitialUser
This mutation will create a new user in the system. If a user already exists an error will be returned. The available input fields are based on the fields
options. This mutation is used by the Admin UI's initial user screen and should generally not be called directly.
Admin UI
The initial user screen is added at /init
, and users are redirected here if there is no active session and no users in the system.