lynndylanhurley / devise_token_auth

Token based authentication for Rails JSON APIs. Designed to work with jToker and ng-token-auth.
Do What The F*ck You Want To Public License
3.54k stars 1.13k forks source link

provider_ignores_state: true doesnt save session #1480

Open GMolini opened 3 years ago

GMolini commented 3 years ago

Hi,

Im trying to develop an addin for outlook. The addin backend is developed in rails, and I am using this gem for authentication. Im using this the omniauth microsoft graph gem for the microsoft authentication. In my addin, I use a dialog to get the /auth/microsoft_graph url and thus start the authentication process.

When I use the addin from the outlook standalone app, authentication runs smoothly and Im able to successfully log in. But if I try to open the addin on outlook for the web i get an CSRF error

Started GET "/auth/microsoft_graph" for 185.227.213.4 at 2021-01-21 12:37:21 +0100
   (0.4ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Started GET "/omniauth/microsoft_graph?resource_class=User" for 185.227.213.4 at 2021-01-21 12:37:21 +0100
I, [2021-01-21T12:37:21.665192 #54893]  INFO -- omniauth: (microsoft_graph) Request phase initiated.
   (0.1ms)  BEGIN
  ActiveRecord::SessionStore::Session Update (0.4ms)  UPDATE "sessions" SET "data" = $1, "updated_at" = $2 WHERE "sessions"."id" = $3  [["data", "BLABLA\n"], ["updated_at", "2021-01-21 11:37:21.695389"], ["id", 4182]]
   (0.7ms)  COMMIT
Started GET "/omniauth/microsoft_graph/callback?code=blabla&state=blabla&session_state=blablabla" for 185.227.213.4 at 2021-01-21 12:37:22 +0100
I, [2021-01-21T12:37:22.041232 #54893]  INFO -- omniauth: (microsoft_graph) Callback phase initiated.
E, [2021-01-21T12:37:22.046415 #54893] ERROR -- omniauth: (microsoft_graph) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected
E, [2021-01-21T12:37:22.046462 #54893] ERROR -- omniauth: (microsoft_graph) Authentication failure! invalid_credentials: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

I have tried setting provider_ignores_state: true int the omniauth.rb config

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :microsoft_graph, ENV['AZURE_APPLICATION_CLIENT_ID'], ENV['AZURE_APPLICATION_CLIENT_SECRET'],
    provider_ignores_state: true,
    scope: ENV['AZURE_SCOPE']
end 

but that then gives a NotImplementedError (no default_devise_mapping set): error.

Ive fixed that by setting a default devise mapping

  def default_devise_mapping
    'user'
  end

And also setting a default resource class, since in my case its always going to be User.

  def resource_class(mapping = nil)
    if omniauth_params['resource_class']
      omniauth_params['resource_class'].constantize
    elsif params['resource_class']
      params['resource_class'].constantize
    else
      User
    end
  end

But then it breaks when it tries to access the auth hash, because session is empty. I dont know why, the redirect_callbacks method is not correctly saving the session (only when it comes from the frame, from outlooks standalone app it works fine), as it says in this comment that it should do, so when the method omniauth_success is called, and then it tries to get the auth_hash, it raises an error NoMethodError (undefined method `[]' for nil:NilClass):

# this sesison value is set by the redirect_callbacks method. its purpose
# is to persist the omniauth auth hash value thru a redirect. the value
# must be destroyed immediatly after it is accessed by omniauth_success
def auth_hash
  @_auth_hash ||= session.delete('dta.omniauth.auth')
  @_auth_hash
end

Ive been investigating a bit more and I think it has to do with CSRF and the session store. I think that if the provider_ignores_state: true is set omniauth doesnt check CSRF and it doesnt raise the error, but the session store does check it and invalidates the session, thus not being able to complete the process. But if I dont use that option, omniauth checks the CSRF token and raises the error

GMolini commented 3 years ago

So, the problem comes definitely after the redirect_to redirect_route in the redirect_callbacks method. If I dont use a redirect and call the omniauth_success instead it works and I am able to log in successfully.