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
Related
I spent hours looking for a solution to my problem without luck.
I created a Rails app that interacts with Google Calendar API and, following a guide, I was able to make it work. Then I shut down my local server and ran it again after 2/3 hours and I started receiving this error when I make a request to the API:
Signet::AuthorizationError (Unexpected error: #<ArgumentError: Missing authorization code.>)
I figured out that the problem is that the token is expired, 'cause I can't understand why it was working and then not anymore.
This is my controller:
require 'google/api_client/client_secrets.rb'
require 'google/apis/calendar_v3'
CALENDAR_ID = Here I have my Calendar_ID
GOOGLE_CLIENT_ID = Here I have my Google_Client_ID
GOOGLE_CLIENT_SECRET = Here I have my Google_Client_Secret
class CalendarController < ApplicationController
def calendars
client = Signet::OAuth2::Client.new(client_options)
client.update!(session[:authorization])
service = Google::Apis::CalendarV3::CalendarService.new
service.authorization = client
#calendar_list = service.list_calendar_lists
rescue Google::Apis::AuthorizationError
response = client.refresh!
session[:authorization] = session[:authorization].merge(response)
retry
end
def redirect
client = Signet::OAuth2::Client.new(client_options)
redirect_to client.authorization_uri.to_s, allow_other_host: true
end
def callback
client = Signet::OAuth2::Client.new(client_options)
client.code = params[:code]
response = client.fetch_access_token!
session[:authorization] = response
redirect_to calendars_url
end
private
def client_options
{
client_id: GOOGLE_CLIENT_ID,
client_secret: GOOGLE_CLIENT_SECRET,
authorization_uri: 'https://accounts.google.com/o/oauth2/auth',
token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
scope: Google::Apis::CalendarV3::AUTH_CALENDAR,
redirect_uri: callback_url
}
end
end
Then my routes:
get '/redirect', to: 'calendar#redirect', as: 'redirect'
get '/callback', to: 'calendar#callback', as: 'callback'
get '/calendars', to: 'calendar#calendars', as: 'calendars'
What can I do to solve my issue? I'm a newbie on Rails, so it's not quite simple for me
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'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.
So I logged in with Google and it hits my callback url with a code parameter.
Here is how I initiate my client, I'm using oauth2 gem.
def oauth_client(channel_name)
file = YAML.load_file("#{Rails.root}/config/oauth_credentials.yml")
client_id = file['oauth_credentials'][channel_name]['client_id']
client_secret = file['oauth_credentials'][channel_name]['secret']
site = file['oauth_credentials'][channel_name]['site']
OAuth2::Client.new(client_id, client_secret, site: site, authorize_url: "/o/oauth2/auth", connection_opts: { params: { scope: "https://www.googleapis.com/auth/adsense https://www.googleapis.com/auth/analytics.readonly" } })
end
def oauth_url_for(channel_name)
client = oauth_client(channel_name)
client.auth_code.authorize_url(:redirect_uri => oauth_callback_url(channel: channel_name))
end
Here's my controller
class Oauth2Controller < ApplicationController
include ApplicationHelper
def callback
token = oauth_client(params[:channel]).auth_code.get_token(params[:code], :redirect_uri => oauth_callback_url(channel: params[:channel]))
current_user.connections.create!(channel: params[:channel], token: token)
render text: request.inspect
end
end
Unfortunately I can't get_token due to a response from google saying The page you requested is invalid.
It doesn't look like you're defining the token_url value in your initialization of the client, or later. It is "o/oauth2/token". By default "/oauth/token" is used, so that's likely the cause of your "page you requested is invalid" error.
Source:
http://rubydoc.info/gems/oauth2/0.8.0/OAuth2/Client#initialize-instance_method
First of all, I am trying to connect my app with an site in China. I am not sure if that matters, it shouldn't since that site fully supports Oauth.
Here is my code.
First step:
require 'oauth'
def consumer
OAuth::Consumer.new("206506xxxx", "574705f63783xxxaa4a0bd35e34390fb", :site =>"http://api.t.sina.com.cn")
end
def request_token
#request_token = consumer.get_request_token
session[:request_token] = #request_token
session[:request_token_secret] = #request_token.secret
redirect_to #request_token.authorize_url(:oauth_callback => 'http://localhost:3000/accesstoken')
end
It worked well, I was able to go to authorize_url and get an oauth_verifier
However, I encountered an issue when I was trying to get the access token.
def access_token
request_token = OAuth::RequestToken.new(
consumer,
session[:request_token],
session[:request_token_secret]
)
access_token = request_token.get_access_token(:oauth_verifier=>params["oauth_verifier"])
end
I also tried
access_token = request_token.get_access_token
But they both returned 401 error.
I cleaned the session so it's probably not due to session expiry
Any Ideas?
I solved the problem myself, so instead of using
session[:request_token] = #request_token
I used
session[:request_token] = #request_token.token
which worked.