omniauth / omniauth_openid_connect

MIT License
157 stars 186 forks source link

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

Open TheRealNeil opened 1 year ago

TheRealNeil commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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.

gucki commented 10 months ago

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.