Skip to content

Commit 84d0c7e

Browse files
authored
Merge branch 'dev' into master
2 parents 43bd23d + 27ead3b commit 84d0c7e

13 files changed

+220
-41
lines changed

gulpfile.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ gulp.task('build-lib-sourcemap', ['jsrsasign'], function() {
1717
entry: npmEntry,
1818
output: {
1919
filename:'oidc-client.js',
20-
libraryTarget:'umd'
20+
libraryTarget:'umd',
21+
// Workaround for https://github.com/webpack/webpack/issues/6642
22+
globalObject: 'this'
2123
},
2224
plugins: [],
2325
devtool:'inline-source-map'
@@ -34,6 +36,8 @@ gulp.task('build-lib-min', ['jsrsasign'], function() {
3436
output: {
3537
filename:'oidc-client.min.js',
3638
libraryTarget:'umd',
39+
// Workaround for https://github.com/webpack/webpack/issues/6642
40+
globalObject: 'this'
3741
},
3842
plugins: [],
3943
devtool: false,

index.d.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ export interface OidcClientSettings {
140140
readonly staleStateAge?: number;
141141
readonly clockSkew?: number;
142142
readonly stateStore?: StateStore;
143+
readonly userInfoJwtIssuer?: 'ANY' | 'OP' | string;
143144
ResponseValidatorCtor?: ResponseValidatorCtor;
144145
MetadataServiceCtor?: MetadataServiceCtor;
145146
extraQueryParams?: {};
@@ -250,13 +251,14 @@ export class WebStorageStateStore implements StateStore {
250251
}
251252

252253
export interface SigninResponse {
253-
new (url: string): SigninResponse;
254+
new (url: string, delimiter: string = '#'): SigninResponse;
254255

255256
access_token: string;
257+
code: string;
256258
error: string;
257259
error_description: string;
258260
error_uri: string;
259-
expires_at: number;
261+
expires_in: number;
260262
id_token: string;
261263
profile: any;
262264
scope: string;
@@ -279,17 +281,31 @@ export interface SignoutResponse {
279281
state: any;
280282
}
281283

284+
export interface UserSettings {
285+
id_token: string;
286+
session_state: any;
287+
access_token: string;
288+
refresh_token: string;
289+
token_type: string;
290+
scope: string;
291+
profile: any;
292+
expires_at: number;
293+
state: any;
294+
}
295+
282296
export class User {
283-
constructor(response: SigninResponse);
297+
constructor(settings: UserSettings);
284298

285299
id_token: string;
286300
session_state: any;
287301
access_token: string;
302+
refresh_token: string;
288303
token_type: string;
289304
scope: string;
290305
profile: any;
291306
expires_at: number;
292307
state: any;
308+
293309
toStorageString(): string;
294310

295311
readonly expires_in: number | undefined;

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,13 @@
4343
"gulp-concat": "^2.6.1",
4444
"mocha": "^5.2.0",
4545
"natives": "^1.1.6",
46+
"open": "0.0.5",
4647
"uglifyjs-webpack-plugin": "^1.2.7",
4748
"webpack": "^4.16.0",
4849
"webpack-stream": "^4.0.3"
4950
},
5051
"dependencies": {
5152
"jsrsasign": "^8.0.12"
5253
},
53-
"optionalDependencies": {
54-
"babel-polyfill": ">=6.9.1"
55-
},
5654
"typings": "index.d.ts"
5755
}

src/JoseUtil.js

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export class JoseUtil {
2323
}
2424
}
2525

26-
static validateJwt(jwt, key, issuer, audience, clockSkew, now) {
26+
static validateJwt(jwt, key, issuer, audience, clockSkew, now, timeInsensitive) {
2727
Log.debug("JoseUtil.validateJwt");
2828

2929
try {
@@ -54,15 +54,15 @@ export class JoseUtil {
5454
return Promise.reject(new Error("Unsupported key type: " + key && key.kty));
5555
}
5656

57-
return JoseUtil._validateJwt(jwt, key, issuer, audience, clockSkew, now);
57+
return JoseUtil._validateJwt(jwt, key, issuer, audience, clockSkew, now, timeInsensitive);
5858
}
5959
catch (e) {
6060
Log.error(e && e.message || e);
6161
return Promise.reject("JWT validation failed");
6262
}
6363
}
6464

65-
static validateJwtAttributes(jwt, issuer, audience, clockSkew, now) {
65+
static validateJwtAttributes(jwt, issuer, audience, clockSkew, now, timeInsensitive) {
6666
if (!clockSkew) {
6767
clockSkew = 0;
6868
}
@@ -96,38 +96,40 @@ export class JoseUtil {
9696
return Promise.reject(new Error("Invalid azp in token: " + payload.azp));
9797
}
9898

99-
var lowerNow = now + clockSkew;
100-
var upperNow = now - clockSkew;
99+
if (!timeInsensitive) {
100+
var lowerNow = now + clockSkew;
101+
var upperNow = now - clockSkew;
101102

102-
if (!payload.iat) {
103-
Log.error("JoseUtil._validateJwt: iat was not provided");
104-
return Promise.reject(new Error("iat was not provided"));
105-
}
106-
if (lowerNow < payload.iat) {
107-
Log.error("JoseUtil._validateJwt: iat is in the future", payload.iat);
108-
return Promise.reject(new Error("iat is in the future: " + payload.iat));
109-
}
103+
if (!payload.iat) {
104+
Log.error("JoseUtil._validateJwt: iat was not provided");
105+
return Promise.reject(new Error("iat was not provided"));
106+
}
107+
if (lowerNow < payload.iat) {
108+
Log.error("JoseUtil._validateJwt: iat is in the future", payload.iat);
109+
return Promise.reject(new Error("iat is in the future: " + payload.iat));
110+
}
110111

111-
if (payload.nbf && lowerNow < payload.nbf) {
112-
Log.error("JoseUtil._validateJwt: nbf is in the future", payload.nbf);
113-
return Promise.reject(new Error("nbf is in the future: " + payload.nbf));
114-
}
112+
if (payload.nbf && lowerNow < payload.nbf) {
113+
Log.error("JoseUtil._validateJwt: nbf is in the future", payload.nbf);
114+
return Promise.reject(new Error("nbf is in the future: " + payload.nbf));
115+
}
115116

116-
if (!payload.exp) {
117-
Log.error("JoseUtil._validateJwt: exp was not provided");
118-
return Promise.reject(new Error("exp was not provided"));
119-
}
120-
if (payload.exp < upperNow) {
121-
Log.error("JoseUtil._validateJwt: exp is in the past", payload.exp);
122-
return Promise.reject(new Error("exp is in the past:" + payload.exp));
117+
if (!payload.exp) {
118+
Log.error("JoseUtil._validateJwt: exp was not provided");
119+
return Promise.reject(new Error("exp was not provided"));
120+
}
121+
if (payload.exp < upperNow) {
122+
Log.error("JoseUtil._validateJwt: exp is in the past", payload.exp);
123+
return Promise.reject(new Error("exp is in the past:" + payload.exp));
124+
}
123125
}
124126

125127
return Promise.resolve(payload);
126128
}
127129

128-
static _validateJwt(jwt, key, issuer, audience, clockSkew, now) {
130+
static _validateJwt(jwt, key, issuer, audience, clockSkew, now, timeInsensitive) {
129131

130-
return JoseUtil.validateJwtAttributes(jwt, issuer, audience, clockSkew, now).then(payload => {
132+
return JoseUtil.validateJwtAttributes(jwt, issuer, audience, clockSkew, now, timeInsensitive).then(payload => {
131133
try {
132134
if (!jws.JWS.verify(jwt, key, AllowedSigningAlgs)) {
133135
Log.error("JoseUtil._validateJwt: signature validation failed");

src/JsonService.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import { Log } from './Log.js';
55
import { Global } from './Global.js';
66

77
export class JsonService {
8-
constructor(additionalContentTypes = null, XMLHttpRequestCtor = Global.XMLHttpRequest) {
8+
constructor(
9+
additionalContentTypes = null,
10+
XMLHttpRequestCtor = Global.XMLHttpRequest,
11+
jwtHandler = null
12+
) {
913
if (additionalContentTypes && Array.isArray(additionalContentTypes))
1014
{
1115
this._contentTypes = additionalContentTypes.slice();
@@ -15,8 +19,12 @@ export class JsonService {
1519
this._contentTypes = [];
1620
}
1721
this._contentTypes.push('application/json');
22+
if (jwtHandler) {
23+
this._contentTypes.push('application/jwt');
24+
}
1825

1926
this._XMLHttpRequest = XMLHttpRequestCtor;
27+
this._jwtHandler = jwtHandler;
2028
}
2129

2230
getJson(url, token) {
@@ -33,6 +41,7 @@ export class JsonService {
3341
req.open('GET', url);
3442

3543
var allowedContentTypes = this._contentTypes;
44+
var jwtHandler = this._jwtHandler;
3645

3746
req.onload = function() {
3847
Log.debug("JsonService.getJson: HTTP response received, status", req.status);
@@ -48,6 +57,11 @@ export class JsonService {
4857
}
4958
});
5059

60+
if (found == "application/jwt") {
61+
jwtHandler(req).then(resolve, reject);
62+
return;
63+
}
64+
5165
if (found) {
5266
try {
5367
resolve(JSON.parse(req.responseText));

src/OidcClient.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,13 @@ export class OidcClient {
123123
});
124124
}
125125

126-
createSignoutRequest({id_token_hint, data, state, post_logout_redirect_uri} = {},
126+
createSignoutRequest({id_token_hint, data, state, post_logout_redirect_uri, extraQueryParams } = {},
127127
stateStore
128128
) {
129129
Log.debug("OidcClient.createSignoutRequest");
130130

131131
post_logout_redirect_uri = post_logout_redirect_uri || this._settings.post_logout_redirect_uri;
132+
extraQueryParams = extraQueryParams || this._settings.extraQueryParams;
132133

133134
return this._metadataService.getEndSessionEndpoint().then(url => {
134135
if (!url) {
@@ -142,7 +143,8 @@ export class OidcClient {
142143
url,
143144
id_token_hint,
144145
post_logout_redirect_uri,
145-
data: data || state
146+
data: data || state,
147+
extraQueryParams
146148
});
147149

148150
var signoutState = request.state;

src/OidcClientSettings.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export class OidcClientSettings {
2525
// behavior flags
2626
filterProtocolClaims = true, loadUserInfo = true,
2727
staleStateAge = DefaultStaleStateAge, clockSkew = DefaultClockSkewInSeconds,
28+
userInfoJwtIssuer = 'OP',
2829
// other behavior
2930
stateStore = new WebStorageStateStore(),
3031
ResponseValidatorCtor = ResponseValidator,
@@ -57,6 +58,7 @@ export class OidcClientSettings {
5758
this._loadUserInfo = !!loadUserInfo;
5859
this._staleStateAge = staleStateAge;
5960
this._clockSkew = clockSkew;
61+
this._userInfoJwtIssuer = userInfoJwtIssuer;
6062

6163
this._stateStore = stateStore;
6264
this._validator = new ResponseValidatorCtor(this);
@@ -177,6 +179,9 @@ export class OidcClientSettings {
177179
get clockSkew() {
178180
return this._clockSkew;
179181
}
182+
get userInfoJwtIssuer() {
183+
return this._userInfoJwtIssuer;
184+
}
180185

181186
get stateStore() {
182187
return this._stateStore;

src/ResponseValidator.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,12 @@ export class ResponseValidator {
187187
}
188188
}
189189
else if (result[name] !== value) {
190-
result[name] = [result[name], value];
190+
if (typeof value === 'object') {
191+
result[name] = this._mergeClaims(result[name], value);
192+
}
193+
else {
194+
result[name] = [result[name], value];
195+
}
191196
}
192197
}
193198
}

src/SignoutRequest.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { UrlUtility } from './UrlUtility.js';
66
import { State } from './State.js';
77

88
export class SignoutRequest {
9-
constructor({url, id_token_hint, post_logout_redirect_uri, data}) {
9+
constructor({url, id_token_hint, post_logout_redirect_uri, data, extraQueryParams}) {
1010
if (!url) {
1111
Log.error("SignoutRequest.ctor: No url passed");
1212
throw new Error("url");
@@ -26,6 +26,10 @@ export class SignoutRequest {
2626
}
2727
}
2828

29+
for(let key in extraQueryParams){
30+
url = UrlUtility.addQueryParam(url, key, extraQueryParams[key])
31+
}
32+
2933
this.url = url;
3034
}
3135
}

0 commit comments

Comments
 (0)