p2-inc / keycloak-magic-link

Magic Link Authentication for Keycloak
https://phasetwo.io
Other
239 stars 48 forks source link

Issuer/audience do not behave the same between production and dev #72

Closed redabourial closed 8 months ago

redabourial commented 8 months ago

If i start keycloak with the start-dev parameter and generate a magic link the link's jwt will have issuer and audience equal to the request's host header. Example :

await axios.post(`${process.env.KEYCLOAK_URL}/realms/${this.realm}/magic-link`, {
      email,
      client_id: `meteorjs`,
      redirect_uri,
      expiration_seconds: verificationLinkTimeout,
      remember_me: true,
    }, {
      headers: {
        Accept: `application/json`,
        'Content-Type': `application/json`,
        Authorization: `Bearer ${this.token}`,
        host: `test.com`,
      },
    });

The link is :

https://auth.localhost:8443/realms/testfordev/login-actions/action-token?key=eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJjY2QxZGY3Ny02NTkyLTRhNzEtYjFhOC03MGQyYjFhNjE1MGMifQ.eyJleHAiOjE3MDk3MzA2OTAsImlhdCI6MTcwOTczMDM5MCwianRpIjoiN2M5NWZiMTQtMTFkMi00ZjQ1LWJlNmEtZjM3YTNmOWNiZTUxIiwiaXNzIjoiaHR0cHM6Ly90ZXN0LmNvbS9yZWFsbXMvdGVzdGZvcmRldiIsImF1ZCI6Imh0dHBzOi8vdGVzdC5jb20vcmVhbG1zL3Rlc3Rmb3JkZXYiLCJzdWIiOiI5ZjMzNjZkZi1iOTNlLTQxYmItODhjZS03MGRhODczNzIyNjEiLCJ0eXAiOiJleHQtbWFnaWMtbGluayIsImF6cCI6Im1ldGVvcmpzIiwibm9uY2UiOiI3Yzk1ZmIxNC0xMWQyLTRmNDUtYmU2YS1mMzdhM2Y5Y2JlNTEiLCJyZHUiOiJodHRwczovL3Rlc3Rmb3JkZXYubG9jYWxob3N0LyIsInJtZSI6dHJ1ZSwicnUiOnRydWV9.b7uYYz8LJ60FO-AkF3jqWj87VNLiVML5m0mjZjEy7dsNKdGhxFLyc9p5o8N3Tvgtu3gExrtfW3PVUkkqY8vJeg&client_id=meteorjs

If i derialize the key, it is :

{
  "exp": 1709730690,
  "iat": 1709730390,
  "jti": "7c95fb14-11d2-4f45-be6a-f37a3f9cbe51",
  "iss": "https://test.com/realms/testfordev",
  "aud": "https://test.com/realms/testfordev",
  "sub": "9f3366df-b93e-41bb-88ce-70da87372261",
  "typ": "ext-magic-link",
  "azp": "meteorjs",
  "nonce": "7c95fb14-11d2-4f45-be6a-f37a3f9cbe51",
  "rdu": "https://testfordev.localhost/",
  "rme": true,
  "ru": true
}

Note that the issuer and audience have the same value as the host header in the request.

Now if i make the same request with "start" and "--hostname-url=https://auth.localhost:8443". I get :

https://auth.localhost:8443/realms/testinprod/login-actions/action-token?key=eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI5OTJlZDk5ZC01YTZhLTQ4MDUtYjg1Ni1jMGFmZTg5ZmU2OTYifQ.eyJleHAiOjE3MDk3MzEwODIsImlhdCI6MTcwOTczMDc4MiwianRpIjoiYTNmZDg4YzAtYTc4MC00NGRjLTgyZDYtNmI4ODVhZmM4Yjg3IiwiaXNzIjoiaHR0cHM6Ly9hdXRoLmxvY2FsaG9zdDo4NDQzL3JlYWxtcy90ZXN0aW5wcm9kIiwiYXVkIjoiaHR0cHM6Ly9hdXRoLmxvY2FsaG9zdDo4NDQzL3JlYWxtcy90ZXN0aW5wcm9kIiwic3ViIjoiMjU1ZGY0OWUtYzc3OC00NWNlLWJlMzctOTJiZDliZDA3N2EzIiwidHlwIjoiZXh0LW1hZ2ljLWxpbmsiLCJhenAiOiJtZXRlb3JqcyIsIm5vbmNlIjoiYTNmZDg4YzAtYTc4MC00NGRjLTgyZDYtNmI4ODVhZmM4Yjg3IiwicmR1IjoiaHR0cHM6Ly90ZXN0aW5wcm9kLmxvY2FsaG9zdC8iLCJybWUiOnRydWUsInJ1Ijp0cnVlfQ.7EEe9svgWSMDqbGqgDv2nOzoco76l_8V6Sbylb6259DxaDKGjTCsMAKT01jvCeoBn-DswyNYHnjay9b1MKRnRA&client_id=meteorjs

Derialize the key and you can see that the issuer and audience have been overwritten by ""--hostname-url":

{
  "exp": 1709731082,
  "iat": 1709730782,
  "jti": "a3fd88c0-a780-44dc-82d6-6b885afc8b87",
  "iss": "https://auth.localhost:8443/realms/testinprod",
  "aud": "https://auth.localhost:8443/realms/testinprod",
  "sub": "255df49e-c778-45ce-be37-92bd9bd077a3",
  "typ": "ext-magic-link",
  "azp": "meteorjs",
  "nonce": "a3fd88c0-a780-44dc-82d6-6b885afc8b87",
  "rdu": "https://testinprod.localhost/",
  "rme": true,
  "ru": true
}

The link also produces an invalid issuer error : "Expected issuer https://testinprod.localhost/realms/testinprod" when clicked.

See 6fe08f9 for a fix.

@xgp please don't hesitate to tell me if you need more details.

xgp commented 8 months ago

@redabourial thanks for filing this.

If i start keycloak with the start-dev parameter and generate a magic link the link's jwt will have issuer and audience equal to the request's host header.

Don't you mean "If i start keycloak with the start-dev parameter any jwt will have issuer and audience equal to the request's host header"?

How is this different than any other token generation in Keycloak? Can you explain how this is specific to this magic link extension?

Also, have you tried using --hostname-url in dev mode?

redabourial commented 8 months ago

@xgp Thank you for your patience. The issue appears with --hostname-url in dev mode. After some investigation it has to do with the frontend url option. Screenshot from 2024-03-06 18-08-37

It is not specific to this extension, it is an issue with keycloak's behavior.

FYI, I reported the issue here https://github.com/keycloak/keycloak/issues/27627.

If you want to keep my hot fix i have added comments to explain the issue.

I think this should be patched in the extension while waiting for the keycloak team to fix this bug, but i let you be the judge of that.

tl;dr : the extension is broken when frontendUrl is set, the issue comes from keycloak.

xgp commented 8 months ago

@redabourial I'm not sure the maintainers will "fix" the issue or consider it a bug.

I'm going to close this for now. If Keycloak chooses to change this behavior and this extension isn't working right, please reopen. Thanks for your efforts.