DuendeSoftware / Support

Support for Duende Software products
21 stars 0 forks source link

Cryptographic exception when using Auth0 paswordless identity provider #443

Closed eugene-rebedailo closed 1 year ago

eugene-rebedailo commented 1 year ago

Which version of Duende IdentityServer are you using? 6.0.4

Which version of .NET are you using? .NET 6

Describe the bug An exception is thrown when trying to sign in using external OAuth provider (Auth0). After having gone through the sign-in process in Auth0 (using paswordless authentication + MFA), when returning to the identity server and calling the following endoint: /federation//signin, a cryptographic exception is thrown.

To Reproduce

Expected behavior User successfully signs into the application through the Auth0 provider.

Log output/exception with stacktrace

System.Security.Cryptography.CryptographicException:
   at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore (Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
   at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect (Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
   at Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Unprotect (Microsoft.AspNetCore.DataProtection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
   at Duende.IdentityServer.Infrastructure.DistributedCacheStateDataFormatter.Unprotect (Duende.IdentityServer, Version=6.0.4.0, Culture=neutral, PublicKeyToken=null: /_/src/IdentityServer/Infrastructure/DistributedCacheStateDataFormatter.cs:101)
   at Duende.IdentityServer.Infrastructure.DistributedCacheStateDataFormatter.Unprotect (Duende.IdentityServer, Version=6.0.4.0, Culture=neutral, PublicKeyToken=null: /_/src/IdentityServer/Infrastructure/DistributedCacheStateDataFormatter.cs:83)
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.ReadPropertiesAndClearState (Microsoft.AspNetCore.Authentication.OpenIdConnect, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler+<HandleRemoteAuthenticateAsync>d__19.MoveNext (Microsoft.AspNetCore.Authentication.OpenIdConnect, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)

Additional context Our setup has two Auth0-based identity providers. One of them is regular login-password and another one is paswordless(email). The regular login-password one seems to work without an issue.

josephdecock commented 1 year ago

You need to specify distinct CallBackPaths in the options of your authentication schemes, because the Microsoft OpenIdConnect handler gets distinct data protection keys each time it is registered as a authentication scheme.

The handler data protects the state parameter it sends to auth0. Then when auth0 returns to your application at the CallBackPath, it tries to unprotect that state value. The problem is, the schemes have conflicting callback paths, so the call back is being handled by the wrong scheme, which has the wrong data protection key.

eugene-rebedailo commented 1 year ago

It seems that every OIDC-type scheme is using a template of "/federation/\<scheme-id>/signin" as its CallbackPath. The Auth0 returns us to the correct return URI which is unique to that scheme.

I am unsure where this configuration could even be injected as we are not explicitely adding the schemes through .AddOpenIdConnect(), we instead rely on Dynamic Identity Provider registrations coming from the IdentityServer's table for "IdentityProviders".

eugene-rebedailo commented 1 year ago

Having debugged the entire sign on process locally, I have discovered that the data protectors on both "Protect" and "Unprotect" have the same "purpose", so it probably is not an issue with the data protectors. The issue seems to be that the state that we are trying to Unprotect is different form the state we sent when we initiated the login process.

josephdecock commented 1 year ago

Thanks Eugene - I was assuming that you were were statically configuring the identity providers, but if you're using dynamic providers, then what I said doesn't apply.

If you're seeing that auth0 is changing the state that would definitely cause this problem, and is an auth0 bug. Unfortunately, there isn't really any viable workaround that I can see. I think you're going to have to raise the issue with auth0.

eugene-rebedailo commented 1 year ago

Yes that's the plan for now, thank you for the valuable input!

We have been able to confirm that somehow when using passwordless sign-in, auth0 POSTs their own encoded "state" onto our federation/signin endpoint and not the state that we sent it originally. It is possibly a bug with their "Auth0PaswordlessLock" component.

josephdecock commented 1 year ago

Okay, great. I'll go ahead and close this issue for now then, but feel free to reopen it if there are further developments that need more discussion.