Skip to content

Commit 6724c07

Browse files
committed
remove keycloak libary
1 parent d9fbe5c commit 6724c07

File tree

8 files changed

+657
-3008
lines changed

8 files changed

+657
-3008
lines changed

package-lock.json

Lines changed: 592 additions & 2954 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,15 @@
4141
"ava": "^0.20.0",
4242
"coveralls": "^2.13.1",
4343
"hapi": "^16.4.3",
44+
"nock": "^9.0.14",
4445
"nyc": "^11.0.3",
4546
"standard": "^10.0.2"
4647
},
4748
"dependencies": {
49+
"axios": "^0.16.2",
4850
"boom": "^5.2.0",
4951
"joi": "^10.6.0",
50-
"keycloak-auth-utils": "^3.2.1",
52+
"jsonwebtoken": "^7.4.1",
5153
"lodash": "^4.17.4"
5254
},
5355
"peerDependencies": {

src/index.js

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { GrantManager } = require('keycloak-auth-utils')
1+
const axios = require('axios')
22
const cache = require('./cache')
33
const token = require('./token')
44
const { error, fakeReply, verify } = require('./utils')
@@ -11,10 +11,26 @@ const pkg = require('../package.json')
1111
* Internally used properties
1212
*/
1313
const internals = {
14-
manager: undefined,
14+
clientOptions: undefined,
1515
userInfoFields: undefined
1616
}
1717

18+
function validateOnline (token) {
19+
const opts = internals.clientOptions
20+
21+
return axios.post(`${opts.realmUrl}/protocol/openid-connect/token/introspect`, {
22+
token,
23+
client_secret: opts.secret,
24+
client_id: opts.clientId
25+
}).then(({ data }) => {
26+
if (!data.active) {
27+
throw Error(error.msg.invalid)
28+
}
29+
30+
return token
31+
})
32+
}
33+
1834
/**
1935
* @function
2036
* @public
@@ -25,19 +41,15 @@ const internals = {
2541
* @param {Function} reply The callback handler
2642
*/
2743
function handleKeycloakValidation (tkn, reply) {
28-
const invalidate = (err) => reply(error('unauthorized', err, error.msg.invalid))
29-
30-
internals.manager.validateAccessToken(tkn.get()).then((res) => {
31-
if (!res) {
32-
return invalidate()
33-
}
34-
44+
validateOnline(tkn.get()).then((res) => {
3545
const { expiresIn, credentials } = tkn.getData(internals.userInfoFields)
3646
const userData = { credentials }
3747

3848
cache.set(tkn.get(), userData, expiresIn)
3949
return reply.continue(userData)
40-
}).catch(invalidate)
50+
}).catch((err) => {
51+
reply(error('unauthorized', err, error.msg.invalid))
52+
})
4153
}
4254

4355
/**
@@ -104,7 +116,7 @@ function plugin (server, opts, next) {
104116
opts = verify(opts)
105117
cache.init(server, opts.cache)
106118

107-
internals.manager = new GrantManager(opts.client)
119+
internals.clientOptions = opts.client
108120
internals.userInfoFields = opts.userInfo
109121

110122
server.auth.scheme('keycloak-jwt', strategy)

src/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function verify (opts) {
4848
* @returns {Boom} The created `Boom` error
4949
*/
5050
function error (type, err, msg) {
51-
return boom[type](err ? err.toString() : msg, 'Bearer')
51+
return boom[type](err ? err.message || err.toString() : msg, 'Bearer')
5252
}
5353

5454
/**

test/_fixtures.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
const token = 'abc.def.ghi'
2-
const realmUrl = 'https://localhost:8080/auth/realms/testme'
2+
const baseUrl = 'http://localhost:8080'
3+
const realmPath = '/auth/realms/testme'
4+
const introspectPath = '/protocol/openid-connect/token/introspect'
5+
const realmUrl = `${baseUrl}${realmPath}`
36
const clientId = 'foobar'
47
const secret = '1234-bar-4321-foo'
58

@@ -21,7 +24,12 @@ const clientConfig = {
2124
*
2225
* Common attributes
2326
*/
24-
const common = Object.assign({}, clientConfig, { token })
27+
const common = Object.assign({}, clientConfig, {
28+
baseUrl,
29+
token,
30+
realmPath,
31+
introspectPath
32+
})
2533

2634
/**
2735
* @type Object
@@ -37,6 +45,7 @@ const content = {
3745
'name': 'John Doe',
3846
'email': '[email protected]',
3947
'admin': true,
48+
'active': true,
4049
'realm_access': {
4150
'roles': [
4251
'admin'
@@ -71,9 +80,9 @@ const content = {
7180
* Various JSON Web Tokens
7281
*/
7382
const jwt = {
74-
userData: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjUsImlhdCI6MSwic3ViIjoiMTIzNDU2Nzg5MCIsIm5hbWUiOiJKb2huIERvZSIsImVtYWlsIjoiam9obi5kb2VAbWFpbC5jb20iLCJhZG1pbiI6dHJ1ZSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImFkbWluIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19LCJzYW1lIjp7InJvbGVzIjpbImVkaXRvciJdfSwib3RoZXItYXBwIjp7InJvbGVzIjpbIm90aGVyLWFwcDpjcmVhdG9yIl19fX0.uuhtpYNVtFZvPuRAEktWEDn_2u-dvimWnspXVt-gObU',
75-
userDataExp: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZW1haWwiOiJqb2huLmRvZUBtYWlsLmNvbSIsImFkbWluIjp0cnVlLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiYWRtaW4iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX0sInNhbWUiOnsicm9sZXMiOlsiZWRpdG9yIl19LCJvdGhlci1hcHAiOnsicm9sZXMiOlsib3RoZXItYXBwOmNyZWF0b3IiXX19fQ.BcTtSEpyiUVBVkUOwVDM0_T9UIy-vk2aaUAR8XM6Hd0',
76-
userDataScope: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjUsImlhdCI6MSwic3ViIjoiMTIzNDU2Nzg5MCIsIm5hbWUiOiJKb2huIERvZSIsImVtYWlsIjoiam9obi5kb2VAbWFpbC5jb20iLCJhZG1pbiI6dHJ1ZX0.2tfThhgwSbIEq2cZcoHSRwL2-UCanF23BXlyphm5ehs'
83+
userData: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjUsImFjdGl2ZSI6dHJ1ZSwiaWF0IjoxLCJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZW1haWwiOiJqb2huLmRvZUBtYWlsLmNvbSIsImFkbWluIjp0cnVlLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiYWRtaW4iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX0sInNhbWUiOnsicm9sZXMiOlsiZWRpdG9yIl19LCJvdGhlci1hcHAiOnsicm9sZXMiOlsib3RoZXItYXBwOmNyZWF0b3IiXX19fQ.rjQkSo132lPSVUEsuz42oB5u_lW9zCBpvnOyngDYa_0',
84+
userDataExp: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY3RpdmUiOnRydWUsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJlbWFpbCI6ImpvaG4uZG9lQG1haWwuY29tIiwiYWRtaW4iOnRydWUsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJhZG1pbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfSwic2FtZSI6eyJyb2xlcyI6WyJlZGl0b3IiXX0sIm90aGVyLWFwcCI6eyJyb2xlcyI6WyJvdGhlci1hcHA6Y3JlYXRvciJdfX19.0_g0X4cOpOEJ37qwRQzBpouQDn2aEyg0-0jnnWECCsk',
85+
userDataScope: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY3RpdmUiOnRydWUsImV4cCI6NSwiaWF0IjoxLCJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZW1haWwiOiJqb2huLmRvZUBtYWlsLmNvbSIsImFkbWluIjp0cnVlfQ.V7lYgZKjnDJcPtUnIBHA9f-8bn8XXB6uH8bXElH-aOU'
7786
}
7887

7988
module.exports = {

test/_helpers.js

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
const hapi = require('hapi')
2-
const _ = require('lodash')
3-
const { GrantManager } = require('keycloak-auth-utils')
2+
const nock = require('nock')
43
const authKeycloak = require('../src')
54
const fixtures = require('./_fixtures')
65

7-
const GrantManagerClone = {}
8-
96
/**
107
* @type Object
118
* @private
@@ -19,24 +16,20 @@ const defaults = {
1916
}
2017

2118
/**
22-
* @type Object.<Function>
19+
* @function
2320
* @public
2421
*
25-
* Provide several functions to clone, reset and
26-
* stub methods of `GrantManager`.
22+
* Mock introspect request to the Keycloak server.
23+
*
24+
* @param {number} code The status code to be returned
25+
* @param {Object} data The response object to be returned
26+
* @param {boolean} isError Whether to reply with an error
2727
*/
28-
const prototypes = {
29-
clone () {
30-
GrantManagerClone.prototype = _.cloneDeep(GrantManager.prototype)
31-
},
32-
reset () {
33-
GrantManager.prototype = GrantManagerClone.prototype
34-
},
35-
stub (name, value, type = 'resolve') {
36-
GrantManager.prototype[name] = function () {
37-
return Promise[type](value)
38-
}
39-
}
28+
function mock (code, data, isError) {
29+
const base = nock(fixtures.common.baseUrl)
30+
.post(`${fixtures.common.realmPath}${fixtures.common.introspectPath}`)
31+
32+
isError ? base.replyWithError(data) : base.reply(code, data)
4033
}
4134

4235
/**
@@ -140,5 +133,5 @@ function getServer (options, done) {
140133
module.exports = {
141134
getServer,
142135
registerPlugin,
143-
prototypes
136+
mock
144137
}

test/index.spec.js

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
const test = require('ava')
22
const cache = require('../src/cache')
3-
const { prototypes, getServer, registerPlugin } = require('./_helpers')
3+
const { mock, getServer, registerPlugin } = require('./_helpers')
44
const fixtures = require('./_fixtures')
55

6-
test.beforeEach(() => {
7-
prototypes.clone()
8-
})
9-
106
test.afterEach('reset instances and prototypes', () => {
117
cache.reset()
12-
prototypes.reset()
138
})
149

1510
test.cb.serial('throw error if plugin gets registered twice', (t) => {
@@ -20,7 +15,7 @@ test.cb.serial('throw error if plugin gets registered twice', (t) => {
2015
})
2116

2217
test.cb.serial('authentication does succeed', (t) => {
23-
prototypes.stub('validateAccessToken', fixtures.content.userData)
18+
mock(200, fixtures.content.userData)
2419

2520
getServer(undefined, (server) => {
2621
server.inject({
@@ -38,7 +33,7 @@ test.cb.serial('authentication does succeed', (t) => {
3833
})
3934

4035
test.cb.serial('authentication does succeed – cached', (t) => {
41-
prototypes.stub('validateAccessToken', fixtures.content.userData)
36+
mock(200, fixtures.content.userData)
4237

4338
const mockReq = {
4439
method: 'GET',
@@ -63,7 +58,7 @@ test.cb.serial('authentication does succeed – cached', (t) => {
6358
})
6459

6560
test.cb.serial('authentication does success – valid roles', (t) => {
66-
prototypes.stub('validateAccessToken', fixtures.content.userData)
61+
mock(200, fixtures.content.userData)
6762

6863
getServer(undefined, (server) => {
6964
server.inject({
@@ -81,7 +76,7 @@ test.cb.serial('authentication does success – valid roles', (t) => {
8176
})
8277

8378
test.cb.serial('authentication does fail – invalid roles', (t) => {
84-
prototypes.stub('validateAccessToken', fixtures.content.userData)
79+
mock(200, fixtures.content.userData)
8580

8681
getServer(undefined, (server) => {
8782
server.inject({
@@ -99,7 +94,7 @@ test.cb.serial('authentication does fail – invalid roles', (t) => {
9994
})
10095

10196
test.cb.serial('authentication does fail – invalid token', (t) => {
102-
prototypes.stub('validateAccessToken', false)
97+
mock(200, { active: false })
10398

10499
getServer(undefined, (server) => {
105100
server.inject({
@@ -135,7 +130,7 @@ test.cb.serial('authentication does fail – invalid header', (t) => {
135130
})
136131

137132
test.cb.serial('server method validates token', (t) => {
138-
prototypes.stub('validateAccessToken', fixtures.content.userData)
133+
mock(200, fixtures.content.userData)
139134

140135
getServer(undefined, (server) => {
141136
server.kjwt.validate(`bearer ${fixtures.jwt.userData}`, (err, res) => {
@@ -148,22 +143,22 @@ test.cb.serial('server method validates token', (t) => {
148143
})
149144

150145
test.cb.serial('server method invalidates token – validation error', (t) => {
151-
prototypes.stub('validateAccessToken', new Error('an error'), 'reject')
146+
mock(400, 'an error', true)
152147

153148
getServer(undefined, (server) => {
154149
server.kjwt.validate(`bearer ${fixtures.jwt.userData}`, (err, res) => {
155150
t.falsy(res)
156151
t.truthy(err)
157152
t.truthy(err.isBoom)
158153
t.is(err.output.statusCode, 401)
159-
t.is(err.output.headers['WWW-Authenticate'], 'Bearer error="Error: an error"')
154+
t.is(err.output.headers['WWW-Authenticate'], 'Bearer error="an error"')
160155
t.end()
161156
})
162157
})
163158
})
164159

165160
test.cb.serial('server method invalidates token – invalid', (t) => {
166-
prototypes.stub('validateAccessToken', false)
161+
mock(200, { active: false })
167162

168163
getServer(undefined, (server) => {
169164
server.kjwt.validate(`bearer ${fixtures.jwt.userData}`, (err, res) => {

test/utils.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test('get boom error with error message', (t) => {
1919
const mockErr = new Error('barfoo')
2020
const result = utils.error('badRequest', mockErr, 'foobar')
2121
t.truthy(result)
22-
t.deepEqual(result, boom.badRequest(mockErr.toString(), 'Bearer'))
22+
t.deepEqual(result, boom.badRequest(mockErr.message, 'Bearer'))
2323
})
2424

2525
test('decorate callback function with `continue`', (t) => {

0 commit comments

Comments
 (0)