google auth1 to oauth2 migration: Invalid authorization header - ruby-on-rails

I've a script to migrate from google oauth1 to oauth2 using oauth gem
everything seems right and i can't detect any problem with the headers but it still responding with: Invalid authorization header.
Here're the headers:
opening connection to accounts.google.com:443...
opened
starting SSL for accounts.google.com:443...
SSL established
<- "POST /o/oauth2/token HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: /\r\nUser-Agent: OAuth gem v0.4.7\r\nContent-Length: 193\r\nAuthorization: OAuth oauth_consumer_key=\"mykey.com\", oauth_nonce=\"LdBeaxxxxxxxxxxxxxxIxgd03U1DHYbs\", oauth_signature=\"wXIuxxxxxxxyxxxxj0%3D\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1416497830\", oauth_token=\"1%2F9G2sKmQxxxxxxxxxxmDXbqqifoRBGUAii-D5sw2o\", oauth_version=\"1.0\"\r\nConnection: close\r\nHost: accounts.google.com\r\n\r\n"
<- "client_id=the_id&client_secret=C-7xxxxxxxxxboMcinh3ofV&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Amigration%3Aoauth1"> "HTTP/1.1 400 Bad Request\r\n"
-> "Content-Type: application/json\r\n"
-> "Cache-Control: no-cache, no-store, max-age=0, must-revalidate\r\n"
-> "Pragma: no-cache\r\n"
-> "Expires: Fri, 01 Jan 1990 00:00:00 GMT\r\n"
-> "Date: Thu, 20 Nov 2014 12:37:03 GMT\r\n"
-> "X-Content-Type-Options: nosniff\r\n"
-> "X-Frame-Options: SAMEORIGIN\r\n"
-> "X-XSS-Protection: 1; mode=block\r\n"
-> "Server: GSE\r\n"
-> "Alternate-Protocol: 443:quic,p=0.01\r\n"
-> "Connection: close\r\n"
-> "\r\n"
reading all...
-> "{\n \"error\" : \"invalid_request\",\n \"error_description\" : \"Invalid authorization
header.\"\n}"
read 90 bytes
Conn close
and here's the code:
oauth1_consumer_key = "mykey"
oauth1_consumer_secret = "Gxxxxxxxxxxxxxxxxqb8"
# OAuth 1 - User Token / Secret.
oauth1_token = '1/9G2xxxxxxxxxxxxxxsw2o'
oauth1_secret = 'a-xxxxxxxxxxxxxxxmqG'
# OAuth 2 - Application ID / Secret
oauth2_client_id = "the_id"
oauth2_client_secret = "C-xxxxxxxxxxxxxxxxV"
# Migration Parameters.
params = {
"grant_type" => "urn:ietf:params:oauth:grant-type:migration:oauth1",
"client_id" => oauth2_client_id,
"client_secret" => oauth2_client_secret,
# "oauth_signature_method" => "HMAC-SHA1"
}
# Create the consumer object.
consumer = OAuth::Consumer.new(
oauth1_consumer_key,
oauth1_consumer_secret,
:site => 'https://accounts.google.com',
:scheme => :header
)
# Create the access token object.
access_token = OAuth::AccessToken.new(consumer, oauth1_token, oauth1_secret)
resp = access_token.post(
"/o/oauth2/token",
params,
{ 'Content-Type' => 'application/x-www-form-urlencoded' })
if resp.code.to_s != "200"
# Raise an error.
raise "#{resp.code} - #{resp.body}"
end
Any ideas?

After updating the oauth gem, I tried it again and it worked.

Related

Getting error 401 while sending push notification in fcm rails

This is my code in push_notification model
belongs_to :push_notificable, polymorphic: true
validates :remarks, presence:true
before_create :send_push_notification
def send_push_notification
device_id = get_device_id
if device_id.present?
fcm_client = FCM.new(ENV['AAAAzWU3na4:APA91bEDFQ2q37C4d41nPrEcRqHJotUoohjCkYcWjfNr2CS5k-VR4YGX9rpF5mqhkQCke_061hZvLwlqCd8mbqg2L9KbOH4mveFmtbYcVHW1c-8yCrML9Sj0uwwes56i6NFxgkaKxEgh'])
options = { priority: 'high',
data: {
message: remarks,
notify_type: "#{notify_type}",
account_id: account_id
},
notification: {
body: remarks,
sound: 'default'
}
}
registration_id = device_id
res = fcm_client.send(registration_id, options)
end
rescue Exception => e
e
end
def get_device_id
device_id = AccountBlock::Account.find_by(id: push_notificable.account_id).device_id
end
this is the response I am getting
{:body=>"\n\nINVALID_KEY\n\n<BODY BGCOLOR="#FFFFFF" TEXT="#000000">\nINVALID_KEY\nError 401\n\n\n", :headers=>{"content-type"=>"text/html; charset=UTF-8", "content-encoding"=>"gzip", "date"=>"Thu, 09 Feb 2023 05:53:03 GMT", "expires"=>"Thu, 09 Feb 2023 05:53:03 GMT", "cache-control"=>"private, max-age=0", "x-content-type-options"=>"nosniff", "x-frame-options"=>"SAMEORIGIN", "content-security-policy"=>"frame-ancestors 'self'", "x-xss-protection"=>"1; mode=block", "server"=>"GSE", "alt-svc"=>"h3=":443"; ma=2592000,h3-29=":443"; ma=2592000", "transfer-encoding"=>"chunked"}, :status_code=>401, :response=>"There was an error authenticating the sender account."}
The 401 error is an authentication error and usually indicates that the API key used in the Authorization header of the request is invalid. Please check that you are using the right Server API key as seen under Firebase Console > [Project] >Project Settings > Cloud Messaging section. You can check the validity of the Server key through a cURL command explained in this document.

Unable to create draft PayPal invoice using v2 API version

I am upgrading PayPal Invoicing feature from v1 to v2 (Because v1 is deprecated) in my Ruby on Rails application.
Since there's no official library/gem supporting v2 invoicing, so I decided to build everything as per this official documentation here: https://developer.paypal.com/docs/api/invoicing/v2.
The flow is like this:
System will get an access-token based on ClientID and ClientSecret
From this access-token, I will be generating a new invoice_number by sending curl request to: https://api.sandbox.paypal.com/v2/invoicing/generate-next-invoice-number
Upon receiving the invoice_number, I am sending curl request to create draft invoice endpoint with all the required data
curl -v -X POST https://api.sandbox.paypal.com/v2/invoicing/invoice
The issue I am facing is with the last point. I am getting 201 created response from create draft invoice endpoint but the endpoint is not returning me the complete invoice object along with Invoice ID.
Here's what I am getting:
"201"
{"rel"=>"self", "href"=>"https://api.sandbox.paypal.com/v2/invoicing/invoices/INV2-Z3K7-Y79X-36EM-ZQX8", "method"=>"GET"}
If you try opening this link, you'll see this:
{
"name":"AUTHENTICATION_FAILURE",
"message":"Authentication failed due to invalid authentication credentials or a missing Authorization header.",
"links": [
{
"href":"https://developer.paypal.com/docs/api/overview/#error",
"rel":"information_link"
}
]
}
Not sure what I am missing here!
Below is the code for reference:
require 'net/http'
require 'uri'
require 'json'
class PaypalInvoice
def initialize order
#order = order
#client_id = ENV['PAYPAL_CLIENT_ID']
#client_secret = ENV['PAYPAL_CLIENT_SECRET']
#base_url = ENV['AD_PP_ENV'] == 'sandbox' ? 'https://api.sandbox.paypal.com' : 'https://api.paypal.com'
#paypal_access_token_identifier = 'paypal_access_token'
#request_id ||= SecureRandom.uuid
end
def create_draft_invoice
raise "Paypal token not found" unless Rails.cache.exist?(#paypal_access_token_identifier)
invoice_number = "#141"
sleep 5
try = 0
uri = URI.parse(#base_url + "/v2/invoicing/invoices")
request = Net::HTTP::Post.new(uri)
request['X-PAYPAL-SANDBOX-EMAIL-ADDRESS'] = ENV['PAYPAL_CLIENT_EMAIL']
request['Authorization'] = "Bearer #{Rails.cache.fetch(#paypal_access_token_identifier)['access_token']}"
request['Content-Type'] = 'application/json'
request['PayPal-Request-Id'] = #request_id.to_s
request.body = JSON.dump({
"detail" => get_detail(invoice_number),
"invoicer" => get_invoicer,
"primary_recipients" => get_primary_recipients,
"items" => items_info,
"configuration" => {
"partial_payment" => {
"allow_partial_payment" => false,
},
"allow_tip" => false,
"tax_calculated_after_discount" => true,
"tax_inclusive" => true
}
})
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.host, uri.port, req_options) do |http|
http.request(request)
end
p 'method: create_draft_invoice. response: '
p response.code
p JSON.parse(response.body)
raise "Paypal token expired" if response.code.to_s == '401'
rescue RuntimeError => error
p "#{error.to_s}"
try += 1
access_token_response_status = get_new_access_token
retry if access_token_response_status.to_s == '200' and try <= 1
end
end
This:
{"rel"=>"self", "href"=>"https://api.sandbox.paypal.com/v2/invoicing/invoices/INV2-Z3K7-Y79X-36EM-ZQX8", "method"=>"GET"}
Is the endpoint for an API call, specifically 'Show invoice details': https://developer.paypal.com/docs/api/invoicing/v2/#invoices_get
Loading it in a browser w/o an Authorization: Bearer <Access-Token> header will give an AUTHENTICATION_FAILURE.
There's currently a bug in Sandbox with unconfirmed emails, so make sure your Sandbox emails are confirmed

Rails xapi call to scorm cloud fails

I'm trying to send data from Rails to an LRS. At the moment, testing is happening using SCORM cloud. I have a valid endpoint and authentication values. The data is being sent from the controller, but the server is refusing it. I have tested the xapi statement in http://tincanapi.com/statement-generator - it validates and sends. I have added statements/ to the end of the endpoint which has stopped it moaning about malformed URL.
Full error result
Started GET "/sendx" for 127.0.0.1 at 2017-03-01 18:20:28 +0000
Started GET "/sendx" for 127.0.0.1 at 2017-03-01 18:20:28 +0000
Processing by SendxapisController#send as HTML
Processing by SendxapisController#send as HTML
Lrsconfig Load (0.0ms) SELECT "lrsconfigs".* FROM "lrsconfigs" WHERE "lrscon
figs"."id" = $1 LIMIT 1 [["id", 1]]
Lrsconfig Load (0.0ms) SELECT "lrsconfigs".* FROM "lrsconfigs" WHERE "lrscon
figs"."id" = $1 LIMIT 1 [["id", 1]]
opening connection to cloud.scorm.com:443...
opened
starting SSL for cloud.scorm.com:443...
SSL established
<- "POST /tc/E9D3QJZJST/sandbox/statements/?actor[mbox]=mailto%3AKarl%40example.
com&actor[name]=Karl&verb[id]=http%3A%2F%2Fadlnet.gov%2Fexpapi%2Fverbs%2Fanswere
d&verb[display][en-US]=answered&object[id]=http%3A%2F%2Fadlnet.gov%2Fexpapi%2Fac
tivities%2Fexample&object[definition][name][en-US]=Karl%20Activity&object[defini
tion][description][en-US]=Karl%20activity%20description HTTP/1.1\r\nContent-Type
: application/json\r\nX-Experience-Api-Version: 1.0.0\r\nAuthorization: Basic Zl
dIQjFWSGtid3lVLWFCUTNkVTpzSVpKQnRwT1hWS2lPc2QzbTZB\r\nConnection: close\r\nHost:
cloud.scorm.com\r\nContent-Length: 0\r\n\r\n"
<- ""
-> "HTTP/1.1 400 Bad Request\r\n"
-> "Content-Length: 37\r\n"
-> "Connection: close\r\n"
-> "Access-Control-Allow-Headers: Content-Type,Content-Length,Authorization,If-M
atch,If-None-Match,X-Experience-API-Version,X-Experience-API-Consistent-Through\
r\n"
-> "Access-Control-Allow-Methods: HEAD,GET,POST,PUT,DELETE\r\n"
-> "Access-Control-Allow-Origin: *\r\n"
-> "Access-Control-Expose-Headers: ETag,Last-Modified,Cache-Control,Content-Type
,Content-Length,WWW-Authenticate,X-Experience-API-Version,X-Experience-API-Consi
stent-Through\r\n"
-> "Date: Wed, 01 Mar 2017 18:20:28 GMT\r\n"
-> "Server: Apache\r\n"
-> "X-Experience-API-Version: 1.0.0\r\n"
-> "X-XSS-Protection: 1; mode=block\r\n"
-> "X-Cache: Error from cloudfront\r\n"
-> "Via: 1.1 f5d27f80802e2b6e66ec3970da5568b8.cloudfront.net (CloudFront)\r\n"
-> "X-Amz-Cf-Id: I4IiYfXehWEqBN04LhHpCdhivUq8_6xrBCztJQemPHg8cV7vjhElEg==\r\n"
-> "\r\n"
reading 37 bytes...
-> "Missing required argument: statements"
read 37 bytes
Conn close
Code that generates this
#lrsconfig = Lrsconfig.find(1)
#auth = { username: #lrsconfig.lrsusername, password: #lrsconfig.lrspassword }
#header = {
'Content-Type' => 'application/json',
'X-Experience-API-Version' => #lrsconfig.XAPIversion
}
#xapi = {
"actor":
{
"mbox": "mailto:Karl#example.com",
"name": "Karl"
},
"verb": {
"id": "http://adlnet.gov/expapi/verbs/answered",
"display": {
"en-US": "answered"
}
},
"object": {
"id": "http://adlnet.gov/expapi/activities/example",
"definition": {
"name": {
"en-US": "Karl Activity"
},
"description": {
"en-US": "Karl activity description"
}
}
}
}
# Make and send an xAPI call
response = HTTParty.post(#lrsconfig.lrsendpoint,
basic_auth: #auth,
headers: #header,
query: #xapi,
#body: #xapi,
debug_output: $stdout
)
It looks from the error message as though SCORM cloud can't read the statement from the HTTP request. There could be a couple of reasons for this.
Firstly, you have the #xapi object being sent in the query rather than the body (it looks like you've tried a few things here, but body is where it should live). Secondly, your #xapi object is a Ruby object when you send it, rather than a JSON object. You need to assign #xapi.to_json to the body, rather than just #xapi.

Trying to update Google Latitude of CurrentLocation using google-api-ruby-client returns "400 Invalid Value"

I am trying to update CurrentLocation to Google Latitude using google-api-ruby-client.
I already have an access token, and refresh token which I obtained from mobile app and sent to by server on Ruby on Rails. The following is the code which I am trying to execute.
client = Google::APIClient.new(:key => gltoken)
client.authorization.client_id = '<my client id>'
client.authorization.client_secret = '<my client secret>'
client.authorization.access_token = "<the access token i ve>"
client.authorization.refresh_token = "<refresh token i ve>"
client.authorization.scope ='https://www.googleapis.com/auth/latitude.all.best https://www.googleapis.com/auth/latitude.current.best'
client.host = "www.googleapis.com"
latitudeapi = client.discovered_api('latitude', 'v1')
result = client.execute(
:api_method => 'latitude.currentLocation.insert',
:parameters => {
'kind' => 'latitude#location',
'latitude'=>37.420352,
'longitude'=>-122.083389,
'accuracy'=>130,
'altitude'=>35
}
)
logger.debug("Response #{result.body}")
result.body
I am getting the following result:
{"message":"{\"error\":{\"errors\":[{\"domain\":\"global\",\"reason\":\"invalid\",\"message\":\"Invalid Value\"}],\"code\":400,\"message\":\"Invalid Value\"}}"}
I am not able to find out which Value that I pass is invalid. I tried to update the same set of values as below to https://www.googleapis.com/latitude/v1/currentLocation?key= and it worked.
Header:
Content-Type: application/json
Authorization: Bearer <My access token>
Host: googleapis.com
Body:
{
"data": {
"kind":"latitude#location",
"latitude":37.420352,
"longitude":-122.083389,
"accuracy":130,
"altitude":35
}
}
Thanks in Advance.
Figured out the answer after debugging the gem code. The following is how the call has to be made.
result = client.execute(
:api_method => 'latitude.currentLocation.insert',
:body => "{\"data\": {\"kind\":\"latitude#location\",\"latitude\":#{latitude},\"longitude\":#{longitude}}}",
:headers => {'Content-Type'=> 'application/json'}
)
Latitude API's look for :body instead of :parameters.

Groovy Httpbuilder authentication with Realm + RABBIT MQ

I am trying to to make a rabbitmq http api call to know how queues are there and other infos...
I need 3 variables to pass on to the api
1) url: (http://localhost:55672/api) 2) username/password: guest/guest
3) realm: "RabbitMQ Management" //i am not sure if this is important
4) path: "/queues"
when i make curl statement it gives a positive response
sudo curl -i -u guest:guest (http://localhost:55672)/api/queues
HTTP/1.1 200 OK
Server: MochiWeb/1.1 WebMachine/1.7 (participate in the frantic)
Date: Tue, 03 Jul 2012 01:39:05 GMT
Content-Type: application/json
Content-Length: 6176
Cache-Control: no-cache
but using httpbuilder from groovy. here is the code
def http = new HTTPBuilder("(http://localhost:55672/api)")
http.auth.basic 'guest','guest'
http.request(GET) { req ->
uri.path = '/queues'
response.success = { resp, reader ->
assert resp.statusLine.statusCode == 200
println "Got response: ${resp.statusLine}"
println "Content-Type: ${resp.headers.'Content-Type'}"
println reader.json
}
response.'404' = { println 'Not found' }
}
I am getting "not found" as the result. I am not including realm because I am unable to if i can insert "realm" in httpbuilder. it only comes with OAuth however I need to use basic auth for rabbit mq http api calls.
Does anyone knows how to include realm name in httpbuilder groovy for basic authentication? is there any other way. Kindly let me know! thanks!
Does this work?
def http = new HTTPBuilder( 'http://localhost:55672' )
http.auth.basic 'guest','guest'
http.request(GET) { req ->
uri.path = '/api/queues'
response.success = { resp, reader ->
assert resp.statusLine.statusCode == 200
println "Got response: ${resp.statusLine}"
println "Content-Type: ${resp.headers.'Content-Type'}"
println reader.json
}
response.'404' = { println 'Not found' }
}
Took the braces and the path out of your base url, added /api to the path

Resources