2021-01-03 14:51:07 +01:00
|
|
|
/*
|
|
|
|
* 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>, January 2021
|
|
|
|
*/
|
|
|
|
|
2020-12-28 16:53:08 +01:00
|
|
|
import http from 'http';
|
2022-05-02 13:30:09 +02:00
|
|
|
import { GatewayClass, create_gateway } from '../../lib/index';
|
2020-12-28 16:53:08 +01:00
|
|
|
import authority from '../../lib/Authority';
|
|
|
|
import blacklist from '../../lib/Blacklist';
|
2021-01-07 15:43:54 +01:00
|
|
|
import { clock_finalize, clock_setup, get } from '../Helper';
|
2020-12-28 16:53:08 +01:00
|
|
|
|
|
|
|
// eslint-disable-next-line max-lines-per-function
|
|
|
|
describe ('gateway', () => {
|
|
|
|
let server: http.Server|null = null;
|
|
|
|
|
|
|
|
beforeAll (() => {
|
2021-01-07 15:43:54 +01:00
|
|
|
clock_setup ();
|
2020-12-28 16:53:08 +01:00
|
|
|
|
2022-05-02 13:30:09 +02:00
|
|
|
const g = new GatewayClass ({
|
2022-01-10 10:06:54 +01:00
|
|
|
redirect_url: 'http://localhost/auth',
|
|
|
|
cookie: { name: 'cookie_jar' },
|
|
|
|
refresh_cookie: { name: 'mint_cookies' },
|
2022-01-04 21:32:04 +01:00
|
|
|
refresh_settings: {
|
|
|
|
access_token_expires_in: 600,
|
|
|
|
include_refresh_token: true,
|
|
|
|
refresh_token_expires_in: 3600
|
|
|
|
}
|
2020-12-28 16:53:08 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
server = http.createServer ((req, res) => {
|
|
|
|
const passed_handler = () => {
|
2022-05-02 13:30:09 +02:00
|
|
|
if (typeof req.url !== 'undefined') {
|
|
|
|
if (req.url.endsWith ('logout'))
|
|
|
|
g.logout (req);
|
|
|
|
}
|
2020-12-28 16:53:08 +01:00
|
|
|
res.writeHead (200);
|
2021-01-05 15:59:06 +01:00
|
|
|
const con = req.connection as unknown as Record<string, unknown>;
|
|
|
|
res.end (JSON.stringify (con.auth));
|
2020-12-28 16:53:08 +01:00
|
|
|
};
|
2022-05-02 13:30:09 +02:00
|
|
|
g.process_request (req, res, passed_handler);
|
2020-12-28 16:53:08 +01:00
|
|
|
});
|
|
|
|
server.listen (3000);
|
|
|
|
});
|
|
|
|
|
|
|
|
afterAll (() => {
|
|
|
|
if (server === null)
|
|
|
|
throw new Error ('server is null');
|
|
|
|
server.close ();
|
|
|
|
|
2021-01-07 15:43:54 +01:00
|
|
|
clock_finalize ();
|
2020-12-28 16:53:08 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
it ('should redirect any unauthorized request', async () => {
|
2020-12-30 17:21:56 +01:00
|
|
|
const resp = await get ();
|
|
|
|
expect (resp.statusCode)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual (302);
|
2020-12-30 17:21:56 +01:00
|
|
|
expect (resp.headers.location)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual ('http://localhost/auth');
|
|
|
|
});
|
|
|
|
|
|
|
|
it ('should allow a valid access token', async () => {
|
2021-01-06 16:06:03 +01:00
|
|
|
const token = await authority.sign ('access_token', 60);
|
2020-12-30 17:21:56 +01:00
|
|
|
const resp = await get ({ authorization: `Bearer ${token.signature}` });
|
|
|
|
expect (resp.statusCode)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual (200);
|
2021-01-05 15:59:06 +01:00
|
|
|
expect (JSON.parse (resp.body as string).token_id)
|
|
|
|
.toEqual (token.id);
|
2020-12-28 16:53:08 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
it ('should allow a valid access token using cookies', async () => {
|
2021-01-06 16:06:03 +01:00
|
|
|
const token = await authority.sign ('access_token', 60);
|
2021-01-12 21:26:19 +01:00
|
|
|
const resp = await get (
|
|
|
|
{ cookie: `foo=bar;cookie_jar=${token.signature};asd=efg` }
|
|
|
|
);
|
2020-12-30 17:21:56 +01:00
|
|
|
expect (resp.statusCode)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual (200);
|
2021-01-05 15:59:06 +01:00
|
|
|
expect (JSON.parse (resp.body as string).token_id)
|
|
|
|
.toEqual (token.id);
|
|
|
|
});
|
|
|
|
|
2022-01-04 21:32:04 +01:00
|
|
|
it ('should automatically return new tokens', async () => {
|
2022-08-03 16:21:00 +02:00
|
|
|
const token = await authority.sign ('access_token', 60, { data: 'foobar' });
|
|
|
|
const refresh = await authority.sign (
|
|
|
|
'refresh_token',
|
|
|
|
3600,
|
|
|
|
{ data: 'foobar' }
|
|
|
|
);
|
2022-01-04 21:32:04 +01:00
|
|
|
jasmine.clock ()
|
|
|
|
.tick (70000);
|
|
|
|
const resp = await get (
|
|
|
|
// eslint-disable-next-line max-len
|
|
|
|
{ cookie: `foo=bar;cookie_jar=${token.signature};asd=efg;mint_cookies=${refresh.signature}` }
|
|
|
|
);
|
|
|
|
expect (resp.statusCode)
|
|
|
|
.toEqual (200);
|
|
|
|
expect (JSON.parse (resp.body as string).token_id)
|
|
|
|
.not
|
|
|
|
.toEqual (token.id);
|
2022-08-03 16:21:00 +02:00
|
|
|
expect (JSON.parse (resp.body as string).token_data)
|
|
|
|
.toEqual ('foobar');
|
2022-01-04 21:32:04 +01:00
|
|
|
});
|
|
|
|
|
2021-01-05 15:59:06 +01:00
|
|
|
it ('should correctly deliver token data', async () => {
|
2021-01-06 16:06:03 +01:00
|
|
|
const token = await authority.sign ('access_token', 60, { data: 'foobar' });
|
2021-01-05 15:59:06 +01:00
|
|
|
const resp = await get ({ authorization: `Bearer ${token.signature}` });
|
|
|
|
expect (resp.statusCode)
|
|
|
|
.toEqual (200);
|
|
|
|
const body = JSON.parse (resp.body as string);
|
|
|
|
expect (body.token_id)
|
|
|
|
.toEqual (token.id);
|
|
|
|
expect (body.token_data)
|
|
|
|
.toEqual ('foobar');
|
2020-12-28 16:53:08 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
it ('should reject an outdated access token', async () => {
|
2021-01-06 16:06:03 +01:00
|
|
|
const token = await authority.sign ('access_token', 60);
|
2020-12-28 16:53:08 +01:00
|
|
|
jasmine.clock ()
|
|
|
|
.tick (70000);
|
2020-12-30 17:21:56 +01:00
|
|
|
const resp = await get ({ authorization: `Bearer ${token.signature}` });
|
|
|
|
expect (resp.statusCode)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual (302);
|
2020-12-30 17:21:56 +01:00
|
|
|
expect (resp.headers.location)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual ('http://localhost/auth');
|
|
|
|
});
|
|
|
|
|
|
|
|
it ('should reject a blacklisted access token', async () => {
|
2021-01-06 16:06:03 +01:00
|
|
|
const token = await authority.sign ('access_token', 60);
|
2020-12-28 16:53:08 +01:00
|
|
|
blacklist.add_signature (token.id);
|
2020-12-30 17:21:56 +01:00
|
|
|
const resp = await get ({ authorization: `Bearer ${token.signature}` });
|
|
|
|
expect (resp.statusCode)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual (302);
|
2020-12-30 17:21:56 +01:00
|
|
|
expect (resp.headers.location)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual ('http://localhost/auth');
|
|
|
|
});
|
|
|
|
|
|
|
|
it ('should reject any refresh_token', async () => {
|
2021-01-06 16:06:03 +01:00
|
|
|
const token = await authority.sign ('refresh_token', 60);
|
2020-12-30 17:21:56 +01:00
|
|
|
const resp = await get ({ authorization: `Bearer ${token.signature}` });
|
|
|
|
expect (resp.statusCode)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual (302);
|
2020-12-30 17:21:56 +01:00
|
|
|
expect (resp.headers.location)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual ('http://localhost/auth');
|
|
|
|
});
|
|
|
|
|
|
|
|
it ('should reject any part_token', async () => {
|
2021-01-06 16:06:03 +01:00
|
|
|
const token = await authority.sign ('part_token', 60);
|
2020-12-30 17:21:56 +01:00
|
|
|
const resp = await get ({ authorization: `Bearer ${token.signature}` });
|
|
|
|
expect (resp.statusCode)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual (302);
|
2020-12-30 17:21:56 +01:00
|
|
|
expect (resp.headers.location)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual ('http://localhost/auth');
|
|
|
|
});
|
|
|
|
|
|
|
|
it ('should reject any noname token', async () => {
|
2021-01-06 16:06:03 +01:00
|
|
|
const token = await authority.sign ('none', 60);
|
2020-12-30 17:21:56 +01:00
|
|
|
const resp = await get ({ authorization: `Bearer ${token.signature}` });
|
|
|
|
expect (resp.statusCode)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual (302);
|
2020-12-30 17:21:56 +01:00
|
|
|
expect (resp.headers.location)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual ('http://localhost/auth');
|
|
|
|
});
|
|
|
|
|
|
|
|
it ('should reject non-bearer auth', async () => {
|
2020-12-30 17:21:56 +01:00
|
|
|
const resp = await get ({ authorization: 'Basic foo:bar' });
|
|
|
|
expect (resp.statusCode)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual (302);
|
2020-12-30 17:21:56 +01:00
|
|
|
expect (resp.headers.location)
|
2020-12-28 16:53:08 +01:00
|
|
|
.toEqual ('http://localhost/auth');
|
|
|
|
});
|
2022-01-04 21:32:04 +01:00
|
|
|
|
|
|
|
it ('should disallow access and refresh cookies with the same name', () => {
|
|
|
|
expect (() => {
|
2022-01-10 10:06:54 +01:00
|
|
|
create_gateway ({
|
|
|
|
cookie: { name: 'foo' },
|
|
|
|
refresh_cookie: { name: 'foo' }
|
|
|
|
});
|
2022-01-04 21:32:04 +01:00
|
|
|
})
|
|
|
|
.toThrowError ('access and refresh cookies cannot have the same name');
|
|
|
|
});
|
2022-05-02 13:30:09 +02:00
|
|
|
|
|
|
|
it ('should logout all tokens', async () => {
|
|
|
|
const token = await authority.sign ('access_token', 60);
|
|
|
|
const refresh = await authority.sign ('refresh_token', 3600);
|
|
|
|
const resp = await get (
|
|
|
|
// eslint-disable-next-line max-len
|
|
|
|
{ cookie: `foo=bar;cookie_jar=${token.signature};asd=efg;mint_cookies=${refresh.signature}` },
|
|
|
|
null,
|
|
|
|
'/logout'
|
|
|
|
);
|
|
|
|
expect (resp.statusCode)
|
|
|
|
.toEqual (200);
|
|
|
|
const blacklisted = blacklist.export_blacklist ()
|
|
|
|
.map ((v) => v.hash);
|
|
|
|
expect (blacklisted)
|
|
|
|
.toContain (token.id);
|
|
|
|
expect (blacklisted)
|
|
|
|
.toContain (refresh.id);
|
|
|
|
});
|
2020-12-28 16:53:08 +01:00
|
|
|
});
|