execute-actions-email and the JWT token in generated link

636 views
Skip to first unread message

Daniel Popowich

unread,
Dec 9, 2021, 12:46:02 PM12/9/21
to Keycloak User
I have docker-compose configuration where my web-app and keycloak containers run on a private internal network. Any public access to these containers is via a nginx container that reverse-proxies as appropriate. Internally, my web-app will communicate directly to keycloak via its REST api at http://keycloak:8080/auth/admin/..., i.e., the hostname:port known within the docker network.  This works like a charm, until ...

Recently I added support in my web-app's REST api to initiate a reset of a user's password using keycloak's PUT /auth/admin/realms/{realm}/users/{uid}/execute-actions-email?client_id={client_id}&redirect_uri={redirect_uri}&lifespan=7200. My first problem was discovering that the generated link delivered in the email had this href:

    http://keycloak:8080/auth/realms/{REALM}/login-actions/action-token?key={JWT}

Clearly, that host:port wouldn't work! It appears when generating the URI keycloak uses the connection information to generate the return URI rather than the client ID's root url. My initial fix was to set the Host header (in the session used by the web-app) to the public domain, e.g., if my public domain is example.com, Host: example.com, then the link in the email becomes:

    http://example.com/auth/realms/{REALM}/login-actions/action-token?key={JWT}

This worked great in my development environment where everything is over http. But in my production environment we use https to communicate with nginx which then reverse-proxies internally via http, so when keycloak receives the the request after the user clicks the link (http), nginx redirects the request to https and then I receive this error from keycloak:

    We are sorry...
    An error occurred, please login again through your application.


Looking at keycloak logs I see this:

16:06:44,971 WARN [org.keycloak.events] (default task-6) type=EXECUTE_ACTION_TOKEN_ERROR, realmId=MyRealm, clientId=null, userId=d6884db2-4fd4-437c-a3b5-9fb01ab04eab, ipAddress=XX.XX.XX.XX, error=not_allowed, reason='Invalid token issuer. Expected 'https://example.com/auth/realms/MyRealm', but was 'http://example.com/auth/realms/MyRealm'', token_id=9ec60517-7b9e-4747-b23e-363d7272a559, action=execute-actions

Looking at the JWT, I see, in part:

    {
     "iss": "http://example.com/auth/realms/TaxCreditPortal",
     "aud": "http://example.com/auth/realms/TaxCreditPortal",
    }

And that seems to be the mismatch: the JWT has http, but the connection is coming over https.

I then tried setting the Host header to example.com:443, but that didn't work either, I see this in the error:

Expected 'https://example.com/auth/realms/MyRealm', but was 'http://example.com:443/auth/realms/MyRealm''

Surely, I can't be the first to attempt this. What am I doing wrong?!?!?

Thanks!

Daniel Popowich

unread,
Dec 9, 2021, 6:21:23 PM12/9/21
to Keycloak User
Answering my own question: the problem is the web-app connects directly to keycloak without using the reverse proxy.  When it makes the execute-actions-email call it does so with a http connection and keycloak, when generating the URI for the JWT key, specifies the current connection's scheme in the URI, http, which will be always in conflict with a client coming in with https (via nginx's X-Forwarded-Proto).

The solution - to set the Host header to the configured domain (always) and optionally, when the configuration uses TLS, X-Forwarded-Proto to "https" in the session my web-app creates to communicate with keycloak.

Reply all
Reply to author
Forward
0 new messages