Open killerham opened 8 years ago
Anyone have any tips on this?
Any solutions are appreciated!
I couldn't find a solution to this using devise_token_auth, and eventually gave up and used devise along with the tiddle gem.
I've uploaded an example rails app, along with an android app currently using Google oAuth2 for authentication. I wonder if that might help you?
https://github.com/glapworth/boilerplate-android-rails-api-oauth
@glapworth I didn't want to re-implement a bunch of my tests and different API setups. However I did find a solution!
Send a GET request to omniauth/:provider/callback
with "access_token": token, "resource_class": "User"}
as params.
Override devise's OmniAuthCallbacksController
not token_auth's.
def self.provides_callback_for(provider)
class_eval %Q{
def #{provider}
if request.format == 'json'
# derive target redirect route from 'resource_class' param, which was set
# before authentication.
redirect_route = "/api/v2/auth/#{provider}/callback?\#{params.to_param}"
# preserve omniauth info for success route. ignore 'extra' in twitter
# auth response to avoid CookieOverflow.
session['dta.omniauth.auth'] = request.env['omniauth.auth'].except('extra')
session['dta.omniauth.params'] = request.env['omniauth.params']
redirect_to redirect_route
return
end
# else do standard devise stuff
end
}
end
[:twitter, :facebook, :facebook_access_token, :linked_in].each do |provider|
provides_callback_for provider
end
As you can see... this method is super hacky... I hardcoded the redirect route. If anyone has a better suggestion for this that would be great! Most of the code was taken from DeviseTokenAuth::OmniauthCallbacksController #redirect_callbacks
+1, waiting for any more answers.
+1
+1
Did anyone find a better solution for this?
+1
I just created 2 pull request for this purpose, FYI! lynndylanhurley/ng-token-auth#341 lynndylanhurley/devise_token_auth#793
+1 on this.
I'm confused. It seems as though one of the main attractions for using token authentication is being able to authenticate a user on a phone using something like facebook-sdk on the client. Is there some standard way to authenticate a mobile user on my rails server that I'm not seeing? I was under the impression that devise is more or less a standard for this, but it feels like I'm jumping through a lot of hoops here( overriding devise controller methods ) just to make this gem not use a redirect for omniauth, and ultimately being able to play nice with the iOS/Android facebook-sdk. If this isn't the standard what is? Or do most people just roll their own authentication entirely?
Any news on this?
+1 Any update on this? Or is there any other alternative for those who are using rails as their backend API and using FACEBOOK login in their mobile APP.
I am stuck at this, I am working on something similar to Tinder facebook login where I need to create account in backend once I get fb_token.
+1
I have implemented a basic working solution on this using the Koala Gem. I created a route for this purpose eg 'customer_facebook_auth'. Then in the relevant controller using the facebook token that the mobile app acquired I create the new user (customer in my case) with the facebook user attributes. The facebook user attributes can be fetched using the Koala library gem.
class Api::V1::CustomerFacebookAuthController < ApplicationController
def login_customer
@graph = Koala::Facebook::API.new(params['access_token'])
@f_profile = @graph.get_object('me', fields: ['email', 'id', 'name'])
create_and_sign_in_user @f_profile
end
private
def create_and_sign_in_user facebook_profile
if Customer.where(provider: 'email', email: facebook_profile['email']).count > 0
render json: 'This email has already been taken'
else
@resource = Customer.where(
uid: facebook_profile['id'],
provider: 'facebook'
).first_or_initialize
p = SecureRandom.urlsafe_base64(nil, false)
@resource.password = p
@resource.password_confirmation = p
@resource.name = facebook_profile['name']
@resource.email = facebook_profile['email']
@token = SecureRandom.urlsafe_base64(nil, false)
@client_id = SecureRandom.urlsafe_base64(nil, false)
@token = SecureRandom.urlsafe_base64(nil, false)
@resource.tokens[@client_id] = {
token: BCrypt::Password.create(@token),
expiry: (Time.now.utc + DeviseTokenAuth.token_lifespan).to_i
}
@resource.save
end
render json: {
data: resource_data(resource_json: @resource.customer_token_validation_response)
}
end
def resource_data(opts={})
opts[:resource_json] || @resource.as_json
end
end
Hope it helps.
is there an official solution for this?
@gibo there is not, but we do take pull requests! We'd love to see yours.
@zachfeldman seems like there is already a PR for this :) https://github.com/lynndylanhurley/devise_token_auth/pull/793
Ah, I didn't realize this was the same thing! Sorry about that @gibo .
Have you tested the code in the open PR? If you've tested it along with the code that's currently in beta: https://github.com/lynndylanhurley/devise_token_auth/issues/972#issuecomment-344097692
then we may merge that PR sooner rather than later.
@zachfeldman I’ll give it a test
I made a small change to @geoandri code, as it was not returning the correct headers
def create_and_or_sign_in_profile facebook_profile
@resource = Profile.find_by email: facebook_profile['email']
@client_id = request.headers['client']
if @resource.nil?
@resource = Profile.create(provider: 'email', uid: facebook_profile['id'], email: facebook_profile['email'])
p = SecureRandom.urlsafe_base64(nil, false)
@resource.password = @resource.password_confirmation = p
@resource.name = facebook_profile['name']
@resource.email = facebook_profile['email']
end
@token = SecureRandom.urlsafe_base64(nil, false)
@resource.tokens[@client_id] = {
token: BCrypt::Password.create(@token),
expiry: (Time.now.utc + DeviseTokenAuth.token_lifespan).to_i
}
auth_header = @resource.create_new_auth_token @client_id
response.headers.merge!(auth_header)
@resource.save
render json: {
data: resource_data(resource_json: @resource.token_validation_response)
}
end
Nice @gibo. Want to maybe submit a clean PR if you're done testing?
I don't think it can really be tidied up into a PR, it really seems that Omniauth cannot be used with rails-api projects and therefore devise token auth.
I think there needs to be a new gem created to handle this scenario which integrates into devise token auth.
but for the time being perhaps the code above could be put into the read me?
My users want to login with facebook and I have it setup where they can log into facebook using Facbook SDK on iOS. I want to pass the oauth access_token from SDK to omniauth, skipping the external window that devise_token_auth handles.
My question is how can I send an API request to /auth/:provider to go through the omniauth process when I already have an omniauth token?
I also am using the facebook-access-token gem which will handle the oauth token.
Related issues: https://github.com/lynndylanhurley/devise_token_auth/issues/556 https://github.com/lynndylanhurley/devise_token_auth/pull/323 https://github.com/lynndylanhurley/devise_token_auth/issues/175
Any advice is appreciated!