Erster Docker-Stand
This commit is contained in:
197
_node_modules/hono/dist/utils/jwt/jwt.js
generated
vendored
Normal file
197
_node_modules/hono/dist/utils/jwt/jwt.js
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
// src/utils/jwt/jwt.ts
|
||||
import { decodeBase64Url, encodeBase64Url } from "../../utils/encode.js";
|
||||
import { AlgorithmTypes } from "./jwa.js";
|
||||
import { signing, verifying } from "./jws.js";
|
||||
import {
|
||||
JwtAlgorithmMismatch,
|
||||
JwtAlgorithmNotAllowed,
|
||||
JwtAlgorithmRequired,
|
||||
JwtHeaderInvalid,
|
||||
JwtHeaderRequiresKid,
|
||||
JwtPayloadRequiresAud,
|
||||
JwtSymmetricAlgorithmNotAllowed,
|
||||
JwtTokenAudience,
|
||||
JwtTokenExpired,
|
||||
JwtTokenInvalid,
|
||||
JwtTokenIssuedAt,
|
||||
JwtTokenIssuer,
|
||||
JwtTokenNotBefore,
|
||||
JwtTokenSignatureMismatched
|
||||
} from "./types.js";
|
||||
import { utf8Decoder, utf8Encoder } from "./utf8.js";
|
||||
var encodeJwtPart = (part) => encodeBase64Url(utf8Encoder.encode(JSON.stringify(part)).buffer).replace(/=/g, "");
|
||||
var encodeSignaturePart = (buf) => encodeBase64Url(buf).replace(/=/g, "");
|
||||
var decodeJwtPart = (part) => JSON.parse(utf8Decoder.decode(decodeBase64Url(part)));
|
||||
function isTokenHeader(obj) {
|
||||
if (typeof obj === "object" && obj !== null) {
|
||||
const objWithAlg = obj;
|
||||
return "alg" in objWithAlg && Object.values(AlgorithmTypes).includes(objWithAlg.alg) && (!("typ" in objWithAlg) || objWithAlg.typ === "JWT");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
var sign = async (payload, privateKey, alg = "HS256") => {
|
||||
const encodedPayload = encodeJwtPart(payload);
|
||||
let encodedHeader;
|
||||
if (typeof privateKey === "object" && "alg" in privateKey) {
|
||||
alg = privateKey.alg;
|
||||
encodedHeader = encodeJwtPart({ alg, typ: "JWT", kid: privateKey.kid });
|
||||
} else {
|
||||
encodedHeader = encodeJwtPart({ alg, typ: "JWT" });
|
||||
}
|
||||
const partialToken = `${encodedHeader}.${encodedPayload}`;
|
||||
const signaturePart = await signing(privateKey, alg, utf8Encoder.encode(partialToken));
|
||||
const signature = encodeSignaturePart(signaturePart);
|
||||
return `${partialToken}.${signature}`;
|
||||
};
|
||||
var verify = async (token, publicKey, algOrOptions) => {
|
||||
if (!algOrOptions) {
|
||||
throw new JwtAlgorithmRequired();
|
||||
}
|
||||
const {
|
||||
alg,
|
||||
iss,
|
||||
nbf = true,
|
||||
exp = true,
|
||||
iat = true,
|
||||
aud
|
||||
} = typeof algOrOptions === "string" ? { alg: algOrOptions } : algOrOptions;
|
||||
if (!alg) {
|
||||
throw new JwtAlgorithmRequired();
|
||||
}
|
||||
const tokenParts = token.split(".");
|
||||
if (tokenParts.length !== 3) {
|
||||
throw new JwtTokenInvalid(token);
|
||||
}
|
||||
const { header, payload } = decode(token);
|
||||
if (!isTokenHeader(header)) {
|
||||
throw new JwtHeaderInvalid(header);
|
||||
}
|
||||
if (header.alg !== alg) {
|
||||
throw new JwtAlgorithmMismatch(alg, header.alg);
|
||||
}
|
||||
const now = Date.now() / 1e3 | 0;
|
||||
if (nbf && payload.nbf && payload.nbf > now) {
|
||||
throw new JwtTokenNotBefore(token);
|
||||
}
|
||||
if (exp && payload.exp && payload.exp <= now) {
|
||||
throw new JwtTokenExpired(token);
|
||||
}
|
||||
if (iat && payload.iat && now < payload.iat) {
|
||||
throw new JwtTokenIssuedAt(now, payload.iat);
|
||||
}
|
||||
if (iss) {
|
||||
if (!payload.iss) {
|
||||
throw new JwtTokenIssuer(iss, null);
|
||||
}
|
||||
if (typeof iss === "string" && payload.iss !== iss) {
|
||||
throw new JwtTokenIssuer(iss, payload.iss);
|
||||
}
|
||||
if (iss instanceof RegExp && !iss.test(payload.iss)) {
|
||||
throw new JwtTokenIssuer(iss, payload.iss);
|
||||
}
|
||||
}
|
||||
if (aud) {
|
||||
if (!payload.aud) {
|
||||
throw new JwtPayloadRequiresAud(payload);
|
||||
}
|
||||
const audiences = Array.isArray(payload.aud) ? payload.aud : [payload.aud];
|
||||
const matched = audiences.some(
|
||||
(payloadAud) => aud instanceof RegExp ? aud.test(payloadAud) : typeof aud === "string" ? payloadAud === aud : Array.isArray(aud) && aud.includes(payloadAud)
|
||||
);
|
||||
if (!matched) {
|
||||
throw new JwtTokenAudience(aud, payload.aud);
|
||||
}
|
||||
}
|
||||
const headerPayload = token.substring(0, token.lastIndexOf("."));
|
||||
const verified = await verifying(
|
||||
publicKey,
|
||||
alg,
|
||||
decodeBase64Url(tokenParts[2]),
|
||||
utf8Encoder.encode(headerPayload)
|
||||
);
|
||||
if (!verified) {
|
||||
throw new JwtTokenSignatureMismatched(token);
|
||||
}
|
||||
return payload;
|
||||
};
|
||||
var symmetricAlgorithms = [
|
||||
AlgorithmTypes.HS256,
|
||||
AlgorithmTypes.HS384,
|
||||
AlgorithmTypes.HS512
|
||||
];
|
||||
var verifyWithJwks = async (token, options, init) => {
|
||||
const verifyOpts = options.verification || {};
|
||||
const header = decodeHeader(token);
|
||||
if (!isTokenHeader(header)) {
|
||||
throw new JwtHeaderInvalid(header);
|
||||
}
|
||||
if (!header.kid) {
|
||||
throw new JwtHeaderRequiresKid(header);
|
||||
}
|
||||
if (symmetricAlgorithms.includes(header.alg)) {
|
||||
throw new JwtSymmetricAlgorithmNotAllowed(header.alg);
|
||||
}
|
||||
if (!options.allowedAlgorithms.includes(header.alg)) {
|
||||
throw new JwtAlgorithmNotAllowed(header.alg, options.allowedAlgorithms);
|
||||
}
|
||||
if (options.jwks_uri) {
|
||||
const response = await fetch(options.jwks_uri, init);
|
||||
if (!response.ok) {
|
||||
throw new Error(`failed to fetch JWKS from ${options.jwks_uri}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
if (!data.keys) {
|
||||
throw new Error('invalid JWKS response. "keys" field is missing');
|
||||
}
|
||||
if (!Array.isArray(data.keys)) {
|
||||
throw new Error('invalid JWKS response. "keys" field is not an array');
|
||||
}
|
||||
if (options.keys) {
|
||||
options.keys.push(...data.keys);
|
||||
} else {
|
||||
options.keys = data.keys;
|
||||
}
|
||||
} else if (!options.keys) {
|
||||
throw new Error('verifyWithJwks requires options for either "keys" or "jwks_uri" or both');
|
||||
}
|
||||
const matchingKey = options.keys.find((key) => key.kid === header.kid);
|
||||
if (!matchingKey) {
|
||||
throw new JwtTokenInvalid(token);
|
||||
}
|
||||
if (matchingKey.alg && matchingKey.alg !== header.alg) {
|
||||
throw new JwtAlgorithmMismatch(matchingKey.alg, header.alg);
|
||||
}
|
||||
return await verify(token, matchingKey, {
|
||||
alg: header.alg,
|
||||
...verifyOpts
|
||||
});
|
||||
};
|
||||
var decode = (token) => {
|
||||
try {
|
||||
const [h, p] = token.split(".");
|
||||
const header = decodeJwtPart(h);
|
||||
const payload = decodeJwtPart(p);
|
||||
return {
|
||||
header,
|
||||
payload
|
||||
};
|
||||
} catch {
|
||||
throw new JwtTokenInvalid(token);
|
||||
}
|
||||
};
|
||||
var decodeHeader = (token) => {
|
||||
try {
|
||||
const [h] = token.split(".");
|
||||
return decodeJwtPart(h);
|
||||
} catch {
|
||||
throw new JwtTokenInvalid(token);
|
||||
}
|
||||
};
|
||||
export {
|
||||
decode,
|
||||
decodeHeader,
|
||||
isTokenHeader,
|
||||
sign,
|
||||
verify,
|
||||
verifyWithJwks
|
||||
};
|
||||
Reference in New Issue
Block a user