3

I am trying to implement a Node.js client application authenticating against Keycloak, and using an external IDP, using the keycloak-nodejs-connector. I have been following the documentation located here for using it.

However, after authenticating, the client application throws the error: "Cannot exchange code for grant in bearer-only mode". This is confusing me because the client is not configured for bearer-only mode, it is configured for confidential mode.

The client application is successfully redirecting me to the external IDP where I am able to log in. If I look in the Keycloak admin console, I also see an active session for myself after logging in. However, the client application still throws the error.

Here is my client configuration pulled from the Keycloak admin console:

{
"realm": "master",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "local",
"verify-token-audience": true,
"credentials": {
    "secret": "redacted"
},
"use-resource-role-mappings": true,
"confidential-port": 0
}

Here is the implementation in my app.js file for Node:

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

 let keycloakMiddleware = new Keycloak({idpHint: 'SSO'});

 app.use( keycloakMiddleware.middleware() );

 app.get( '/', keycloakMiddleware.protect(), complaintHandler);

I have keycloak.json in the same directory as app.js and it is picking up the above client configuration details.

B. Jones
  • 31
  • 1

1 Answers1

0

I ran into the same problem. What I figured out is that when constructing the Keycloak instance, you have to either set cookies=true, or pass in a session store. So one of these:

const session = require('express-session');
const store = new session.MemoryStore();
const keycloakMiddleware = new Keycloak({ idpHint: 'SSO', store });

or

const keycloakMiddleware = new Keycloak({ idpHint: 'SSO', cookies: true });

If you choose the latter, you'll also need to use cookie-parser or something like it. And either way, you need to use express-session, as far as I can tell.

app.use(require('cookie-parser')); // only if using cookies=true, i think
app.use(session({ secret }));
app.use(keycloakMiddleware.middleware());