Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KeyCloak-Nodejs-Goes into an infinite loop after returning authorization code and state

I am setting up Open Id connect for a dummy node application using KeyCloak. I am using the nodejs adapter suggested here in key cloak docs.

Here is the routes.js file of the node application:

'use strict';

/**
 * Module dependencies.
 */

const home = require('../app/controllers/home');

/**
 * Expose
 */

module.exports = function (app, passport) {

    var session = require('express-session');
    var Keycloak = require('keycloak-connect');

    var memoryStore = new session.MemoryStore();
    var keycloak = new Keycloak({ store: memoryStore })
    // app.use(session({
    //       secret: 'mySecret',
    //       resave: false,
    //       saveUninitialized: true,
    //       store: memoryStore
    // }));
    app.use( keycloak.middleware() ); 
    // console.log("In Routes.js. Compare with post auth message");
  app.get('/', keycloak.protect(), home.index);
  // app.get('/redirect', keycloak.protect(),  home.index);
  //   app.get('/venky', keycloak.protect(),  function(request, response) {
  //       response.send("Hello World");
  //   });
  app.get('/redirecta',  home.index);

  /**
   * Error handling
   */

  app.use(function (err, req, res, next) {
    // treat as 404
    if (err.message
      && (~err.message.indexOf('not found')
      || (~err.message.indexOf('Cast to ObjectId failed')))) {
      return next();
    }
    console.error(err.stack);
    // error page
    res.status(500).render('500', { error: err.stack });
  });

  // assume 404 since no middleware responded
  app.use(function (req, res, next) {
    res.status(404).render('404', {
      url: req.originalUrl,
      error: 'Not found'
    });
  });
};

When I access the root url localhost:3000, initially I get redirected to the login page on KeyCloak. Once I login, I get the following error:enter image description here

Here is the server log of node app:enter image description here

As you can see, it is going into an infinite loop.

Additional details I have found:

  1. In the first redirect, after the login, the state value is same as the value before logging in. As you can see from the server log screenshot above, the state value changes in every redirection after that.

  2. From what I have figured out so far the redirection is happening in post-auth.js (line number 49) leading to an infinite loop. Here is a link to post-auth.js - https://github.com/keycloak/keycloak-nodejs-connect/blob/master/middleware/post-auth.js

  3. sessionId in getGrantFromCode function in index.js is undefined. Here is the function:

Keycloak.prototype.getGrantFromCode = function (code, request, response) {
  if (this.stores.length < 2) {
    // bearer-only, cannot do this;
    throw new Error('Cannot exchange code for grant in bearer-only mode');
  }

  var sessionId = request.session.id;
    // console.log(sessionId, "BBB BEGIN NNNN - in index.js getGrantFromCode");
    // console.log(request, "sessionId from getGrantFromCode function");
    // console.log("EEE END DDD - in index.js getGrantFromCode");

  var self = this;
  return this.grantManager.obtainFromCode(request, code, sessionId)
    .then(function (grant) {
      self.storeGrant(grant, request, response);
    // console.log(grant, "iS this the grant from getGrantFromCode?");
    // console.log("Inside the return function of getGrantFromCode");
      return grant;
    });
};

Link to source code: https://github.com/keycloak/keycloak-nodejs-connect/blob/master/index.js

  1. The following is a sample grant I get when I log it in the grant function mentioned above: https://pastebin.com/eqUaiAvb

Questions:

  1. How can I fix this problem?
  2. Where can I find keycloak logs(jboss)? Right now I can only see keycloak logs only if there is an error. I am using mvn -f testsuite/integration/pom.xml exec:java -Pkeycloak-server to run keycloak. I have never worked on java before.
  3. Where is the request(using authorization code) for id token happening?

Thanks a lot in advance.

like image 384
Ravikanth Andhavarapu Avatar asked Jun 06 '17 08:06

Ravikanth Andhavarapu


1 Answers

  1. To get your code working, you need to uncomment session initialization:

    // app.use(session({
    //       secret: 'mySecret',
    //       resave: false,
    //       saveUninitialized: true,
    //       store: memoryStore
    // }));
    
  2. As you do not have experience in java, I would suggest to use docker image for keycloak

    docker run -e KEYCLOAK_LOGLEVEL=DEBUG --name keycloak -p 8080:8080 jboss/keycloak
    

Afterwards, you can access keycloak running on port 8080 and in the console you will see keycloak logs

  1. When using the Authorization Code Flow, all tokens are returned from the Token Endpoint. Here you can find a detailed description of the Authorization Code flow.
like image 100
tycoon Avatar answered Oct 26 '22 08:10

tycoon