I'm trying to access all the contacts from Google Contacts for invite purposes from my site.
So I'm using OAuth2 but when I first request I get a 401 error with access_token. :(
Keep in mind I'm working local!!
Here's my code.
def authenticate
# initiate authentication w/ gmail
# create url with url-encoded params to initiate connection with contacts api
# next - The URL of the page that Google should redirect the user to after authentication.
# scope - Indicates that the application is requesting a token to access contacts feeds.
# secure - Indicates whether the client is requesting a secure token.
# session - Indicates whether the token returned can be exchanged for a multi-use (session) token.
next_param = "http://localhost:3000/import/authorise"
scope_param = "https://www.google.com/m8/feeds/"
#session_param = "1"
state="profile"
client_id="535946964206.apps.googleusercontent.com"
root_url = "https://accounts.google.com/o/oauth2/auth"
response_type="token"
#TO FIND MORE ABOUT THESE PARAMETERS AND THERE MEANING SEE GOOGLE API DOCS.
query_string = "?scope=#{scope_param}&state=#{state}&redirect_uri=#{next_param}&response_type=#{response_type}&client_id=#{client_id}"
#render :text=> root_url + query_string and return
# redirect_to "https://accounts.google.com/o/oauth2/auth?
#scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&
#state=%2Fprofile&
#redirect_uri=http://localhost:3000/import/authorise&
#response_type=token&
#client_id=535946964206.apps.googleusercontent.com
#"
redirect_to root_url + query_string
end
this is for authentication now i get response with access token
http://localhost:3000/import/authorise#state=profile&access_token=ya29.1.AADtN_WPohnlKYBH16kFrqEcYUTZ558WDICpqCqiz1mwBKESFr5PTiJFA5vsyoc&token_type=Bearer&expires_in=3600
Now next it will redirected to here,this is where i get above error
# YOU WILL BE REDIRECTED TO THIS ACTION AFTER COMPLETION OF AUTHENTICATION PROCESS WITH TEMPORARY SINGLE USE AUTH TOKEN.
def authorise
#FIRST SINGEL USE TOKEN WILL BE RECEIVED HERE..
token = params[:token]
#PREPAIRING FOR SECOND REQUEST WITH AUTH TOKEN IN HEADER.. WHICH WILL BE EXCHANED FOR PERMANENT AUTH TOKEN.
uri = URI.parse("https://www.google.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
path = '/accounts/AuthSubSessionToken'
headers = {'Authorization' => "AuthSub token=#{token}"}
render :text=> http.get(path, headers) and return
#GET REQUEST ON URI WITH SPECIFIED PATH...
resp, data = http.get(path, headers)
#ender :text=> data and return
resp.code="200"
#SPLIT OUT TOKEN FROM RESPONSE DATA.
if resp.code == "200"
token = ''
data.split.each do |str|
if not(str =~ /Token=/).nil?
token = str.gsub(/Token=/, '')
end
end
return redirect_to(:action => 'import', :token => token)
else
redirect_to root_url , :notice => "fail"
end
end
here at above function when it requests resp, data = http.get(path, headers) the responce resp.code is 401 . i dont know what's wrong i'm following https://gist.github.com/miketucker/852849 example which uses AuthSub which is now not in use so i'm adapting oauth2 .
i already have made app at clode console and given return url and other info.
any help or point me to other working example,thanks you!!!
thank you.
Related
I'm building an application with Rails 5 API and ExtJs.
My ExtJs single page app loaded via the public/index.html.
I get redirected to the Oauth Login page with the required params via a button click in the ExtJs app.
Then the Oauth Server calls my Rails App and go through authentication and getting the token back.
All works fine.
My problem is that now I have my user loaded, updated, access_token ready but I need to load the single page app in the browser and pass on the access_token. Somehow I can not manage this.
def login
if params[:code]
response = request_token(params[:code])
if response.header.code == '200'
token_data = JSON.parse response.body
user_info = JWT.decode(token_data['id_token'],nil,false).first
#user = User.find_by email: user_info['email']
#user ? #user : #user = User.new
#user.name = "#{user_info['given_name']} #{user_info['family_name']}"
#user.access_token = token_data['access_token']
#user.access_token_created_at = Time.zone.now
#user.token_data = response.body
#user.save
render file: '/public/index.html'
else
redirect_to('/', status: response.header.code, alert: response.header.message)
end
elsif params[:error]
redirect_to('/', status: 401, alert: params[:error])
end
end
I either get stuck in an empty browser window with the localhost:3000 url and the code param or if I redirect I get a message with You are being redirected that reloads the window but I think the parameters are not passed on.
I usually use doorkeeper gem to create OAuth server and save redirect_uri to session[:return_to].
resource_owner_authenticator do
session[:return_to] = request.fullpath
current_user || redirect_to(new_user_session_url)
end
Then after authentication, inject javascript
window.location = redirect_uri + params
OR create XMLHttpRequest to authentication server and then parse response like this:
parseAccessToken: function(response) {
return {
accessToken: response.match(/access_token=([^&]*)/)[1],
expiresIn: response.match(/expires=([^&]*)/)[1]
};
}
Am requesting access token from ExactOnline API using refresh token as their documentation states but I all get is Bad Request am using Oauth2 to send POST request to there API. I have tried googling but none of the examples given is helpful.
This is what i have so far.
def to_params
{
'refresh_token' => refresh_token,
'client_id' => CLIENT_ID,
'client_secret' => CLIENT_SECRET,
'grant_type' => 'refresh_token'
}
end
def request_token_from_exact
#Request a new token if the given token is expired.
client = OAuth2::Client.new(self.to_params['client_id'], self.to_params['client_secret'], site: 'https://start.exactonline.nl')
access_token = OAuth2::AccessToken.new(client, self.to_params['fresh_token'])
#response = access_token.post('/api/oauth2/token')
puts "Response Status: "+#response.status
end
How can i use Oauth2 to get a new token. Or is their any way I can do it to get a new token if the given one has expired.
Your response will be appreciated.
In your code replace
self.to_params['fresh_token'] with self.to_params['refresh_token'] here
I am developing a Rails 4 web application and i am planning to authenticate a user from my Windows Azure AD.
For that i have subscribed to Windows Azure and created Active Directory. I then created an application inside AD to get Client and Secret ID to access API exposed by windows Azure from my Rails web application.
For this i am planning to use Devise gem . Is this the right solution or is there any other libraries available to achieve this.
Any help is appreciated.
Not sure if you're still looking for anything, but this Gist has the requisite request code using the OAuth2 gem. If you were ultimately able to get things working with another means (Devise, etc.), I'd also be interested to know what you did.
Here's the code from the Gist as packaged into a controller by omercs:
require 'oauth2'
class WelcomeController < ApplicationController
# You need to configure a tenant at Azure Active Directory(AAD) to register web app and web service app
# You will need two entries for these app at the AAD portal
# You will put clientid and clientsecret for your web app here
# ResourceId is the webservice that you registered
# RedirectUri is registered for your web app
CLIENT_ID = 'b6a42...'
CLIENT_SECRET = 'TSbx..'
AUTHORITY = 'https://login.windows.net/'
AUTHORIZE_URL = "/yourtenant.onmicrosoft.com/oauth2/authorize"
TOKEN_URL = "/yourtenant.onmicrosoft.com/oauth2/token"
RESOURCE_ID = 'https://yourtenant.onmicrosoft.com/AllHandsTry' #ResourceId or ResourceURI that you registered at Azure Active Directory
REDIRECT_URI = 'http://localhost:3000/welcome/callback'
def index
update_token
if session['access_token']
# show main page and use token
redirect_to welcome_use_token_path
else
# start authorization
client = get_client
a = client.auth_code.authorize_url(:client_id => CLIENT_ID, :resource => RESOURCE_ID, :redirect_uri => REDIRECT_URI)
redirect_to(a)
end
end
def callback
begin
#code = params[:code]
client = get_client
# post token to mobile service api
#token = client.auth_code.get_token(CGI.escape(#code), :redirect_uri => REDIRECT_URI)
# id_token token.params["id_token"]
#multi resource token token.params["resource"]
token = client.auth_code.get_token(#code, :redirect_uri => REDIRECT_URI, )
session['access_token'] = token.token
session['refresh_token'] = token.refresh_token
session['expire_at'] = token.expire_at
session['instance_url'] = token.params['instance_url']
redirect '/'
rescue => exception
output = '<html><body><p>'
output += "Exception: #{exception.message}<br/>"+exception.backtrace.join('<br/>')
output += '</p></body></html>'
end
end
def update_token
puts "update token inside"
token = session['access_token']
refresh_token = session['refresh_token']
expire_at = session['expire_at']
#access_token = OAuth2::AccessToken.from_hash(get_client, { :access_token => token, :refresh_token => refresh_token, :expire_at => expire_at, :header_format => 'Bearer %s' } )
if #access_token.expired?
puts "refresh token"
#access_token = #access_token.refresh!;
session['access_token'] = #access_token.token
session['refresh_token'] = #access_token.refresh_token
session['expire_at'] = #access_token.expire_at
session['instance_url'] = #access_token.params['instance_url']
end
end
# send post request to webservice to send token and create a post request
def use_token
# we got the token and now it will posted to the web service in the header
# you can specify additional headers as well
# token is included by default
update_token
conn = Faraday.new(:url => 'https://yoursite.azurewebsites.net/') do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
end
response = conn.get do |req|
req.url '/api/WorkItem'
req.headers['Content-Type'] = 'application/json'
req.headers['Authorization'] = 'Bearer '+#access_token.token
end
#out = response.body
end
def get_client
client = OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET, :site => AUTHORITY, :authorize_url => AUTHORIZE_URL, :token_url => TOKEN_URL )
client
end
end
I want to write a script which calls a REST API using a URL like:
http://localhost:3000/api/v1/user/xyz
If I open this URL in the browser, it asks for a user email and password. Once I've authenticated, it returns a JSON response with a user id. I don't know how I should I authenticate through the script. Can someone give me a suggestion?
This is what I started with:
require 'rubygems'
require 'net/http'
require 'json'
api_url = "http://localhost:3000/api/v1//user/xyz"
response = Net::HTTP.get_response(URI.parse(api_url))
data = JSON.parse(response.body)
fields = data.keys
puts fileds
puts data.keys
This is the authentication for the API:
before_filter :authorize, :except => [:keys]
private
def authorize
authenticate_or_request_with_http_basic do |username, password|
user = User.find_by_email(username)
if user && user.valid_password?(password)
sign_in :user, user
end
end
end
How I can pass email and password to authenticate this API so I can get "id" as return?
rest_client gem works great for me. As far as what the API returns that should be in the documentation. You can always try it in IRB and see what the response contains.
HTTP Basic authentication is pretty simple to add to your request, though I don't think you can use the get_response convenience method.
See: http://ruby-doc.org/stdlib-2.0/libdoc/net/http/rdoc/Net/HTTP.html#label-Basic+Authentication
Example from the documentation:
uri = URI('http://example.com/index.html?key=value')
req = Net::HTTP::Get.new(uri)
req.basic_auth 'user', 'pass' # username, password go here.
res = Net::HTTP.start(uri.hostname, uri.port) {|http|
http.request(req)
}
puts res.body
I am new to iOS programming and using Rubymotion to build my first application. In my Rubymotion app I POST to a webserver (an app built using RoR) to authenticate a user wanting to Login and am using the BubbleWrap gem for RubyMotion https://github.com/rubymotion/BubbleWrap/blob/master/motion/http.rb
def login(sender)
payload = {email: #email, password: #password}
BubbleWrap::HTTP.post("http://example.com/sessions", {payload: payload}) do |response|
#authCookie = response.headers['Set-Cookie']
end
end
Now once I receive successful authentication I move onto to receive JSON data from the web application using the following code:
BubbleWrap::HTTP.get("http://example.com/events.json", {cookie: #authCookie, :headers=>{"Content-Type"=>'json'} }) do |response|
puts response.body #testing the response
end
For some reason, the authentication token received from the POST request is not being correctly passed on by the GET request. I know this because in the web app if authentification fails it redirects to the login page and that's the response (HTML code of the Login page) am receiving from the GET request.
Authentication check on the Web App:
def session_check
if session[:bizid].nil?
redirect_to login_url
flash[:notice] = "Please login to view your account!"
end
end
Additionally, on the web app this authentication token is set by the following method:
def create
current_biz = Bizname.find_by_email(params[:email])
if current_biz && current_biz.authenticate(params[:password])
session[:bizid] = current_biz.id
flash[:notice] = 'Login Successful!'
if current_biz.events.empty?
redirect_to getsetup_url
else
redirect_to account_summary_url
end
else
flash[:notice] = 'Incorrect Email or Password.'
redirect_to login_url
end
end
Any ideas of what I might be doing wrong here?
Thanks in advance!
You just need to pass the cookie in as a header too. For example:
BubbleWrap::HTTP.get("http://example.com/events.json", :headers=> {"Content-Type"=>'json', "Cookie" => #authCookie}) do |response|
puts response.body #testing the response
end