88 lines
2.2 KiB
TypeScript
88 lines
2.2 KiB
TypeScript
/*
|
|
* 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
|
|
*/
|
|
|
|
import { IncomingMessage, ServerResponse } from 'http';
|
|
import { run_regex } from '@sapphirecode/utilities';
|
|
import authority from './Authority';
|
|
|
|
type AnyFunc = (...args: unknown[]) => unknown;
|
|
type Gateway = (
|
|
req: IncomingMessage,
|
|
res: ServerResponse, next: AnyFunc
|
|
) => unknown;
|
|
|
|
interface GatewayOptions {
|
|
redirect_url: string;
|
|
cookie_name?: string;
|
|
}
|
|
|
|
class GatewayClass {
|
|
private _options: GatewayOptions;
|
|
|
|
public constructor (options: GatewayOptions) {
|
|
this._options = options;
|
|
}
|
|
|
|
private redirect (res: ServerResponse): void {
|
|
res.statusCode = 302;
|
|
res.setHeader ('Location', this._options.redirect_url);
|
|
res.end ();
|
|
}
|
|
|
|
private get_header_auth (req: IncomingMessage): string | null {
|
|
const auth_header = req.headers.authorization;
|
|
const auth = (/(?<type>\w+) (?<data>.*)/u).exec (auth_header || '');
|
|
if (auth === null)
|
|
return null;
|
|
if (auth.groups?.type !== 'Bearer')
|
|
return null;
|
|
return auth.groups?.data;
|
|
}
|
|
|
|
private get_cookie_auth (req: IncomingMessage): string | null {
|
|
if (typeof this._options.cookie_name === 'undefined')
|
|
return null;
|
|
let auth = null;
|
|
run_regex (
|
|
/(?:^|;)(?<name>[^;=]+)=(?<value>[^;]+)/gu,
|
|
req.headers.cookie,
|
|
(res: RegExpMatchArray) => {
|
|
if (res.groups?.name === this._options.cookie_name)
|
|
auth = res.groups?.value;
|
|
}
|
|
);
|
|
return auth;
|
|
}
|
|
|
|
private authenticate (req: IncomingMessage): boolean {
|
|
let auth = this.get_header_auth (req);
|
|
if (auth === null)
|
|
auth = this.get_cookie_auth (req);
|
|
if (auth === null)
|
|
return false;
|
|
|
|
return authority.verify (auth).authorized;
|
|
}
|
|
|
|
public process_request (
|
|
req: IncomingMessage,
|
|
res: ServerResponse,
|
|
next: AnyFunc
|
|
): unknown {
|
|
if (this.authenticate (req))
|
|
return next ();
|
|
return this.redirect (res);
|
|
}
|
|
}
|
|
|
|
export default function create_gateway (options: GatewayOptions): Gateway {
|
|
const g = new GatewayClass (options);
|
|
return g.process_request.bind (g);
|
|
}
|
|
|
|
export { Gateway, AnyFunc };
|