/* * 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 , January 2021 */ import http from 'http'; import { GatewayClass, create_gateway } from '../../lib/index'; import authority from '../../lib/Authority'; import blacklist from '../../lib/Blacklist'; import { clock_finalize, clock_setup, get } from '../Helper'; // eslint-disable-next-line max-lines-per-function describe ('gateway', () => { let server: http.Server|null = null; beforeAll (() => { clock_setup (); const g = new GatewayClass ({ redirect_url: 'http://localhost/auth', cookie: { name: 'cookie_jar' }, refresh_cookie: { name: 'mint_cookies' }, refresh_settings: { access_token_expires_in: 600, include_refresh_token: true, refresh_token_expires_in: 3600 } }); server = http.createServer ((req, res) => { const passed_handler = () => { if (typeof req.url !== 'undefined') { if (req.url.endsWith ('logout')) g.logout (req); } res.writeHead (200); const data = { ...g.get_info (req), foo: g.has_permission (req, 'foo'), bar: g.has_permission (req, 'bar') }; res.end (JSON.stringify (data)); }; g.process_request (req, res, passed_handler); }); server.listen (3000); }); afterAll (() => { if (server === null) throw new Error ('server is null'); server.close (); clock_finalize (); }); it ('should redirect any unauthorized request', async () => { const resp = await get (); expect (resp.statusCode) .toEqual (302); expect (resp.headers.location) .toEqual ('http://localhost/auth'); }); it ('should allow a valid access token', async () => { const token = await authority.sign ('access_token', 60); const resp = await get ({ authorization: `Bearer ${token.signature}` }); expect (resp.statusCode) .toEqual (200); expect (JSON.parse (resp.body as string).token_id) .toEqual (token.id); }); it ('should allow a valid access token using cookies', async () => { const token = await authority.sign ('access_token', 60); const resp = await get ( { cookie: `foo=bar;cookie_jar=${token.signature};asd=efg` } ); expect (resp.statusCode) .toEqual (200); expect (JSON.parse (resp.body as string).token_id) .toEqual (token.id); }); it ('should automatically return new tokens', async () => { const token = await authority.sign ('access_token', 60, { data: 'foobar' }); const refresh = await authority.sign ( 'refresh_token', 3600, { data: 'foobar' } ); 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); expect (JSON.parse (resp.body as string).token_data) .toEqual ('foobar'); }); it ('should correctly deliver token data', async () => { const token = await authority.sign ('access_token', 60, { data: 'foobar' }); 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'); expect (body.permissions) .toEqual ([]); }); it ('should reject an outdated access token', async () => { const token = await authority.sign ('access_token', 60); jasmine.clock () .tick (70000); const resp = await get ({ authorization: `Bearer ${token.signature}` }); expect (resp.statusCode) .toEqual (302); expect (resp.headers.location) .toEqual ('http://localhost/auth'); }); it ('should reject a blacklisted access token', async () => { const token = await authority.sign ('access_token', 60); await blacklist.add_signature (token.id); const resp = await get ({ authorization: `Bearer ${token.signature}` }); expect (resp.statusCode) .toEqual (302); expect (resp.headers.location) .toEqual ('http://localhost/auth'); }); it ('should reject any refresh_token', async () => { const token = await authority.sign ('refresh_token', 60); const resp = await get ({ authorization: `Bearer ${token.signature}` }); expect (resp.statusCode) .toEqual (302); expect (resp.headers.location) .toEqual ('http://localhost/auth'); }); it ('should reject any part_token', async () => { const token = await authority.sign ('part_token', 60); const resp = await get ({ authorization: `Bearer ${token.signature}` }); expect (resp.statusCode) .toEqual (302); expect (resp.headers.location) .toEqual ('http://localhost/auth'); }); it ('should reject any noname token', async () => { const token = await authority.sign ('none', 60); const resp = await get ({ authorization: `Bearer ${token.signature}` }); expect (resp.statusCode) .toEqual (302); expect (resp.headers.location) .toEqual ('http://localhost/auth'); }); it ('should reject non-bearer auth', async () => { const resp = await get ({ authorization: 'Basic foo:bar' }); expect (resp.statusCode) .toEqual (302); expect (resp.headers.location) .toEqual ('http://localhost/auth'); }); it ('should disallow access and refresh cookies with the same name', () => { expect (() => { create_gateway ({ cookie: { name: 'foo' }, refresh_cookie: { name: 'foo' } }); }) .toThrowError ('access and refresh cookies cannot have the same name'); }); 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.token_id); expect (blacklisted) .toContain (token.id); expect (blacklisted) .toContain (refresh.id); }); it ('should correctly check permissions', async () => { const token = await authority.sign ( 'access_token', 60, { permissions: [ 'foo' ] } ); const resp = await get ({ authorization: `Bearer ${token.signature}` }); expect (resp.statusCode) .toEqual (200); expect (JSON.parse (resp.body as string)) .toEqual ({ token_id: token.id, permissions: [ 'foo' ], foo: true, bar: false }); }); });