2020-12-03 09:54:27 +01:00
# auth-server-helper
2020-03-06 12:06:10 +01:00
2022-08-08 15:52:56 +02:00
version: 3.3.x
2020-05-17 17:37:41 +02:00
2021-01-05 16:50:23 +01:00
customizable and simple authentication
2020-05-17 17:37:41 +02:00
## Installation
npm:
2020-12-03 09:54:27 +01:00
> npm i --save auth-server-helper
2020-05-17 17:37:41 +02:00
yarn:
2020-12-03 09:54:27 +01:00
> yarn add auth-server-helper
2020-03-06 12:06:10 +01:00
## Usage
2021-01-05 16:50:23 +01:00
### 1. put a gateway in front of the routes you want to secure
```js
const {create_gateway} = require('@sapphirecode/auth -server-helper');
const gateway = create_gateway({
2022-01-03 14:44:27 +01:00
redirect_url: '/auth', // if defined, unauthorized requests will be redirected
2022-01-10 10:06:54 +01:00
cookie: { name: 'auth_cookie' }, // if defined, access tokens will be read from or written to this cookie,
refresh_cookie: { name: 'refresh_cookie' }, // if defined, refresh tokens will be read and used to automatically refresh client tokens (requires the refresh_settings attribute)
2022-01-04 21:32:04 +01:00
refresh_settings: {
// same as settings for allow_access under section 2
2022-01-05 08:11:18 +01:00
// the options data, redirect_to and leave_open are not supported here
2022-01-04 21:32:04 +01:00
}
2021-01-05 16:50:23 +01:00
});
// express
app.use(gateway);
// node http
http.createServer((main_req, main_res) =>
gateway(main_req, main_res, (req, res) => {
// your request handler
});
);
```
the gateway will forward any authorized requests to the next handler and
redirect all others to the specified url
2022-01-03 14:44:27 +01:00
#### 1.1. Creating a gateway for manual processing of requests
```js
const {GatewayClass} = require('@sapphirecode/auth -server-helper');
const gateway = new GatewayClass({ /* options */ }); // options are the same as for create_gateway above
// process a request
if (gateway.authenticate(http_request)) { // returns true if request is valid and sets req.connection.token_id and .token_data
console.log('access granted');
} else {
gateway.redirect(response); // redirects the client, triggers deny if no redirect_url was set in options
// or
gateway.deny(response); // sends status 403
}
```
2021-01-05 16:50:23 +01:00
### 2. creating the auth endpoint
```js
const {create_auth_handler} = require('@sapphirecode/auth -server-helper');
const handler = create_auth_handler(
2021-01-06 16:06:03 +01:00
async (req) => {
2021-01-05 16:50:23 +01:00
if (req.user === 'foo' & & req.password === 'bar')
2021-01-06 16:06:03 +01:00
const {access_token_id, refresh_token_id} = await req.allow_access({
2021-01-05 16:50:23 +01:00
access_token_expires_in: 600, // seconds until access tokens expire
include_refresh_token: true, // should the answer include a refresh token? default: false
refresh_token_expires_in: 3600, // seconds until refresh tokens expire (required if refresh tokens are generated)
data: {user: 'foo'}, // additional custom data to include in the token
});
if (req.user === 'part' & & req.password === 'baz')
2021-01-06 16:06:03 +01:00
const part_id = await req.allow_part(
2021-01-05 16:50:23 +01:00
60, // seconds until part_token expires
'some_module', // next module handler (defined below)
{foo: 'bar'} // custom data to attach to the token
);
// all allow_ functions return a token id, which can later be used to invalidate specific tokens from the server side
req.deny();
},
{
refresh: {
/*...same options as allow_access */
}, // define the behaviour of refresh tokens. Refresh tokens will not be accepted if this option is undefined
modules: {
some_module(req) {
// request handlers for part_tokens
// access custom data:
const auth_data = req.request.connection.auth;
auth_data.token_id; // token id
auth_data.token_data; // custom data
// the same works in handlers after the gateway, information is always stored in request.connection.auth
},
},
2022-01-10 10:06:54 +01:00
cookie: { name: 'auth_cookie' }, // if defined, access tokens will be stored in this cookie,
2022-01-26 09:08:45 +01:00
refresh_cookie: { name: 'refresh_cookie' }, // if defined, refresh tokens will be stored in this cookie
parse_body: true // read the request body into a string (default false)
2021-01-05 16:50:23 +01:00
}
);
// express
app.use(handler);
// node http
// ... create server, on path /auth run the handler
2022-01-03 15:40:13 +01:00
handler(req, res); // the handler will also return true if allow_access or allow_part was called
2021-01-05 16:50:23 +01:00
```
after the auth handler, the request will be completed, no additional content
2022-01-03 16:26:23 +01:00
should be served here. (Read 2.1 for info on disabling this)
#### 2.1. Processing Auth Requests without closing the response object
to prevent the auth handler from closing the response object you can provide additional options on each of the allow/deny functions.
```js
allow_access({leave_open: true, ...});
allow_part(
60,
'some_module',
{foo: 'bar'},
true // additional flag to leave request open
);
invalid('error description', true);
deny(true);
```
if this flag is set, no data will be written to the response body and no data will be sent.
Status code and Headers will still be set.
2021-01-05 16:50:23 +01:00
2022-01-10 10:06:54 +01:00
### Defining Custom Cookie Settings
By default all cookies will be sent with 'Secure; HttpOnly; SameSite=Strict' Attributes
In the appropriate settings object, you can set the following options:
```js
{
name: 'foo', // name of the cookies
secure: true, // option to enable or disable the Secure option default: true
http_only: true, // option to enable or disable HttpOnly default: true
same_site: 'Strict', // SameSite property (Strict, Lax or None) default: 'Strict'. Set this to null to disable
expires: 'Mon, 10 Jan 2022 09:28:00 GMT', // Expiry date of the cookie
max_age: 600, // Maximum age in Seconds
domain: 'example.com', // Domain property
path: '/cookies_here' // Path property
}
```
For Documentation on the different Cookie Attributes see < https: // developer . mozilla . org / en-US / docs / Web / HTTP / Cookies #creating_cookies >
2021-01-05 16:50:23 +01:00
### Invalidating tokens after they are delivered to the client
```js
const {blacklist} = require('@sapphirecode/auth -server-helper');
blacklist.add_signature(token_id); // the token id is returned from any function that creates tokens
```
2020-05-17 17:37:41 +02:00
2022-05-02 13:30:09 +02:00
#### Logout function
```js
const {logout} = require('@sapphirecode/auth -server-helper');
// create a new express route
app.get('logout',(req,res)=>{
// call the gateway's logout function
gateway.logout(req);
// respond ok
res.status(200);
res.end();
})
```
2021-01-08 13:30:53 +01:00
### Exporting and importing public keys to validate tokens across server instances
```js
const {keystore} = require('@sapphirecode/auth -server-helper');
const export = keystore.export_verification_data();
// second instance
keystore.import_verification_data(export);
```
2022-08-08 15:52:56 +02:00
These keys can also be live synchronized with redis to allow sessions to be shared between servers
```js
const {keystore} = require('@sapphirecode/auth -server-helper');
keystore.sync_redis('redis://localhost');
```
2021-01-09 12:20:14 +01:00
### Exporting and importing blacklist entries across server instances
```js
const {blacklist} = require('@sapphirecode/auth -server-helper');
const export = blacklist.export_blacklist();
// second instance
blacklist.import_blacklist(export);
```
2021-01-15 14:45:05 +01:00
### Clearing Keystore and Blacklist
Resetting the Keystore instance generates a new instance id and deletes all
imported or generated keys.
```js
const {keystore, blacklist} = require('@sapphirecode/auth -server-helper');
// clear keystore
keystore.reset_instance();
// clear blacklist
blacklist.clear();
// clear blacklist items older than 10 seconds
blacklist.clear(Date.now() - 10000);
```
2020-05-17 17:37:41 +02:00
## License
MIT © Timo Hocker < timo @scode .ovh >