This repository has been archived by the owner on Mar 28, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
token.ts
105 lines (91 loc) · 2.81 KB
/
token.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import {createHmac} from 'node:crypto';
import {DurationString, parseDuration} from '@alwatr/math';
import type {CryptoAlgorithm, CryptoEncoding} from './type.js';
export type TokenValidity = 'valid' | 'invalid' | 'expired';
/**
* Represents the configuration for a token generator.
*/
export interface TokenGeneratorConfig {
/**
* The prefix to be added to the generated hash.
*/
prefix: string;
/**
* The algorithm used for hashing.
*/
algorithm: CryptoAlgorithm;
/**
* The encoding used for the generated hash.
*/
encoding: CryptoEncoding;
/**
* The secret used for encryption and decryption tokens.
*/
secret: string;
/**
* The duration for which the token is valid.
*/
duration: DurationString | 'infinite';
}
/**
* Secure authentication HOTP token generator (HMAC-based One-Time Password algorithm).
*/
export class AlwatrTokenGenerator {
private _duration: number;
/**
* The current epoch based on the configured duration.
*/
protected get _epoch(): number {
return this._duration == 0 ? 0 : Math.floor(Date.now() / this._duration);
}
/**
* Creates a new instance of AlwatrTokenGenerator.
* @param config The configuration for the token generator.
*/
constructor(public config: TokenGeneratorConfig) {
this._duration = config.duration == 'infinite' ? 0 : parseDuration(config.duration);
}
/**
* Generates a HOTP token based on the provided data for special duration.
* @param data The data to generate the token from.
* @returns The generated token.
* @example
* ```typescript
* user.auth = tokenGenerator.generate(`${user.id}-${user.role}`);
* ```
*/
generate(data: string): string {
return this._generate(data, this._epoch);
}
/**
* Verifies if a token is valid.
* @param data The data used to generate the token.
* @param token The token to verify.
* @returns The validity of the token.
* @example
* ```typescript
* const validateStatus = tokenGenerator.verify([user.id,user.role].join(), user.auth);
* ```
*/
verify(data: string, token: string): TokenValidity {
const epoch = this._epoch;
if (token === this._generate(data, epoch)) return 'valid';
if (this._duration == 0) return 'invalid';
if (token === this._generate(data, epoch - 1)) return 'expired';
return 'invalid';
}
/**
* Generates a cryptographic token based on the provided data and epoch.
* @param data - The data to be used in the token generation.
* @param epoch - The epoch value to be used in the token generation.
* @returns The generated cryptographic token.
*/
protected _generate(data: string, epoch: number): string {
return (
this.config.prefix +
createHmac(this.config.algorithm, data)
.update(data + epoch)
.digest(this.config.encoding)
);
}
}