Following the tutorial exactly has callback URL errors
GeordieGuy opened this issue · comments
Following this tutorial for Rails to the letter doesn't result in a functional app. The callback URL for authentication is either wrong or there's something else missing. Following it exactly and attempting to log in raises the error;
AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application: '37869d77-ef74-43f7-a135-208dcc7997e9'.
Callback URL for application is http://localhost:3000/auth/microsoft_graph_auth/callback
Ruby 2.6.3
Rails 6.0.2.1
I just recently went through this tutorial and confirmed the steps. When you click the sign in button, and the browser goes off to login.microsoftonline.com, what's the full URL?
Moving this to the ruby tutorial repo.
@GeordieGuy do you still need help with this?
Hi @jasonjoh, I think I have a similar error:
No route matches [POST] "/auth/microsoft_graph_auth"
My routes.rb here:
Rails.application.routes.draw do
get 'calendar/index'
get 'home/index'
root 'home#index'
# Add future routes here
# Add route for OmniAuth callback
match '/auth/:provider/callback', to: 'auth#callback', via: [:get, :post]
get 'auth/signout'
end
I couldnt find the error. I followed the tutorial exactly as it says.
Ruby 2.6.5p114
Rails 6.0.2.1
The funny thing is that if you use the msgraph-training-rubyrailsapp/Demos/03-add-msgraph/
code, with your APP_ID and APP_SECRET, it works!
Can you help me please? Thanks!
Hmm. It should be going to /auth/microsoft_graph_auth/callback
, not /auth/microsoft_graph_auth
. Can you find any differences if you diff your project with the msgraph-training-rubyrailsapp/Demos/03-add-msgraph/
code? Using a tool like WinMerge?
I just recently repeated this tutorial from scratch, and didn't hit any issues. Granted I've done this numerous times, so it's possible I've glossed over some step unknowingly.
Nop.. No differences. I did a diff from a shell in linux.
Well, the only differences are in the Gemfile with gems updated.
My Gemfile:
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.6.5'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.0'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
gem 'duktape'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
# Rubocop
gem 'rubocop', require: false
end
group :development do
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
gem 'web-console', '>= 3.3.0'
end
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15', '< 4.0'
gem 'selenium-webdriver'
# Easy installation and use of chromedriver to run system tests with Chrome
gem 'chromedriver-helper'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem 'omniauth-oauth2', '~> 1.6'
gem 'httparty', '~> 0.17.1'
gem 'nokogiri', '~> 1.10.7'
gem 'activerecord-session_store', '~> 1.1'
gem "omniauth-rails_csrf_protection", "~> 0.1.2"
NOTE: I had to change de ruby version. Which version do you have of Ruby and Rails?
I'm on Windows, and currently I have:
ruby 2.6.5p114 (2019-10-01 revision 67812) [x64-mingw32]
Rails 6.0.2.2
- What were the differences?
- Did you use the same app ID for both projects?
Yes. I used same app ID for both projects.
I'm starting a new rails new graph-tutorial
from scratch. I'm trying to test my app, following the tutorial, before the step: Storing the tokens
.
So my callback for now is:
def callback
# Access the authentication hash for omniauth
data = request.env['omniauth.auth']
# Temporary for testing!
render json: data.to_json
end
When I go to http://localhost:3000/ I have the following error:
ActionView::Template::Error (The asset "application.js" is not present in the asset pipeline.):
15: <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"
16: integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
17: <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
18: <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
19: </head>
20:
21: <body>
app/views/layouts/application.html.erb:18
I'm still with Ruby 2.6.5p114 and Rails 6.0.2.1 on MacOS Catalina.
Didn't you have this error when you started from scratch?
Ah yep, I did. This is a Rails change. Change the javascript_include_tag
to javascript_pack_tag
.
Yup! I read that on stackoverflow and I did it.
I was finishing the tutorial, and now it works! :D
Maybe you can add a note in the tutorial about javascript_pack_tag
if javascript_include_tag
doesn't work properly. Because that was the only mistake I had.
Thank you very much @jasonjoh!
I've changed it in the refresh, which hasn't been merged yet. Glad you got it working!
Hi @jasonjoh
I have the similar issue following the tutorial or cloning the completed tutorial.
For both the the cloned demo or the following the tutorial steps, when I click "Click here to sign in" I get a rails error page.
No route matches [GET] "/auth/microsoft_graph_auth"
Focusing on the demo cloned from GitHub.
I pulled the latest version: Latest commit e5a253d on Apr 15
e5a253d
It has the following routes file (omitting comments):
Rails.application.routes.draw do
get 'calendar/index'
get 'calendar', to: 'calendar#index'
get 'home/index'
root 'home#index'
match '/auth/:provider/callback', to: 'auth#callback', via: [:get, :post]
get 'auth/signout'
end
And rails routes -c auth
returns the following.
~/Dev/msgraph-training-rubyrailsapp/demo/graph-tutorial(master*) » rails routes -c auth mark@Marks-MacBook-Pro
Prefix Verb URI Pattern Controller#Action
GET|POST /auth/:provider/callback(.:format) auth#callback
auth_signout GET /auth/signout(.:format) auth#signout
First confusing point is that there is no route that corresponds to the path: POST /auth/:provider
or GET /auth/:provider
Secondly, the error page says no route matches GET, but the link in app/views/home/index.html.erb
is a POST link.
<%= link_to "Click here to sign in", "/auth/microsoft_graph_auth", method: :post, class: "btn btn-primary btn-large" %>
I can see that it is using the data-method attribute when I inspect the HTML:
<a class="btn btn-primary btn-large" rel="nofollow" data-method="post" href="/auth/microsoft_graph_auth">Click here to sign in</a>
Even if it did correctly submit a POST request through js (data-method=POST), I don't know how it would know where to direct it without the corresponding route.
I see there was a massive commit on the 15th of April. I skimmed through it, but I don't see any breaking changes in the main files mentioned above.
Am I miss understanding the intended behaviour of the sign in link? Any help would be greatly appreciated. Thanks
@markhallen what Rails and Ruby version are you using?
The cloned repo is as per the Gemfile:
=> Booting Puma
=> Rails 6.0.2.2 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.3 (ruby 2.6.5-p114), codename: Mysterious Traveller
The follow through is a slightly later version:
=> Booting Puma
=> Rails 6.0.3.1 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.5 (ruby 2.7.0-p0), codename: Mysterious Traveller
Both exhibit exactly the same behaviour.
And you get this error when you click sign-in, or after you sign-in and consent?
Also which browser are you using?
Firefox 77
So to explain what's going on with the routes.rb and using a POST instead of GET:
The sample uses OmniAuth, which has support for multiple auth providers on an app. They use this /auth/:provider/callback
route so whichever provider is being used gets inserted where :provider
is. It then sends that to the callback
method inside the AuthController
. This is ONLY for the auth callback - when the user finishes signing in and consenting, and the browser goes back to the app.
The request to /auth/microsoft_graph_auth
is handled by OmniAuth in the middleware pipeline. It knows to redirect that request to the authorize URL configured by the auth provider.
So why POST? Why not GET? Unfortunately OmniAuth has an unresolved security issue: https://nvd.nist.gov/vuln/detail/CVE-2015-9284. To mitigate it, the sample uses omniauth-rails_csrf_protection. For that gem to protect against the attacks, it disables GET on the /auth/microsoft_graph_auth path. Follow that link for their explanation.
So the issue is likely that for whatever reason your browser is not sending the request as a POST. I can't reproduce your problem with Edge or Chrome. I can force the error by manually entering the URL in the address bar. Are you able to test with another browser to eliminate the browser?
Sorry, I missed the other question. It is when I click sign in at the very start. I never get to the point where I can enter credentials. The error is a standard rails routing error. It presents the routes table to show all the available routes.
No problem - GET is never going to work (by design) unless you remove the csrf_protection gem. That's going to potentially open you up to CSRF attacks though.
I agree that there seems to be something missing, I cannot seem to find or understand where it sends you back a login URL for microsoft. This sample does not work as is.
Closing this issue as it's not actionable. OmniAuth does abstract a lot of the auth work and redirects, which can make it a bit hard to follow. Here's how the sample works.
In route.rb, you configure OmniAuth routing like so:
# Add route for OmniAuth callback
match '/auth/:provider/callback', to: 'auth#callback', via: [:get, :post]
So anything going to /auth/:provider/callback will get sent to the callback method in auth_controller.rb. :provider is a placeholder and depends on which authentication provider is being used. In this sample, there's only one (microsoft_graph_auth), but in a production app you might have multiple (Facebook, Google, GitHub, etc.).
The sign in flow goes like this:
- The sign-in links in the app go to /auth/microsoft_graph_auth
- OmniAuth middleware intercepts and handles this request for you - there is no code that you have to write for it because OmniAuth's default OAuth handling of building the login URL works with only slight tweaking. How does that work? Well OAuth is a standard, and most OAuth providers follow that standard, so OmniAuth can get pretty close to working out of the box. All we need to do in our OmniAuth strategy is:
- Tell OmniAuth the login site for Microsoft
- Tweak the query parameters for the login to convert the scope array to a flat list of scopes
- Tweak the callback URL to strip query parameters
Here's the request as captured in the Network tab in Dev Tools:
Request URL: http://localhost:3000/auth/microsoft_graph_auth
Request Method: POST
Status Code: 302 Found
Remote Address: [::1]:3000
Referrer Policy: strict-origin-when-cross-origin
Cache-Control: no-cache
Content-Length: 352
Location: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=9d9349f2-57ed-49bd-92c1-3035d15bf579&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fmicrosoft_graph_auth%2Fcallback&response_type=code&scope=openid+profile+email+offline_access+user.read+calendars.read&state=98cf9a405028aa654558a93d65baf0c8273715b9e1183a4d