ruby-on-railsoauth-2.0google-directory-apigoogle-api-ruby-clientgoogle-provisioning-api

Migrate from Google Provisioning API to Directory API in Rails Application


I am currently maintaing a Rails application that relies on the Google Provisioning API. Unfortunately, this API is being phased out soon and replaced by the Admin SDK and Directory APIs.

It uses a username and password combination to login to the API and create Google Groups. Here is an example:

gapps = ProvisioningApi.new(ENV[GAPPS_USER], ENV[GAPPS_PASSWORD])

group = gapps.create_group(listserv_group.group_id, [listserv_group.name, listserv_group.desc, "blah"])

users = User.all(:joins => :user_listserv_groups,
                 :conditions => "user_listserv_groups.listserv_group_id = #{county.listserv_group.id}")
users.each do |u|
  if !params[:excluded_members].include?(u.id.to_s)
    gapps.add_member_to_group(u.email, listserv_group.group_id)
  end
end

The new API uses the OAuth protocol which does have a Client Credentials Flow that allows simply using a username/password combination, but according to the book Getting Started with OAuth 2.0:

While the preceding paragraphs describe some potential use cases for this flow, these providers (Google and Amazon) have not yet implemented the Client Credentials flow in OAuth 2.0.

In short, what would be the most straight-forward way to update code like the above in order to make use of the newer API? Thanks in advance. Any help would be appreciated.


Solution

  • You should set up a service account and use that method for access. You set up the account in your API console under APIs & auth | Credentials. Make sure to create/download a p12 key credential pair (currently it defaults to downloading a JSON set for you).

    Take a look at the service account sample code for details on how to do that.

    Basically, you do this:

    @client = Google::APIClient.new(
      :application_name => application_name,
      :application_version => application_version)
    
    ## Load our credentials for the service account
    key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, key_secret)
    
    @client.authorization = Signet::OAuth2::Client.new(
      :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
      :audience => 'https://accounts.google.com/o/oauth2/token',
                # Replace this with the scope for the Directory api
      :scope => 'https://www.googleapis.com/auth/analytics.readonly',
      :issuer => service_account_email,
      :signing_key => key)
    
    ## Request a token for our service account
    @client.authorization.fetch_access_token!
    

    In addition you may need to authorize the service account to impersonate users within your domain or set up API access. Both of these are done in the Admin panel for your Google Apps domain. This allows you to access resources that have been authorized for other users on the account by passing a :person parameter to the client constructor.

    @client.authorization = Signet::OAuth2::Client.new(
      :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
      :audience => 'https://accounts.google.com/o/oauth2/token',
                # Replace this with the scope for the Directory api
      :scope => 'https://www.googleapis.com/auth/analytics.readonly',
      :issuer => service_account_email,
      :signing_key => key,
      :person => 'another_user@example.com')