2020-12-28 15:04:52 +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>, December 2020
|
|
|
|
*/
|
|
|
|
|
2020-12-19 15:40:49 +01:00
|
|
|
import {
|
|
|
|
create_salt,
|
|
|
|
sign_object,
|
|
|
|
verify_signature_get_info
|
|
|
|
} from '@sapphirecode/crypto-helper';
|
|
|
|
import keystore from './KeyStore';
|
|
|
|
import blacklist from './Blacklist';
|
2022-01-05 12:32:04 +01:00
|
|
|
import { debug } from './debug';
|
|
|
|
|
|
|
|
const logger = debug ('authority');
|
2020-12-19 15:40:49 +01:00
|
|
|
|
|
|
|
// eslint-disable-next-line no-shadow
|
2021-05-10 12:41:00 +02:00
|
|
|
type TokenType = 'access_token' | 'none' | 'part_token' | 'refresh_token'
|
2020-12-19 15:40:49 +01:00
|
|
|
|
|
|
|
interface VerificationResult {
|
|
|
|
authorized: boolean;
|
2020-12-28 14:53:14 +01:00
|
|
|
valid: boolean;
|
2020-12-19 15:40:49 +01:00
|
|
|
type: TokenType;
|
2021-01-03 15:32:29 +01:00
|
|
|
id: string;
|
2020-12-28 14:53:14 +01:00
|
|
|
next_module?: string;
|
2021-01-05 15:59:06 +01:00
|
|
|
data?: unknown;
|
2021-01-03 15:32:29 +01:00
|
|
|
error?: string;
|
2020-12-19 15:40:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
interface SignatureResult {
|
|
|
|
signature: string;
|
|
|
|
id: string;
|
|
|
|
}
|
|
|
|
|
2021-01-03 15:13:03 +01:00
|
|
|
interface SignatureOptions
|
|
|
|
{
|
2021-01-05 15:59:06 +01:00
|
|
|
data?: unknown
|
2021-01-03 15:13:03 +01:00
|
|
|
next_module?: string
|
|
|
|
}
|
|
|
|
|
2020-12-19 15:40:49 +01:00
|
|
|
class Authority {
|
2022-08-08 15:52:56 +02:00
|
|
|
public async verify (key: string): Promise<VerificationResult> {
|
2022-08-15 17:33:25 +02:00
|
|
|
const log = logger.extend ('verify');
|
|
|
|
log ('verifying token');
|
2020-12-19 16:19:09 +01:00
|
|
|
const result: VerificationResult = {
|
2020-12-28 14:53:14 +01:00
|
|
|
authorized: false,
|
|
|
|
valid: false,
|
2021-01-03 15:32:29 +01:00
|
|
|
type: 'none',
|
|
|
|
id: ''
|
2020-12-19 16:19:09 +01:00
|
|
|
};
|
2022-08-08 15:52:56 +02:00
|
|
|
const data = await verify_signature_get_info (
|
2020-12-19 15:40:49 +01:00
|
|
|
key,
|
2022-08-10 11:11:39 +02:00
|
|
|
async (info) => {
|
2020-12-28 16:53:08 +01:00
|
|
|
try {
|
2022-08-10 11:08:14 +02:00
|
|
|
return await keystore.get_key (info.iat / 1000, info.iss);
|
2020-12-28 16:53:08 +01:00
|
|
|
}
|
|
|
|
catch {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
},
|
2020-12-19 15:40:49 +01:00
|
|
|
(info) => info.valid_for * 1000
|
|
|
|
);
|
|
|
|
|
2021-01-03 15:32:29 +01:00
|
|
|
if (data === null) {
|
2022-08-15 17:33:25 +02:00
|
|
|
log ('token invalid');
|
2021-01-03 15:32:29 +01:00
|
|
|
result.error = 'invalid signature';
|
2020-12-19 15:40:49 +01:00
|
|
|
return result;
|
2021-01-03 15:32:29 +01:00
|
|
|
}
|
2020-12-19 15:40:49 +01:00
|
|
|
|
2021-01-03 15:32:29 +01:00
|
|
|
result.id = data.id;
|
2020-12-19 15:40:49 +01:00
|
|
|
result.type = data.type;
|
|
|
|
|
2022-08-15 17:33:25 +02:00
|
|
|
log ('parsing token %s %s', result.type, result.id);
|
2022-01-05 12:32:04 +01:00
|
|
|
|
2022-08-27 16:39:07 +02:00
|
|
|
if (!(await blacklist.is_valid (data.id))) {
|
2022-08-15 17:33:25 +02:00
|
|
|
log ('token is blacklisted');
|
2021-01-03 15:32:29 +01:00
|
|
|
result.error = 'blacklisted';
|
2020-12-19 15:40:49 +01:00
|
|
|
return result;
|
2021-01-03 15:32:29 +01:00
|
|
|
}
|
2020-12-19 15:40:49 +01:00
|
|
|
|
2020-12-28 14:53:14 +01:00
|
|
|
result.valid = true;
|
2020-12-19 15:40:49 +01:00
|
|
|
result.authorized = result.type === 'access_token';
|
2021-01-03 15:13:03 +01:00
|
|
|
result.next_module = data.next_module;
|
|
|
|
result.data = data.obj;
|
2020-12-19 15:40:49 +01:00
|
|
|
|
2022-08-15 17:33:25 +02:00
|
|
|
log (
|
2022-01-05 12:32:04 +01:00
|
|
|
'valid %s; targeting module %s',
|
|
|
|
result.type,
|
|
|
|
result.next_module
|
|
|
|
);
|
|
|
|
|
2020-12-19 15:40:49 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-01-06 16:06:03 +01:00
|
|
|
public async sign (
|
2020-12-19 15:40:49 +01:00
|
|
|
type: TokenType,
|
|
|
|
valid_for: number,
|
2021-01-03 15:13:03 +01:00
|
|
|
options?: SignatureOptions
|
2021-01-06 16:06:03 +01:00
|
|
|
): Promise<SignatureResult> {
|
2022-08-15 17:33:25 +02:00
|
|
|
const log = logger.extend ('sign');
|
|
|
|
log ('signing new %s', type);
|
2020-12-19 15:40:49 +01:00
|
|
|
const time = Date.now ();
|
2021-01-06 16:06:03 +01:00
|
|
|
const key = await keystore.get_sign_key (time / 1000, valid_for);
|
2020-12-19 15:40:49 +01:00
|
|
|
const attributes = {
|
2021-01-03 15:13:03 +01:00
|
|
|
id: create_salt (),
|
|
|
|
iat: time,
|
2021-01-08 13:30:53 +01:00
|
|
|
iss: keystore.instance_id,
|
2020-12-19 15:40:49 +01:00
|
|
|
type,
|
2021-01-03 15:13:03 +01:00
|
|
|
valid_for,
|
|
|
|
next_module: options?.next_module
|
2020-12-19 15:40:49 +01:00
|
|
|
};
|
2021-01-03 15:13:03 +01:00
|
|
|
const signature = sign_object (options?.data, key, attributes);
|
2022-08-15 17:33:25 +02:00
|
|
|
log ('created token %s', attributes.id);
|
2020-12-19 15:40:49 +01:00
|
|
|
return { id: attributes.id, signature };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const auth = (new Authority);
|
|
|
|
|
2021-01-05 22:10:41 +01:00
|
|
|
export {
|
|
|
|
TokenType,
|
|
|
|
VerificationResult,
|
|
|
|
SignatureResult,
|
|
|
|
SignatureOptions,
|
|
|
|
Authority
|
|
|
|
};
|
|
|
|
|
2020-12-19 15:40:49 +01:00
|
|
|
export default auth;
|