Hello Please would you take a look at this for me and advise....
Thanks in advance James Kay I am getting an authorization failure calling Google Data APIs (Docs, Calendar etc). The test Marketplace app has been created. OpenID authentication has already succeeded. Here is my log: https://sandbox/openid_login?openid_identifier=workbooks.com Mar 31 10:44:40,sandbox,info,user,workbooks_app[23521]: 0.023952 +0.000605 OAUTH REQUEST: get, /feeds/documents/private/full?showfolders=true&xoauth_requestor_id=james.kay%40workbooks.com, #<OAuth::AccessToken:0xc775d38 @secret="", @token="", @params={}, @consumer=#<OAuth::Consumer:0xc7764b8 @http=#<Net::HTTP docs.google.com:443 open=false>, @uri=#<URI::HTTPS:0xc76dfe8 URL:https://docs.google.com/feeds/documents/private/full?showfolders=true&xoauth_requestor_id=james.kay%40workbooks.com>, @secret="[THE SECRET]", @options={:scheme=>:header, :request_token_path=>"/oauth/request_token", :proxy=>nil, :signature_method=>"HMAC-SHA1", :authorize_path=>"/oauth/authorize", :http_method=>:post, :access_token_path=>"/oauth/access_token", :oauth_version=>"1.0"}, @key="[THE KEY].apps.googleusercontent.com">>, {}, [{"GData-Version"=>"2.0"}] Mar 31 10:44:40,sandbox,info,user,workbooks_app[23521]: 0.025020 +0.001068 OAUTH REQUEST2: #<Net::HTTP::Get GET> Mar 31 10:44:40,sandbox,info,user,workbooks_app[23521]: 0.515249 +0.490229 OAUTH RESPONSE: #<Net::HTTPUnauthorized 401 Unknown authorization header readbody=true> I have augmented oauth/consumer.rb with some logging: # Creates, signs and performs an http request. # It's recommended to use the OAuth::Token classes to set this up correctly. # request_options take precedence over consumer-wide options when signing # a request. # arguments are POST and PUT bodies (a Hash, string-encoded parameters, or # absent), followed by additional HTTP headers. # # @consumer.request(:get, '/people', @token, { :scheme => :query_string }) # @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' }) # def request(http_method, path, token = nil, request_options = {}, *arguments) if path !~ /^\// @http = create_http(path) _uri = URI.parse(path) path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}" end RAILS_DEFAULT_LOGGER.info("OAUTH REQUEST: #{http_method}, #{path}, #{token.inspect}, #{request_options.inspect}, #{arguments.inspect}") # override the request with your own, this is useful for file uploads which Net::HTTP does not do req = create_signed_request(http_method, path, token, request_options, *arguments) return nil if block_given? and yield(req) == :done RAILS_DEFAULT_LOGGER.info("OAUTH REQUEST2: #{req.inspect}") rsp = http.request(req) RAILS_DEFAULT_LOGGER.info("OAUTH RESPONSE: #{rsp.inspect}") # check for an error reported by the Problem Reporting extension # (http://wiki.oauth.net/ProblemReporting) # note: a 200 may actually be an error; check for an oauth_problem key to be sure if !(headers = rsp.to_hash["www-authenticate"]).nil? && (h = headers.select { |hdr| hdr =~ /^OAuth / }).any? && h.first =~ /oauth_problem/ RAILS_DEFAULT_LOGGER.info("Header: #{h.first}") # TODO doesn't handle broken responses from api.login.yahoo.com # remove debug code when done params = OAuth::Helper.parse_header(h.first) RAILS_DEFAULT_LOGGER.info("Params: #{params.inspect}") RAILS_DEFAULT_LOGGER.info("Body: #{rsp.body}") raise OAuth::Problem.new(params.delete("oauth_problem"), rsp, params) end rsp end I have an application manifest like this: <ApplicationManifest xmlns="http://schemas.google.com/ApplicationManifest/2009"> <Name>Workbooks CRM</Name> <Description>Workbooks CRM - a complete solution to track your customers from prospect-to-cash</Description> <!-- Administrators and users will be sent to this URL for application support --> <Support> <Link rel="support" href="http://www.workbooks.com/forum?from=google-apps"/> <Link rel="setup" href="https://sandbox/google_signup?domain=${DOMAIN_NAME}"/> </Support> <!-- Declare our OpenID realm so our app is white listed --> <Extension id="realm" type="openIdRealm"> <Url>https://sandbox</Url> </Extension> <!-- Configures extensions available for the free edition of the application. --> <Edition id="free"> <Name>Free</Name> <Extension ref="navLink"/> <Extension ref="realm"/> </Edition> <!-- Show this link in Google's universal navigation for all users --> <Extension id="navLink" type="link"> <Name>Workbooks</Name> <Url>https://sandbox/openid_login?openid_identifier=${DOMAIN_NAME}</Url> <Scope ref="calendarAPI"/> <Scope ref="contactAPI"/> <Scope ref="docsAPI"/> <Scope ref="provisioningAPI"/> </Extension> <!-- Need access to a variety of APIs --> <Scope id="calendarAPI"> <Url>https://www.google.com/calendar/feeds/</Url> <Reason>Workbooks creates appointments in your Google Calendar.</Reason> </Scope> <Scope id="contactAPI"> <Url>https://www.google.com/m8/feeds/</Url> <Reason>Workbooks creates contacts in your Google address book.</Reason> </Scope> <Scope id="docsAPI"> <Url>https://docs.google.com/feeds/</Url> <Reason>Workbooks creates documents such as quotations and invoices in Google Docs.</Reason> </Scope> <Scope id="provisioningAPI"> <Url>https://apps-apis.google.com/a/feeds/user/#readonly</Url> <Reason>Workbooks uses this to make it easier to give your users access to the system.</Reason> </Scope> </ApplicationManifest> My (Ruby, using ruby-openid) test code looks like this: def complete completed_consumer = complete_openid if completed_consumer.nil? flash[:error] = "Please check your #{human_credential_type}.".t redirect_to :action => 'new', :controller => 'sessions' return end ax = OpenID::AX::FetchResponse.from_success_response(completed_consumer,true) email = ax && ax.get_single(ax_attributes['email']) logger.debug("Email address from AX: #{email.inspect}") session[:openid] = completed_consumer.identity_url user_openid = Global::UserOpenid.find(:first, :conditions => {:openid => session[:openid]}) if user_openid.nil? flash[:notice] = "Your #{human_credential_type} is valid but it is not yet associated with a Workbooks user.\nLogin now with your Workbooks username and password to link these accounts and you will be automatically logged in future.".t redirect_to :action => 'new', :controller => 'sessions', :username => email return end ... RAILS_DEFAULT_LOGGER.info("GCAL-REQ #{current_user.login_name}") docs = fetch_from_google_docs(current_user.login_name) RAILS_DEFAULT_LOGGER.info("GDOCS #{docs.inspect}") cal = fetch_from_google_cal(current_user.login_name) RAILS_DEFAULT_LOGGER.info("GCAL #{cal.inspect}") ... def fetch_from_google_docs(email_addr) # Scope: <Url>https://docs.google.com/feeds/</Url> oauth_consumer = OAuth::Consumer.new(Workbooks::GOOGLE_APPS_CONSUMER_KEY, Workbooks::GOOGLE_APPS_CONSUMER_SECRET) access_token = OAuth::AccessToken.new(oauth_consumer) client = Google::Client.new(access_token, '2.0'); feed = client.get("https://docs.google.com/feeds/documents/private/full", { 'xoauth_requestor_id' => email_addr, 'showfolders' => 'true', }) raise "Unable to query DOCS feed" if feed.nil? entries = [] feed.elements.each('//entry') do |entry| entries << { :title => entry.elements["title"].text, } end logger.info("DOCS #{entries.inspect}") end def fetch_from_google_cal(email_addr) # Scope: <Url>https://www.google.com/calendar/feeds/</Url> oauth_consumer = OAuth::Consumer.new(Workbooks::GOOGLE_APPS_CONSUMER_KEY, Workbooks::GOOGLE_APPS_CONSUMER_SECRET) access_token = OAuth::AccessToken.new(oauth_consumer) client = Google::Client.new(access_token, '2.0'); feed = client.get('https://www.google.com/calendar/feeds/default/private/full', { 'xoauth_requestor_id' => email_addr, 'orderby' => 'starttime', 'singleevents' => 'true', 'sortorder' => 'a', 'start-min' => Time.now.strftime('%Y-%m-%dT%H:%M:%S') } ) raise "Unable to query calendar feed" if feed.nil? entries = [] feed.elements.each('//entry') do |entry| entries << { :title => entry.elements["title"].text, :content => entry.elements["content"].text, :start_time => entry.elements["gd:when"].attribute("startTime").value, :end_time => entry.elements["gd:when"].attribute("endTime").value, } end logger.info("CALENDAR #{entries.inspect}") end -- You received this message because you are subscribed to the Google Groups "Google Apps Domain Information and Management APIs" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-apps-mgmt-apis?hl=en.
