Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OmniAuth::Strategies::OpenIDConnect::CallbackError, csrf_detected | Invalid 'state' parameter #160

Open
TheRealNeil opened this issue May 16, 2023 · 3 comments

Comments

@TheRealNeil
Copy link

Hi,

I am trying to configure omniauth_openid_connect to work with Devise and Microsoft Azure AD. I have the following config for devise

# config/initializers/devise.rb
config.omniauth :openid_connect, {
    issuer: "https://login.microsoftonline.com/#{Rails.application.credentials.azure.tenant_id}/v2.0",
    scope: [:openid],
    response_type: :code,
    response_mode: :form_post,
    uid_field: "preferred_username",
    discovery: true,
    state: Proc.new { SecureRandom.hex(32) },
    client_options: {
      port: 443,
      scheme: "https",
      host: "login.microsoftonline.com/#{Rails.application.credentials.azure.tenant_id}/v2.0",
      identifier: Rails.application.credentials.azure.client_id,
      redirect_uri: "http://localhost:3000/users/auth/openid_connect/callback",
    },
  }

When attempting to authenticate, I see the following errors in my rails log

web.1    | Started POST "/users/auth/openid_connect" for ::1 at 2023-05-16 11:36:50 +0100
web.1    | D, [2023-05-16T11:36:50.593978 #78216] DEBUG -- omniauth: (openid_connect) Request phase initiated.
web.1    | Started POST "/users/auth/openid_connect/callback" for ::1 at 2023-05-16 11:36:51 +0100
web.1    | D, [2023-05-16T11:36:51.046305 #78216] DEBUG -- omniauth: (openid_connect) Callback phase initiated.
web.1    | E, [2023-05-16T11:36:51.046843 #78216] ERROR -- omniauth: (openid_connect) Authentication failure! csrf_detected: OmniAuth::Strategies::OpenIDConnect::CallbackError, csrf_detected | Invalid 'state' parameter
web.1    | Processing by Users::OmniauthCallbacksController#failure as HTML
web.1    |   Parameters: {"code"=>"filtered", "state"=>"filtered", "session_state"=>"filtered"}
web.1    | Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms | Allocations: 599)
web.1    | 
web.1    | 
web.1    | E, [2023-05-16T11:36:51.059259 #78216] ERROR -- omniauth: (openid_connect) Authentication failure! The browser returned a 'null' origin for a request with origin-based forgery protection turned on. This usually
web.1    | means you have the 'no-referrer' Referrer-Policy header enabled, or that the request came from a site that
web.1    | refused to give its origin. This makes it impossible for Rails to verify the source of the requests. Likely the
web.1    | best solution is to change your referrer policy to something less strict like same-origin or strict-origin.
web.1    | If you cannot change the referrer policy, you can disable origin checking with the
web.1    | Rails.application.config.action_controller.forgery_protection_origin_check setting.

Adding skip_forgery_protection to my OmniauthCallbacksController results in just the csrf error

web.1    | Started POST "/users/auth/openid_connect" for ::1 at 2023-05-16 11:32:19 +0100
web.1    | D, [2023-05-16T11:32:19.340738 #78216] DEBUG -- omniauth: (openid_connect) Request phase initiated.
web.1    | Started POST "/users/auth/openid_connect/callback" for ::1 at 2023-05-16 11:32:22 +0100
web.1    | D, [2023-05-16T11:32:22.146487 #78216] DEBUG -- omniauth: (openid_connect) Callback phase initiated.
web.1    | E, [2023-05-16T11:32:22.147050 #78216] ERROR -- omniauth: (openid_connect) Authentication failure! csrf_detected: OmniAuth::Strategies::OpenIDConnect::CallbackError, csrf_detected | Invalid 'state' parameter
web.1    | Processing by Users::OmniauthCallbacksController#failure as HTML
web.1    |   Parameters: {"code"=>"filtered", "state"=>"filtered", "session_state"=>"filtered"}
web.1    | Redirected to http://localhost:3000/
web.1    | Completed 302 Found in 2ms (ActiveRecord: 0.0ms | Allocations: 504)

Can anyone offer me any guidance?

Thanks,
Neil

@davidwessman
Copy link
Contributor

What SameSite-config do you have?

We ran into errors like this after upgrading to Samesite=lax.
Found the reason in this blog post:
https://www.ubisecure.com/technical-announcements/samesite-cookies-changes/

Caution: unless some of the OIDC integrations are using response_mode=form_post

So if Microsoft Azure AD supports other response_modes I would suggest removing response_mode=form_post.

@difernandez
Copy link

Are you using the gem omniauth-rails_csrf_protection, or have you included something like this? It's needed when using omniauth v2. I remember getting some csrf related errors and adding the gem, plus the skip_forgery_protection, and that seemed to solve them.
Might not be the same though, I'm not using the same provider.

jeremyf added a commit to scientist-softserv/palni-palci that referenced this issue Aug 25, 2023
I believe there are two existing problems:

1. Regarding the loss of state.
2. The issuer is invalid.

I have been using the following JSON identity provider configuration:

```
{
  "name": "https://vufind.reshare-dev.indexdata.com/north/cdl/auth",
  "scope": [
    "https://reshare.palni-palci-staging.notch8.cloud/concern/cdls/74ebfc53-ee7c-4dc9-9dd7-693e4d840745",
    "openid"
  ],
  "issuer": "https://vufind.reshare-dev.indexdata.com/north/cdl/auth",
  "uid_field": "username",
  "send_nonce": true,
  "require_state": false,
  "response_mode": "form_post",
  "response_type": "id_token",
  "client_options": {
    "host": "vufind.reshare-dev.indexdata.com",
    "port": "443",
    "scheme": "https",
    "secret": "REDACTED",
    "identifier": "REDACTED",
    "redirect_uri": "https://reshare.commons-archive.org/users/auth/openid_connect/1/callback",
    "authorization_endpoint": "/north/cdl/auth"
  }
}
```

Note, for this set of tests, I toggled the original `send_nonce: false`
to `send_nonce: true`.  I have since restored the setting.

**Regarding the Loss of State:**

We never hit the callback method in the OmniauthCallbacksController.  We
continue to encounter the `invalid_state` error in the callback phase.
I am stuck on this.

I have looked to
omniauth/omniauth_openid_connect#160 to fiddle
with things, but haven't found any success.

**Regarding the Issuer Is Invalid:**

Being stuck on the loss of state, I chose to skip those validations to
see what next failed.  And found something interesting, namely that the
issuer is invalid.  Which has me wondering if there's something else
going on that the "issuer" is dropping/mishandling information.

```
irb(main):001:0> ::OpenIDConnect::Discovery::Provider::Config.discover!("https://vufind.reshare-dev.indexdata.com/north/cdl/auth")
Traceback (most recent call last):
        1: from (irb):1
OpenIDConnect::Discovery::DiscoveryFailed (Internal Server Error)
irb(main):002:0> ::OpenIDConnect::Discovery::Provider::Config.discover!("https://vufind.reshare-dev.indexdata.com/")
Traceback (most recent call last):
        2: from (irb):1
        1: from (irb):2:in `rescue in irb_binding'
OpenIDConnect::Discovery::DiscoveryFailed (Not Found)
```
@gucki
Copy link

gucki commented Aug 29, 2023

I had the same issue in development, but it was my fault and super easy to fix: I was using "http://127.0.0.1:3000/..." when accessing my app but the callback had to point to a domain, so I had to use "http://localhost:3000/..." for it. This of course doesn't work, because the cookie that contains the state gets lost when the domain is switched by the redirect happening in the callback. Simply always using "http://localhost:3000/..." fixed the issue for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants