This commit is contained in:
parent
fe037d43d3
commit
210696dda0
@ -1 +1,2 @@
|
|||||||
|
/dist/
|
||||||
*.d.ts
|
*.d.ts
|
||||||
|
16
.eslintrc.js
16
.eslintrc.js
@ -1,22 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||||
* This file is part of auth-server-helper which is released under MIT.
|
* This file is part of Auth-Server-Helper which is released under MIT.
|
||||||
* See file 'LICENSE' for full license details.
|
* See file 'LICENSE' for full license details.
|
||||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
* Created by Timo Hocker <timo@scode.ovh>, December 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
env: {
|
env: {
|
||||||
commonjs: true,
|
commonjs: true,
|
||||||
es6: true,
|
es6: true,
|
||||||
node: true
|
node: true
|
||||||
},
|
},
|
||||||
extends: [ '@sapphirecode' ],
|
extends: [
|
||||||
|
'@sapphirecode'
|
||||||
|
],
|
||||||
globals: {
|
globals: {
|
||||||
Atomics: 'readonly',
|
Atomics: 'readonly',
|
||||||
SharedArrayBuffer: 'readonly'
|
SharedArrayBuffer: 'readonly'
|
||||||
},
|
},
|
||||||
parserOptions: { ecmaVersion: 2018 }
|
parserOptions: {
|
||||||
};
|
ecmaVersion: 2018
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,6 +2,3 @@
|
|||||||
/dist/
|
/dist/
|
||||||
/.nyc_output/
|
/.nyc_output/
|
||||||
/coverage/
|
/coverage/
|
||||||
/db.sqlite
|
|
||||||
# stryker temp files
|
|
||||||
.stryker-tmp
|
|
||||||
|
@ -4,5 +4,5 @@
|
|||||||
"author": "Timo Hocker",
|
"author": "Timo Hocker",
|
||||||
"company": "Sapphirecode",
|
"company": "Sapphirecode",
|
||||||
"email": "timo@scode.ovh",
|
"email": "timo@scode.ovh",
|
||||||
"software": "auth-server-helper"
|
"software": "Auth-Server-Helper"
|
||||||
}
|
}
|
@ -1,9 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
## 1.1.0
|
|
||||||
|
|
||||||
add user_id to res.connection, so request handlers can access the current user
|
|
||||||
|
|
||||||
## 1.0.0
|
|
||||||
|
|
||||||
initial release
|
|
53
README.md
53
README.md
@ -1,63 +1,22 @@
|
|||||||
# @sapphirecode/auth-server-helper
|
# auth-server-helper
|
||||||
|
|
||||||
version: 1.1.x
|
version: 0.0.0
|
||||||
|
|
||||||
authentication middleware for express
|
undefined
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
npm:
|
npm:
|
||||||
|
|
||||||
> npm i --save @sapphirecode/auth-server-helper
|
> npm i --save auth-server-helper
|
||||||
|
|
||||||
yarn:
|
yarn:
|
||||||
|
|
||||||
> yarn add @sapphirecode/auth-server-helper
|
> yarn add auth-server-helper
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```js
|
TODO: Add usage
|
||||||
const auth = require('@sapphirecode/auth-server-helper');
|
|
||||||
const password_helper = require('@sapphirecode/password_helper');
|
|
||||||
|
|
||||||
const users = {
|
|
||||||
foo: {
|
|
||||||
id: 0
|
|
||||||
password: await password_helper.hash('bar'),
|
|
||||||
salt: '123'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add cookieParser to allow session management via cookies
|
|
||||||
app.use(cookieParser());
|
|
||||||
|
|
||||||
// the middleware needs a function to determine user data
|
|
||||||
// this function can also return a promise
|
|
||||||
app.use(auth((user_name) => {
|
|
||||||
if (!users[user_name])
|
|
||||||
return null;
|
|
||||||
return users[user_name];
|
|
||||||
}));
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
when a client logs in, it will set a header called 'session' that the client can
|
|
||||||
use to authorize the following requests. it also sets a cookie to make
|
|
||||||
requesting from the client more simple. (cookie parser is needed to make
|
|
||||||
authentication with cookies possible)
|
|
||||||
|
|
||||||
the id of the logged in user will be available in `req.connection.user_id` in
|
|
||||||
all of the following request handlers.
|
|
||||||
|
|
||||||
### Excluding routes
|
|
||||||
|
|
||||||
exceptions to the auth module can be added by adding an array of regular
|
|
||||||
expressions a specific method can also be filtered for by giving an object
|
|
||||||
instead of a plain regular expression.
|
|
||||||
|
|
||||||
```js
|
|
||||||
auth(..., [/no-auth/, {regex: '/no-auth-post/', method: 'POST'}]);
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
206
index.js
206
index.js
@ -1,206 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
||||||
* This file is part of auth-server-helper which is released under MIT.
|
|
||||||
* See file 'LICENSE' for full license details.
|
|
||||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
// @ts-nocheck
|
|
||||||
/* eslint-disable no-magic-numbers */
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const password_helper = require ('@sapphirecode/password-helper');
|
|
||||||
const crypto = require ('@sapphirecode/crypto-helper');
|
|
||||||
const consts = require ('@sapphirecode/consts');
|
|
||||||
|
|
||||||
const me = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* initializes the module
|
|
||||||
*
|
|
||||||
* @param {Function<Promise|object>} get_user
|
|
||||||
* function that returns {id:number, password:string, salt:string}
|
|
||||||
* for a given user identifier
|
|
||||||
* @param {Array<RegExp>} ignore_paths array of regex to skip auth
|
|
||||||
* @returns {Function} request handler
|
|
||||||
*/
|
|
||||||
function init (get_user, ignore_paths = []) {
|
|
||||||
me.get_user = get_user;
|
|
||||||
me.session_timeout_milliseconds = 300000;
|
|
||||||
me.ignore_paths = ignore_paths;
|
|
||||||
me.jwt_secret = crypto.create_salt ();
|
|
||||||
me.app_id = crypto.create_salt ();
|
|
||||||
return request_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tries to authenticate a user
|
|
||||||
*
|
|
||||||
* @param {string} user name or email of the given user
|
|
||||||
* @param {string} password hashed password
|
|
||||||
* @param {any} req request object
|
|
||||||
* @returns {Promise<string>} session key if successful
|
|
||||||
*/
|
|
||||||
async function authenticate (user, password, req) {
|
|
||||||
const user_entry
|
|
||||||
= await new Promise ((res) => res (me.get_user (user)));
|
|
||||||
|
|
||||||
if (!user_entry)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (!await password_helper.verify (user_entry.password, password))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
req.connection.user_id = user_entry.id;
|
|
||||||
|
|
||||||
const session_key = crypto.sign_object (
|
|
||||||
{ id: user_entry.id },
|
|
||||||
me.jwt_secret
|
|
||||||
);
|
|
||||||
|
|
||||||
return session_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets the correct salt for a given user
|
|
||||||
*
|
|
||||||
* @param {string} user user name or email to query
|
|
||||||
*/
|
|
||||||
async function salt (user) {
|
|
||||||
const user_entry
|
|
||||||
= await new Promise ((res) => res (me.get_user (user)));
|
|
||||||
if (!user_entry)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return user_entry.salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* block if no auth header found
|
|
||||||
*
|
|
||||||
* @param {string} session session key
|
|
||||||
* @param {string} user user name
|
|
||||||
* @param {any} res response object
|
|
||||||
* @returns {boolean} true if handler blocked request
|
|
||||||
*/
|
|
||||||
function request_handler_block (session, user, res) {
|
|
||||||
if (typeof session === 'undefined' && typeof user === 'undefined') {
|
|
||||||
res.status (consts.http.status_unauthorized);
|
|
||||||
res.end ();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* handle authentication
|
|
||||||
*
|
|
||||||
* @param {string} session session key
|
|
||||||
* @param {string} user user name
|
|
||||||
* @param {string} key user hash
|
|
||||||
* @param {any} req request object
|
|
||||||
* @param {any} res response object
|
|
||||||
* @param {any} next next handler
|
|
||||||
* @returns {Promise<boolean>} true if handler authenticated
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line max-len, max-params
|
|
||||||
async function request_handler_authenticate (session, user, key, req, res, next) {
|
|
||||||
if (typeof session === 'undefined' && typeof user !== 'undefined') {
|
|
||||||
if (typeof key === 'undefined') {
|
|
||||||
const user_salt = await salt (user);
|
|
||||||
res.status (
|
|
||||||
user_salt === null
|
|
||||||
? consts.http.status_forbidden
|
|
||||||
: consts.http.status_ok
|
|
||||||
);
|
|
||||||
res.end (user_salt);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const session_key = await authenticate (user, key, req);
|
|
||||||
|
|
||||||
res.status (
|
|
||||||
session_key === null
|
|
||||||
? consts.http.status_forbidden
|
|
||||||
: consts.http.status_ok
|
|
||||||
)
|
|
||||||
.cookie (me.app_id, session_key, { maxAge: 900000, httpOnly: true })
|
|
||||||
.end (session_key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const jwt = crypto.verify_signature (
|
|
||||||
session,
|
|
||||||
me.jwt_secret,
|
|
||||||
me.session_timeout_milliseconds
|
|
||||||
);
|
|
||||||
res.locals.user_id = jwt.id;
|
|
||||||
const new_user_token = crypto.sign_object (
|
|
||||||
{ id: jwt.id },
|
|
||||||
me.jwt_secret
|
|
||||||
);
|
|
||||||
req.connection.user_id = jwt.id;
|
|
||||||
res.cookie (
|
|
||||||
me.app_id,
|
|
||||||
new_user_token,
|
|
||||||
{ maxAge: 900000, httpOnly: true }
|
|
||||||
)
|
|
||||||
.header ('session', new_user_token);
|
|
||||||
next ();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check if a filter matches a request
|
|
||||||
*
|
|
||||||
* @param {any} req request
|
|
||||||
* @param {any} filter filter
|
|
||||||
* @returns {boolean} true if filter matches
|
|
||||||
*/
|
|
||||||
function filter_matches (req, filter) {
|
|
||||||
if (filter instanceof RegExp && filter.test (req.url))
|
|
||||||
return true;
|
|
||||||
return req.method === filter.method
|
|
||||||
&& filter.regex
|
|
||||||
&& filter.regex.test (req.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* handles http requests
|
|
||||||
*
|
|
||||||
* @param {any} req request
|
|
||||||
* @param {any} res response
|
|
||||||
* @param {any} next next handler
|
|
||||||
*/
|
|
||||||
async function request_handler (req, res, next) {
|
|
||||||
if (Array.isArray (me.ignore_paths)) {
|
|
||||||
for (const ignore of me.ignore_paths) {
|
|
||||||
if (filter_matches (req, ignore)) {
|
|
||||||
next ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { user, key, session: header_session } = req.headers;
|
|
||||||
const cookie_session = typeof req.cookies === 'undefined'
|
|
||||||
? null
|
|
||||||
: req.cookies[me.app_id];
|
|
||||||
|
|
||||||
const session = cookie_session || header_session;
|
|
||||||
|
|
||||||
if (request_handler_block (session, user, res))
|
|
||||||
return;
|
|
||||||
if (await request_handler_authenticate (session, user, key, req, res, next))
|
|
||||||
return;
|
|
||||||
|
|
||||||
res.status (consts.http.status_forbidden);
|
|
||||||
res.end ();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = init;
|
|
24
lib/.eslintrc.js
Normal file
24
lib/.eslintrc.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||||
|
* This file is part of Auth-Server-Helper which is released under MIT.
|
||||||
|
* See file 'LICENSE' for full license details.
|
||||||
|
* Created by Timo Hocker <timo@scode.ovh>, December 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
commonjs: true,
|
||||||
|
es6: true,
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'@sapphirecode/eslint-config-ts'
|
||||||
|
],
|
||||||
|
globals: {
|
||||||
|
Atomics: 'readonly',
|
||||||
|
SharedArrayBuffer: 'readonly'
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2018
|
||||||
|
}
|
||||||
|
}
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
||||||
* This file is part of auth-server-helper which is released under MIT.
|
|
||||||
* See file 'LICENSE' for full license details.
|
|
||||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* eslint-disable no-magic-numbers */
|
|
||||||
// @ts-nocheck
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const express = require ('express');
|
|
||||||
const auth = require ('./index');
|
|
||||||
const consts = require ('@sapphirecode/consts');
|
|
||||||
const crypto = require ('@sapphirecode/crypto-helper');
|
|
||||||
const password_helper = require ('@sapphirecode/password-helper');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* start the server
|
|
||||||
*/
|
|
||||||
async function start_server () {
|
|
||||||
const app = express ();
|
|
||||||
|
|
||||||
const id = 69;
|
|
||||||
const name = 'testuser';
|
|
||||||
const salt = crypto.create_salt ();
|
|
||||||
const password = await password_helper.hash (
|
|
||||||
crypto.hash_sha512 ('foo', salt)
|
|
||||||
);
|
|
||||||
const user = { id, name, salt, password };
|
|
||||||
|
|
||||||
app.use (auth ((user_name) => {
|
|
||||||
if (user.name === user_name)
|
|
||||||
return user;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}, [
|
|
||||||
/noauthreg/u,
|
|
||||||
{ method: 'POST', regex: /noauthobj/u }
|
|
||||||
]));
|
|
||||||
|
|
||||||
app.use ((req, res) => {
|
|
||||||
res.status (consts.http.status_ok)
|
|
||||||
.end (`foo:${req.connection.user_id}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
return new Promise ((res) => {
|
|
||||||
const listener = app.listen (0, () => {
|
|
||||||
res (listener.address ().port);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { start_server };
|
|
39
package.json
39
package.json
@ -1,44 +1,33 @@
|
|||||||
{
|
{
|
||||||
"name": "@sapphirecode/auth-server-helper",
|
"name": "@sapphirecode/auth-server-helper",
|
||||||
"version": "1.1.4",
|
"version": "2.0.0",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Timo Hocker",
|
"name": "Timo Hocker",
|
||||||
"email": "timo@scode.ovh"
|
"email": "timo@scode.ovh"
|
||||||
},
|
},
|
||||||
"bugs": "https://redmine.scode.ovh/projects/auth-server-helper",
|
|
||||||
"license": "MIT",
|
|
||||||
"description": "authentication middleware for express",
|
"description": "authentication middleware for express",
|
||||||
"repository": {
|
"license": "MIT",
|
||||||
"type": "git",
|
|
||||||
"directory": "https://git.scode.ovh:timo/auth-server-helper.git"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sapphirecode/auth-client-helper": "^1.0.45",
|
"@sapphirecode/eslint-config-ts": "^1.1.27",
|
||||||
"@sapphirecode/eslint-config": "^2.1.4",
|
"@types/jasmine": "^3.6.2",
|
||||||
"@stryker-mutator/core": "^4.0.0",
|
"jasmine": "^3.6.3",
|
||||||
"@stryker-mutator/jasmine-runner": "^4.0.0",
|
"jasmine-ts": "^0.3.0",
|
||||||
"@types/jasmine": "^3.5.14",
|
"nyc": "^15.1.0",
|
||||||
"eslint": "^7.0.0",
|
"ts-node": "^8.0.0",
|
||||||
"express": "^4.17.1",
|
"typescript": "^4.1.2"
|
||||||
"jasmine": "^3.6.1",
|
|
||||||
"node-fetch": "^2.6.0",
|
|
||||||
"nyc": "^15.0.1"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.vue,.mjs",
|
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.vue,.mjs",
|
||||||
"test": "nyc jasmine --config=\"jasmine.json\"",
|
"test": "nyc jasmine-ts --config=\"jasmine.json\"",
|
||||||
"mutate": "stryker run",
|
"mutate": "stryker run",
|
||||||
"compile": "tsc --allowJs --declaration --emitDeclarationOnly index.js"
|
"compile": "tsc"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@sapphirecode/consts": "^1.1.18",
|
|
||||||
"@sapphirecode/crypto-helper": "^1.1.44",
|
|
||||||
"@sapphirecode/password-helper": "^1.0.35"
|
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"LICENSE",
|
"LICENSE",
|
||||||
"index.js"
|
"*.js",
|
||||||
|
"*.ts",
|
||||||
|
"*.d.ts"
|
||||||
],
|
],
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"authentication",
|
"authentication",
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
||||||
* This file is part of auth-server-helper which is released under MIT.
|
|
||||||
* See file 'LICENSE' for full license details.
|
|
||||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {import('@stryker-mutator/api/core').StrykerOptions}
|
|
||||||
*/
|
|
||||||
module.exports = {
|
|
||||||
packageManager: 'yarn',
|
|
||||||
reporters: [
|
|
||||||
'clear-text',
|
|
||||||
'progress'
|
|
||||||
],
|
|
||||||
testRunner: 'jasmine',
|
|
||||||
jasmineConfigFile: 'jasmine.json',
|
|
||||||
coverageAnalysis: 'perTest',
|
|
||||||
mutate: [ 'index.js' ]
|
|
||||||
};
|
|
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
||||||
* This file is part of auth-server-helper which is released under MIT.
|
|
||||||
* See file 'LICENSE' for full license details.
|
|
||||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
// @ts-nocheck
|
|
||||||
/* eslint-disable no-undef */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const mock_server = require ('../../mock_server');
|
|
||||||
const client = require ('@sapphirecode/auth-client-helper');
|
|
||||||
const consts = require ('@sapphirecode/consts');
|
|
||||||
const fetch = require ('node-fetch');
|
|
||||||
|
|
||||||
let port = 0;
|
|
||||||
|
|
||||||
// eslint-disable-next-line max-lines-per-function
|
|
||||||
describe ('server-helper', () => {
|
|
||||||
beforeAll (async () => {
|
|
||||||
port = await mock_server.start_server ();
|
|
||||||
});
|
|
||||||
|
|
||||||
it ('should login', async () => {
|
|
||||||
const session = await client.login (
|
|
||||||
'testuser',
|
|
||||||
'foo',
|
|
||||||
`http://localhost:${port}`
|
|
||||||
);
|
|
||||||
expect (typeof session)
|
|
||||||
.toEqual ('string');
|
|
||||||
|
|
||||||
const resp = await fetch (
|
|
||||||
`http://localhost:${port}`,
|
|
||||||
{ headers: { session } }
|
|
||||||
);
|
|
||||||
|
|
||||||
expect (resp.status)
|
|
||||||
.toEqual (consts.http.status_ok);
|
|
||||||
expect (await resp.text ())
|
|
||||||
.toEqual ('foo:69');
|
|
||||||
});
|
|
||||||
|
|
||||||
it ('should allow access to excluded paths', async () => {
|
|
||||||
const resp = await fetch (`http://localhost:${port}/noauthreg`);
|
|
||||||
|
|
||||||
expect (resp.status)
|
|
||||||
.toEqual (consts.http.status_ok);
|
|
||||||
expect (await resp.text ())
|
|
||||||
.toEqual ('foo:undefined');
|
|
||||||
});
|
|
||||||
|
|
||||||
it (
|
|
||||||
'should allow access to excluded paths with correct method',
|
|
||||||
async () => {
|
|
||||||
const resp = await fetch (
|
|
||||||
`http://localhost:${port}/noauthobj`,
|
|
||||||
{ method: 'POST' }
|
|
||||||
);
|
|
||||||
|
|
||||||
expect (resp.status)
|
|
||||||
.toEqual (consts.http.status_ok);
|
|
||||||
expect (await resp.text ())
|
|
||||||
.toEqual ('foo:undefined');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
it ('should reject access to excluded paths with wrong method', async () => {
|
|
||||||
const resp = await fetch (
|
|
||||||
`http://localhost:${port}/noauthobj`
|
|
||||||
);
|
|
||||||
|
|
||||||
expect (resp.status)
|
|
||||||
.toEqual (consts.http.status_unauthorized);
|
|
||||||
});
|
|
||||||
|
|
||||||
it ('should reject invalid user', async () => {
|
|
||||||
await expectAsync (client.login (
|
|
||||||
'foo',
|
|
||||||
'foo',
|
|
||||||
`http://localhost:${port}`
|
|
||||||
))
|
|
||||||
.toBeRejectedWithError ('user or password invalid');
|
|
||||||
});
|
|
||||||
|
|
||||||
it ('should reject and recover', async () => {
|
|
||||||
await expectAsync (client.login (
|
|
||||||
'testuser',
|
|
||||||
'bar',
|
|
||||||
`http://localhost:${port}`
|
|
||||||
))
|
|
||||||
.toBeRejectedWithError ('user or password invalid');
|
|
||||||
|
|
||||||
const session = await client.login (
|
|
||||||
'testuser',
|
|
||||||
'foo',
|
|
||||||
`http://localhost:${port}`
|
|
||||||
);
|
|
||||||
expect (typeof session)
|
|
||||||
.toEqual ('string');
|
|
||||||
|
|
||||||
const resp = await fetch (
|
|
||||||
`http://localhost:${port}`,
|
|
||||||
{ headers: { session } }
|
|
||||||
);
|
|
||||||
|
|
||||||
expect (resp.status)
|
|
||||||
.toEqual (consts.http.status_ok);
|
|
||||||
expect (await resp.text ())
|
|
||||||
.toEqual ('foo:69');
|
|
||||||
});
|
|
||||||
|
|
||||||
it ('should reject invalid password', async () => {
|
|
||||||
await expectAsync (client.login (
|
|
||||||
'testuser',
|
|
||||||
'bar',
|
|
||||||
`http://localhost:${port}`
|
|
||||||
))
|
|
||||||
.toBeRejectedWithError ('user or password invalid');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
12
tsconfig.json
Normal file
12
tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "commonjs",
|
||||||
|
"outDir": "./dist",
|
||||||
|
"rootDir": "./lib",
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"declaration": true
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user