Add JWT
ci/woodpecker/push/test Pipeline failed

Closes #13
This commit is contained in:
2024-05-15 10:36:54 +02:00
parent de864ebab1
commit 0347f30bd0
4 changed files with 124 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
import {Result} from 'result'
import * as jose from 'jose'
export type JWTstring = `${string}.${string}.${string}`
export type JWTalgorithm = "HS256" | "HS512" | "ES256" | "ES512" | "EdDSA"
export type Key = jose.KeyLike | Uint8Array
/** KeyPair for asymmetric algorithms, [PrivKey, PubKey] */
export type KeyPair = [Key, Key]
export class JWTcontext {
public constructor(
private readonly key: Key | KeyPair,
private readonly alg: JWTalgorithm,
) {}
public static async gen_key(alg: JWTalgorithm, extractable: boolean = false) : Promise<Key | KeyPair> {
switch (alg) {
case "HS256":
case "HS512":
return jose.generateSecret(alg, { extractable })
case "EdDSA":
case "ES256":
case "ES512":
{
const key = await jose.generateKeyPair(alg)
return [key.privateKey, key.publicKey]
}
}
}
public async sign<T extends jose.JWTPayload>(message: T, set_issued: boolean = false, exp?: number | string | Date, audience?: string | string[], issuer?: string): Promise<JWT<T>> {
let jwt = new jose.SignJWT({payload: message}).setProtectedHeader({ alg: this.alg })
if (set_issued) jwt = jwt.setIssuedAt()
if (issuer !== undefined) jwt = jwt.setIssuer(issuer)
if (audience !== undefined) jwt = jwt.setAudience(audience)
if (exp !== undefined) jwt = jwt.setExpirationTime(exp)
const key = this.get_key(true)
const res = await jwt.sign(key) as JWTstring
return new JWT<T>(res)
}
public async verify<T>(jwt: JWT<T>, audience?: string | string[], issuer?: string | string[]): Promise<Result<T>> {
const key = this.get_key(false)
try {
let payload = await jose.jwtVerify(jwt.jwt, key)
return Result.ok(payload.payload.payload as T)
} catch(_) {}
return Result.error([])
}
private get_key(sign: boolean) : Key {
switch (this.alg) {
case "HS256":
case "HS512":
return this.key as Key
case "ES256":
case "ES512":
case "EdDSA":
return (this.key as KeyPair)[sign ? 0 : 1]
}
}
}
export class JWT<T> {
public constructor(
public readonly _jwt: `${string}.${string}.${string}`
) {}
public get payload() : T {
return jose.decodeJwt(this.jwt).payload as T
}
public get jwt() : JWTstring {
return this._jwt
}
}