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.

Reply via email to