Reputation: 129
I'm new to Keycloak and having a hard time authenticating a desktop app written on Electron. I looked at the documentation that discusses the OpenID Connect endpoint and then found a blog that walks through Keycloak and Postman and I was able to get tokens from Keycloak via this method.
I'm pretty sure this is incorrect for a few reasons.
How can I authenticate my Electron app without running a client side web server to handle the redirects? There is an example for authenticating a web app, but does anyone have a simple example of how to authenticate an Electron app against Keycloak?
Upvotes: 3
Views: 5036
Reputation: 730
This question is pretty old but I just ran into this problem and here is my solution:
Keycloak config:
// Keycloak config
var keycloak = new Keycloak({
url: 'https://keycloak-server/auth',
realm: 'myrealm',
clientId: 'myapp'
});
// Keycloak initConfig
keycloak.init({
checkLoginIframe: false,
redirectUri: 'http://localhost/keycloak-redirect'
});
Electron - main.js
const {session: {webRequest}} = mainWindow.webContents;
const filter = {
urls: [
'http://localhost/keycloak-redirect*'
]
};
webRequest.onBeforeRequest(filter, async ({url}) => {
const params = url.slice(url.indexOf('#'));
mainWindow.loadURL('file://' + path.join(__dirname, 'index.html') + params);
});
Quick explanation: When keycloak redirect after login the params are intercepted by Electron, so you need to slice the params from the redirect Url and add them to the loadURL so they will be present for the keycloak lib to use. I have made a small article with more details: https://medium.com/@xavier.bauquet/keycloak-authentication-in-electron-application-ed1acd2559c2
I hope this will help some of you.
Upvotes: 2
Reputation: 1862
To use Keycloak in build Electron You must add server listener in your main.js:
const Keycloak = http.createServer((request, response) => {
response.writeHeader(200, {"Content-Type": "text/html"});
var readSream = fs.createReadStream(__static + '/index.html','utf8')
readSream.pipe(response);
});
Keycloak.listen(3000);
Next add file index.html
to folder __static
. In this file add JS script like in this instruction.
And you must add ipcRenderer
and send token to main.js:
keycloak.init({ onLoad: 'login-required', redirectUri: 'http://localhost:3000' }).success(function(authenticated) {
if (authenticated) {
ipcRenderer.send('keycloak-token', keycloak.token);
}
}).error(function() {
console.log('error');
});
Remember to add http://localhost:3000
in Keycloak setting in redirectUri
.
Next in main.js
you can send token to check autorization:
ipcMain.on('keycloak-token', (event, token) => {
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080?token=${token}`
: `file://${__dirname}/index.html?token=${token}`
mainWindow.loadURL(winURL);
});
Upvotes: 2
Reputation: 166
Finally, I've managed to implement Keycloak authentication with Electron app. The thing is to fork a temporary http server from the main process of your app. This server should listen to a redirect request after successful Keycloak login. Of course, for this to work you should specify the address of this server in the *Valid Redirect URIs input of your Keycloak client, say http://localhost:33333
. When the request comes to the server, you parse it and extract the 'search' part of the request. Then you append this 'search' part to your index.html path and load mainWindow from it:
const url = `file://${path.join(__dirname, '../index.html')}${searchString}`;
mainWindow.loadURL(url);
Works good for me.
PS. I can elaborate on this solution with sample code upon request.
Upvotes: 0
Reputation: 948
import Keycloak from 'keycloak-js';
if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
// don't need keycloak in development mode, change the condition to if (false) to force keycloak to be required locally
} else {
keycloak.init({ onLoad: 'login-required', checkLoginIframeInterval: 1 }).success((authenticated) => {
if (authenticated) {
sessionStorage.setItem('kctoken', keycloak.token);
setInterval(() => {
keycloak.updateToken(10).error(() => keycloak.logout());
sessionStorage.setItem('kctoken', keycloak.token);
}, 10000);
} else {
keycloak.login();
}
});
}
Try that and post back thanks :)
Upvotes: -1