I would like to use the purchase token from the in app purchases in an android app to validate it to the google server on my own server.
With the following code I can validate a token, but I have to authenticate myself with my OAuth credentials every time:
class GooglePlayVerification
require 'google/api_client'
# Refer:
# https://code.google.com/p/google-api-ruby-client/issues/detail?id=72
# and
# http://jonathanotto.com/blog/google_oauth2_api_quick_tutorial.html
# and
# http://milancermak.wordpress.com/2012/08/24/server-side-verification-of-google-play-subsc/
GOOGLE_KEY = 'xxx.apps.googleusercontent.com'
GOOGLE_SECRET = 'xxxx'
APP_NAME = 'xx.xx.xx'
SCOPE = "https://www.googleapis.com/auth/androidpublisher"
def self.token
##token ||= begin
require 'oauth2'
raise "Missing client_id variable" if GOOGLE_KEY.to_s.empty?
raise "Missing client_secret variable" if GOOGLE_SECRET.to_s.empty?
raise "Missing scope variable" if SCOPE.to_s.empty?
redirect_uri = 'https://localhost/oauth2callback'
auth_client_obj = OAuth2::Client.new(GOOGLE_KEY, GOOGLE_SECRET, {:site => 'https://accounts.google.com', :authorize_url => "/o/oauth2/auth", :token_url => "/o/oauth2/token"})
puts "1) Paste this URL into your browser where you are logged in to the relevant Google account\n\n"
puts auth_client_obj.auth_code.authorize_url(:scope => SCOPE, :access_type => "offline", :redirect_uri => redirect_uri, :approval_prompt => 'force')
puts "\n\n\n2) Accept the authorization request from Google in your browser:"
puts "\n\n\n3) Google will redirect you to localhost, but just copy the code parameter out of the URL they redirect you to, paste it here and hit enter:\n"
code = gets.chomp.strip
access_token_obj = auth_client_obj.auth_code.get_token(code, {:redirect_uri => redirect_uri, :token_method => :post})
puts "Result: #{access_token_obj.inspect}\n\n"
puts "Token is: #{access_token_obj.token}"
puts "Refresh token is: #{access_token_obj.refresh_token}"
{
:access_token => access_token_obj.token,
:refresh_token => access_token_obj.refresh_token,
:expires_in => access_token_obj.expires_in,
:expires_at => access_token_obj.expires_at
}
end
end
def self.refresh_token
refresh_client_obj = OAuth2::Client.new(GOOGLE_KEY, GOOGLE_SECRET, {:site => 'https://accounts.google.com', :authorize_url => '/o/oauth2/auth', :token_url => '/o/oauth2/token'})
refresh_access_token_obj = OAuth2::AccessToken.new(refresh_client_obj, token[:access_token], {refresh_token: token[:refresh_token]})
refresh_access_token_obj.refresh!
puts "refresh token: #{refresh_access_token_obj.inspect}"
##token = {
:access_token => refresh_access_token_obj.token,
:refresh_token => refresh_access_token_obj.refresh_token,
:expires_in => refresh_access_token_obj.expires_in,
:expires_at => refresh_access_token_obj.expires_at
}
end
# ie. https://developers.google.com/android-publisher/v1/
# eg.
# #subscription_id com.stocklight.stocklight.standardsubscription
# #purchase_token xxx
def self.verify_subscription(subscription_id, purchase_token)
response = RestClient.get "https://www.googleapis.com/androidpublisher/v1.1/applications/#{APP_NAME}/inapp/#{subscription_id}/purchases/#{purchase_token}?access_token=#{token[:access_token]}"
puts "Respnse \n #{response.inspect}"
puts response.code == 200
puts JSON.parse(response)
return response.code == 200 && JSON.parse(response)['kind'] =='androidpublisher#inappPurchase'
rescue
return false
end
end
Has anyone an idea how to authenticate a server without such things like OAuth on the server? Is there another authentification possibility?
Thanks!
Here is my ruby code:
def self.verify_subscription(subscription_id, transaction_id)
json = JSON.parse(transaction_id)
order = ["orderId", "packageName", "productId", "purchaseTime", "purchaseState", "purchaseToken"]
signature = json["signature"]
data = {}
order.each do |o|
data[o] = json[o]
end
key = OpenSSL::PKey::RSA.new(Base64.decode64(GOOGLE_PUBLIC_KEY))
verified = key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(signature), data.to_json)
verified
end
Related
Error - Google::Apis::ClientError: insufficientPermissions: Request had insufficient authentication scopes.
Facing error - at line result = service.list_user_labels user_id in dashboards_controller.rb
Following are my files.
devise.rb
config.omniauth :google_oauth2, client_id, client_secret
users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
#create user
if user.present?
flash[:success] = t 'devise.omniauth_callbacks.success', kind: 'Google'
sign_in_and_redirect user, event: :authentication
else
flash[:alert] = t 'devise.omniauth_callbacks.failure', kind: 'Google', reason: "#{auth.info.email} is not authorized."
redirect_to new_user_session_path
end
end
end
dashboards_controller.rb
require 'google/api_client/client_secrets.rb'
require 'google/apis/gmail_v1'
require 'googleauth'
class DashboardsController < ApplicationController
def show
# Initialize the API
service = Google::Apis::GmailV1::GmailService.new
service.authorization = google_secret.to_authorization
service.authorization.refresh!
# Show the user's labels
user_id = current_user.uid
result = service.list_user_labels user_id
puts "Labels:"
#puts "No labels found" if result.labels.empty?
#result.labels.each { |label| puts "- #{label.name}" }
end
private
def google_secret
scope = "https://www.googleapis.com/auth/gmail.labels"
Google::APIClient::ClientSecrets.new(
{ "web" =>
{ "access_token" => current_user.token,
"refresh_token" => current_user.refresh_token,
"client_id" => client_id,
"client_secret" => client_secret,
"scope" => scope
}
}
)
end
end
I want to start working with Magento's REST API, but I can't seem to get it working.
To start with I need to get access tokens, here's what I'm trying:
require 'oauth'
#consumer = OAuth::Consumer.new("4200100753b2c8b03bde1f5b062c5a80", "c06abdcb734c85dfd7bb115c6a67ae4d", {:site=>"http://178.62.173.99/"})
#request_token = #consumer.get_request_token
# => oauth-0.4.7/lib/oauth/consumer.rb:216:in `token_request': 404 Not Found (OAuth::Unauthorized)
But I keep getting a 404 error.
What should I try next?
Here's a Ruby module I've written to create an access token for the Magento REST API:
module Token
def create_consumer
OAuth::Consumer.new(
CONSUMER_KEY,
CONSUMER_SECRET,
:request_token_path => '/oauth/initiate',
:authorize_path=>'/admin/oauth_authorize',
:access_token_path=>'/oauth/token',
:site => URL
)
end
def request_token(args = {})
args[:consumer].get_request_token(:oauth_callback => URL)
end
def get_authorize_url(args = {})
args[:request_token].authorize_url(:oauth_callback => URL)
end
def authorize_application(args = {})
m = Mechanize.new
m.get(args[:authorize_url]) do |login_page|
auth_page = login_page.form_with(:action => "#{URL}/index.php/admin/oauth_authorize/index/") do |form|
form.elements[1].value = ADMIN_USERNAME
form.elements[2].value = ADMIN_PASSWORD
end.submit
authorize_form = auth_page.forms[0]
#callback_page = authorize_form.submit
end
#callback_page.uri.to_s
end
def extract_oauth_verifier(args = {})
callback_page = "#{args[:callback_page]}".gsub!("#{URL}/?", '')
callback_page_query_string = CGI::parse(callback_page)
callback_page_query_string['oauth_verifier'][0]
end
def get_access_token(args = {})
args[:request_token].get_access_token(:oauth_verifier => args[:oauth_verifier])
end
def save_tokens_to_json(args = {})
auth = {}
auth[:time] = Time.now
auth[:token] = args[:access_token].token
auth[:secret] = args[:access_token].secret
File.open("#{args[:path]}#{args[:filename]}.json", 'w') {|f| f.write(auth.to_json)}
auth
end
def get_new_access_tokens
new_consumer = self.create_consumer
new_request_token = self.request_token(consumer: new_consumer)
new_authorize_url = self.get_authorize_url(request_token: new_request_token)
authorize_new_application = self.authorize_application(authorize_url: new_authorize_url)
extract_new_oauth_verifier = self.extract_oauth_verifier(callback_page: authorize_new_application)
new_access_token = self.get_access_token(request_token: new_request_token, oauth_verifier: extract_new_oauth_verifier)
save_tokens_to_json(filename: 'magento_oauth_access_tokens', path: '/', access_token: new_access_token)
return 'Successfully obtained new access tokens.'
end
end
Run #get_new_access_tokens to get an access token.
Don't forget to define the following variable:
CONSUMER_KEY
CONSUMER_SECRET
URL
ADMIN_USERNAME
ADMIN_PASSWORD
Check out mage on rails. It should work right out of the box. Check out this page for annotated ruby code showcasing the oauth flow
My SOAP-Server expects every request to have a valid token in the soap-header to authenticate the soap-client. This token is only valid for a certain period of time, so I have to expect it to be invalid in every call.
I am trying to find a way to force savon to rebuild the SOAP-Header (i.e. use the new auth-token) after I (re)authenticate with the SOAP-Server. I am not sure, if that is either a savon problem or a ruby one. Here is what I have so far.
class Soapservice
extend Savon::Model
# load stored auth-token
##header_data = YAML.load_file "settings.yaml"
client wsdl: 'locally-cached-wsdl.xml',
soap_header: {'verifyingToken' => ##header_data}
operations :get_authentification_token, :get_server_time
# request a new auth-token and store it
def get_authentification_token
response = super(:message => {
'oLogin' => {
'Username' => 'username',
'Userpass' => 'password'
}
})
settings = {
'UserID' => response[:user_id].to_i,
'Token' => response[:token],
}
File.open("settings.yaml", "w") do |file|
file.write settings.to_yaml
end
##header_data = settings
end
def get_server_time
return super()
rescue Savon::SOAPFault => error
fault_code = error.to_hash[:fault][:faultstring]
if fault_code == 'Unauthorized Request - Invalide Token'
get_authentification_token
retry
end
end
end
When I call
webservice = Soapservice.new
webservice.get_server_time
with an invalid Token, it reauthenticates and saves the new Token successfully, but the retry doesn't load the new header (the result is an infinite loop). Any ideas?
I added rubiii's answer from the GitHub-Issue here for future reference:
class Soapservice
# load stored auth-token
##header_data = YAML.load_file "settings.yaml"
def initialize
#client = Savon.client(wsdl: 'locally-cached-wsdl.xml')
end
def call(operation_name, locals = {})
#client.globals[:soap_header] = {'verifyingToken' => ##header_data}
#client.call(operation_name, locals)
end
# request a new auth-token and store it
def get_authentification_token
message = {
'Username' => 'username',
'Userpass' => 'password'
}
response = call(:get_authentification_token, :message => message)
settings = {
'UserID' => response[:user_id].to_i,
'Token' => response[:token],
}
File.open("settings.yaml", "w") do |file|
file.write settings.to_yaml
end
##header_data = settings
end
def get_server_time
call(:get_server_time)
rescue Savon::SOAPFault => error
fault_code = error.to_hash[:fault][:faultstring]
if fault_code == 'Unauthorized Request - Invalide Token'
get_authentification_token
retry
end
end
end
rubiii added:
notice that i removed Savon::Model, as you actually don't need it and i don't know if it supports this workaround.
if you look at the #call method, it accesses and changes the globals before every request.
I am importing a list of contacts from gmail and using a checkbox to select the returned emails and send an invitation out to users after they have been selected. When I look at the my logs the output has the email in the correct format and everything seems fine.
When I look at my email activity on Sendgrid I am seeing additional characters attached to the email address hence making it fail. I do not have any issues sending email with my other mailers using sendmail but this one seems to add these additional characters and I do not know where they are coming from.
Has anyone else seen this happening? Or have a suggestion on how to fix this?
Expected result
Email: test#gmail.com
Actual result
Email: "test#gmail.com"#i04-01
user_mailer
def invitation(email_addresses)
#host = ((Rails.env == "production") ? "http://www.test.com" : "http://localhost:3000")
attachments.inline['people.jpg'] = File.read("#{Rails.root}/app/assets/images/people.jpg")
#attachments.inline['people.jpg'] = File.read("#{Rails.root}/app/assets/images/Girl.jpeg")
email_addresses.each do |email|
mail(:to => email, :subject => "Hello from test!")
end
end
user_controller
def import
##user = User.find(params[:id])
##users = User.find(session[:user_id])
begin
#sites = {"gmail" => Contacts::Gmail, "yahoo" => Contacts::Yahoo, "hotmail" => Contacts::Hotmail}
#contacts = #sites[params[:from]].new(params[:login], params[:password]).contacts
#users, #no_users = [], []
#contacts.each do |contact|
#if u = User.find(:first , :conditions => #users.email = �#{contact[1]}� , :include =>[:user])
if u = User.find(:first, :conditions => "email = '#{contact[1]}'")
#users << u
else
#no_users << {:name => contact[0], :email => contact[1]}
end
end
#if #contacts.save
#end
respond_to do |format|
format.html { render :template => 'shared/_contact_list', :layout => false }
format.xml { render :xml => #contacts.to_xml }
end
end
end
def send_bulk_mail
name_email =[]
email_addresses=[]
names=[]
post=params[:post]
post.each do |k,v|
if v=="1"
name_email << k
end
end
name_email.each do |n|
email_addresses << n.split(",")[1]
end
UserMailer.invitation(email_addresses).deliver
end
Thanks
Has anybody connected to Salesforce through Rails 3 App via oauth? Could you please post code for doing same. I am trying to same but I get some error below is my code
def oauth_client
consumer_key = '....'
consumer_secret = '....'
oauth_options = {
:site => 'https://login.salesforce.com',
:scheme => :body,
:request_token_path => '/_nc_external/system/security/oauth/RequestTokenHandler',
:authorize_path => '/setup/secur/RemoteAccessAuthorizationPage.apexp',
:access_token_path => '/_nc_external/system/security/oauth/AccessTokenHandler',
}
OAuth::Consumer.new consumer_key, consumer_secret, oauth_options
end
def oauth_redirect_uri
uri = URI.parse(request.url)
uri.path = '/sfdc/oauth_callback'
uri.query = nil
# uri = "http://localhost:3000/sfdc/oauth_callback"
uri.to_s
end
def oauth_connect
consumer_key = '...' # from SalesForce
consumer = oauth_client
request_t = consumer.get_request_token
redirect_to request_t.authorize_url(
:redirect_uri => oauth_redirect_uri,
:oauth_consumer_key => consumer_key
)
end
def oauth_callback
access = request_t.get_access_token :oauth_verifier => params[:oauth_verifier]
p access
render :text => access.token
end
Error undefined method get_access_token for #<ActionDispatch::Request:0x12b79f370>. the request variable is nil here. How do I get it back?
The rforce gem has quite a bit of an example that I pasted below. However you might just want to use rforce instead of rolling your own.
def init_server(url)
#url = URI.parse(url)
if (#oauth)
consumer = OAuth::Consumer.new \
#oauth[:consumer_key],
#oauth[:consumer_secret],
{
:site => url,
:proxy => #proxy
}
consumer.http.set_debug_output $stderr if show_debug
#server = OAuth::AccessToken.new \
consumer,
#oauth[:access_token],
#oauth[:access_secret]
class << #server
alias_method :post2, :post
end
else
#server = Net::HTTP.Proxy(#proxy).new(#url.host, #url.port)
#server.use_ssl = #url.scheme == 'https'
#server.verify_mode = OpenSSL::SSL::VERIFY_NONE
# run ruby with -d or env variable SHOWSOAP=true to see SOAP wiredumps.
#server.set_debug_output $stderr if show_debug
end
end