2

I have a nodejs express application with keycloak adapter protecting https://example.com (with SSL)

My keycloak adapter is configured this way: enter image description here Notice the httpS in both URLs.

Now I am facing an issue, when the user login successfully (via keycloak) he is presented with a "Invalid Parameter: redirect_uri" error message.

Using the browser devtools I see after going to https://example.com (with SSL) the user is redirected to https://sso.example.com/auth/realms/myrealm/protocol/openid-connect/auth?client_id=my-client-id&state=22f41ed3-ddc6-4758-970b-d876cf631ded&redirect_uri=http%3A%2F%2Fexample.com%2F%3Fauth_callback%3D1&scope=openid&response_type=code

And the key point in the link above is redirect_uri=http%3A%2F%2Fexample.com%2F%3Fauth_callback%3D1&scope=openid&response_type=code. Here we can see the redirect_uri has no SSL. It is http instead of https.

This is how I protect the root of my domain:

   const server = express()
   server.set('trust proxy', 'loopback')
   server.use(keycloak.middleware({}))

   const keycloak = new Keycloak({ store: memoryStore }, KEYCLOAK_CONFIG) // KEYCLOAK_CONFIG is the json config below
   (...)
   server.get('/', keycloak.protect('private-user'), (req: Request, res: Response) => {
        // Set the cookie
        res.cookie(ConfigService.CONFIG_COOKIE_KEY, JSON.stringify(ConfigService.CONFIG), { httpOnly: false })
        res.sendFile(path.join(__dirname, 'build', 'index.html'))
        return res
    })

And my keycloak configuration is:

{
  realm: 'myrealm',
  'auth-server-url': 'https://sso.example.com/auth/',
  'ssl-required': 'external',
  resource: 'my-client-id',
  'verify-token-audience': false,
  credentials: { secret: 'super-secret-credential' },
  'use-resource-role-mappings': true,
  'confidential-port': 443,
  'bearer-only': false,
  'enable-cors': true,
  'cors-max-age': 1000,
  'enable-basic-auth': false,
  'expose-token': true,
  'disable-trust-manager': false,
  'allow-any-hostname': false,
  'token-minimum-time-to-live': 10,
  'min-time-between-jwks-requests': 10,
  'connection-pool-size': 20,
  'public-key-cache-ttl': 86400
}

The redirect_uri must be with SSL. How can I force keycloak to use https (SSL) in redirect_uri?

Adding http://example.com (non SSL) to the Valid Redirect URIs is not an option.

dazito
  • 7,740
  • 15
  • 75
  • 117
  • Is your node application running behind a reverse proxy and the connection between proxy and node app is http instead of https? – dasniko Jun 28 '21 at 09:26
  • @dasniko The app is running on kubernetes and SRE team told me there are no special logic neither redirects configured – dazito Jun 28 '21 at 09:54
  • That's not what I asked... But as you say it runs on K8s, I assume that there is an ingress or some other kind of proxy in front of your pod. There doesn't need to be "logic" nor "redirects", but the connection between your proxy and your pod has to be on any protocol... – dasniko Jun 28 '21 at 12:07
  • Sorry @dasniko I misread your initial comment. Yes, there is a load balancer in front of the k8s pod. The communication between the load balancer and the k8s pod is thru http – dazito Jun 28 '21 at 13:57
  • Ok, this might(!) be the issue, I had a similar situation with a Tomcat app, there I had to make some settings in the context to listen to the "x-forwarded-..." headers, set by the proxy/loadbalancer. But I don't know how to set it in node. – dasniko Jun 28 '21 at 14:09
  • https://stackoverflow.com/questions/53653123/keycloak-nodejs-adapter-ignores-x-forwarded-proto – Jan Garaj Jun 28 '21 at 21:10
  • @dasniko I tried applying the suggestion of @Jan Garaj by setting `server.set('trust proxy', 'loopback')` but unfortunately it did not work. The location header still contains `redirect_uri` without ssl. Example: https://sso.example.com/auth/realms/mycompany/protocol/openid-connect/auth?client_id=my-client-id&state=692b0c9f-3f3c-4d19-8a90-d4572523d641&redirect_uri=http%3A%2F%2Fexample.com%2F%3Fauth_callback%3D1&scope=openid&response_type=code – dazito Jun 29 '21 at 10:16
  • @JanGaraj thanks for that link, Unfortunately, adding `server.set('trust proxy', 'loopback')` did not solve the issue, please check the comment above this one. I also edited the question to add some more code example, how I instantiate express and keycloak – dazito Jun 29 '21 at 10:18
  • I wouldn't copy `server.set('trust proxy', 'loopback')` without thinking and not reading of the doc https://expressjs.com/en/guide/behind-proxies.html. You are in the K8s cluster, so I really don't believe that used proxy layer (ingress pod, dedicated machine, e.g. AWS ALB, F5, ...) is running on `loopback` as you have specified. It can be a `app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal'])`, but to be 100% sure I have to know how is networking configured, so it is only a guess. That "no special logic neither" is actually important for correct setup. – Jan Garaj Jun 29 '21 at 15:46
  • @JanGaraj you are right. I was testing locally simulating the prod env - sorry for not being clear on that. For our test env I tested with `app.set('trust proxy', 'linklocal, uniquelocal')` and it also did not work. I debugged the requests and found out that SRE for some reason disabled the `x-forwarded-proto` header on all environments. So after talking with SRE they enabled the header again I now get the correct `redirect_uri` :) If you or @Dasniko want to add an answer to this question I will gladly give the bounty. – dazito Jun 30 '21 at 07:51

0 Answers0