I've had an instagram omniauth integration working now for a few years and I haven't changed anything in a long time but my customers are occasionally out of the blue getting an error when connecting their Instagram accounts:
Started GET "/auth/instagram/callback?code=d3b1c4d88e2f440b8a8a98037b821c15&state=2565d32ecd3cc5967f32d8c945db6ffba74dc784100777f2" for 127.0.0.1 at 2016-12-15 15:29:59 -
0800
I, [2016-12-15T15:29:59.276712 #32520] INFO -- omniauth: (instagram) Callback phase initiated.
E, [2016-12-15T15:29:59.519801 #32520] ERROR -- omniauth: (instagram) Authentication failure! invalid_credentials: OAuth2::Error, :
{"code": 400, "error_type": "OAuthException", "error_message": "Matching code was not found or was already used."}
The only way I can consistently get this to happen is to connect the account from my app, then remove permissions from the instagram end, then try to reconnect again on my app, but it seems like some of my customers are getting this the first time they connect their instagram accounts.
Anyone encountered this before? My config/initializers/omniauth.rb looks like this:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :instagram, ENV['INSTAGRAM_CLIENT_ID'], ENV['INSTAGRAM_CLIENT_SECRET'], scope: 'basic comments public_content'
end
Edit:
I'm using omniauth 1.3.1 and omniauth-instagram 1.0.2
My routes is just your basic omniauth route:
get '/auth/:provider/callback', to: 'omniauth_callbacks#create'
And my controller action is a bit complex but it looks like this:
class OmniauthCallbacksController < ApplicationController
def create
if user_signed_in?
social_account = SocialAccount.from_omniauth(auth_params, current_user)
social_account.save!
redirect_to root_path
else
user = User.from_omniauth auth_params
sign_in_and_redirect user
end
end
private
def auth
request.env['omniauth.auth']
end
def auth_params
{
provider: auth['provider'],
uid: auth['uid'],
token: auth['credentials']['token'],
secret: auth['credentials']['secret'] || auth['credentials']['refresh_token'],
name: auth['info']['nickname'] || auth['info']['name'],
emails_sent: 0
}
end
end
Basically it creates a new user and signs them in if they haven't connected, and it updates their login info if they have.
There seems to be a problem on Instagram around getting access tokens. https://news.ycombinator.com/item?id=13178789
Related
My aplication initially used Devise for authentication, but I recently had to install the omniauth-keycloak gem to support authentication through Keycloak. And it worked as expected in Development and Validation, relying on the same Keycloak instance.
But since the last deployment in Validation, it looks like OmniAuth does not query Keycloak anymore, and switches directly to the failure method of the OmniauthCallbacksController. It returns this trace when the user clicks on the login link to request for the Keycloak login form:
Started POST "/users/auth/keycloakopenid" for 10.228.50.117 at 2022-06-30 15:41:29 +0200
Processing by Users::OmniauthCallbacksController#failure as HTML
Parameters: {"authenticity_token"=>"M+Zr3ZcZc08mthj3LBuoS4Jwb9GBdBsm8m9nmqGDNyssgIf8rmtyJQbpOcmK4OTidRNK3mzZpOOnaTSfJFJlEQ=="}
Redirected to https://l821000109918b.adr.admin.ch/users/sign_in
Completed 302 Found in 1ms (ActiveRecord: 0.0ms)
Started GET "/users/sign_in" for 10.228.50.117 at 2022-06-30 15:41:29 +0200
Netwotk analysis does not even report a request to the Keycloak server.
Here is the Devise configuration:
config/initializers/devise.rb
config.omniauth :keycloak_openid,
"BFS.SIS",
client_options: { base_url: '', site: Rails.application.credentials.integration[:authentication_url], realm: "bfs-sis-a" },
strategy_class: OmniAuth::Strategies::KeycloakOpenId
app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def keycloakopenid
# Read OmniAuth token
auth = request.env["omniauth.auth"]
# auth.extra.raw_info.resource_access.map {|h| h[1].roles.map(&:itself).join(',')} provides the list of all roles
# resources_accesses.first[1].roles provides an array hash
#user = User.from_omniauth(auth) # Finds or create the user
if #user.persisted?
# The user has been identified or created: then manage groups, activities access and roles
# 1-set roles in user's external_roles array
# 2-set statistical activities in user's preferred_activities array
# 3-make sure that the user is a member of the relevant groups (Everyone and External users)
--- do some stuff ---
sign_in_and_redirect #user, event: :authentication
else
redirect_to new_user_session_path
end
end
def failure
redirect_to new_user_session_path
end
end
The link requesting Keycloak from the devise/sessions/new.html.erb view is given by:
<%= link_to "Sign in with SIS Portal", user_keycloakopenid_omniauth_authorize_path,
method: :post,
class: "mat-flat-button mat-button-base mat-primary",
style: "width:200px;" %>
Since it keeps working correctly in Development, and I did not touch this feature for several months, I am wandering what may have happened, and how to investigate deeper ine the code execution?
Thank you for your suggestions!
I am currently developing a website and i have a problem with te confirmation link with devise token auth.
Everything is working right, after someones registers they get an email with a confirmation link. This link is confirming and working properly BUT when this link expires (i set it up in the configuration with config.confirm_within = 1.day ) or someone clicks this link again they get a "Routing error". So i suppose there should be a way of redirecting to the homepage when that link expires and maybe showing a message saying that they have to ask for the email confirmation again..
i have this confirmation routes:
new_api_user_confirmation GET /api/auth/confirmation/new(.:format) devise_token_auth/confirmations#new
api_user_confirmation GET /api/auth/confirmation(.:format) devise_token_auth/confirmations#show
POST /api/auth/confirmation(.:format) devise_token_auth/confirmations#create
I use the last route POST for resending the email and it is working, but the other to routes are not working and that makes sense because i am using API. But there should be a redirect url for when you get an error
Any thoughts? thank you in advance
you can override the DeviseTokenAuth::ConfirmationsController#show and redirect to root_path
DeviseTokenAuth ConfirmationsController#show
class ConfirmationsController < DeviseTokenAuth::ConfirmationsController
def show
...
else
# raise ActionController::RoutingError, 'Not Found'
redirect_to :root_path
end
...
in routes
mount_devise_token_auth_for 'User', at: 'auth', controllers: {
# confirmations: 'devise_token_auth/confirmations',
confirmations: 'confirmations',
devise-token-auth docs
I am getting Signet::AuthorizationError in LoginController#callback and Authorization failed. Server message: { "error" : "redirect_uri_mismatch" } on the line auth_client.fetch_access_token! when I click "Allow" on the OAuth screen and execute my callback method during the OAuth process.
I have checked out this: Google OAuth 2 authorization - Error: redirect_uri_mismatch, but I still can't figure it out.
I am trying to get a login with Google set up like this:
User goes to /login and clicks on the "sign in with google" button.
The Google login prompt comes up, user signs in with Gmail, and then gets redirected to /home.
I have the following uris in my web application credentials in Google consoles:
http://localhost:3000
http://localhost:3000/login/callback
http://localhost/login/callback
http://localhost
routes.rb
get '/home' => 'home#index'
get '/login' => 'login#prompt'
get '/login/callback' => 'login#callback'
login_controller.rb
require 'google/api_client/client_secrets'
class LoginController < ApplicationController
GOOGLE_CLIENT_SECRET_FILE = Rails.root.join('config/google_oauth2_secret.json')
def prompt
if session[:credentials]
redirect_to '/home'
else
auth_client = get_auth_client
auth_client.update!(
:scope => ['profile', 'email'],
:redirect_uri => 'http://localhost:3000/login/callback'
)
#auth_uri = auth_client.authorization_uri.to_s
render layout: false
end
end
def callback
auth_client = get_auth_client
auth_client.code = request['code']
auth_client.fetch_access_token!
auth_client.client_secret = nil
session[:credentials] = auth_client.to_json
redirect_to '/home'
end
private
def get_auth_client
Google::APIClient::ClientSecrets.load(GOOGLE_CLIENT_SECRET_FILE).to_authorization
end
end
I also have a concern. In my prompt method, how do I verify that session[:credentials] is the correct session code? Couldn't anyone just put some bogus string into the credentials session and gain access?
I have been following this guide: https://developers.google.com/api-client-library/ruby/auth/web-app
This happens because localhost is not a valid domain name. Instead of using localhost, you need to use lvh.me
In Google consoles the url will become
http://lvh.me:3000
http://lvh.me:3000/login/callback
Trying accessing your application in the browser using http://lvh.me:3000 instead of http://localhost:3000
lvh.me is a valid domain name with is pointing to 127.0.0.1
I realize the issue is I am setting the scope in the prompt function when I am generating the auth uri but in my callback function, I am not setting the scope.
It should be like this:
def callback
auth_client = get_auth_client
auth_client.update!(
:scope => ['profile', 'email'],
:redirect_uri => 'http://localhost:3000/login/callback'
)
auth_client.code = request['code']
auth_client.fetch_access_token!
auth_client.client_secret = nil
session[:credentials] = auth_client.to_json
redirect_to '/home'
end
I am using omniauth-facebook gem to authorize using facebook in my rails application.
I have followed these instructions but the problem I am facing is error about invalid credentials:
(facebook) Authentication failure! invalid_credentials: OAuth2::Error, :
{"error":{"message":"Error validating application. Invalid application ID.","type":"OAuthException","code":101}}
What is weird about this is that I am getting user info even though I get this error from facebook api.
the value of request.env['omniauth.auth']
is(server log).
#<OmniAuth::AuthHash credentials=#<OmniAuth::AuthHash expires=true
expires_at=1421256863 token="some_long_value"> extra=#<OmniAuth::AuthHash
raw_info=#<OmniAuth::AuthHash education=[#<OmniAuth::AuthHash school=
#<OmniAuth::AuthHash id="174179219354091" name="Udacity"> type="College">]
email="ashish#gmail.com" favorite_athletes=[#<OmniAuth::AuthHash id="51926382304"
name="Derrick Rose">, #<OmniAuth::AuthHash id="344128252278047" name="Sachin
Tendulkar">,.... so on
routes.rb
devise_for :users, :controllers => {:omniauth_callbacks => "omniauth_callbacks"}
config/initializers/omniauth.rb
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'key', 'secret', {:provider_ignores_state => true}
# key and secret are correctly added in above line
end
app/model/user.rb
devise :omniauthable, :omniauth_providers => [:facebook]
app/controller/omniauth_callback_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
omniauth = request.env['omniauth.auth']
# Other code to create authentication and other logic
puts "===>>> Omniauth is #{omniauth}"
end
def failure
res = request.env['omniauth.auth']
puts "======>>>>>> Authentication failed #{res}"
redirect_to root_path
end
end
Every time response goes to failure method but not to facebook method.
What I don't understand is when I am getting invalid credentials error from api then how come I get all the data from facebook. I doubt I have something wrong on my end while handling the callback from facebook.
Can anyone point where the problem can be?
I am pretty sure I am using correct application id and key I am getting data from facebook in the response.
Can anybody help me with this issue?
everybody.
I'm working with a simple Facebook authentication system on my platform (with Rails and Koala) and it's almost working as expected. But there's this one critical bug that's driving me nuts.
Given I am NOT logged into my platform and I am NOT registered and I have NOT yet authorized my app on my Facebook profile.
I go signing up with a Facebook account
Facebook asks me to log in
I successfully log in
The Facebook application requests permission
I authorize the app
I'm redirected to the correct redirect_uri
Koala fails in the client.get_access_token(params[:code]) step with a OAuthException: Code was invalid or expired. Session is invalid. This could be because the application was uninstalled after the session was created.
In short, Facebook is complaining about a code it has just provided. Here are the methods for authentication:
Login Action for OAuth
def login
reset_session
session[:facebook_client] = get_client
redirect_to session[:facebook_client].url_for_oauth_code(:callback => FacebookAPI.oauth_callback_url, :permissions => "email, user_status, publish_stream, publish_actions")
rescue => err
end
Callback action
def terminate
client = session[:facebook_client]
if client.nil?
redirect_to '/', notice: 'Error on FacebookAPI'
else
access_token = client.get_access_token(params[:code]) if params[:code] # IT FAILS HERE
# omitting the rest
end