i am using the "github_api" gem in my project to get user data through github
and hear is my controller got this task
class SocialController < ApplicationController
def index
end
def authorize
address = github.authorize_url redirect_uri: 'http://localhost:3000/social/callback'
redirect_to address
end
def callback
puts params
authorization_code = params[:code]
access_token = github.get_token authorization_code
access_token.token
puts Github::Client::Repos.new.list
end
private
def github
#github ||= Github.new client_id: 'f11661f7a9ba943', client_secret: '08aa35ed997b162de257c'
end
end
and i am calling it through this link in my views
<%=link_to "gitouath", controller: "social", action: "authorize" %>
by this i am able to authorize the github profile but i need some other details like his name, profile and projects but i am not able to figure it out, please tell me if there is a way to get those details
I'm not familiar with the github_api gem, so I'll give a generic answer: the API docs are your friends and contain everything you need to know, it's a good idea to get familiar with reading them.
To get you started, the user name and profile information is available via the GET /user endpoint and the list of repositories (I assume this is what you mean by "projects") can be found via the GET /user/repos endpoint.
Related
I currently have a Rails application that is connected to an existing SQL database. I am using Devise for my user management, however the pre-existing User table in the database uses a very customized password encryption method.
There is a web service I can connect to that passes a JSON object with the login information to authenticate whether it is valid or not, and I have to manage my own session and everything after that.
I attempted to follow "Railscast #250", and combine it with Devise and some Stack Overflow searches, but things are not going very well.
This is what I have now, but it isn't doing anything, and I just don't feel like I am on the right track with this.
class SessionsController < Devise::SessionsController
def new
super
end
def create
post_params = {
"RuntimeEnvironment" => 1,
"Email" => params[:session][:email],
"Password" => params[:session][:password]
}.to_json
user_params = RestClient.post 'http://some.ip/WebServices', post_params, :content_type => "json"
user = User.authenticate(user_params)
if user
session[:user_id] = user.user_id
redirect_to root_path
else
flash.now.alert = "Invalid Username or Password"
render "new"
end
end
end
This is the JSON Object returned if there is a successful login:
{"Success":true,"ErrorMessage":"","ResponseString":"","LoginResultData":{"FailMessage":"","ResultCode":0,"User":{"AccountCompleteFlag":1,"CreationDtime":"\/Date(1430848539000-0400)\/","DeleteFlag":0,"Email":"john#doe.com","FailedPasswordCount":1,"HistoricalFlag":0,"IsDirty":false,"IsAdminFlag":0,"IsSiteAdminFlag":0,"LastLoginDtime":"\/Date(1447789258000-0500)\/","NameFirst":"Ttest","NameLast":"test","Password":"TRQt3d2Z7caDsSKL0ARVRd8nInks+pIyTSqp3BLxUgg=","PasswordLockDtime":"\/Date(-62135578800000-0500)\/","PasswordLockFlag":0,"PasswordResetCode":"","PasswordResetStatus":0,"Phone":"1-X-5555555555-","RegistrationSource":"Registration","UserId":100029,"UserType":1,"PhoneInfo":{"AreaCode":"555","CountryCode":"X","Extension":"","FirstThree":"555","InternationalPhoneNumber":"","IsDirty":false,"IsInternational":false,"LastFour":"5555"}}}}
And what is returned for a failed one:
{"Success":true,"ErrorMessage":"","ResponseString":"","LoginResultData":{"FailMessage":"Invalid email address","ResultCode":1,"User":null}}
Is there a way where I can use Devise's session management while connecting to the API?
You can still authenticate through Devise using the email and password that the user provided. The RestClient would just be like a double check: just make sure that there are no routes that the user can authenticate through besides going through the RestClient. You can check this by doing rake routes.
For checking whether the result code was valid, you can do some JSON parsing as follows:
authentication_response = RestClient.post 'http://some.ip/WebServices', post_params, :content_type => "json"
json_authentication_response = JSON.parse(authentication_response)
result_code = json_authentication_response["LoginResultData"]["ResultCode"]
if result_code == 0
# Authenticate
else
# Don't authenticate
end
I haven't had the time to go through .6 and .7 as well as .8 in depth to make sure that I wasn't missing something, but today I decided to update my application, which is mostly an API with some front end work.
I updated the application to rails 4.1.8 and I got a lot of errors in my specs, in fact anything where the api had to be authenticated it blew up.
My controllers that use an api have a method called restrict_api_access which is done via
def restrict_api_access
authenticate_or_request_with_http_token do |token, options|
#api_key = ApiKey.find_by(api_key: token)
end unless current_user
end
Now you can log into the app and manage things, in that case we still use the same API that you would access say via a terminal or out side app. so the unless current_user basically looks like like:
def current_user
if (#api_key)
#current_user = User.find_by!(id: #api_key.xaaron_users_id)
else
super
end
end
Ans then the super of this current user basically states - are you logged in or not.
So one of the tests that are failing is set up like such:
context "Create new tag" do
before(:each) do
#tag = FactoryGirl.build(:tag, blog_id: #blog.id)
set_auth_header(#user)
end
it "should create a tag for a post" do
post :create, :blog_id => #blog.id, tag: {name: #tag.name, description: 'asdasddsa'}
json = JSON.parse(response.body)
expect(json['tag']['name']).to eql #tag.name
end
end
#user is set up else where. But I can assure you that a user is being passed in and is created.
The other interesting method here is set_auth_header(#user) this method looks like:
# Create a random api key
def create_api_key(user)
ApiKey.create!(:xaaron_users_id => user.id, :api_key => SecureRandom.hex(16))
end
# Set authentication headers for the API use
def set_auth_header(user)
key = create_api_key(user)
request.env['HTTP_AUTHORIZATION'] = "Token #{key.api_key}"
end
You can see we create an API key with the user, we then set the request environment variable to have that api key.
So before 4.1.8 (I was on 4.1.5) this worked fine, all my tests would pass life was grand. Now, with this particular test, I get:
1) Api::V1::TagsController Create new tag should create a tag for a post
Failure/Error: json = JSON.parse(response.body)
JSON::ParserError:
757: unexpected token at 'HTTP Token: Access denied.
'
# ./spec/controllers/api/v1/tags_controller_spec.rb:112:in `block (3 levels) in <top (required)>'
Essentially I am denied access. I have traced this through to the restrict_api_access to the line: authenticate_or_request_with_http_token which holds, as a value: HTTP Token: Access denied.
Is there something that changed in 4.1.8 that would be causing all my api that requires authentication to break?
You're computing your authorization header manually here, which might be wrong:
request.env['HTTP_AUTHORIZATION'] = "Token #{key.api_key}"
There's an ActionController method that does this for you:
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(key.api_key)
Try that instead.
Short version
Is there a way to have facebook POST back to your return url from their oauth dialog after logging in?
With background story
I am developing a Rails application in which a user can buy products. In order to buy a product, he has to request it by creating a Request. That Request stores the product's id, the product owner's id as well as the requester's id, just to associate the three with each other.
All this happens through a form that is sent, of course, through a post request.
Here comes the tricky part: The user has to be logged in to place a request. They can log in through facebook. In my application controller, I currently have the following method to check if a user is logged in:
def user_signed_in?
unless current_user # from other method
flash[:error] = "Please log in first."
redirect_to root_path and return false
end
true
end
helper_method :user_signed_in?
I want to change root_path to the facebook auth dialog url. At the moment, I have the following:
def user_signed_in?
unless current_user
raise "https://www.facebook.com/dialog/oauth/?client_id=#{ENV['FACEBOOK_APP_ID']}&redirect_uri=#{request.url}&scope=#{User::BASIC_PERMISSIONS}"
redirect_to "https://www.facebook.com/dialog/oauth/?client_id=#{ENV['FACEBOOK_APP_ID']}&redirect_uri=#{request.url}&scope=#{User::BASIC_PERMISSIONS}" and return false
end
true
end
So far, all this works fine - after logging in, facebook redirects me to the right url. However, the redirect would have to happen through a post request, because otherwise the Request record won't be created. Does facebook support that? Ideally, in a way that my post parameters don't get lost along the way? I have checked facebook's documentation on the matter and searched the web, but couldn't find anything.
I'm currently working on a rails Spree application(v 1.3.x).
I have also another application that i have created couple of months ago just suppose myfirstapp.com that is live and so many users have created account on this application so they are registered users now.
So, now i want in my new application which is one i'm currently working on just suppose it is **mysecondapp.com to allow registered users (i.e users who created account on myfirstapp.com) to sign_in in my second app without using my secondapp signup proccess. They should authenticate from myfirstapp.com and get into my secondapp.**
Any way to achieve this?
I think you could use your first app authentication on the seconde one, you can create a link just like facebook or twitter with redirects to a controller and then this controller sends a request to your first app(you will need the security code to do that) and then get the response, save the data you want(user_id or account) and works great...
Api class using protect_from_forgery:
class ApiController < ApplicationController
protect_from_forgery :except => 'custom_login'
end
Doing this you will avoid the default rails protection, with verifies the
<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
commonly used on rails forms.
Then you can implement your secret hash code, and verifies it like:
class ApiController < ApplicationController
protect_from_forgery :except => :login_from_app2
def login_from_app2
if params[:authentication] == auth_hash
if login(params[:user_credentials])
render :text => "Success" #better you return a json
else
render :text => "Fail login" #better you return a json
end
else
render :text => 'Invalid security hash'
end
end
def auth_hash
"8f2e4b354f193744272fe246ca9e8bf5"
end
end
That way you have a code with only app2 will send on a "post" request to access app1
and you can control the login.
I dont know if this is 100% secure, i think it is, but i will be glad if anyone could explain why this is not a good approach in this case.
I've implemented authlogic in a rails site, and I'm trying to get openid to work correctly. So far, you can login just fine as long as you have an existing account, but not so much if you don't. I'd like to be able to automagically create a new account if the identity_url is not already in the database.
The problem is that I also need to store some additional info. if the user is logging in for the first time with their openid, I'd like to ask them to fill in basic info (name, email), BEFORE the account is created.
I've played around with a few methods, but nothing seems to be working.
Thanks in advance for any input!
acts_as_authentic do |c|
c.openid_required_fields = [:email,"http://axschema.org/contact/email"]
end
Will allow you to require an email. I'm unsure of how to require other fields, but maybe check that axschema.org page. There is no need for the user to fill anything out other than their OpenID provider URL.
Combining login and registration could be done with something like this (untested create method from UserSessions controller, like from the authlogic tutorial stuff)
def create
if User.find_by_openid_provider(params[:user_session]).nil? # or something like that
#user = User.new(params[:user_session])
if #user.save
redirect_to whatever_path
else
# handle error
end
else
#user_session = UserSession.new(params[:user_session])
if #user_session.save
add_message 'Login successful!'
redirect_to whatever_path
else
render :action => :new
end
end
end
Maybe try putting the additional information into a temp table of some kind, and keep track of the session the user is in. Once they have authenticated, connect the previously entered information with the OpenID information to create the real user.