UNPKG

@trimble-oss/trimble-id

Version:

Trimble Identity SDK for JavaScript/ TypeScript

154 lines (146 loc) 6.49 kB
'use strict'; (function (root, factory) { /* istanbul ignore next */ if (typeof define === 'function' && define.amd) { // AMD define(['./AnalyticsHttpClient', 'jsrsasign'], (AnalyticsHttpClient, rs) => { return factory({ AnalyticsHttpClient: AnalyticsHttpClient, KJUR: rs.KJUR, b64utoutf8: rs.b64utoutf8, KEYUTIL: rs.KEYUTIL }) }); } else if (typeof exports === 'object') { // CommonJS var rs = require('jsrsasign'); module.exports = factory({ AnalyticsHttpClient: require('./AnalyticsHttpClient'), KJUR: rs.KJUR, b64utoutf8: rs.b64utoutf8, KEYUTIL: rs.KEYUTIL }); } else { // Browser globals (Note: root is window) root.ValidatedClaimsetProvider = factory(root); } }(this, function (imports) { /** * @implements {IClaimsetProvider} * @description Provides validated claimset for a JSON web token */ class ValidatedClaimsetProvider { /** * @description Public constructor for ValidatedClaimsetProvider class * @param {IKeysetProvider} keysetProvider A provider for the keyset used to validate the JWT claimset. * It can be OpenIdKeysetProvider/FixedKeysetProvider */ constructor(keysetProvider) { this._keysetProvider = keysetProvider; this._keyset = null; this._clockSkewInSeconds = 5 * 60; this._tokenValidationRequired = true; //Send analytics this._analyticshttpclient = imports.AnalyticsHttpClient; this._analyticshttpclient.sendInitEvent(this.constructor.name); } /** * @description Fluent extension for setting clock skew/grace period while validating the token. * @param {number} clockSkewInSeconds is the acceptable time difference between signer and verifier in seconds. */ WithClockSkew(clockSkewInSeconds) { this._clockSkewInSeconds = clockSkewInSeconds; return this; } /** * @description Fluent extension for allowing token validation. * @param {boolean} token is validated before retrieving claims if tokenValidationRequired is set to true. */ WithTokenValidation(tokenValidationRequired) { this._tokenValidationRequired = tokenValidationRequired return this; } /** * @description Retrieves a validated claimset from a given JSON web token * @returns {PromiseLike<any>} A Task that resolves to the claimset completion * @exception Thrown when the keyset provider does not provide the named key * @exception Thrown when the JSON web token is invalid */ RetrieveClaimset(token) { //Send analytics this._analyticshttpclient.sendMethodEvent(this.RetrieveClaimset.name); var _this = this; return new Promise((resolve, reject) => { // get the kid from the JWT header var a = token.split('.'); var header = imports.KJUR.jws.JWS.readSafeJSONString(imports.b64utoutf8(a[0])); _this._findMatchingKey(header.kid) .then((key) => { if (_this._tokenValidationRequired) { if (_this._clockSkewInSeconds < 0) { reject("ClockSkew is less than 0") } else if (!_this._validateToken(token, key, _this._clockSkewInSeconds)) { reject('Unable to validate token'); } } var claimset = imports.KJUR.jws.JWS.readSafeJSONString(imports.b64utoutf8(a[1])); resolve(claimset); }) .catch((err) => { _this._analyticshttpclient.sendExceptionEvent(_this.RetrieveClaimset.name, err); reject('No key matching token KID in keyset: ' + err); }); }); } _retrieveKeyset() { var _this = this; return new Promise((resolve, reject) => { if (_this._keyset != null) { resolve(_this._keyset); } else { _this._keysetProvider.RetrieveKeyset() .then((keyset) => { _this._keyset = keyset; resolve(_this._keyset); }) .catch((err) => { reject('Unable to retrieve JSON web key set: ' + err); }); } }); } _findMatchingKey(kid) { var _this = this; return new Promise((resolve, reject) => { _this._retrieveKeyset() .then((keyset) => { var key = keyset.find((k) => k.kid == kid); if (key !== undefined) { resolve(key); } else { _this._keyset = null; _this._retrieveKeyset() .then((keyset) => { key = keyset.find((k) => k.kid == kid); if (key !== undefined) { resolve(key); } else { reject('No key matching token KID in keyset'); } }) .catch((err) => { reject('Unable to retrieve JSON web key set: ' + err); }); } }) .catch((err) => { reject('Unable to retrieve JSON web key set: ' + err); }); }); } _validateToken(token, key, clockSkewInSeconds) { var cryptoKey = imports.KEYUTIL.getKey(key); return imports.KJUR.jws.JWS.verifyJWT(token, cryptoKey, { alg: ["RS256"], gracePeriod: clockSkewInSeconds }); } } // Exposed public methods return ValidatedClaimsetProvider; }));