oviva-ag / ehealthid-relying-party

OpenID Connect Relying Party for Germany's GesundheitsID (eHealthID)
Apache License 2.0
16 stars 3 forks source link

Configuration with FusionAuth #43

Closed yvesonline closed 6 months ago

yvesonline commented 7 months ago

Instead of Keycloak I'm trying to make this work with FusionAuth but I'm running into a couple of problems.

The RP is running under rp.d.uhhq.dev and registered with the TU and I'm now initiating a login from FusionAuth.

FusionAuth redirects me to the URL: https://rp.d.uhhq.dev/auth?code_challenge=...&code_challenge_method=S256&client_id=admin&redirect_uri=<FusionAuth callback URL>&response_type=code&scope=openid&state=...

Which brings me to the page where I can select the provider: image

Now when I execute a login it fails with a 500 because the request to the Gematik fails with a 400: "unexpected exception: http request failed: bad status 'POST https://gsi.dev.gematik.solutions/PAR_Auth' status=400"

When I print the parBody with System.out.println(new String(parBody.build())); in redirectToSectoralIdp I see that the nonce is missing: client_id=https%3A%2F%2Frp.d.uhhq.dev&code_challenge=...&code_challenge_method=S256&redirect_uri=<RP callback URL>&nonce&state=...&scope=openid+urn%3Atelematik%3Aemail+urn%3Atelematik%3Aversicherter+urn%3Atelematik%3Adisplay_name&acr_values=gematik-ehealth-loa-high&response_type=code

Shouldn't FusionAuth send the nonce?

If I manually inject the nonce for testing purposes the 400 disappears and I run into a 403 with the Gematik sectoral IdP (I haven't further investigated why).

The configuration in FusionAuth looks like this: image

I'm aware that this is new territory as you're using Keycloak but was wondering if you have any pointers/thoughts? I'm stepping a bit in the dark at the moment.

eduardOrthopy commented 7 months ago

I do not have any experience with FusionAuth, so I can not really help you with that. If I find time later, I will try to give that a look, no promises, though.

However, regarding the 403, have you set up a local proxy that attaches the X-Auth-Header for the Gematik IDP for requests from your local machine? If not, that is one reason for 403 responses from them.

Instructions on how you can set this up are here.

The header value can be requested from Gematik.

yvesonline commented 7 months ago

Thanks for the pointer @eduardOrthopy , I somehow thought that setting the GEMATIK_AUTH_HEADER environment variable would be enough. I'll have a look into that later and test it. Will report back here.

eduardOrthopy commented 7 months ago

Again, as I said, I have 0 experience with FusionAuth and I have not done any test setup experiments, so take all of this with a rather large grain of salt.

Here are some things that I think you could try to reconfigure:

Not sure, that any of this will help wrt. the nonce issue you described, but those are some things I noticed.

yvesonline commented 7 months ago

Thanks for the valuable pointers (especially the proxy hint) @eduardOrthopy , I'm a step further!

The flow is now working until it comes back to auth/token where it returns with a 401 in the relying party. I'm not sure why, I'm still debugging but I assume something is not right with signing. But it's a hunch, I'm still investigating.

I've noticed two items while testing with FusionAuth:

I'm more than happy to provide PRs for both items if this is helpful at all but I'd need some guidance in implementing it.

Maybe @thomasrichner-oviva or someone from the Oviva team has pointers/notes?

And btw thanks for making this available @thomasrichner-oviva and team, so helpful and such good work 💪🏻 🎉 🙂

yvesonline commented 7 months ago

I'm a bit lost now debugging the 401 to the auth/token endpoint. I'm trying to replay this locally because the flow always puts me back to our deployed relying party. I've got the debug level set to DEBUG there but I can't see anything in the logs. I assume that it fails somewhere in TokenEndpoint in line 45 (as far as I can see only in authenticate AuthenticationExceptions are thrown). How do I get the client_assertion to replay this locally? Which JWT from which step is this? Do you have any pointers how to debug this?

thomasrichner-oviva commented 7 months ago

Hey @yvesonline !

Nonce

First off, it seems your IDP is trying to run a PKCE flow as indicated by code_challenge_method=S256 in your initial URL. At the moment the RP only supports the authorization_code flow. Would be neat though to support PKCE.

The nonce is just forwarded to the GesundheitsID sektoraler IDP, i.e. the Gematik IDP. It enforces its presence. An option would be to just generate one in the RP in case it's missing. Somewhere here probably: https://github.com/oviva-ag/ehealthid-relying-party/blob/a0e3c2b0bd310aa064387f1882dc58ef4265e438/ehealthid-rp/src/main/java/com/oviva/ehealthid/relyingparty/svc/AuthService.java#L79

auth/token

auth/token is the last call in the flow, are you sure you are getting this far? If you get a 401 you probably fail here somewhere: https://github.com/oviva-ag/ehealthid-relying-party/blob/a0e3c2b0bd310aa064387f1882dc58ef4265e438/ehealthid-rp/src/main/java/com/oviva/ehealthid/relyingparty/svc/ClientAuthenticator.java#L49

Debugging

Reg. debugging, you can set the JAVA_DEBUG environment variable to true. After that you can attach a remote debugger. See also https://github.com/fabric8io-images/run-java-sh/blob/master/fish-pepper/run-java-sh/readme.md

yvesonline commented 7 months ago

Thank you for your answer @thomasrichner-oviva !

You're right, FusionAuth is initiating a PKCE flow. I don't seem to be able to explicitly disable it. The doc says it automatically falls back:

Proof Key for Code Exchange, more commonly referred to as PKCE (pronounced pixy) is an extension to the Authorization Code grant. This extension is intended to help secure the code exchange workflow utilized by this OpenID Connect configuration. This extension is used by default on all OpenID Connect IdP configurations, and it cannot be disabled. The use of this extension is backwards compatible with identity providers that either do not require or support PKCE. FusionAuth will pass along the required PKCE request parameters to the OpenID Connect identity provider and if the provider supports PKCE, the extension will be utilized, and if it is not supported it will be ignored.

From: https://fusionauth.io/docs/lifecycle/authenticate-users/identity-providers/overview-oidc

However this doesn't seem to work. When the flow comes back FusionAuth complains that it can't determine the code_verifier, pointing towards that it's trying to do PKCE.

Any idea why FusionAuth thinks that the RP supports PKCE? I see code fragments called PKCE in the code but I'm not sure I understand why they're called PKCE?

What would be necessary to support PKCE? (Disclaimer: I'm no OpenID Connect expert.)

thomasrichner-oviva commented 7 months ago

The relying party uses PKCE between itself and the OpenID federation. That's why there is code related to it. Not sure why FusionAuth would think it supports it though, the /.well-known/openid-configuration is very clear in what it supports.

It would not be a huge amount of work to actually support it. Handling and verifying a few more query params should be it.

thomasrichner-oviva commented 6 months ago

@yvesonline can we close this?

yvesonline commented 6 months ago

@thomasrichner-oviva Yes, can be closed, we couldn't make it work together with FusionAuth.