auth-server-helper/lib/Gateway.ts

98 lines
2.4 KiB
TypeScript
Raw Normal View History

/*
* 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
*/
2020-12-28 16:53:08 +01:00
import { IncomingMessage, ServerResponse } from 'http';
2020-12-13 12:26:40 +01:00
import { run_regex } from '@sapphirecode/utilities';
2020-12-19 15:40:49 +01:00
import authority from './Authority';
2020-12-12 15:53:47 +01:00
2020-12-28 16:53:08 +01:00
type AnyFunc = (...args: unknown[]) => unknown;
type Gateway = (
req: IncomingMessage,
res: ServerResponse, next: AnyFunc
) => unknown;
2020-12-06 15:51:59 +01:00
interface GatewayOptions {
redirect_url: string;
2020-12-13 12:26:40 +01:00
cookie_name?: string;
2020-12-06 15:51:59 +01:00
}
class GatewayClass {
2020-12-06 21:06:40 +01:00
private _options: GatewayOptions;
2020-12-06 15:51:59 +01:00
public constructor (options: GatewayOptions) {
2020-12-06 21:06:40 +01:00
this._options = options;
2020-12-06 15:51:59 +01:00
}
2020-12-28 16:53:08 +01:00
private redirect (res: ServerResponse): void {
2020-12-06 15:51:59 +01:00
res.statusCode = 302;
2020-12-06 21:06:40 +01:00
res.setHeader ('Location', this._options.redirect_url);
2020-12-06 15:51:59 +01:00
res.end ();
}
2020-12-28 16:53:08 +01:00
private get_header_auth (req: IncomingMessage): string | null {
const auth_header = req.headers.authorization;
const auth = (/(?<type>\w+) (?<data>.*)/u).exec (auth_header || '');
2020-12-13 12:26:40 +01:00
if (auth === null)
return null;
2020-12-28 16:53:08 +01:00
if (auth.groups?.type !== 'Bearer')
2020-12-13 12:26:40 +01:00
return null;
2020-12-28 16:53:08 +01:00
return auth.groups?.data;
2020-12-13 12:26:40 +01:00
}
2020-12-28 16:53:08 +01:00
private get_cookie_auth (req: IncomingMessage): string | null {
if (typeof this._options.cookie_name === 'undefined')
return null;
2020-12-13 12:26:40 +01:00
let auth = null;
run_regex (
2021-01-12 22:04:24 +01:00
/(?:^|;)\s*(?<name>[^;=]+)=(?<value>[^;]+)/gu,
2020-12-28 16:53:08 +01:00
req.headers.cookie,
(res: RegExpMatchArray) => {
if (res.groups?.name === this._options.cookie_name)
auth = res.groups?.value;
2020-12-13 12:26:40 +01:00
}
);
return auth;
}
2020-12-28 16:53:08 +01:00
private authenticate (req: IncomingMessage): boolean {
2020-12-13 12:26:40 +01:00
let auth = this.get_header_auth (req);
if (auth === null)
auth = this.get_cookie_auth (req);
if (auth === null)
2020-12-12 15:53:47 +01:00
return false;
2021-01-03 15:32:29 +01:00
const ver = authority.verify (auth);
2021-01-05 15:59:06 +01:00
const con = req.connection as unknown as Record<string, unknown>;
con.auth = { token_id: ver.id, token_data: ver.data };
2021-01-03 15:32:29 +01:00
return ver.authorized;
2020-12-06 15:51:59 +01:00
}
2020-12-12 15:53:47 +01:00
public process_request (
2020-12-28 16:53:08 +01:00
req: IncomingMessage,
res: ServerResponse,
2020-12-06 21:06:40 +01:00
next: AnyFunc
2020-12-28 16:53:08 +01:00
): unknown {
2020-12-12 15:53:47 +01:00
if (this.authenticate (req))
2020-12-06 21:06:40 +01:00
return next ();
return this.redirect (res);
2020-12-06 15:51:59 +01:00
}
}
export default function create_gateway (options: GatewayOptions): Gateway {
const g = new GatewayClass (options);
2020-12-28 16:53:08 +01:00
return g.process_request.bind (g);
2020-12-06 15:51:59 +01:00
}
2020-12-28 16:53:08 +01:00
2021-01-05 22:10:41 +01:00
export {
AnyFunc,
Gateway,
GatewayOptions,
GatewayClass
};