Getting error 401 while sending push notification in fcm rails - ruby-on-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.

Related

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

Generate JWT for Apple Music API with online editor

I read the full documentation https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/AppleMusicWebServicesReference/SetUpWebServices.html#//apple_ref/doc/uid/TP40017625-CH2-SW1.
I generated JWT with kid,iss , iat exp. But when I hit apple music api
with
"Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6Iko4UTJNTFA5RjMifQ.eyJpYXQiOjE1MTE0Mzc5ODgsImV4cCI6MTUxNjcwODM4OCwiaXNzIjoiN0Y0Ujk4WDRNVCJ9.iPFxiHc475spn2AVmO8-Q2bGOM_Rz5OqhAb-sMQ2cXQlGcbx6pfZaTpjI0r6vAaQnqeoFb8fNvVobjtiC2eyzw" header authorization.
API is https://api.music.apple.com/v1/catalog/us/search?term=khalid&types=albums
I am getting the following response header
{ URL: https://api.music.apple.com/v1/catalog/us/search?term=khalid&types=albums } { status code: 401, headers {
Connection = close;
"Content-Type" = "text/plain; charset=UTF-8";
Date = "Fri, 24 Nov 2017 09:21:29 GMT";
} })
Please help.
Thanks in advance.

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.

google auth1 to oauth2 migration: Invalid authorization header

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.

Google API for plusDomains.circles.addPeople in Rails produces 403 Forbidden

Using: Google API Ruby Client
class GooglePlus
def self.follow_contact(contact, user = current_user)
plus = GooglePlus.plus_domains
GooglePlus.
authorized(user).
execute api_method: plus.circles.add_people,
parameters: {circleId: "Following", userId: contact}
end
private
def self.plus_domains
GooglePlus.client.discovered_api('plusDomains')
end
def self.client
require 'google/api_client'
Google::APIClient.new(
application_name: "My Application",
application_version: "1.0.0",
discovery_cache: ActiveSupport::Cache::Store
)
end
def self.authorized(user = current_user)
client = GooglePlus.client
client.authorization.client_id = Rails.application.secrets.google[:client_id]
client.authorization.client_secret = Rails.application.secrets.google[:client_secret]
client.authorization.scope = %w^openid
profile
email
https://www.googleapis.com/auth/plus.circles.write
https://www.googleapis.com/auth/plus.me
https://www.googleapis.com/auth/plus.login
https://www.google.com/m8/feeds^
client.authorization.grant_type = 'refresh_token'
client.authorization.refresh_token = user.socials.
where(kind: Social.kinds[:google_plus]).
select(&:verified?).first.token_secret
client.authorization.fetch_access_token!
client
end
end
I know my OAuth key has the right permissions as I've set this line for my 'omniauth-google-oauth2' gem:
google = Rails.application.secrets.google
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, google[:client_id], google[:client_secret], {
scope: %w^openid
profile
email
https://www.googleapis.com/auth/plus.circles.write
https://www.googleapis.com/auth/plus.me
https://www.googleapis.com/auth/plus.login
https://www.google.com/m8/feeds^.join(","),
access_type: "offline",
prompt: "consent"
}
end
And that works fine. Everything looks like it works up until the point where I execute the client.execute api_method: plus.circles.add_people, parameters: {circleId: "Following", userId: contact} I get back the following.
=> #<Google::APIClient::Result:0x000000093853e8
#data=
#<Google::APIClient::Schema::PlusDomains::V1::Circle:0x49c79f4 DATA:{"error"=>{"errors"=>[{"domain"=>"global", "reason"=>"forbidden", "message"=>"Forbidden"}], "code"=>403, "message"=>"Forbidden"}}>,
#request=
#<Google::APIClient::Request:0x0000000943f978
#api_method=#<Google::APIClient::Method:0x3441238 ID:plusDomains.circles.addPeople>,
#authenticated=nil,
#authorization=
#<Signet::OAuth2::Client:0x00000009450930
#access_token="...",
#additional_parameters={},
#authorization_uri=
#<Addressable::URI:0x4a2813c URI:https://accounts.google.com/o/oauth2/auth>,
#client_id=
"...",
#client_secret="...",
#code=nil,
#expires_in=3600,
#expiry=60,
#extension_parameters={},
#grant_type="refresh_token",
#id_token=
"...",
#issued_at=2014-09-13 00:49:08 -0400,
#refresh_token="...",
#scope=
["openid", "profile", "email",
"https://www.googleapis.com/auth/plus.circles.write",
"https://www.googleapis.com/auth/plus.me",
"https://www.googleapis.com/auth/plus.login",
"https://www.google.com/m8/feeds"],
#token_credential_uri=
#<Addressable::URI:0x4a21e68 URI:https://accounts.google.com/o/oauth2/token>>,
#body="",
#headers=
{"User-Agent"=>
"My Application/1.0.0 google-api-ruby-client/0.7.1 Linux/3.13.0-32-generic\n (gzip)",
"Accept-Encoding"=>"gzip",
"Content-Type"=>""},
#parameters={"circleId"=>"Following", "usersId"=>"+contact_name"}>,
#response=
#<Faraday::Response:0x00000009386680
#env=
#<struct Faraday::Env
method=:put,
body=
"{\n \"error\": {\n \"errors\": [\n {\n \"domain\": \"global\",\n \"reason\": \"forbidden\",\n \"message\": \"Forbidden\"\n }\n ],\n \"code\": 403,\n \"message\": \"Forbidden\"\n }\n}\n",
url=
#<URI::HTTPS:0x00000009420370 URL:https://www.googleapis.com/plusDomains/v1/circles/Following/people?usersId=%2Bcontact_name>,
request=
#<struct Faraday::RequestOptions
params_encoder=Faraday::FlatParamsEncoder,
proxy=nil,
bind=nil,
timeout=nil,
open_timeout=nil,
boundary=nil,
oauth=nil>,
request_headers=
{"User-Agent"=>
"My Application/1.0.0 google-api-ruby-client/0.7.1 Linux/3.13.0-32-generic\n (gzip)",
"Accept-Encoding"=>"gzip",
"Content-Type"=>"",
"Authorization"=>
"Bearer ...",
"Cache-Control"=>"no-store"},
ssl=
#<struct Faraday::SSLOptions
verify=true,
ca_file=
"/home/user/.rvm/gems/ruby-2.1.2/gems/google-api-client-0.7.1/lib/cacerts.pem",
ca_path=nil,
verify_mode=nil,
cert_store=nil,
client_cert=nil,
client_key=nil,
certificate=nil,
private_key=nil,
verify_depth=nil,
version=nil>,
parallel_manager=nil,
params=nil,
response=nil,
response_headers=
{"content-type"=>"application/json; charset=UTF-8",
"date"=>"Sat, 13 Sep 2014 05:01:30 GMT",
"expires"=>"Sat, 13 Sep 2014 05:01:30 GMT",
"cache-control"=>"private, max-age=0",
"x-content-type-options"=>"nosniff",
"x-frame-options"=>"SAMEORIGIN",
"x-xss-protection"=>"1; mode=block",
"server"=>"GSE",
"alternate-protocol"=>"443:quic,p=0.002",
"connection"=>"close",
"transfer-encoding"=>"chunked"},
status=403>,
#on_complete_callbacks=[]>>
I've edited out keys and private information with a '...'. So it's not really telling me what it didn't like about my request. Help would be appreciated.
Maybe you have an expired token. From the docs:
4. Refresh the access token, if necessary.
Access tokens have limited lifetimes. If your application needs access
to a Google API beyond the lifetime of a single access token, it can
obtain a refresh token. A refresh token allows your application to
obtain new access tokens.
Have you tried setting the refresh token from the omniauth auth hash?
client.authorization.refresh_token = request.env["omniauth.auth"]["credentials"]["refresh_token"]
HTH.

Resources