rkm
rkm

Reputation: 3131

Keycloak token exchange fails with "invalid_token" error

I have two Keycloak instances running locally. They are connected via OIDC. Everything works so far - I can login via any of Keycloak instances.

Now I am trying to setup token exchage and it fails with "invalid_token" error. I want to do "external to internal" token exchange. There are following Keycloak logs showing that Keycloak sending HTTP GET request with the token I provided to another Keycloak instance to get user info:

08:14:36,523 DEBUG http-outgoing-19 >> "GET /auth/realms/master/protocol/openid-connect/userinfo HTTP/1.1[\r][\n]"
08:14:36,523 DEBUG http-outgoing-19 >> "Authorization: Bearer eyJhbGciOiJSU...[\r][\n]"

and the response is 401:

08:14:36,530 DEBUG http-outgoing-19 << "HTTP/1.1 401 Unauthorized[\r][\n]"
08:14:36,530 DEBUG http-outgoing-19 << "X-XSS-Protection: 1; mode=block[\r][\n]"
08:14:36,530 DEBUG http-outgoing-19 << "X-Frame-Options: SAMEORIGIN[\r][\n]"
08:14:36,530 DEBUG http-outgoing-19 << "Referrer-Policy: no-referrer[\r][\n]"
08:14:36,530 DEBUG http-outgoing-19 << "Date: Tue, 24 Nov 2020 08:14:36 GMT[\r][\n]"
08:14:36,530 DEBUG http-outgoing-19 << "Connection: keep-alive[\r][\n]"
08:14:36,530 DEBUG http-outgoing-19 << "WWW-Authenticate: Bearer realm="master", error="invalid_token", error_description="Token verification failed"[\r][\n]"

The weird part is this: when I am sending the same response with curl using the same token that does not work in Keycloak - it works:

curl -X GET 'http://localhost:8050/auth/realms/master/protocol/openid-connect/userinfo' \
 -H 'Authorization: Bearer eyJhbGciOiJSUzI1N...'

{"name":"r o","sub":"fff41a6f-6910-4419-8d46-7630b57ed420","email_verified":true,"preferred_username":"ttt","given_name":"r","family_name":"o"}

All permissions for token exchange set up (otherwise it does not send the request at all and it fails with another error).

What am I missing here? Any help is highly appreciated.

Upvotes: 3

Views: 14058

Answers (1)

rkm
rkm

Reputation: 3131

I figured it out. It worked using curl, because I was using localhost, and it did not work in Keycloak, because Keycloak used local IP address (192.168.X.X). The core reason is in the token that has to be exchanged. Field iss must match the IP/Host that is sending the request. In other words, in the token that I used to test token exchange, iss was equal http://localhost..., and I also used localhost in curl request. After using token that's been issued from 192.168.XX, token exchange started to work.

Actually, from a security perspective it totally makes sense. Only issuer of the token should be able to use it to get user info.

Upvotes: 10

Related Questions