Skip to content

Commit

Permalink
withAuth example (#5612)
Browse files Browse the repository at this point in the history
  • Loading branch information
timleslie committed May 12, 2021
1 parent deb7f95 commit 5606e59
Show file tree
Hide file tree
Showing 9 changed files with 692 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/quick-stingrays-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystone-next/example-next-auth': major
---

Initial version of the `withAuth` example.
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ You can use these as a starting point for general experimentation in a clean env
Each of the examples below demonstrates a particular feature of Keystone.
You can use these projects to learn about, and experiment with specific features.

(coming soon)
* [`withAuth`](./with-auth): Adding password based authentication to your Keystone application.

## Solution Examples

Expand Down
1 change: 1 addition & 0 deletions examples/with-auth/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# @keystone-next/example-with-auth
82 changes: 82 additions & 0 deletions examples/with-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
## Feature Example - Authentication

This project demonstrates how to add password based authentication to your Keystone system.
It builds on the [Task Manager](../todo) starter project.

## Instructions

To run this project, clone the Keystone repository locally then navigate to this directory and run:

```shell
yarn dev
```

This will start the Admin UI at [localhost:3000](http://localhost:3000).
You can use the Admin UI to create items in your database.

You can also access a GraphQL Playground at [localhost:3000/api/graphql](http://localhost:3000/api/graphql), which allows you to directly run GraphQL queries and mutations.

## Features

This project demonstrates how to add authentication to a Keystone system.
We're going to use the [`@keystone-next/auth`](https://next.keystonejs.com/apis/auth) package, along with Keystone's [session management API](https://next.keystonejs.com/apis/session), to add the following features to the base system:

* Configure which fields to use for signin
* Set up stateless session handling to keep track of the signed in user
* Add a signin screen to the Admin UI
* Add a signout button to the Admin UI
* Allow the signed in user to access their own details in the Admin UI
* Add a helper page to the Admin UI to allow you to create your first user when starting from an empty database

### Added fields

In this example we add two new fields, `email` and `password`, to the `Person` list.
These are used as our _identity_ and _secret_ fields for login.

```typescript
email: text({ isRequired: true, isUnique: true }),
password: password({ isRequired: true }),
```

### Auth config

We use the `createAuth` function from `@keystone-next/auth` to configure a `withAuth` config wrapper, which will inject all the extra config used to enabled configuration.

```typescript
import { createAuth } from '@keystone-next/auth';

const { withAuth } = createAuth({
listKey: 'Person',
identityField: 'email',
secretField: 'password',
initFirstItem: { fields: ['name', 'email', 'password'] },
});
```

### Session

We use a basic `statelessSessions` from `@keystone-next/keystone/session` for session handling.
You need to have sessions enabled in order to use the `withAuth` config wrapper.

```typescript
import { statelessSessions } from '@keystone-next/keystone/session';

const session = statelessSessions({ secret: '-- EXAMPLE COOKIE SECRET; CHANGE ME --' });
```

### Wrapped config

We wrap our config using the `withAuth` function, which injects added Admin UI configuration, as well as the GraphQL queries and mutations for authentication.

```typescript
export default withAuth(
config({
db: {
provider: 'sqlite',
url: process.env.DATABASE_URL || 'file:./keystone-example.db',
},
lists,
session,
})
);
```
45 changes: 45 additions & 0 deletions examples/with-auth/keystone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { config } from '@keystone-next/keystone/schema';
import { statelessSessions } from '@keystone-next/keystone/session';
import { createAuth } from '@keystone-next/auth';
import { lists } from './schema';

// createAuth configures signin functionality based on the config below. Note this only implements
// authentication, i.e signing in as an item using identity and secret fields in a list. Session
// management and access control are controlled independently in the main keystone config.
const { withAuth } = createAuth({
// This is the list that contains items people can sign in as
listKey: 'Person',
// The identity field is typically a username or email address
identityField: 'email',
// The secret field must be a password type field
secretField: 'password',

// initFirstItem turns on the "First User" experience, which prompts you to create a new user
// when there are no items in the list yet
initFirstItem: {
// These fields are collected in the "Create First User" form
fields: ['name', 'email', 'password'],
},
});

// Stateless sessions will store the listKey and itemId of the signed-in user in a cookie.
// This session object will be made availble on the context object used in hooks, access-control,
// resolvers, etc.
const session = statelessSessions({
// The session secret is used to encrypt cookie data (should be an environment variable)
secret: '-- EXAMPLE COOKIE SECRET; CHANGE ME --',
});

// We wrap our config using the withAuth function. This will inject all
// the extra config required to add support for authentication in our system.
export default withAuth(
config({
db: {
provider: 'sqlite',
url: process.env.DATABASE_URL || 'file:./keystone-example.db',
},
lists,
// We add our session configuration to the system here.
session,
})
);
23 changes: 23 additions & 0 deletions examples/with-auth/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "@keystone-next/example-with-auth",
"version": "0.0.0",
"private": true,
"license": "MIT",
"scripts": {
"dev": "keystone-next dev",
"start": "keystone-next start",
"build": "keystone-next build"
},
"dependencies": {
"@keystone-next/auth": "^23.0.0",
"@keystone-next/fields": "^8.0.0",
"@keystone-next/keystone": "^17.0.0"
},
"devDependencies": {
"typescript": "^4.2.4"
},
"engines": {
"node": ">=v12.13.1"
},
"repository": "https://github.com/keystonejs/keystone/tree/master/examples/with-auth"
}
Loading

1 comment on commit 5606e59

@vercel
Copy link

@vercel vercel bot commented on 5606e59 May 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.