@trimble-oss/trimble-id
Version:
Trimble Identity SDK for JavaScript/ TypeScript
154 lines (146 loc) • 6.49 kB
JavaScript
;
(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;
}));