OAuth/OpenID login with Keycloak

I would like to authenticate to the Node-RED editor against my Keycloak server.

I used npm to install passport and passport-keycloak-oauth2-oidc

When I click the button to login, it goes to Keycloak and I login, then it redirects back to Node-RED where I see this error:

InternalOAuthError: Failed to obtain access token
    at Strategy.OAuth2Strategy._createOAuthError (/home/ubuntu/.node-red/node_modules/passport-oauth2/lib/strategy.js:423:17)
    at /home/ubuntu/.node-red/node_modules/passport-oauth2/lib/strategy.js:177:45
    at /home/ubuntu/.node-red/node_modules/oauth/lib/oauth2.js:191:18
    at ClientRequest.<anonymous> (/home/ubuntu/.node-red/node_modules/oauth/lib/oauth2.js:162:5)
    at ClientRequest.emit (events.js:314:20)
    at Socket.socketErrorListener (_http_client.js:427:9)
    at Socket.emit (events.js:314:20)
    at emitErrorNT (internal/streams/destroy.js:92:8)
    at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
    at processTicksAndRejections (internal/process/task_queues.js:84:21)

The URL is https://node-red.mydomain.com/auth/strategy/callback?session_state=removed&code=removed

(replaced the codes with "removed")

I wonder if the problem has to do with the verify function in the strategy object in settings.js. I'm not really clear on what's going on here. I left it the same as in the Node-RED example, which is different from the example for passport-keycloak-oauth2-oidc...

adminAuth: {
    strategy: {
        name: "keycloak",
        label: 'Sign in',
        strategy: require("passport-keycloak-oauth2-oidc").Strategy,
        options: {
            clientID: "node-red",
            realm: 'myrealm',
            publicClient: "false",
            clientSecret: "[deleted]",
            sslRequired: "external",
            authServerURL: "http://keycloak.mydomain.com/auth",
            callbackURL: "https://node-red.mydomain.com/auth/strategy/callback",
            verify: function(token, tokenSecret, profile, done) {
                done(null, profile);
    users: [
       { username: "jason@mydomain.com",permissions: ["*"]}

For bonus points... I'd rather not have to supply the usernames in settings.js. I would rather provide a group name, and it would let in any user that belongs to that group... possible?

@strmar or @heincar did you solve your issue from adminAuth config for OpenID based Authentication on Keycloak ?

I am using a different Passport strategy but same problem...


As you can see if you have eagle eyes, I had input the authServerURL with http instead of https!

1 Like

Also figured out how to do group-based authentication in case anyone is interested...

Modified the verify function to check for the presence of the required group name and if yes, overwrite the username in the profile object.

verify: function(token, tokenSecret, profile, done) {
                if(profile._json.groups.includes("the-group-name")) {
                done(null, profile);

Then the users array just uses the group name instead of the username:

users: [
       { username: "the-group-name",permissions: ["*"]}