I'm trying to use Keycloak with JavaScript and these are the steps that I followed.
I create a client inside KeyCloak admin panel.
Link to image
I copy the .json file to my apache folder.
{
"realm": "master",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "test",
"public-client": true,
"confidential-port": 0
}
I go to my index.html and I add these two lines for calling the script.
<script src="keycloak.js"></script>
<script>
function initKeycloak() {
const keycloak = new Keycloak();
keycloak.init().then(function(authenticated) {
alert(authenticated ? 'authenticated' : 'not authenticated');
}).catch(function() {
alert('failed to initialize');
});
}
</script>
this is what i have in myLogical.js
var keycloak = new Keycloak();
function initKeycloak() {
keycloak.init({onLoad: 'login-required'}).then(function() {
constructTableRows(keycloak.idTokenParsed);
pasteToken(keycloak.token);
}).catch(function() {
alert('failed to initialize');
});
}
function constructTableRows(keycloakToken) {
document.getElementById('row-username').innerHTML = keycloakToken.preferred_username;
document.getElementById('row-firstName').innerHTML = keycloakToken.given_name;
document.getElementById('row-lastName').innerHTML = keycloakToken.family_name;
document.getElementById('row-name').innerHTML = keycloakToken.name;
document.getElementById('row-email').innerHTML = keycloakToken.email;
}
function pasteToken(token){
document.getElementById('ta-token').value = token;
document.getElementById('ta-refreshToken').value = keycloak.refreshToken;
}
var refreshToken = function() {
keycloak.updateToken(-1)
I tried to download the file keycloak.js and put it directly on my root folder but it happen the same problem.
These is the message I got when I try to open the page
I'm confused about point 1, does keycloak automatically load configuration from json file in Apache folder? Let's assume that no, and I think that where your problem lies, you're not passing config param to keycloak constructor.
How to initialize keycloak:
const initKeycloak = async () => {
//you can hardcode these values for now just to see if everything works
const config = { url: 'http://localhost:8080/auth', realm: 'master', clientId: 'test'};
const keycloak = new Keycloak(config);
await keycloak
.init({ onLoad: 'login-required' })
.then(isAuthenticated => {
//user is authenticated
})
.catch(error => { console.log('keycloak error', error); });
}
Another important thing is that keycloak-js library version (in package.json) must match keycloak server version. Sometimes different versions work with each other but it's always best practice that keycloak-js version matches keycloak server version.
You can also look here: https://github.com/m-s7/react-core/blob/devel/src/services/keycloak-service.ts this is my repo with working keycloak-js implementation.
Ok, so I know this is probably going to be something obvious and straightforward, but I just can't seem to get it to work.
Using the Nigthwatchjs perform command, I'm trying to re-use a variable from a step into the next step.
Below is a snippet of my code from my test script;
'2) Breadcrumbs': function (browser) {
browser.perform(function() {
var testMake = browser.globals.specsTestMake;
var testModel = browser.globals.specsTestModel;
var testRange = browser.globals.specsTestRange;
var testYear = browser.globals.specsTestYear;
browser.assert.containsText('nav.site-breadcrumbs', 'Home', testMake, testModel, testRange, testYear, 'specs');
console.log('test make from step 2 = ', testMake);
});
},
'3) Heading': function (browser) {
browser.perform(function(testMake, done) {
console.log('test make from step 3 = ', testMake);
done();
});
},
The console.log from the first step, '2) Breadcrumbs' is correctly displayed (for this test example) as BMW, as defined in the globals file.
I therefore thought that the console.log for the second step, '3) Heading' would also be correctly displayed as BMW.
However, this is not the case.
The second console.log displays what appears to be the entire page, settings, etc.
A small snippet is below;
✔ 2) Breadcrumbs (26ms)
test make from step 3 = { capabilities:
{ acceptInsecureCerts: true,
acceptSslCerts: true,
applicationCacheEnabled: false,
browserConnectionEnabled: false,
browserName: 'chrome',
chrome:
{ chromedriverVersion: '2.44.609545 (c2f88692e98ce7233d2df7c724465ecacfe74df5)',
userDataDir:
'/var/folders/6x/3kzp0zhd6vv0q_mfstkxd73m0000gr/T/.org.chromium.Chromium.iDQCXI' },
cssSelectorsEnabled: true,
databaseEnabled: false,
'goog:chromeOptions': { debuggerAddress: 'localhost:52102' },
handlesAlerts: true,
Any idea on what I'm doing wrong with my perform command?
Thanks
I am getting
Jasmine spec timed out. Resetting the WebDriver Control Flow.
I have also used fakesyn before but getting same error message as above.
Please help me
This is my specs:
describe('CW Login Page', function() {
var username;
var password;
var login;
beforeEach(() => {
browser.waitForAngularEnabled(false);
browser.get('http://www.testing.com/');
console.log('after link await');
});
it('should find the element and send the parameters', fakeAsync(() => {
setTimeout(function() {
value=0;
console.log('Inside it function');
username = element(by.id('userIDInput'));
password= element(by.id('passwordInput'));
login= element(by.id('login'));
console.log('After await');
username.sendKeys('abc');
password.sendKeys('abc');
login.click();
console.log("After it function");
},5000);
tick(5000);
}));
`beforeEach`(() => {
console.log('\r\n ---=== TESTS FINISHED!!! ===--- \r\n');
});
});
This is my config:
exports.config = {
allScriptsTimeout: 50000,
getPageTimeout:40000,
framework:'jasmine2',
/*seleniumAddress: 'http://localhost:4723/wd/hub', // Ignored if directConnect is true
specs: ['loginpage.js'],*/
seleniumAddress: 'https://hub.testingbot.com/wd/hub',
specs: ['./src/loginpage_fakeasync.e2e-specs.js'],
seleniumArgs: ['--dev-server-target'], // '--dev-server-target' ],
directConnect: false, //Change this to true for your local testing
multiCapabilities: [{ // in 1 chrome run the 10 specs sequentially
browserName: 'chrome',
platform: 'Android',
version: '7.1',
platformName: 'Android',
deviceName: 'Pixel 2',
client_key: "abc",
client_secret: "xyz"
}],
jasmineNodeOpts: {
onComplete: null, //jasmine framework details
isVerbose: false,
showColors: true,
includeStackTrace: true,
defaultTimeoutInterval: 40000,
print: function() {}
I expect to open the webpage and login using the automation script. If someone can figure out the error it would be a great help
I am getting
Jasmine spec timed out. Resetting the WebDriver Control Flow.
I have also used fakesyn before but getting same error message as above.
Please help me
The control flow should keep everything running in sync so the fakeAsync & setTimeout should not be required. If your framework is not too large then you should consider disabling the control flow and using the async/await style of handling promises.
I doubt this will solve your issue but can you try the below code and post the results.
describe('CW Login Page', function () {
var username;
var password;
var login;
beforeEach(() => {
browser.waitForAngularEnabled(false);
browser.get('http://www.testing.com/');
console.log('after link await');
});
it('should find the element and send the parameters', () => {
value = 0;
console.log('Inside it function');
username = element(by.id('userIDInput'));
password = element(by.id('passwordInput'));
login = element(by.id('login'));
console.log('After await');
username.sendKeys('abc');
password.sendKeys('abc');
login.click();
console.log("After it function");
})
afterEach(() => {
console.log('\r\n ---=== TESTS FINISHED!!! ===--- \r\n');
}
});
Sentry by defaults has integration for console.log to make it part of breadcrumbs:
Link: Import name: Sentry.Integrations.Console
How can we make it to work for bunyan logger as well, like:
const koa = require('koa');
const app = new koa();
const bunyan = require('bunyan');
const log = bunyan.createLogger({
name: 'app',
..... other settings go here ....
});
const Sentry = require('#sentry/node');
Sentry.init({
dsn: MY_DSN_HERE,
integrations: integrations => {
// should anything be handled here & how?
return [...integrations];
},
release: 'xxxx-xx-xx'
});
app.on('error', (err) => {
Sentry.captureException(err);
});
// I am trying all to be part of sentry breadcrumbs
// but only console.log('foo'); is working
console.log('foo');
log.info('bar');
log.warn('baz');
log.debug('any');
log.error('many');
throw new Error('help!');
P.S. I have already tried bunyan-sentry-stream but no success with #sentry/node, it just pushes entries instead of treating them as breadcrumbs.
Bunyan supports custom streams, and those streams are just function calls. See https://github.com/trentm/node-bunyan#streams
Below is an example custom stream that simply writes to the console. It would be straight forward to use this example to instead write to the Sentry module, likely calling Sentry.addBreadcrumb({}) or similar function.
Please note though that the variable record in my example below is a JSON string, so you would likely want to parse it to get the log level, message, and other data out of it for submission to Sentry.
{
level: 'debug',
stream:
(function () {
return {
write: function(record) {
console.log('Hello: ' + record);
}
}
})()
}
I am new to extjs, and I try to integrate extjs 5 with django 1.7 on my localhost. I have set the backend and got the rest api work (at /api/), as at https://github.com/MaZderMind/django-vs-extjs , but when the index.html runs app.js, which displays the login page, it seems that:
The controller file (Login.js) isn't loaded,
the launch function is not executed.
In firebug I can see that it reads the function definition and then returns without executing it automatically (also, when defining controller it steps over like it is simple command, but on the require statement steps into the function that fetches them), hence the login page is not displayed. But the other js files (for authentication) are loaded, as I see in console. Do you have any ideas what is happening? The codes are:
app.js
Ext.Loader.setConfig({enabled:true});
Ext.application({
// base-package of all classes
name: 'MyApp',
// url to load js-files from - adapted to django project
appFolder : 'static/static',
// required controllers
controllers: ['Login'],
// other required components
requires: [
'MyApp.helper.CrsfTokenHelper',
'MyApp.helper.PhantomStoreInserter'
],
// application launch method
launch: function () {
// save the scope
var app = this;
console.log('launched');
// ensure the user is logged in before showing her the main navigation with all our application goodies
app.getController('Login').ensureLoggedIn(function(userinfo) {
console.log('Login-Controller ensured that user', userinfo.username, 'is is currently loggeg in. Proceeding to navigation.')
// upate display of the navigation conteoller and show it
//app.getController('Navigation')
//.updateUserinfo(userinfo)
//.view.show();
console.log('Here should be loaded the view after the login page');
});
}
});
Login.js (controller)
Ext.define('MyApp.controller.Login', {
extend: 'Ext.app.Controller',
mixins: ['Ext.mixin.Observable'],
views: ['Login'],
// pointers into the view
refs: [
{ 'ref': 'userField', selector: '#user' },
{ 'ref': 'passField', selector: '#pass' },
{ 'ref': 'submitButton', selector: '#submit' }
],
// stored user information as received from the server
userinfo: null,
// controller initialisation
init: function() {
// save the scope
var loginController = this;
// create an instance of the view
var win = loginController.loginWindow = loginController.getView('Login').create();
this.control({
// register for the login-click
'#submit': {
click: function() {
// retrieve username & password from view
var username = this.getUserField().getValue(), password = this.getPassField().getValue();
// mask the form out
win.mask('Verifying…');
// process the login with the backend
loginController.performLogin(username, password, function(success) {
// the user was successfully authorized
if(success) {
// now request additional information on the user (name and such)
loginController.fetchLoginStatus(function(userinfo) {
// test if the server responded with data as expected
if(userinfo) {
// hide the login-window
win.hide();
// store received information locally
loginController.userinfo = userinfo;
// raise a event on the controller when finished
loginController.fireEvent('login', userinfo);
loginController.fireEvent('ready', userinfo);
}
// we did not receive valid data from the server
// this sould not fail, but if it does, just handle it like a failed login
else {
// disable the login on the form
win.unmask();
// set error-message on password-field
loginController.clearPasswordAndFocus().setPasswordError('Invalid Username or Password!');
}
})
}
// authorization was not successful
// unmask the form, show an error message and restart login process
else {
win.unmask();
loginController.clearPasswordAndFocus().showError('Invalid Username or Password!');
}
})
}
}
});
// register keyboard handler
this.nav = new Ext.KeyNav(win.getEl(), {
// enter key -> login-button click
enter: function() {
loginController.getSubmitButton().fireEvent('click')
}
});
},
// test if the user is logged in.
// if she is, call back immediatly. if she is not, show a login form
// delay the callback until she logged in successfully
ensureLoggedIn: function(callback) {
// save the scope
var loginController = this;
// test if the backend knows us
loginController.fetchLoginStatus(function(userinfo) {
// analyze if a user is logged in
if(userinfo) {
// callback, if she is
loginController.userinfo = userinfo;
loginController.fireEvent('ready', userinfo);
return callback(userinfo);
}
// no, we're not. show the login-window
console.log('no user logged in, showing login-window');
// login-testing and re-trying is handled by the handler set in the init-method
// it raises an event on the controller once it is finished
// we listen on this event and relay it to our callback - but only once
// -> the callback shouldn't be called multiple times
loginController.on('login', callback, {single: true});
// initiate login procedure by showing the login window
loginController.loginWindow.show();
loginController.clearForm();
});
},
// ask the backend if and which user is currently logged in
fetchLoginStatus: function(callback) {
console.info('requesting current userinfo from backend');
Ext.Ajax.request({
url: '/api/auth/user/',
success: function(response) {
// decode json-response
var userinfo = Ext.util.JSON.decode(response.responseText);
// request user permission list
Ext.Ajax.request({
url: '/api/auth/permissions/',
success: function(response) {
// decode json-response
userinfo.permissions = Ext.util.JSON.decode(response.responseText);
// callback with the decoded response
console.log('received userinfo:', userinfo);
callback(userinfo);
},
failure: function(response) {
// callback without info
console.log('received no permission list - nobody logged in');
callback();
}
});
},
failure: function(response) {
// callback without info
console.log('received no userinfo - nobody logged in');
callback();
}
});
},
// submit username & password to the backend
performLogin: function(username, password, callback) {
console.info('trying to log into backend with username=', username, 'password=', password.length, 'Chars');
// send login data via ajax to the server and callback with result
Ext.Ajax.request({
url: '/api/auth/login/',
method: 'POST',
params: {
'username': username,
'password': password
},
success: function(){
callback(true);
},
failure: function() {
callback(false);
}
});
},
// ask the backend to throw away our session which makes us logged out
performLogout: function(callback) {
console.info('trying to log out from backend');
// ensure userinfo is unset
this.userinfo = null;
Ext.Ajax.request({
url: '/api/auth/logout/',
method: 'GET',
success: function(){
callback(true);
},
failure: function() {
callback(false);
}
});
},
// shorthand to test iff userinfo is available
isLoggedIn: function() {
// null -> false, string -> true
return !!this.userinfo;
},
// shorthand to get the current username
getUserinfo: function() {
return this.userinfo;
},
// shorthand to get the current username
getUsername: function() {
return this.isLoggedIn() ? this.getUserinfo().username : null;
},
// shorthand to get the current username
getPermissions: function() {
return this.isLoggedIn() ? this.userinfo.permissions.user_permissions : [];
},
// shorthand to get the current username
isSuperuser: function() {
return this.isLoggedIn() ? this.userinfo.permissions.is_superuser : [];
},
hasPermission: function(permission) {
return this.isLoggedIn() && (this.isSuperuser() || this.getPermissions().indexOf(permission) !== -1)
},
// clears all form elements in the view
clearForm: function() {
this.loginWindow.unmask();
this.getPassField().setValue('').unsetActiveError();
this.getUserField().setValue('').unsetActiveError();
this.getUserField().focus();
return this;
},
// clears the password-field in the view and sets the typing-focus to it
clearPasswordAndFocus: function() {
this.getPassField().setValue('').focus();
return this;
},
// set an error-message on the password-fieldy
setPasswordError: function(msg) {
this.getPassField().setActiveErrors([msg]);
return this;
}
});
Login.js (view)
Ext.define('MyApp.view.Login', {
extend: 'Ext.window.Window',
renderTo: Ext.getBody(),
id: "loginBox",
title: 'Login',
width: 400,
layout: 'form',
bodyPadding: 5,
closable: false,
resizable: false,
draggable: false,
defaultFocus: 'user',
defaultType: 'textfield',
items: [{
itemId: 'user',
fieldLabel: 'Username',
allowBlank: false
},{
inputType: 'password',
fieldLabel: 'Password',
itemId: 'pass',
allowBlank: false
}],
buttons: [{
text: 'Login',
itemId: 'submit'
}]
});
console output:
GET localhost /static/static/helper/CrsfTokenHelper.js?_dc=1414444486439 200 OK 3ms ext-all-debug.js (line 1010)
GET localhost /static/static/helper/PhantomStoreInserter.js?_dc=1414444486439 200 OK 2ms ext-all-debug.js (line 1010)
Thanks anyway!
Well, apparently you are getting errors with your required files. If you comment the requires line inside your Ext.application:
Ext.application({
// base-package of all classes
name: 'MyApp',
// url to load js-files from - adapted to django project
appFolder : 'static/static',
// required controllers
controllers: ['Login'],
// other required components
//requires: [
// 'MyApp.helper.CrsfTokenHelper',
// 'MyApp.helper.PhantomStoreInserter'
//],
...
});
You will see that your Login window will show up. Assuming of course that you have your folder structure setup correctly
index.html
app.js
static/
static/static/
static/static/controller/Login.js
static/static/view/Login.js