I am trying to make an authentication request to Micrsoft Graph API via a rails controller. I don't use rails erb templates and, therefore, do not include <%= csrf_meta_tags %> to automatically generate the required CSRF meta tags.
Instead, I'm making a POST request directly from an ApplicationController. I'm using omniauth-oauth2 and omniauth-rails_csrf_protection gems, as per the example project provided for rails/ms-graphs integration (https://github.com/microsoftgraph/msgraph-training-rubyrailsapp). Remaining configurations are per the example.
In my controller, I try to make the oauth request with something like:
response = Faraday.post('http://localhost:3000/omniauth/microsoft_graph_auth') do |req|
req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
req.headers['X-CSRF-Token'] = form_authenticity_token
end
where the form_authenticity_token method from RequestForgeryProtection modules automatically sets the raw token in the session and returns an encrypted token for use in the html meta, or in the X-CSRF-Token request header in my case.
Despite my best efforts and toiling over this for days, I invariably get an InvalidAuthenticityToken error. The omniauth middleware intercepts the request and fails with the following:
Started POST "/omniauth/microsoft_graph_auth" for ::1 at 2021-08-03 22:34:26 +0100
D, [2021-08-03T22:34:26.859167 #76841] DEBUG -- omniauth: (microsoft_graph_auth) Request phase initiated.
E, [2021-08-03T22:34:26.860607 #76841] ERROR -- omniauth: (microsoft_graph_auth) Authentication failure! ActionController::InvalidAuthenticityToken: ActionController::InvalidAuthenticityToken, ActionController::InvalidAuthenticityToken
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
omniauth-rails_csrf_protection (1.0.0) lib/omniauth/rails_csrf_protection/token_verifier.rb:34:in `call'
omniauth (2.0.4) lib/omniauth/strategy.rb:240:in `request_call'
omniauth (2.0.4) lib/omniauth/strategy.rb:193:in `call!'
omniauth (2.0.4) lib/omniauth/strategy.rb:169:in `call'
omniauth (2.0.4) lib/omniauth/builder.rb:45:in `call'
rack-cors (1.1.1) lib/rack/cors.rb:100:in `call'
...
I have tried a series of request variations, different "Content-Type" values, setting the CSRF token in the request body, but to no avail. Am I missing something basic in my request? Or perhaps is there something more fundamental I am not understanding about the CSRF verification mechanism, and form_authenticity_token simply can't be used in this manner. If so, how can I insert the correct CSRF token meta from the rails application into a javascript frontend? Any help or guidance is much appreciated.