Google API Client secrets failing to load issued_at - ruby

I'm getting the following error message when I try to do an OAuth2 connection to google.
.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/google-api-client-0.7.1/lib/google/api_client/auth/file_storage.rb:49:in `at': can't convert nil into an exact number (TypeError)
Looking at the source this is trying to read a cached credentials file and is failing to parse an attribute called issued_at.
I initially set up my app with the wrong port in the google developer console. Now I've updated the client_secrets.json but I'm continually getting this error.
My code is trying doing the calendar example from the google site, but converted to use the admin directory API, but it isn't getting beyond the auth step.
Where is this cached value coming from?
require 'rubygems'
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/file_storage'
require 'sinatra'
require 'logger'
enable :sessions
CREDENTIAL_STORE_FILE = "client_secrets.json"
def logger; settings.logger end
def api_client; settings.api_client; end
def directory_api; settings.directory; end
def user_credentials
# Build a per-request oauth credential based on token stored in session
# which allows us to use a shared API client.
#authorization ||= (
auth = api_client.authorization.dup
auth.redirect_uri = to('/oauth2callback')
auth.update_token!(session)
auth
)
end
configure do
log_file = File.open('directory.log', 'a+')
log_file.sync = true
logger = Logger.new(log_file)
logger.level = Logger::DEBUG
client = Google::APIClient.new(
:application_name => 'Ruby Directory sample',
:application_version => '1.0.0')
puts "store file : #{CREDENTIAL_STORE_FILE}"
file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
if file_storage.authorization.nil?
client_secrets = Google::APIClient::ClientSecrets.load
client.authorization = client_secrets.to_authorization
client.authorization.scope = 'https://www.googleapis.com/auth/admin.directory.user'
else
client.authorization = file_storage.authorization
end
# Since we're saving the API definition to the settings, we're only retrieving
# it once (on server start) and saving it between requests.
# If this is still an issue, you could serialize the object and load it on
# subsequent runs.
directory = client.discovered_api('admin', "directory_v1")
set :logger, logger
set :api_client, client
set :directory, directory
end
before do
# Ensure user has authorized the app
unless user_credentials.access_token || request.path_info =~ /\A\/oauth2/
redirect to('/oauth2authorize')
end
end
after do
# Serialize the access/refresh token to the session and credential store.
session[:access_token] = user_credentials.access_token
session[:refresh_token] = user_credentials.refresh_token
session[:expires_in] = user_credentials.expires_in
session[:issued_at] = user_credentials.issued_at
file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
file_storage.write_credentials(user_credentials)
end
get '/oauth2authorize' do
# Request authorization
redirect user_credentials.authorization_uri.to_s, 303
end
get '/oauth2callback' do
# Exchange token
user_credentials.code = params[:code] if params[:code]
user_credentials.fetch_access_token!
redirect to('/')
end
get '/' do
result = api_client.execute(:api_method => directory.users.list)
# # Fetch list of events on the user's default calandar
# result = api_client.execute(:api_method => calendar_api.events.list,
# :parameters => {'calendarId' => 'primary'},
# :authorization => user_credentials)
[result.status, {'Content-Type' => 'application/json'}, result.data.to_json]
end

Change the line to CREDENTIAL_STORE_FILE = "#{$0}-oauth2.json" and then rename the json you downloaded from the Google dashboard to client_secrets.json per convention. CREDENTIAL_STORE_FILE is where your OAuth tokens get stored and is created by the FileStorage instance.

Related

Google Sheets API: Error 400: redirect_uri_mismatch

I keep getting Authorization errors when sending a POST request from my React/Ruby app. I'm getting different errors depending on what OOB_URI I'm using.
If I use
OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze then I get the following error:
When I use OOB_URI = "http://127.0.0.1".freeze then I get the following error:
Here's my Ruby code
require "google/apis/sheets_v4"
require "googleauth"
require "googleauth/stores/file_token_store"
require "fileutils"
# Get authorization
OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze
# OOB_URI = "http://127.0.0.1".freeze
APPLICATION_NAME = "mimirgettingmarried".freeze
CREDENTIALS_PATH = "/Users/michelleroos/Desktop/mimirgettingmarried/mimirgettingmarried/config/credentials.json".freeze
# The file token.yaml stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
TOKEN_PATH = "token.yaml".freeze
SCOPE = Google::Apis::SheetsV4::AUTH_SPREADSHEETS
# Ensure valid credentials, either by restoring from the saved credentials
# files or intitiating an OAuth2 authorization. If authorization is required,
# the user's default browser will be launched to approve the request.
# #return [Google::Auth::UserRefreshCredentials] OAuth2 credentials
def authorize
client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH
token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH
authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store
user_id = "default"
credentials = authorizer.get_credentials user_id
if credentials.nil?
url = authorizer.get_authorization_url base_url: OOB_URI
puts "Open the following URL in the browser and enter the " \
"resulting code after authorization:\n" + url
code = gets
credentials = authorizer.get_and_store_credentials_from_code(
user_id: user_id, code: code, base_url: OOB_URI
)
end
credentials
end
# Initialize the API
service = Google::Apis::SheetsV4::SheetsService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize
spreadsheet_id = '17bXAJELWjXIRmcJ-RPeg5_W4wszqZI3QxvE_ZIL3L6A'
range = 'rsvp'
class Api::RsvpsController < ApplicationController
def create # append
values = [
'hi', 'hello'
]
# TODO: Assign values to desired members of `request_body`:
request_body = Google::Apis::SheetsV4::ValueRange.new(values: values)
response = service.append_spreadsheet_value(spreadsheet_id, range, request_body)
# TODO: Change code below to process the `response` object:
puts response.to_json
end
def show
# range = "Class Data!A2:E"
# response = service.get_spreadsheet_values(spreadsheet_id, range)
# puts "Name, Major:"
# puts "No data found." if response.values.empty?
# response.values.each do |row|
# # Print columns A and E, which correspond to indices 0 and 4.
# puts "#{row[0]}, #{row[4]}"
# end
range_names = [
# Range names ...
]
result = service.batch_get_spreadsheet_values(spreadsheet_id)
# result = service.batch_get_spreadsheet_values(spreadsheet_id, ranges: range_names)
puts "#{result.value_ranges.length} ranges retrieved."
end
end
Here's how I set up my credentials in Google Cloud Console:

How do I authorize a service account for Google Calendar API in Ruby?

How do I authorize a service account for Google Calendar API in Ruby? I tried the quick start guide, but it crashed.
https://developers.google.com/calendar/quickstart/ruby#step_3_set_up_the_sample
quickstart.rb
require 'google/apis/calendar_v3'
require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'fileutils'
OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'.freeze
APPLICATION_NAME = 'Google Calendar API Ruby Quickstart'.freeze
CLIENT_SECRETS_PATH = 'client_secrets.json'.freeze
CREDENTIALS_PATH = 'token.yaml'.freeze
SCOPE = Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY
##
# Ensure valid credentials, either by restoring from the saved credentials
# files or intitiating an OAuth2 authorization. If authorization is required,
# the user's default browser will be launched to approve the request.
#
# #return [Google::Auth::UserRefreshCredentials] OAuth2 credentials
def authorize
client_id = Google::Auth::ClientId.from_file(CLIENT_SECRETS_PATH) ### LINE 19
token_store = Google::Auth::Stores::FileTokenStore.new(file: CREDENTIALS_PATH)
authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, token_store)
user_id = 'default'
credentials = authorizer.get_credentials(user_id)
if credentials.nil?
url = authorizer.get_authorization_url(base_url: OOB_URI)
puts 'Open the following URL in the browser and enter the ' \
'resulting code after authorization:\n' + url
code = gets
credentials = authorizer.get_and_store_credentials_from_code(
user_id: user_id, code: code, base_url: OOB_URI
)
end
credentials
end
# Initialize the API
service = Google::Apis::CalendarV3::CalendarService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize
# Fetch the next 10 events for the user
calendar_id = 'primary'
response = service.list_events(calendar_id,
max_results: 10,
single_events: true,
order_by: 'startTime',
time_min: Time.now.iso8601)
puts 'Upcoming events:'
puts 'No upcoming events found' if response.items.empty?
response.items.each do |event|
start = event.start.date || event.start.date_time
puts "- #{event.summary} (#{start})"
end
Console
>ruby quickstart.rb
C:/ruby23/lib/ruby/gems/2.3.0/gems/googleauth-0.6.2/lib/googleauth/client_id.rb:97:in `from_hash': Expected top level property 'installed' or 'web' to be present. (RuntimeError)
from C:/ruby23/lib/ruby/gems/2.3.0/gems/googleauth-0.6.2/lib/googleauth/client_id.rb:83:in `block in from_file'
from C:/ruby23/lib/ruby/gems/2.3.0/gems/googleauth-0.6.2/lib/googleauth/client_id.rb:80:in `open'
from C:/ruby23/lib/ruby/gems/2.3.0/gems/googleauth-0.6.2/lib/googleauth/client_id.rb:80:in `from_file'
from quickstart.rb:19:in `authorize'
from quickstart.rb:39:in `<main>'
The (outdated) documentation for authorizing service accounts only has examples for Java and Python.
https://developers.google.com/identity/protocols/OAuth2ServiceAccount#authorizingrequests
Old similar question with 0 answers: Google Calendar API in Ruby using Service Account
For anyone still looking this is what worked for me:
require 'google/apis/calendar_v3'
require 'googleauth'
scope = 'https://www.googleapis.com/auth/calendar'
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: File.open('/path/to/creds.json'),
scope: scope)
authorizer.fetch_access_token!
service = Google::Apis::CalendarV3::CalendarService.new
service.authorization = authorizer
calendar_id = 'primary'
response = service.list_events(calendar_id,
max_results: 10,
single_events: true,
order_by: 'startTime',
time_min: Time.now.iso8601)
puts 'Upcoming events:'
puts 'No upcoming events found' if response.items.empty?
response.items.each do |event|
start = event.start.date || event.start.date_time
puts "- #{event.summary} (#{start})"
end
The trick was finding the docs for the google-auth-library-ruby
https://github.com/googleapis/google-auth-library-ruby
OK I found a way.
https://developers.google.com/api-client-library/ruby/auth/service-accounts
require 'google/apis/calendar_v3'
require 'googleauth'
# Get the environment configured authorization
scopes = ['https://www.googleapis.com/auth/calendar']
authorization = Google::Auth.get_application_default(scopes)
# Clone and set the subject
auth_client = authorization.dup
auth_client.sub = 'myemail#mydomain.com'
auth_client.fetch_access_token!
# Initialize the API
service = Google::Apis::CalendarV3::CalendarService.new
service.authorization = auth_client
# Fetch the next 10 events for the user
calendar_id = 'primary'
response = service.list_events(calendar_id,
max_results: 10,
single_events: true,
order_by: 'startTime',
time_min: Time.now.iso8601)
puts 'Upcoming events:'
puts 'No upcoming events found' if response.items.empty?
response.items.each do |event|
start = event.start.date || event.start.date_time
puts "- #{event.summary} (#{start})"
end
And
>set GOOGLE_APPLICATION_CREDENTIALS=client_secrets.json
C:\Users\Chloe\workspace>ruby quickstart.rb
Upcoming events:
- Test (2018-05-17)
- SSL Certificate for CMS (2019-02-13)
But I wonder where it saves the refresh token and access token? All I have to do now is make it work for ephemeral file systems like Heroku and store the tokens in the database.

Google API for Blogger 3.0 error

I am trying to run sample code in Ruby to fetch blog posts list using Google's APIs for Blogger 3.0. This is the code:
require 'rubygems'
require 'google/api_client'
require 'sinatra'
require 'google/api_client'
require 'logger'
enable :sessions
def logger; settings.logger end
def api_client; settings.api_client; end
def blogger_api; settings.blogger; end
def user_credentials
# Build a per-request oauth credential based on token stored in session
# which allows us to use a shared API client.
#authorization ||= (
auth = api_client.authorization.dup
auth.redirect_uri = to('/oauth2callback')
auth.update_token!(session)
auth
)
end
configure do
log_file = File.open('blogger.log', 'a+')
log_file.sync = true
logger = Logger.new(log_file)
logger.level = Logger::DEBUG
client = Google::APIClient.new
client.authorization.client_id = 'XXXXXXXXXXXXX'
client.authorization.client_secret = 'XXXXXXXXXXXXX'
client.authorization.scope = 'https://www.googleapis.com/auth/blogger'
blogger = client.discovered_api('blogger', 'v3')
set :logger, logger
set :api_client, client
set :blogger, blogger
end
before do
# Ensure user has authorized the app
unless user_credentials.access_token || request.path_info =~ /^\/oauth2/
redirect to('/oauth2authorize')
end
end
after do
# Serialize the access/refresh token to the session
session[:access_token] = user_credentials.access_token
session[:refresh_token] = user_credentials.refresh_token
session[:expires_in] = user_credentials.expires_in
session[:issued_at] = user_credentials.issued_at
end
get '/oauth2authorize' do
# Request authorization
redirect user_credentials.authorization_uri.to_s, 303
end
get '/oauth2callback' do
# Exchange token
user_credentials.code = params[:code] if params[:code]
user_credentials.fetch_access_token!
redirect to('/')
end
get '/' do
# Fetch list of posts
result = api_client.execute(:api_method => settings.blogger.posts.list, :parameters => {'blogId' => 'XXXXXXXXXXXXX'})
[result.status, {'Content-Type' => 'application/json'}, result.data.to_json]
end
When I connect to the running local application (after authorized it) I can see this "sinatra" error:
#<NameError: undefined local variable or method `blogger' for #<Sinatra::Application:0x92ac2dc>>
It is a bit obscure to me. Any idea?

OAuth2 gem: implementation for third party - access other accounts data in seek.com

I'm connecting to an API (seek.com.au) which uses OAuth2 for authentication. I struggled with OAuth2 gem for a while and I ended up writing the plain requests as will follow. Although this is working, I still would like to understand what was wrong with my initial OAuth2 implementation.
Here is my current working code, **the third party* relates to the fact that I'm accessing the API with an account that have access to other accounts. This logic is mainly implemented in the scope method (at the bottom of this snippet).
The following includes some extra logic, but the get_grant and post_for_token methods should include everything.
module Seek::Base
CONFIG = YAML.load_file "#{Rails.root}/config/seek.yml"
HOST = 'http://test.api.seek.com.au/v1/'
REQUEST_URIS = {
get_grant: HOST + 'OAuth/auth',
post_for_token: HOST + 'OAuth/token',
get_applications: HOST + 'advertiser/applications'
}
def uri_for(request, params = {})
uri = REQUEST_URIS[request]
uri += '?' + params.to_param if params.any?
URI.parse uri
end
end
class Seek::OAuth2 # TODO? is instance needed?
include Seek::Base
# by account_id
##tokens = {}
def initialize(account_id)
#account_id = account_id
end
def self.authenticate!(account_id)
new(account_id).authenticate!
end
# eg: when a request responded that the token is expired
def self.expire_token(account_id)
##tokens.delete account_id
end
###########################################################################
############################### begin #####################################
# authentication
# see: http://developer.seek.com.au/docs/partner-api/api-methods/oauth-2.0
def authenticate!
##tokens[#account_id] ||= begin
grant = get_grant
raise Exception.new(#error) if #error
Rails.logger.info "Retrive token for #{#account_id}"
post_for_token
end
end
private
# part of t he authentication process
# as we have one account for many entities, we use third party variation
# see: http://developer.seek.com.au/docs/partner-api/api-methods/oauth2/auth
def get_grant
uri = uri_for :get_grant, {response_type: :code, client_id: username, scope: scope}
response = Net::HTTP.get_response uri
params = response['location'].split('?').second
#error = params.split('error=').second
#grant_code = params.split('code=').second
end
# part of the authentication process
# see: http://developer.seek.com.au/docs/partner-api/api-methods/oauth2/token
def post_for_token
uri = uri_for :post_for_token
request = Net::HTTP::Post.new uri.path, {'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'}
request.set_form grant_type: :authorization_code, code: #grant_code, redirect_uri: ''
request.basic_auth username, password
response = Net::HTTP.new(uri.host, uri.port).request request
JSON(response.body)['access_token']
end
########################## end ############################################
###########################################################################
def username
CONFIG['credentials']['username']
end
def password
CONFIG['credentials']['password']
end
############## the scope method
############## I think I need to insert this in the OAuth request
def scope
"urn:seek:thirdparty:username:#{username},urn:seek:advertiser:identity:#{#account_id}"
end
end
And here are the few lines (to replace the authenticate! method) that were meant to do the same, but sadly, OAuth returns invalid_client.
client = OAuth2::Client.new(username, password, :site => 'http://test.api.seek.com.au/v1')
client.auth_code.authorize_url redirect_uri: ''
token = client.auth_code.get_token 'authorization_code_value',
headers: {'Authorization' => %^Basic #{Base64.encode64 "#{username}:#{password}"}^ }
I think the problem relies in the scope method created by OAuth (see bottom of the first snippet), but I'm not sure and anyways I couldn't find a way to amend it.
I also opened an issue in GitHub, but I think this is covered, just it's not documented (or I can't find it).
Ruby (Rails) implementation
This implementation is not using any wrapper, I tried the gem OAuth2 but I was not able to get the grant code,
I presume because the third party implementation require a customization of the scope which I was not able to set with the gem.
module Api::Base
CONFIG = YAML.load_file "#{Rails.root}/config/api.yml"
HOST = 'https://api.com.au/v1/'
REQUEST_URIS = {
get_grant: HOST + 'OAuth/auth',
post_for_token: HOST + 'OAuth/token',
get_applications: HOST + 'advertiser/applications'
}
def uri_for(request, params = {})
uri = REQUEST_URIS[request]
uri += '?' + params.to_param if params.any?
URI.parse uri
end
end
class Api::OAuth2
include Api::Base
# by account_id
##tokens = {}
def initialize(account_id)
#account_id = account_id
end
def self.authenticate!(account_id)
new(account_id).authenticate!
end
# eg: when a request responded that the token is expired
def self.expire_token(account_id)
##tokens.delete account_id
end
# authentication
def authenticate!
##tokens[#account_id] ||= begin
grant = get_grant
raise StandardError.new(#error) if #error
puts "Retrive token for #{#account_id}"
post_for_token
end
end
private
# part of t he authentication process
# as we have one account for many entities, we use third party variation
def get_grant
uri = uri_for :get_grant, {response_type: :code, client_id: username, scope: scope}
http = Net::HTTP.new uri.host, uri.port
http.use_ssl = uri.port == 443
puts "SSL not set for uri #{uri}" unless http.use_ssl?
response = http.get uri.to_s
raise Exception.new(response.message) unless response.is_a? Net::HTTPFound
params = response['location'].split('?').second
#error = params.split('error=').second
#grant_code = params.split('code=').second
end
# part of the authentication process
def post_for_token
uri = uri_for :post_for_token
request = Net::HTTP::Post.new uri.path, {'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'}
request.set_form grant_type: 'authorization_code', code: #grant_code, redirect_uri: ''
request.basic_auth username, password
http = Net::HTTP.new uri.host, uri.port
http.use_ssl = uri.port == 443
response = http.start {|http| http.request request}
JSON(response.body)['access_token']
end
end
def username
CONFIG['credentials']['username']
end
def password
CONFIG['credentials']['password']
end
def scope
"urn:api:thirdparty:username:#{username},urn:api:advertiser:identity:#{#account_id}"
end
end
I'm still planning to use OAuth 2, I'll post my updates here if any

How do I set HTTParty configuration parameters on my class dynamically?

The simple_client.rb file below works perfectly fine against my emulation cas server; however, the casport.rb file (main file of oa-casport OmniAuth strategy) is not setting or passing the headers / format properly. It needs to be dynamically assigned to the class to allow initializer options to be able to create them, but I'm not sure how else to do it besides how I've attempted to do it here. I was fairly certain I had this working at some point, but I can't see any other explanation for why this wouldn't be working given the simplicity of the client file.
Any help is greatly appreciated on figuring out how to best set the format and headers settings for HTTParty within my Casport class dynamically. As it is it just keeps returning the HTML view for that particular user.
simple_client.rb:
### simple_client.rb - works properly w/ parsed XML response
### The cas.dev project is coming from this Github repo:
### https://github.com/stevenhaddox/oa-casport-server
require 'rubygems'
require 'httparty'
require 'awesome_print'
class Casport
include HTTParty
base_uri 'cas.dev/users'
format :xml
headers 'Accept' => 'application/xml'
def self.find_user(id)
get("/#{id}").parsed_response
end
end
user = Casport.find_user(1)
ap user
casport.rb:
# lib/omniauth/strategies/casport.rb
require 'omniauth/core'
require 'httparty'
require 'redis'
require 'uri'
module OmniAuth
module Strategies
#
# Authentication to CASPORT
#
# #example Basic Usage
#
# use OmniAuth::Strategies::Casport, {
# :setup => true
# }
# #example Full Options Usage
#
# use OmniAuth::Strategies::Casport, {
# :setup => true,
# :cas_server => 'http://cas.slkdemos.com/users/',
# :format => 'xml',
# :format_header => 'application/xml',
# :ssl_ca_file => 'path/to/ca_file.crt',
# :pem_cert => '/path/to/cert.pem',
# :pem_cert_pass => 'keep it secret, keep it safe.'
# }
class Casport
include OmniAuth::Strategy
include HTTParty
def initialize(app, options)
super(app, :casport)
#options = options
#options[:cas_server] ||= 'http://cas.dev/users'
#options[:format] ||= 'xml'
#options[:format_header] ||= 'application/xml'
end
def request_phase
Casport.setup_httparty(#options)
redirect(callback_path)
end
def callback_phase
begin
raise 'We seemed to have misplaced your credentials... O_o' if user.nil?
super
rescue => e
redirect(request_path)
# fail!(:invalid_credentials, e)
end
call_app!
end
def auth_hash
# store user in a local var to avoid new method calls for each attribute
# convert all Java camelCase keys to Ruby snake_case, it just feels right!
user_obj = user.inject({}){|memo, (k,v)| memo[k.gsub(/[A-Z]/){|c| '_'+c.downcase}] = v; memo}
begin
user_obj = user_obj['userinfo']
rescue => e
fail!(:invalid_user, e)
end
OmniAuth::Utils.deep_merge(super, {
'uid' => user_obj['uid'],
'user_info' => {
'name' => user_obj['full_name'],
'email' => user_obj['email']
},
'extra' => {'user_hash' => user_obj}
})
end
# Set HTTParty params that we need to set after initialize is called
# These params come from #options within initialize and include the following:
# :ssl_ca_file - SSL CA File for SSL connections
# :format - 'json', 'xml', 'html', etc. || Defaults to 'xml'
# :format_header - :format Header string || Defaults to 'application/xml'
# :pem_cert - /path/to/a/pem_formatted_certificate.pem for SSL connections
# :pem_cert_pass - plaintext password, not recommended!
def self.setup_httparty(opts)
format opts[:format].to_sym
headers 'Accept' => opts[:format_header]
if opts[:ssl_ca_file]
ssl_ca_file opts[:ssl_ca_file]
if opts[:pem_cert_pass]
pem File.read(opts[:pem_cert]), opts[:pem_cert_pass]
else
pem File.read(opts[:pem_cert])
end
end
end
def user
# Can't get user data without a UID from the application
begin
raise "No UID set in request.env['omniauth.strategy'].options[:uid]" if #options[:uid].nil?
#options[:uid] = #options[:uid].to_s
rescue => e
fail!(:uid_not_found, e)
end
url = URI.escape(#options[:cas_server] + '/' + #options[:uid])
# It appears the headers aren't going through properly to HTTParty...
# The URL + .xml works in the application & the url w/out .xml works in standalone file
# Which means somehow the setup with self.setup_httparty isn't kicking in properly :(
ap Casport.get(url+'.xml').parsed_response
begin
cache = #options[:redis_options].nil? ? Redis.new : Redis.new(#options[:redis_options])
unless #user = (cache.get #options[:uid])
# User is not in the cache
# Retrieving the user data from CASPORT
# {'userinfo' => {{'uid' => UID}, {'fullName' => NAME},...}},
#user = Casport.get(url).parsed_response
cache.set #options[:uid], #user
# CASPORT expiration time for user (24 hours => 1440 seconds)
cache.expire #options[:uid], 1440
end
# If we can't connect to Redis...
rescue Errno::ECONNREFUSED => e
#user ||= Casport.get(url).parsed_response
end
#user = nil if user_empty?
#user
end
# Investigate user_obj to see if it's empty (or anti-pattern data)
def user_empty?
is_empty = false
is_empty = true if #user.nil?
is_empty = true if #user.empty?
# If it isn't empty yet, let's convert it into a Hash object for easy parsing via eval
unless #user.class == Hash
is_empty = true
raise "String returned when a Hash was expected."
end
is_empty == true ? true : nil
end
end
end
end
This was apparently working properly, what I failed to do was to provide the header for Content-Type:
...
def self.setup_httparty(opts)
format opts[:format].to_sym
headers 'Accept' => opts[:format_header]
headers 'Content-Type' => opts[:format_header]
...
Once I added that additional line everything kicked in properly.

Resources