I'm trying use a service account with google's api to work with classroom data with the goal of synchronizing our web service for schools with the google classroom data.
I have delegated domain wide authority to the service account and have activated the Google Classroom API. I have downloaded the json Key file used below. I have added https://www.googleapis.com/auth/classroom.courses to the scope of the service account.
My test code in app/models/g_service.rb:
class GService
require 'google/apis/classroom_v1'
def get_course
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: File.open('/Users/jose/Downloads/skt1-301603-4a655caa8963.json'),
scope: [ Google::Apis::ClassroomV1::AUTH_CLASSROOM_COURSES ]
)
authorizer.fetch_access_token!
service = Google::Apis::ClassroomV1::ClassroomService.new
service.authorization = authorizer
puts "\n service\n #{service.inspect}"
response = service.get_course( '99999' )
puts "\n response \n#{response.inspect}"
end
end
The results in the console are:
>> GService.new.get_course
service
#<Google::Apis::ClassroomV1::ClassroomService:0x007fe1cff98338 @root_url="https://classroom.googleapis.com/", @base_path="", @upload_path="upload/", @batch_path="batch", @client_options=#<struct Google::Apis::ClientOptions application_name="unknown", application_version="0.0.0", proxy_url=nil, open_timeout_sec=nil, read_timeout_sec=nil, send_timeout_sec=nil, log_http_requests=false, transparent_gzip_decompression=true>, @request_options=#<struct Google::Apis::RequestOptions authorization=#<Google::Auth::ServiceAccountCredentials:0x0xxxxxxx @project_id="sssssssss", @authorization_uri=nil, @token_credential_uri=#<Addressable::URI:0x000000000 URI:https://www.googleapis.com/oauth2/v4/token>, @client_id=nil, @client_secret=nil, @code=nil, @expires_at=2021-01-13 20:56:46 -0800, @issued_at=2021-01-13 19:56:47 -0800, @issuer="xxxxxxx.iam.gserviceaccount.com", @password=nil, @principal=nil, @redirect_uri=nil, @scope=["https://www.googleapis.com/auth/classroom.courses"], @state=nil, @username=nil, @access_type=:offline, @expiry=60, @audience="https://www.googleapis.com/oauth2/v4/token", @signing_key=#<OpenSSL::PKey::RSA:0xxxxxxxxx>, @extension_parameters={}, @additional_parameters={}, @connection_info=nil, @grant_type=nil, @refresh_token=nil, @access_token="-------------------------------------------------------------------------------------->, retries=0, header=nil, normalize_unicode=false, skip_serialization=false, skip_deserialization=false, api_format_version=nil, use_opencensus=true>>
Google::Apis::ClientError: forbidden: The caller does not have permission
It appears everything is working fine until the service.get_course('99999') call. I've tested this call using the https://developers.google.com/classroom/reference/rest/v1/courses/get online tool and it works fine.
I've poured over the documentation but have been unable to resolve this. Can anybody please let me know what I am missing?
I'm running rails 3.2 and ruby 2.1
Considering the error you're getting, I think you are not impersonating any account.
The purpose of domain-wide delegation is that the service account can impersonate a regular account in your domain, but in order to do that, you have to specify which account you want to impersonate. Otherwise, you are calling the service account by itself, and it doesn't matter that you've enabled domain-wide delegation for it.
In the Ruby library, you can specify that using the :sub
parameter, as shown in the section Preparing to make an authorized API call at the library docs:
authorizer.sub = "<email-address-to-impersonate>"
Make sure the account you impersonate has access to this course, otherwise you'll get the same error.