UNPKG

@stacks/auth

Version:

Authentication for Stacks apps.

141 lines 4.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.doSignaturesMatchPublicKeys = doSignaturesMatchPublicKeys; exports.doPublicKeysMatchIssuer = doPublicKeysMatchIssuer; exports.isIssuanceDateValid = isIssuanceDateValid; exports.isExpirationDateValid = isExpirationDateValid; exports.isManifestUriValid = isManifestUriValid; exports.isRedirectUriValid = isRedirectUriValid; exports.verifyAuthRequest = verifyAuthRequest; exports.verifyAuthRequestAndLoadManifest = verifyAuthRequestAndLoadManifest; exports.verifyAuthResponse = verifyAuthResponse; const common_1 = require("@stacks/common"); const encryption_1 = require("@stacks/encryption"); const jsontokens_1 = require("jsontokens"); const dids_1 = require("./dids"); const provider_1 = require("./provider"); function doSignaturesMatchPublicKeys(token) { const payload = (0, jsontokens_1.decodeToken)(token).payload; if (typeof payload === 'string') { throw new Error('Unexpected token payload type of string'); } const publicKeys = payload.public_keys; if (publicKeys.length === 1) { const publicKey = publicKeys[0]; try { const tokenVerifier = new jsontokens_1.TokenVerifier('ES256k', publicKey); return tokenVerifier.verify(token); } catch (e) { return false; } } else { throw new Error('Multiple public keys are not supported'); } } function doPublicKeysMatchIssuer(token) { const payload = (0, jsontokens_1.decodeToken)(token).payload; if (typeof payload === 'string') { throw new Error('Unexpected token payload type of string'); } const publicKeys = payload.public_keys; const addressFromIssuer = (0, dids_1.getAddressFromDID)(payload.iss); if (publicKeys.length === 1) { const addressFromPublicKeys = (0, encryption_1.publicKeyToBtcAddress)(publicKeys[0]); if (addressFromPublicKeys === addressFromIssuer) { return true; } } else { throw new Error('Multiple public keys are not supported'); } return false; } function isIssuanceDateValid(token) { const payload = (0, jsontokens_1.decodeToken)(token).payload; if (typeof payload === 'string') { throw new Error('Unexpected token payload type of string'); } if (payload.iat) { if (typeof payload.iat !== 'number') { return false; } const issuedAt = new Date(payload.iat * 1000); if (new Date().getTime() < issuedAt.getTime()) { return false; } else { return true; } } else { return true; } } function isExpirationDateValid(token) { const payload = (0, jsontokens_1.decodeToken)(token).payload; if (typeof payload === 'string') { throw new Error('Unexpected token payload type of string'); } if (payload.exp) { if (typeof payload.exp !== 'number') { return false; } const expiresAt = new Date(payload.exp * 1000); if (new Date().getTime() > expiresAt.getTime()) { return false; } else { return true; } } else { return true; } } function isManifestUriValid(token) { const payload = (0, jsontokens_1.decodeToken)(token).payload; if (typeof payload === 'string') { throw new Error('Unexpected token payload type of string'); } return (0, common_1.isSameOriginAbsoluteUrl)(payload.domain_name, payload.manifest_uri); } function isRedirectUriValid(token) { const payload = (0, jsontokens_1.decodeToken)(token).payload; if (typeof payload === 'string') { throw new Error('Unexpected token payload type of string'); } return (0, common_1.isSameOriginAbsoluteUrl)(payload.domain_name, payload.redirect_uri); } function verifyAuthRequest(token) { if ((0, jsontokens_1.decodeToken)(token).header.alg === 'none') { throw new Error('Token must be signed in order to be verified'); } const values = [ isExpirationDateValid(token), isIssuanceDateValid(token), doSignaturesMatchPublicKeys(token), doPublicKeysMatchIssuer(token), isManifestUriValid(token), isRedirectUriValid(token), ]; return Promise.resolve(values.every(val => val)); } async function verifyAuthRequestAndLoadManifest(token) { const valid = await verifyAuthRequest(token); if (!valid) { throw new Error('Token is an invalid auth request'); } return (0, provider_1.fetchAppManifest)(token); } function verifyAuthResponse(token) { const conditions = [ isExpirationDateValid(token), isIssuanceDateValid(token), doSignaturesMatchPublicKeys(token), doPublicKeysMatchIssuer(token), ]; return Promise.resolve(conditions.every(val => val)); } //# sourceMappingURL=verification.js.map