We have encountered an issue during development of an application for the new Google Apps Marketplace using Oauth2.0 for SSO.
As a part of our application we are using the Google Calendar V3 API, on offline mode - meaning we are required to keep a 'refresh_token' for our clients.
In order to get the 'refresh_token' during the first OAuth2.0 authentication we need to configure the google_oauth2.0 provider (using omniauth-google-oauth2 gem) such as:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, CONFIG[:app_id], CONFIG[:app_secret], {
access_type: 'offline',
prompt: 'consent' }
end
Without specifying the access_type: 'offline, and prompt:'consent' we do not receive the refresh_token, and can not use the calendar API properly.
However, specifying the prompt: 'consent' attribute, leads to an authorization popup, which negates the whole SSO idea - where only the domain admin gets prompted during installation.
Is it possible to get the refresh_token without prompting the domain users? How does new Google Apps Marketplace support offline access without prompting of end-users?
It looks like a service account for offline access was what I'm looking for.
Inspired by this thread: Trouble with Google Apps API and Service Accounts in Ruby
I found out that I can create a service account on the apps marketplace configuration. Project -> APIs & Auth -> Credentials -> Create New Client Id -> Choose Service account. And in my code use Signet to provide domain level authorization for the end-users:
key = Google::APIClient::PKCS12.load_key('privatekey.p12', 'notasecret')
client = Google::APIClient.new
client.authorization = Signet::OAuth2::Client.new(
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:audience => 'https://accounts.google.com/o/oauth2/token',
:scope => 'https://www.googleapis.com/auth/calendar',
:issuer => '<email-address-of-service-account>@developer.gserviceaccount.com',
:signing_key => key,
:person => email)
client.authorization.fetch_access_token!
Not only does this allowed me to authenticate without prompting the end-user at any phase during the process - but I don't require the refresh_token anymore, and I can execute the API calls with domain level authorizations. The person option allows me to specify which end-user I'm using the API call for.