Google Calendar API – Impersonating Users

devops, Google API, ruby

WIU is in the process of moving from Zimbra to Google Apps for Education. I’ve been working on the code to migrate mail and calendar data and had a really hard time getting calendar impersonation working so I could create calendars and import events for people.

Much of my confusion was because most of the published information and samples you can find on the Internet reference the previous Google API (v0.8). The newer API (v0.9) works completely differently. If I had simply followed the published instructions about using the “Default Credentials”, and put that together with the instructions about making an authorized API call, this would have gone much easier.

To hopefully help someone else out there who may be struggling with this, here is what worked for me.

Create a Service Account

  1. Create a service account in the Google Developer Console and save the JSON file. You are going to want to deploy the JSON file securely with your application.
  2. Make sure your service account has access to the correct APIs. It should probably have Domain-wide-Delegation set and you must enable the scope of access for your client ID. Check out this page about delegating domain-wide authority.
  3. Create a .env file in the root of your application and store the GOOGLE_APPLICATION_CREDENTIALS path there. This is where the JSON file from step one will reside in your application.
# ~/.env

You can use the dotenv gem, or some other method, to retrieve the GOOGLE_APPLICATION_CREDENTIALS in your app. See below…

Create a Google::ServiceAccount Class in Your Application

Something like this…

# ~/lib/google.rb
require 'googleauth'

class Google::ServiceAccount

  def initialize(mail: nil, scopes: )
    @mail = mail
    @scopes = scopes

  def user_auth
    auth = Google::Auth.get_application_default(@scopes)
    user = auth.dup
    user.sub = @mail

  attr_reader :mail

  def scopes
    Array(@scopes).join(" ")

Main Program

In your main program or another class you can do something like this. In my example here I am just getting a list of existing calendars in the individual’s Google account.

# ~/main.rb
require 'dotenv'
require 'google/apis/calendar_v3'

require_relative 'lib/google'

APPLICATION_NAME = 'Zimbra Migration'.freeze

def gcal_list(email)
  service =
  service.client_options.application_name = APPLICATION_NAME
  service.authorization = user_client(email)

  gcals = {}
  page_token = nil
    result = service.list_calendar_lists(page_token: page_token)
    result.items.each do |e|
      gcals[e.summary] =
    if result.next_page_token != page_token
      page_token = result.next_page_token
      page_token = nil
  end while !page_token.nil?

def user_client(email)
    mail: email,
    scopes: [Google::Apis::CalendarV3::AUTH_CALENDAR]


puts gcal_list('')

Congratulations! You’ve just impersonated an account using the Google Calendar API.

Leave a Reply

Your email address will not be published. Required fields are marked *