keycloak-connect
Version:
Keycloak Connect Middleware
320 lines (287 loc) • 11 kB
JavaScript
/*
* Copyright 2016 Red Hat Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
const test = require('blue-tape')
const admin = require('./utils/realm')
const TestVector = require('./utils/helper').TestVector
const page = require('./utils/webdriver').newPage
const realmAccountPage = require('./utils/webdriver').realmAccountPage
const driver = require('./utils/webdriver').driver
const NodeApp = require('./fixtures/node-console/index').NodeApp
const session = require('express-session')
const realmManager = admin.createRealm()
const app = new NodeApp()
test('setup', t => {
return realmManager.then(() => {
return admin.createClient(app.publicClient())
.then((installation) => {
return app.build(installation)
})
})
})
// test('setup', t => {
// return client = realmManager.then((realm) => {
// return admin.createClient(app.publicClient());
// });
// });
test('Should be able to access public page', t => {
t.plan(1)
return page.get(app.port)
.then(() => page.output().getText()
.then(text => {
t.equal(text, 'Init Success (Not Authenticated)', 'User should not be authenticated')
})
)
})
test.skip('Should login with admin credentials', t => {
t.plan(3)
return page.get(app.port)
.then(() => page.output().getText()
.then(text => {
t.equal(text, 'Init Success (Not Authenticated)', 'User should not be authenticated')
return page.logInButton()
.then(webElement => webElement.click())
.then(() => page.login('test-admin', 'password'))
.then(() => page.events().getText().then(text => {
t.equal(text, 'Auth Success', 'User should be authenticated')
return page.logOutButton()
.then(webElement => webElement.click())
.then(() => page.output().getText()
.then(text => {
t.equal(text, 'Init Success (Not Authenticated)', 'User should not be authenticated')
})
)
}))
})
)
})
test.skip('Login should not change tokens when they are valid', t => {
t.plan(3)
return page.get(app.port).then(() =>
page.logInButton().click().then(() =>
page.login('test-admin', 'password').then(() =>
page.events().getText().then(text => {
t.equal(text, 'Auth Success', 'User should be authenticated')
return page.output().getText().then(firstToken =>
page.logInButton().click().then( // Invoke login for the second time, token shouldn't be changed
page.output().getText().then(secondToken => {
t.equal(secondToken, firstToken, 'Token should not be changed as first session is still valid')
page.logOutButton().click()
return page.output().getText().then(text => {
t.equal(text, 'Init Success (Not Authenticated)', 'User should not be authenticated')
})
})
)
)
})
)
)
)
})
test.skip('SSO should work for nodejs app and testRealmAccountPage', t => {
return page.get(app.port).then(() =>
page.logInButton().click().then(() =>
page.login('test-admin', 'password').then(() =>
page.events().getText().then(text => {
t.equal(text, 'Auth Success', 'User should be authenticated')
return realmAccountPage.get().then(() =>
driver.getCurrentUrl().then(currentUrl => {
t.equal(currentUrl, realmAccountPage.getUrl(), 'Should be on account page')
return realmAccountPage.logout().then(() =>
driver.getCurrentUrl().then(currentUrl => {
t.true(currentUrl.startsWith('http://127.0.0.1:8080/realms/test-realm/protocol/openid-connect/auth'), 'Should be on login page after AccountPage logout, current url: ' + currentUrl)
return page.get(app.port, '/login').then(() =>
t.true(currentUrl.startsWith('http://127.0.0.1:8080/realms/test-realm/protocol/openid-connect/auth'), 'Should be on login page, current url: ' + currentUrl)
)
})
)
})
)
})
)
)
)
})
test.skip('Public client should be redirected to GitHub when idpHint is provided', t => {
t.plan(1)
const app = new NodeApp()
const client = admin.createClient(app.publicClient('appIdP'))
return client.then((installation) => {
app.build(installation, { store: new session.MemoryStore(), idpHint: 'github' })
return page.get(app.port, '/restricted')
.then(() =>
page.h1().getText().then(text => {
t.equal(text, 'Sign in to GitHub', 'Application should redirect to GitHub')
})
).then(() => {
app.destroy()
}).catch(err => {
app.destroy()
throw err
})
})
})
test.skip('User should be forbidden to access restricted page', t => {
return page.get(app.port, '/restricted').then(() =>
page.login('alice', 'password').then(() =>
page.body().getText().then(text => {
t.equal(text, 'Access denied', 'Message should be access denied')
return page.logout(app.port) // we need to wait a bit until the logout is fully completed
})
)
)
})
test.skip('Public client should be forbidden for invalid public key', t => {
t.plan(2)
const app = new NodeApp()
const client = admin.createClient(app.publicClient('app2'))
return client.then((installation) => {
installation['realm-public-key'] = TestVector.wrongRealmPublicKey
app.build(installation)
return page.get(app.port).then(() =>
page.output().getText().then(text => {
t.equal(text, 'Init Success (Not Authenticated)', 'User should not be authenticated')
return page.logInButton().click().then(() =>
page.login('test-admin', 'password').then(() =>
page.body().getText().then(text => {
t.equal(text, 'Access denied', 'Message should be access denied')
})
)
)
})
).then(() => {
app.destroy()
}).catch(err => {
app.destroy()
throw err
})
})
})
test.skip('Confidential client should be forbidden for invalid public key', t => {
t.plan(3)
const app = new NodeApp()
const client = admin.createClient(app.confidential('app3'))
return client.then((installation) => {
installation['realm-public-key'] = TestVector.wrongRealmPublicKey
app.build(installation)
return page.get(app.port).then(() =>
page.output().getText().then(text => {
t.equal(text, 'Init Success (Not Authenticated)', 'User should not be authenticated')
return page.logInButton().click().then(() =>
page.body().getText().then(text => {
t.equal(text, 'Access denied', 'Message should be access denied')
})
.then(() => page.logout(app.port))
.then(() => page.logoutConfirm())
.then(() => page.get(app.port, '/check-sso'))
.then(() => page.output().getText().then(text => t.equal(text, 'Check SSO Success (Not Authenticated)', 'User should not be authenticated')))
)
})
).then(() => {
app.destroy()
}).catch(err => {
app.destroy()
throw err
})
})
})
test.skip('Should test check SSO after logging in and logging out', t => {
t.plan(3)
// make sure user is logged out
page.get(app.port, '/check-sso').then(() =>
page.output().getText().then(text => {
t.equal(text, 'Check SSO Success (Not Authenticated)', 'User should not be authenticated')
page.logInButton().click().then(() =>
page.login('alice', 'password').then(() =>
page.get(app.port, '/check-sso').then(() =>
page.output().getText().then(text => {
t.equal(text, 'Check SSO Success (Authenticated)', 'User should be authenticated')
return page.logout(app.port)
}).then(() => {
page.get(app.port, '/check-sso').then(() =>
page.output().getText().then(text => {
t.equal(text, 'Check SSO Success (Not Authenticated)', 'User should not be authenticated')
})
)
})
)
)
)
})
)
})
test.skip('Public client should work with slash in the end of auth-server-url', t => {
t.plan(3)
const app = new NodeApp()
const client = admin.createClient(app.publicClient('authServerSlashes'))
return client.then((installation) => {
installation['auth-server-url'] = 'http://localhost:8080/'
app.build(installation)
return page.get(app.port)
.then(() => page.output().getText()
.then(text => {
t.equal(text, 'Init Success (Not Authenticated)', 'User should not be authenticated')
return page.logInButton()
.then(webElement => webElement.click())
.then(() => page.login('test-admin', 'password'))
.then(() => page.events().getText().then(text => {
t.equal(text, 'Auth Success', 'User should be authenticated')
return page.logOutButton()
.then(webElement => webElement.click())
.then(() => page.output().getText()
.then(text => {
t.equal(text, 'Init Success (Not Authenticated)', 'User should not be authenticated')
})
)
}))
})
).then(() => {
app.destroy()
}).catch(err => {
app.destroy()
throw err
})
})
})
test.skip('App should be able to use cookie-store', t => {
t.plan(1)
const app = new NodeApp()
const client = admin.createClient(app.publicClient('appCookies'))
return client.then((installation) => {
app.build(installation, { cookies: true })
return page.get(app.port, '/cookie').then(() => {
page.login('alice', 'password').then(() => {
driver.navigate().refresh().then(() => {
page.events().getText().then(text => {
t.equal(text, 'Auth Success', 'User should be authenticated')
})
})
})
}).then(() => {
app.destroy()
}).catch(err => {
app.destroy()
throw err
})
})
})
test('teardown', t => {
return realmManager.then((realm) => {
app.destroy()
admin.destroy('test-realm')
page.quit()
})
})