npm package: @skimia/issuer
Description: ## Quickstart
Latest version: 0.1.8

# Skimia Issuer (JWT)

## Quickstart

```bash
yarn add @skimia/issuer @skimia/issuer-local
# or
npm install --save @skimia/issuer @skimia/issuer-local
```

Run!

```javascript
// index.js
// imports
const appConstructor = require('@skimia/issuer')
const localStore = require('@skimia/issuer-local')

// construct
const app = appConstructor({
  jwt: {
    basePath: [__dirname, 'files'],
  },
  imports: [localIssuer([__dirname, 'users.json'])],
})

// run

app.then(application => {
  application.listen(4000, () => {
    console.log('Server ready at http://localhost:4000/graphql')
  })
})
```

you can now use [GraphQL playground](http://localhost:4000/graphql)

## What is Skimia Issuer

**Skimia Issuer** is a `@skimia/modules (graphql-modules)` based library which helps you to not reinvent the wheel when you need an authentication layer for your application.

It help you to create an Authentication Microservice with all neede features

## Features

- Issue a JWT
- GraphQL API
- Support `Json Web Key Store` standard (you can use `jwks-rsa`)
- Extendable with `@skimia/module`
- Intended to support various storage layers and complementary features with modules.

## Constructor Options

```javascript
const appConstructor = require('@skimia/issuer')

appConstructor(options)
```

### `options.[before|after]Middlewares` Additional Koa middlewares

the appConstructor create a koa application, order of middlewares:

1. A middleware to provide `injector` in koa `ctx`
1. `before` middlewares (`beforeMiddlewares[]`)
1. A middleware to use graphql (`ApolloServer.applyMiddleware()` from `apollo-server-koa`)
1. `after` middlewares (`afterMiddlewares[]`)
1. All other middlewares from `http` hooks

this option is for adding middlewares before or after graphql middleware

### `options.jwt` JWT options

- `basePath (string) = './config'` : directory for find "file" options

all Other variables are resolved using `@skimia/config` see [Documentation](...)

- `algorithm (string) = 'RS256'` : jwt algorithm
- `issuer (string) = '@skimia/issuer'` : jwt issuer
- `audience (string) = '@skimia'` : jwt audience
- `expiresIn (string) = '1d'` : jwt token expiration delay [zeit/ms](https://github.com/zeit/ms) compatible string
- `privateKey (file) = './private.pem'` : load from `basePath` the file if you prefer using the content set `privateKeyContent`
- `publicKey (file) = './public.pem'` : load from `basePath` the file if you prefer using the content set `publicKeyContent`
- `jwtKeyId (file) = './public.pem.id'` : load from `basePath` the file if you prefer using the content set `jwtKeyIdContent`

### `options.imports` Skimia Modules additional imports

array of modules needed by your application

### `options.apollo` Apollo Server options

Options passed to `ApolloServer`, see [Apollo server docs](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#parameters)

## Hooks

an hook is simply a middleware chain (same as koa or express)

Hooks are segregated in 3 types:

- **[C]** Check Hook: with this hook type you can only throw an Error in order to control if an action can terminate or not, **ctx and returned value are not used by the caller** , **next() call is mandatory**

- **[U]** Update Hook: Same as Check only but caller can use the muted context **next() call is mandatory**

- **[R]** Return Hook: The caller use the returned value

for all types you can throw an Error to stop execution
for all hooks bellow the **[BA]** mention indicate a before & after Check hook, with same params (+ the return value or updated value)

ex: **[R,BA]** 3 Hooks => `auth.find`, `auth.find.before`, `auth.find.after`

### Login Process

#### **[R,BA]** `auth.find`

this hook use all sources to found user with criterion

##### Context

- `criteria` (object of string): user provided criteria
- `user` (string): **[After Only]** user found

##### Return

User (object)

#### **[C,BA]** `auth.login.verify`

throw an exception if the provided user cannot connect

##### Context

- `identifier` (string): user provided identifier
- `password` (string): user provided password
- `user` (object): user found by `auth.find` hook

#### **[U,BA]** `auth.login.clean`

##### Context

- `user` (object): mutate user to remove fields ex `password`
- `userCleaned` (string): **[After Only]** user cleaned

### Register Process

#### **[U,BA]** `auth.register.defaults`

##### Context

- `user` (object): user to create with at least `identifier` && `password` fields (mutate `ctx.user` to add custom fields)
- `userUpdated` (string): **[After Only]** user after transformations

##### Note

an hook (weight: -inf) encrypt user `password` field if provided && add `id` (uuid/v4) field if user have not if you dont want this behavior dont call next and return in a hook with more than -inf weight

#### **[R,BA]** `auth.register.save`

##### Context

- `user` (object, readonly): user to create in store
- `userCreated` (string): **[After Only]** user after saved

##### Return

User (object) if user is stored successfully

### Other Hooks

#### **[R,BA]** `auth.update`

this hook use all sources to found user with criterion

##### Context

- `criteria` (object of string): user provided criteria
- `update` (object, readonly): fields to update in store
- `userUpdated` (string): **[After Only]** user after saved

##### Note

in update object, undefined values are considered to removing filed on found user (remove key)

##### Return

User (object) if user is stored successfully