I'm building Rails API for AngularJS app. I'm using devise_token_auth and omniauth-steam gems. When I try to authenticate user using the Steam there is an error:
ActionController::RoutingError (No route matches [POST] "/omniauth/steam/callback"
I've added devise_token_auth routes, but they don't create POST callbacks. I've tried to manually create POST route for callback, but it hasn't worked and I'm not sure if it is even correct solution. I'm trying to solve this problem from yesterday and I can't find anyone with the similar one.
config/routes.rb
Rails.application.routes.draw do
namespace 'api' do
namespace 'v1' do
mount_devise_token_auth_for 'Api::V1::User', at: 'auth'
end
end
end
config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :steam, ENV['steam_api_key']
end
I use figaro gem and save steam_api_key in application.yml file.
rake routes task
Prefix Verb URI Pattern Controller#Action
new_api_v1_api_v1_user_session GET /api/v1/auth/sign_in(.:format) devise_token_auth/sessions#new
api_v1_api_v1_user_session POST /api/v1/auth/sign_in(.:format) devise_token_auth/sessions#create
destroy_api_v1_api_v1_user_session DELETE /api/v1/auth/sign_out(.:format) devise_token_auth/sessions#destroy
api_v1_api_v1_user_password POST /api/v1/auth/password(.:format) devise_token_auth/passwords#create
new_api_v1_api_v1_user_password GET /api/v1/auth/password/new(.:format) devise_token_auth/passwords#new
edit_api_v1_api_v1_user_password GET /api/v1/auth/password/edit(.:format) devise_token_auth/passwords#edit
PATCH /api/v1/auth/password(.:format) devise_token_auth/passwords#update
PUT /api/v1/auth/password(.:format) devise_token_auth/passwords#update
cancel_api_v1_api_v1_user_registration GET /api/v1/auth/cancel(.:format) devise_token_auth/registrations#cancel
api_v1_api_v1_user_registration POST /api/v1/auth(.:format) devise_token_auth/registrations#create
new_api_v1_api_v1_user_registration GET /api/v1/auth/sign_up(.:format) devise_token_auth/registrations#new
edit_api_v1_api_v1_user_registration GET /api/v1/auth/edit(.:format) devise_token_auth/registrations#edit
PATCH /api/v1/auth(.:format) devise_token_auth/registrations#update
PUT /api/v1/auth(.:format) devise_token_auth/registrations#update
DELETE /api/v1/auth(.:format) devise_token_auth/registrations#destroy
api_v1_api_v1_user_confirmation POST /api/v1/auth/confirmation(.:format) devise_token_auth/confirmations#create
new_api_v1_api_v1_user_confirmation GET /api/v1/auth/confirmation/new(.:format) devise_token_auth/confirmations#new
GET /api/v1/auth/confirmation(.:format) devise_token_auth/confirmations#show
api_v1_auth_validate_token GET /api/v1/auth/validate_token(.:format) devise_token_auth/token_validations#validate_token
api_v1_auth_failure GET /api/v1/auth/failure(.:format) devise_token_auth/omniauth_callbacks#omniauth_failure
GET /api/v1/auth/:provider/callback(.:format) devise_token_auth/omniauth_callbacks#omniauth_success
GET /omniauth/:provider/callback(.:format) devise_token_auth/omniauth_callbacks#redirect_callbacks
omniauth_failure GET /omniauth/failure(.:format) devise_token_auth/omniauth_callbacks#omniauth_failure
GET /api/v1/auth/:provider(.:format) redirect(301)
I know that it's a bit messy because of namespaces, but it shouldn't cause this problem, right?
EDIT:
I did some research and here is the link https://github.com/lynndylanhurley/devise_token_auth#usage-tldr it says that /:provider/callback url should have GET/POST action, but as we can see I don't have POST action for callback.
Finally I've solved this problem by adding below line to the routes.rb file.
post '/omniauth/steam/callback', to: 'overrides/omniauth_callbacks#redirect_callbacks'
I've created omniauth_callbacks_controller.rb file in controllers/overrides folder and removed below line.
skip_before_action :set_user_by_token, raise: false
The last step was editing line with redirect route. I've changed this:
redirect_route = "#{request.protocol}#{request.host_with_port}/#{Devise.mappings[devise_mapping].fullpath}/#{params[:provider]}/callback"
To hard-coded route.
redirect_route = "/api/v1/auth/steam/callback"
Related
I'm trying to allow my users to login with their Google accounts using devise, omniauth and devise-token-auth. To do so I have added the following code to the rails API-only boilerplate.
# Gemfile
...
# authentication
gem 'devise', '~> 4.7'
gem 'devise_token_auth', git: 'https://github.com/lynndylanhurley/devise_token_auth'
gem 'omniauth', '~> 1.9.1'
gem 'omniauth-google-oauth2
...
# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET']
end
# config/routes.rb
Rails.application.routes.draw do
root 'application#home'
mount_devise_token_auth_for 'User', at: 'auth'
end
For the frontend I use j-toker and have set it up as follows
Auth.configure({
apiUrl: `http://localhost:8000/`,
authProviderPaths: {
google: `/auth/google_oauth2`,
},
});
When the user clicks on the login with google button I then call
Auth.oAuthSignIn({ provider: `google` }).then(() => {
// handle result
});
The Issue: When the user clicks on the login button, a new tab opens up with the rails error message No route matches [GET] "/omniauth/google_oauth2"
It seems like /auth/google_oauth2 redirects to /omniauth/google_oauth2 but the /omniauth/:provider path doesn't exist
The output of rails routes is as follows:
Prefix Verb URI Pattern Controller#Action
root GET / application#home
new_user_session GET /auth/sign_in(.:format) devise_token_auth/sessions#new
user_session POST /auth/sign_in(.:format) devise_token_auth/sessions#create
destroy_user_session DELETE /auth/sign_out(.:format) devise_token_auth/sessions#destroy
new_user_password GET /auth/password/new(.:format) devise_token_auth/passwords#new
edit_user_password GET /auth/password/edit(.:format) devise_token_auth/passwords#edit
user_password PATCH /auth/password(.:format) devise_token_auth/passwords#update
PUT /auth/password(.:format) devise_token_auth/passwords#update
POST /auth/password(.:format) devise_token_auth/passwords#create
cancel_user_registration GET /auth/cancel(.:format) devise_token_auth/registrations#cancel
new_user_registration GET /auth/sign_up(.:format) devise_token_auth/registrations#new
edit_user_registration GET /auth/edit(.:format) devise_token_auth/registrations#edit
user_registration PATCH /auth(.:format) devise_token_auth/registrations#update
PUT /auth(.:format) devise_token_auth/registrations#update
DELETE /auth(.:format) devise_token_auth/registrations#destroy
POST /auth(.:format) devise_token_auth/registrations#create
auth_validate_token GET /auth/validate_token(.:format) devise_token_auth/token_validations#validate_token
auth_failure GET /auth/failure(.:format) users/omniauth_callbacks#omniauth_failure
GET /auth/:provider/callback(.:format) users/omniauth_callbacks#omniauth_success
GET|POST /omniauth/:provider/callback(.:format) users/omniauth_callbacks#redirect_callbacks
omniauth_failure GET|POST /omniauth/failure(.:format) users/omniauth_callbacks#omniauth_failure
GET /auth/:provider(.:format) redirect(301)
As you can see the /omniauth/:provider route doesn't even exist... Any idea what the Issue is?
Placing OmniAuth.config.allowed_request_methods = [:get] in the omniauth initializer fixed this issue for me.
Like this:
Rails.application.config.middleware.use OmniAuth::Builder do
OmniAuth.config.allowed_request_methods = [:get]
provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET']
end
However, it must be noted that allowing GET requests gives the following warning:
You are using GET as an allowed request method for OmniAuth. This may leave
you open to CSRF attacks. As of v2.0.0, OmniAuth by default allows only POST
to its own routes. You should review the following resources to guide your
mitigation:
https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284
https://github.com/omniauth/omniauth/issues/960
https://nvd.nist.gov/vuln/detail/CVE-2015-9284
https://github.com/omniauth/omniauth/pull/809
You can ignore this warning by setting:
OmniAuth.config.silence_get_warning = true
So its probably best to only allow POST requests
In building a Rails API, I declared my routes file as:
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
root 'budgets#index'
resources :users do
resources :budgets
end
post '/login', to: 'sessions#create'
post '/logout', to: 'sessions#destroy'
resources :budgets do
resources :budget_totals
end
end
end
end
However, after running the rails routes command, I found that the "new" and "edit" routes are missing. How do I rectify this?
The relevant portion of the rails routes response is:
Prefix Verb URI Pattern Controller#Action
api_v1_root GET /api/v1(.:format) api/v1/budgets#index
api_v1_user_budgets GET /api/v1/users/:user_id/budgets(.:format) api/v1/budgets#index
POST /api/v1/users/:user_id/budgets(.:format) api/v1/budgets#create
api_v1_user_budget GET /api/v1/users/:user_id/budgets/:id(.:format) api/v1/budgets#show
PATCH /api/v1/users/:user_id/budgets/:id(.:format) api/v1/budgets#update
PUT /api/v1/users/:user_id/budgets/:id(.:format) api/v1/budgets#update
DELETE /api/v1/users/:user_id/budgets/:id(.:format) api/v1/budgets#destroy
api_v1_users GET /api/v1/users(.:format) api/v1/users#index
POST /api/v1/users(.:format) api/v1/users#create
api_v1_user GET /api/v1/users/:id(.:format) api/v1/users#show
PATCH /api/v1/users/:id(.:format) api/v1/users#update
PUT /api/v1/users/:id(.:format) api/v1/users#update
DELETE /api/v1/users/:id(.:format) api/v1/users#destroy
api_v1_login POST /api/v1/login(.:format) api/v1/sessions#create
api_v1_logout POST /api/v1/logout(.:format) api/v1/sessions#destroy
api_v1_budget_budget_totals GET /api/v1/budgets/:budget_id/budget_totals(.:format) api/v1/budget_totals#index
POST /api/v1/budgets/:budget_id/budget_totals(.:format) api/v1/budget_totals#create
api_v1_budget_budget_total GET /api/v1/budgets/:budget_id/budget_totals/:id(.:format) api/v1/budget_totals#show
PATCH /api/v1/budgets/:budget_id/budget_totals/:id(.:format) api/v1/budget_totals#update
PUT /api/v1/budgets/:budget_id/budget_totals/:id(.:format) api/v1/budget_totals#update
DELETE /api/v1/budgets/:budget_id/budget_totals/:id(.:format) api/v1/budget_totals#destroy
api_v1_budgets GET /api/v1/budgets(.:format) api/v1/budgets#index
POST /api/v1/budgets(.:format) api/v1/budgets#create
api_v1_budget GET /api/v1/budgets/:id(.:format) api/v1/budgets#show
PATCH /api/v1/budgets/:id(.:format) api/v1/budgets#update
PUT /api/v1/budgets/:id(.:format) api/v1/budgets#update
DELETE /api/v1/budgets/:id(.:format) api/v1/budgets#destroy
Are you perhaps using the api_only app? Those do not generate New and Edit routes.
Did you create your app with the --api switch, such as: rails new my-api --api? The --api argument tells Rails that you want an API application only.
See "What Is Rails API?" and "Rails: Building a Ruby on Rails API-only app".
I want to create rails routes by hand rather than using the automatic resource :tasks (it's just an exercise, I'll go back to the using resources :tasks once I understand this).
I /think/ that I have the right syntax, but the prefixes (path_helpers) generated when I write the routes by hand are wrong. Why, and what am I not doing properly?
Here is my code:
Rails.application.routes.draw do
root to: 'tasks#index'
get 'tasks', to: 'tasks#index'
get 'tasks/:id', to: 'tasks#show'
get 'tasks/new', to: 'tasks#new'
post 'tasks', to: 'tasks#create'
get 'tasks/:id/edit', to: 'tasks#edit'
patch 'tasks/:id', to: 'tasks#update'
delete 'tasks/:id', to: 'tasks#destroy'
end
Here are the routes & prefixes it creates when I call rails routes in my terminal:
Prefix Verb URI Pattern Controller#Action
root GET / tasks#index
tasks GET /tasks(.:format) tasks#index
GET /tasks/:id(.:format) tasks#show
tasks_new GET /tasks/new(.:format) tasks#new
POST /tasks(.:format) tasks#create
GET /tasks/:id/edit(.:format) tasks#edit
PATCH /tasks/:id(.:format) tasks#update
DELETE /tasks/:id(.:format) tasks#destroy
Here is what I get when I use resource :tasks
Prefix Verb URI Pattern Controller#Action
tasks GET /tasks(.:format) tasks#index
POST /tasks(.:format) tasks#create
new_task GET /tasks/new(.:format) tasks#new
edit_task GET /tasks/:id/edit(.:format) tasks#edit
task GET /tasks/:id(.:format) tasks#show
PATCH /tasks/:id(.:format) tasks#update
PUT /tasks/:id(.:format) tasks#update
DELETE /tasks/:id(.:format) tasks#destroy
EDIT:
To answer a few of the answers: I know that I can use 'as' to name the prefixes, but I think that I shouldn't have to in this case.
From what I understand, 'as' is only used in case you want to change the standard prefix to a personalized one, or if you think your routes might change in the future and you don't want to risk to mess with with your helpers. I should still get correct prefixes without using 'as'.
Here though, the prefix tasks_new with the get method is both linked to the tasks#new and tasks#edit methods, which I don't think is right.
Rails will let you name the routes. For example:
get 'tasks/new', to: 'tasks#new', as: :new_task
Use as for naming the route.
Write the code as following:
Rails.application.routes.draw do
root 'tasks#index'
get 'tasks' => 'tasks#index', as: 'task_list'
get 'tasks/:id' => 'tasks#show', as: 'display_task'
get 'tasks/new' => 'tasks#new', as: 'task_new'
post 'tasks' => 'tasks#create', as: 'task_create
get 'tasks/:id/edit' => 'tasks#edit', as: 'task_edit'
patch 'tasks/:id', to: 'tasks#update'
delete 'tasks/:id', to: 'tasks#destroy'
end
GET on /auth/sign_up is not functioning as expected. Getting the following 404 error
{
"status": 404,
"error": "Not Found",
"exception": "#<AbstractController::ActionNotFound: The action 'new' could not be found for DeviseTokenAuth::RegistrationsController>",
"traces": #too long to post; 46 traces; none includes user created files
}
Here's everything I did
Created a new Rails API project
rails new untitled --javascript=jquery --api
Added this to Gemfile
#authentication
gem 'devise'
gem 'omniauth'
gem 'devise_token_auth'
Ran the following
bundle install
rails generate devise_token_auth:install User auth
rails db:migrate
rails s
Tested the url localhost:3000/auth/sign_up from browser and from Postman
My routes.rb
Rails.application.routes.draw do
mount_devise_token_auth_for 'User', at: 'auth'
end
My rails routes output
Prefix Verb URI Pattern Controller#Action
new_user_session GET /auth/sign_in(.:format) devise_token_auth/sessions#new
user_session POST /auth/sign_in(.:format) devise_token_auth/sessions#create
destroy_user_session DELETE /auth/sign_out(.:format) devise_token_auth/sessions#destroy
user_password POST /auth/password(.:format) devise_token_auth/passwords#create
new_user_password GET /auth/password/new(.:format) devise_token_auth/passwords#new
edit_user_password GET /auth/password/edit(.:format) devise_token_auth/passwords#edit
PATCH /auth/password(.:format) devise_token_auth/passwords#update
PUT /auth/password(.:format) devise_token_auth/passwords#update
cancel_user_registration GET /auth/cancel(.:format) devise_token_auth/registrations#cancel
user_registration POST /auth(.:format) devise_token_auth/registrations#create
new_user_registration GET /auth/sign_up(.:format) devise_token_auth/registrations#new
edit_user_registration GET /auth/edit(.:format) devise_token_auth/registrations#edit
PATCH /auth(.:format) devise_token_auth/registrations#update
PUT /auth(.:format) devise_token_auth/registrations#update
DELETE /auth(.:format) devise_token_auth/registrations#destroy
user_confirmation POST /auth/confirmation(.:format) devise_token_auth/confirmations#create
new_user_confirmation GET /auth/confirmation/new(.:format) devise_token_auth/confirmations#new
GET /auth/confirmation(.:format) devise_token_auth/confirmations#show
auth_validate_token GET /auth/validate_token(.:format) devise_token_auth/token_validations#validate_token
auth_failure GET /auth/failure(.:format) devise_token_auth/omniauth_callbacks#omniauth_failure
GET /auth/:provider/callback(.:format) devise_token_auth/omniauth_callbacks#omniauth_success
GET|POST /omniauth/:provider/callback(.:format) devise_token_auth/omniauth_callbacks#redirect_callbacks
omniauth_failure GET|POST /omniauth/failure(.:format) devise_token_auth/omniauth_callbacks#omniauth_failure
GET /auth/:provider(.:format) redirect(301)
Other things I've noticed
Other routes, for eg. /auth/sign_in work flawlessly and I'm able to sign in successfully for the users I've created using Rails Console
Looks like a similar error caused this post, but not caused due to subdomain constraints in routes.rb Some have mentioned in the comments even after doing like what's given in the answer did not get rid of 404
Here's what I tried then
Tried rails generate devise:controller users
Uuncommmented new section in RegistrationsController
Added some random render :jsons which always throws up an empty JSON with status 200 with weird bin/rails: No such file or directory error on terminal
Tried to get rid of it using rails app:update:bin, nothing changes :(
What am I doing wrong?
As stated in the README documentation of devise_token_auth
Why are the new routes included if this gem doesn't use them?
Removing the new routes will require significant modifications to
devise. If the inclusion of the new routes is causing your app any
problems, post an issue in the issue tracker and it will be addressed
ASAP.
new and edit functionality is not provided by devise_token_auth, but the routes would still display them as the routes are coming from devise which devise_token_auth is built upon and hard to undo those routes.
Typically you don't need that functionality anyway for API based application, as that logic is built into the API client (for ex: angular.js or react.js). If for some reason, you need to let the API client know of the data required for create or update, you could document it or when the API client provides wrong data, you could provide the required fields information as part of the errors.
I keep getting the error "Circular dependency detected while autoloading constant API::V1::CitysController" when I try load my api page. Everything I've searched seems to suggest their might be a typo but I don't think there is one.
My routes:
namespace :api , defaults: {format: 'json'} do
namespace :v1 do
resources :citys
end
end
my controller is in app/controllers/api/v1/citys_controller.rb
Theres nothing in it really at the moment
class Api::V1::CitysController < ApplicationController
respond_to :json
def index
end
end
Not sure what else is relevant to the problem? It should just load a blank page without any errors when I go to localhost:3000/api/v1/citys
Added routes
Prefix Verb URI Pattern Controller#Action
pages_home GET /pages/home(.:format) pages#home
root GET / pages#home
api_v1_citys GET /api/v1/citys(.:format) api/v1/citys#index {:format=>"json"}
POST /api/v1/citys(.:format) api/v1/citys#create {:format=>"json"}
new_api_v1_city GET /api/v1/citys/new(.:format) api/v1/citys#new {:format=>"json"}
edit_api_v1_city GET /api/v1/citys/:id/edit(.:format) api/v1/citys#edit {:format=>"json"}
api_v1_city GET /api/v1/citys/:id(.:format) api/v1/citys#show {:format=>"json"}
PATCH /api/v1/citys/:id(.:format) api/v1/citys#update {:format=>"json"}
PUT /api/v1/citys/:id(.:format) api/v1/citys#update {:format=>"json"}
DELETE /api/v1/citys/:id(.:format) api/v1/citys#destroy {:format=>"json"}
I'm not sure why, but the error says it is looking for API::V1::CitysController class in your citys_controller.rb file and you have Api::V1::CitysController. So first and foremost change the name of your class to API::V1::CitysController (note the capitalized 'API'). That should solve your immediate problem.