forked from DuendeArchive/identity-model-oidc-client-js
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJoseUtil.js
More file actions
154 lines (133 loc) · 5.06 KB
/
JoseUtil.js
File metadata and controls
154 lines (133 loc) · 5.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
import { jws, KEYUTIL as KeyUtil, X509, crypto, hextob64u } from 'jsrsasign';
import Log from './Log';
const AllowedSigningAlgs = ['RS256', 'RS384', 'RS512', 'PS256', 'PS384', 'PS512', 'ES256', 'ES384', 'ES512'];
export default class JoseUtil {
static parseJwt(jwt) {
Log.debug("JoseUtil.parseJwt");
try {
var token = jws.JWS.parse(jwt);
return {
header: token.headerObj,
payload: token.payloadObj
}
}
catch (e) {
Log.error(e);
}
}
static validateJwt(jwt, key, issuer, audience, clockSkew, now) {
Log.debug("JoseUtil.validateJwt");
try {
if (key.kty === "RSA") {
if (key.e && key.n) {
key = KeyUtil.getKey(key);
}
else if (key.x5c && key.x5c.length) {
key = KeyUtil.getKey(X509.getPublicKeyFromCertPEM(key.x5c[0]));
}
else {
Log.error("RSA key missing key material", key);
return Promise.reject(new Error("RSA key missing key material"));
}
}
else if (key.kty === "EC") {
if (key.crv && key.x && key.y) {
key = KeyUtil.getKey(key);
}
else {
Log.error("EC key missing key material", key);
return Promise.reject(new Error("EC key missing key material"));
}
}
else {
Log.error("Unsupported key type", key && key.kty);
return Promise.reject(new Error("Unsupported key type: " + key && key.kty));
}
return JoseUtil._validateJwt(jwt, key, issuer, audience, clockSkew, now);
}
catch (e) {
Log.error(e && e.message || e);
return Promise.reject("JWT validation failed");
}
}
static _validateJwt(jwt, key, issuer, audience, clockSkew, now) {
Log.debug("JoseUtil._validateJwt");
if (!clockSkew) {
clockSkew = 0;
}
if (!now) {
now = parseInt(Date.now() / 1000);
}
var payload = JoseUtil.parseJwt(jwt).payload;
if (!payload.iss) {
Log.error("issuer was not provided");
return Promise.reject(new Error("issuer was not provided"));
}
if (payload.iss !== issuer) {
Log.error("Invalid issuer in token", payload.iss);
return Promise.reject(new Error("Invalid issuer in token: " + payload.iss));
}
if (!payload.aud) {
Log.error("aud was not provided");
return Promise.reject(new Error("aud was not provided"));
}
var validAudience = payload.aud === audience || (Array.isArray(payload.aud) && payload.aud.indexOf(audience) >= 0);
if (!validAudience) {
Log.error("Invalid audience in token", payload.aud);
return Promise.reject(new Error("Invalid audience in token: " + payload.aud));
}
var lowerNow = now + clockSkew;
var upperNow = now - clockSkew;
if (!payload.iat) {
Log.error("iat was not provided");
return Promise.reject(new Error("iat was not provided"));
}
if (lowerNow < payload.iat) {
Log.error("iat is in the future", payload.iat);
return Promise.reject(new Error("iat is in the future: " + payload.iat));
}
if (payload.nbf && lowerNow < payload.nbf) {
Log.error("nbf is in the future", payload.nbf);
return Promise.reject(new Error("nbf is in the future: " + payload.nbf));
}
if (!payload.exp) {
Log.error("exp was not provided");
return Promise.reject(new Error("exp was not provided"));
}
if (payload.exp < upperNow) {
Log.error("exp is in the past", payload.exp);
return Promise.reject(new Error("exp is in the past:" + payload.exp));
}
try {
if (!jws.JWS.verify(jwt, key, AllowedSigningAlgs)) {
Log.error("signature validation failed");
return Promise.reject(new Error("signature validation failed"));
}
}
catch (e) {
Log.error(e && e.message || e);
return Promise.reject(new Error("signature validation failed"));
}
return Promise.resolve();
}
static hashString(value, alg) {
Log.debug("JoseUtil.hashString", value, alg);
try {
return crypto.Util.hashString(value, alg);
}
catch (e) {
Log.error(e);
}
}
static hexToBase64Url(value) {
Log.debug("JoseUtil.hexToBase64Url", value);
try {
return hextob64u(value);
}
catch (e) {
Log.error(e);
}
}
}