Skip to content

Commit 0db16e3

Browse files
committed
allow certificates in PEM format
1 parent 3ffe224 commit 0db16e3

File tree

3 files changed

+82
-6
lines changed

3 files changed

+82
-6
lines changed

src/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const scheme = joi.object({
1818
.description('The related secret of the Keycloak client/application')
1919
.example('1234-bar-4321-foo'),
2020
publicKey: joi.alternatives().try(
21-
joi.string().regex(/^-----BEGIN(?: RSA)? PUBLIC KEY-----[\s\S]*-----END(?: RSA)? PUBLIC KEY-----\s?$/ig, 'PEM'),
21+
joi.string().regex(/^-----BEGIN((( RSA)? PUBLIC KEY)| CERTIFICATE)-----[\s\S]*-----END((( RSA)? PUBLIC KEY)| CERTIFICATE)-----\s?$/ig, 'PEM'),
2222
joi.object().type(Buffer),
2323
joi.object({
2424
kty: joi.string().required()

test/fixtures/index.js

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,20 @@ const realmUrl = `${baseUrl}${realmPath}`
99
const clientId = 'foobar'
1010
const secret = '1234-bar-4321-foo'
1111
const publicKeyBuffer = fs.readFileSync('./test/fixtures/public.pem')
12-
const publicKey = `-----BEGIN RSA PUBLIC KEY-----
12+
const publicKey = `-----BEGIN PUBLIC KEY-----
13+
MIICCgKCAgEAur96MoQa/blg5eJFqmN//V4oQjKaBJl6KEvWSGAVgRm2PsnFKzCJ
14+
K9aJrUjETS473/x6fAHXyF5QKun6avNxpWs2VzwlO4t8Bi2EpSW2w0led2OzR/MF
15+
CYUX1Bg00OXLmdh0kvemABHXSOL4Zs4nN95rr77JsdG6ntylWmtnZlofySwLjFrX
16+
B2JFpunl4n7eF7y8vD4Zyycvi+xl+OuMA6qomLQmfIDF0qJh0QMt/xh6CB4ooK5a
17+
Fy6VHORU5gS6MoSgJ78ZPhqmKayRd6U0rhDOq7bWiVykktTPdB1X/YlMbQHonyqZ
18+
0z2sh7e7olroUdE1FsDi0SdxV2Zzvff8IIPSGT74gQuaU4buoVUpMjSdXDfJw9m4
19+
i/mhsZwX1/MUU8Oq1AsBHdgTkNVaVwFc6Z7AqJSGW/mxMKQqspOr+/BAM8pnw5BC
20+
R/RnZBJfMjAYiSh6rVYuEWUBBLgZWIRNAMyRwS8OtWxADfOBtVwn8fmw8schro9X
21+
D17VcqTdjlS1Mkr73ZoD1GagWZvuSOaz2P0PhnfapRUF1KkbjjnbyzLpfT8Mgovv
22+
xBQJDIcRYL5oetXu//V5rNAr0na4zMBkPOi3ArpFp+Z4YKulYmSEG//216rLmzjl
23+
WKEkH1OK39jddDrMTidlxDKY+THheyQBPZ6pFfbKEM5281glYjkeQpECAwEAAQ==
24+
-----END PUBLIC KEY-----`
25+
const publicKeyRsa = `-----BEGIN RSA PUBLIC KEY-----
1326
MIICCgKCAgEAur96MoQa/blg5eJFqmN//V4oQjKaBJl6KEvWSGAVgRm2PsnFKzCJ
1427
K9aJrUjETS473/x6fAHXyF5QKun6avNxpWs2VzwlO4t8Bi2EpSW2w0led2OzR/MF
1528
CYUX1Bg00OXLmdh0kvemABHXSOL4Zs4nN95rr77JsdG6ntylWmtnZlofySwLjFrX
@@ -22,7 +35,20 @@ D17VcqTdjlS1Mkr73ZoD1GagWZvuSOaz2P0PhnfapRUF1KkbjjnbyzLpfT8Mgovv
2235
xBQJDIcRYL5oetXu//V5rNAr0na4zMBkPOi3ArpFp+Z4YKulYmSEG//216rLmzjl
2336
WKEkH1OK39jddDrMTidlxDKY+THheyQBPZ6pFfbKEM5281glYjkeQpECAwEAAQ==
2437
-----END RSA PUBLIC KEY-----`
25-
const publicKeyJWK = {
38+
const publicKeyCert = `-----BEGIN CERTIFICATE-----
39+
MIICCgKCAgEAur96MoQa/blg5eJFqmN//V4oQjKaBJl6KEvWSGAVgRm2PsnFKzCJ
40+
K9aJrUjETS473/x6fAHXyF5QKun6avNxpWs2VzwlO4t8Bi2EpSW2w0led2OzR/MF
41+
CYUX1Bg00OXLmdh0kvemABHXSOL4Zs4nN95rr77JsdG6ntylWmtnZlofySwLjFrX
42+
B2JFpunl4n7eF7y8vD4Zyycvi+xl+OuMA6qomLQmfIDF0qJh0QMt/xh6CB4ooK5a
43+
Fy6VHORU5gS6MoSgJ78ZPhqmKayRd6U0rhDOq7bWiVykktTPdB1X/YlMbQHonyqZ
44+
0z2sh7e7olroUdE1FsDi0SdxV2Zzvff8IIPSGT74gQuaU4buoVUpMjSdXDfJw9m4
45+
i/mhsZwX1/MUU8Oq1AsBHdgTkNVaVwFc6Z7AqJSGW/mxMKQqspOr+/BAM8pnw5BC
46+
R/RnZBJfMjAYiSh6rVYuEWUBBLgZWIRNAMyRwS8OtWxADfOBtVwn8fmw8schro9X
47+
D17VcqTdjlS1Mkr73ZoD1GagWZvuSOaz2P0PhnfapRUF1KkbjjnbyzLpfT8Mgovv
48+
xBQJDIcRYL5oetXu//V5rNAr0na4zMBkPOi3ArpFp+Z4YKulYmSEG//216rLmzjl
49+
WKEkH1OK39jddDrMTidlxDKY+THheyQBPZ6pFfbKEM5281glYjkeQpECAwEAAQ==
50+
-----END CERTIFICATE-----`
51+
const publicKeyJwk = {
2652
kty: 'RSA',
2753
n: 'ALq_ejKEGv25YOXiRapjf_1eKEIymgSZeihL1khgFYEZtj7JxSswiSvWia1IxE0uO9_8enwB18heUCrp-mrzcaVrNlc8JTuLfAYthKUltsNJXndjs0fzBQmFF9QYNNDly5nYdJL3pgAR10ji-GbOJzfea6--ybHRup7cpVprZ2ZaH8ksC4xa1wdiRabp5eJ-3he8vLw-GcsnL4vsZfjrjAOqqJi0JnyAxdKiYdEDLf8YeggeKKCuWhculRzkVOYEujKEoCe_GT4apimskXelNK4Qzqu21olcpJLUz3QdV_2JTG0B6J8qmdM9rIe3u6Ja6FHRNRbA4tEncVdmc733_CCD0hk--IELmlOG7qFVKTI0nVw3ycPZuIv5obGcF9fzFFPDqtQLAR3YE5DVWlcBXOmewKiUhlv5sTCkKrKTq_vwQDPKZ8OQQkf0Z2QSXzIwGIkoeq1WLhFlAQS4GViETQDMkcEvDrVsQA3zgbVcJ_H5sPLHIa6PVw9e1XKk3Y5UtTJK-92aA9RmoFmb7kjms9j9D4Z32qUVBdSpG44528sy6X0_DIKL78QUCQyHEWC-aHrV7v_1eazQK9J2uMzAZDzotwK6RafmeGCrpWJkhBv_9teqy5s45VihJB9Tit_Y3XQ6zE4nZcQymPkx4XskAT2eqRX2yhDOdvNYJWI5HkKR',
2854
e: 'AQAB'
@@ -48,8 +74,10 @@ const clientConfig = {
4874
*/
4975
const common = Object.assign({}, clientConfig, {
5076
publicKey,
77+
publicKeyRsa,
78+
publicKeyCert,
5179
publicKeyBuffer,
52-
publicKeyJWK,
80+
publicKeyJwk,
5381
baseUrl,
5482
token,
5583
realmPath,

test/utils.spec.js

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ test('throw error if options are invalid – publicKey', (t) => {
143143

144144
test('throw error if options are invalid – publicKey/secret conflict', (t) => {
145145
t.throws(() => utils.verify(helpers.getOptions({
146-
publicKey: fixtures.common.publicKey
146+
publicKey: fixtures.common.publicKeyRsa
147147
})), Error, 'publicKey/secret: both defined')
148148
})
149149

@@ -269,6 +269,30 @@ test('throw no error if options are valid – offline', (t) => {
269269
})
270270
})
271271

272+
test('throw no error if options are valid – publicKeyRsa/string', (t) => {
273+
const valids = [
274+
{ cache: {} },
275+
{ cache: { segment: 'foobar' } },
276+
{ cache: true },
277+
{ cache: false },
278+
{ userInfo: [] },
279+
{ userInfo: ['string'] },
280+
{ minTimeBetweenJwksRequests: 0 },
281+
{ minTimeBetweenJwksRequests: 42 }
282+
]
283+
284+
t.plan(valids.length)
285+
286+
valids.forEach((valid) => {
287+
t.notThrows(
288+
() => utils.verify(helpers.getOptions(Object.assign({
289+
secret: undefined,
290+
publicKey: fixtures.common.publicKeyRsa
291+
}, valid))),
292+
Error, helpers.log('valid.publicKeyRsa.string', valid))
293+
})
294+
})
295+
272296
test('throw no error if options are valid – publicKey/string', (t) => {
273297
const valids = [
274298
{ cache: {} },
@@ -293,6 +317,30 @@ test('throw no error if options are valid – publicKey/string', (t) => {
293317
})
294318
})
295319

320+
test('throw no error if options are valid – publicKeyCert/string', (t) => {
321+
const valids = [
322+
{ cache: {} },
323+
{ cache: { segment: 'foobar' } },
324+
{ cache: true },
325+
{ cache: false },
326+
{ userInfo: [] },
327+
{ userInfo: ['string'] },
328+
{ minTimeBetweenJwksRequests: 0 },
329+
{ minTimeBetweenJwksRequests: 42 }
330+
]
331+
332+
t.plan(valids.length)
333+
334+
valids.forEach((valid) => {
335+
t.notThrows(
336+
() => utils.verify(helpers.getOptions(Object.assign({
337+
secret: undefined,
338+
publicKey: fixtures.common.publicKeyCert
339+
}, valid))),
340+
Error, helpers.log('valid.publicKeyCert.string', valid))
341+
})
342+
})
343+
296344
test('throw no error if options are valid – publicKey/Buffer', (t) => {
297345
const valids = [
298346
{},
@@ -362,7 +410,7 @@ test('throw no error if options are valid – publicKey/JWK', (t) => {
362410
t.notThrows(
363411
() => utils.verify(helpers.getOptions(Object.assign({
364412
secret: undefined,
365-
publicKey: fixtures.common.publicKeyJWK
413+
publicKey: fixtures.common.publicKeyJwk
366414
}, valid))),
367415
Error, helpers.log('valid.publicKey.JWK', valid))
368416
})

0 commit comments

Comments
 (0)