Multi-Tenant Google Cloud Platform B2B SaaS Applications How-to

Authentication and Authorization

Ferris Argyle
Google Cloud - Community
6 min readJun 18, 2018

--

Overview

This article addresses the authentication and authorization challenges described in the Concepts article.

Both authentication and authorization are intrinsically bound up with identity.

There are a number of identity mechanisms in Google Cloud Platform, all of which can serve as principals for authorization policy:

  • Cloud Identities represent user identities, and can also be used for authentication.
  • Google Groups represent groupings of user identities. There are several types of Google Groups; we’ll focus on Admin Console Groups.
  • Service accounts are primarily used to represent applications, typically via OAuth-based authentication.
  • Google domains; we’ll review these in more depth in the How to: Isolation article.
  • Signed URLs are time-bound tokens for authorizing Google Cloud Storage uploads and downloads.

Authentication

Cloud Identities

As described earlier, Cloud Identities are the primary user authentication mechanism. Identities can be federated via SAML and OpenID Connect; this means that your customers can either federate their users directly with Google Cloud Platform, or you can federate your customers’ users on their behalf if they already have a federation relationship with you, for instance via AD FS.

The Google Cloud SAML Service Provider supports a single SAML IDP, so to support multiple customer tenants you’ll need to take one of the following approaches:

  • Use a SAML broker such as Apigee or Auth0.
  • Allocate a domain or sub-domain per customer if you’re providing your customer with end-user management capabilities (see the Isolation article for more on this).

Note that Google Cloud federation does not support dynamic SAML (ie. creation of identities at authentication); the users’ Cloud Identities must be provisioned in advance using one of the supported mechanisms:

In some cases you may want to provide a self-service user provisioning portal to your customers’s users. The following Python code snippet demonstrate how to leverage the Admin SDK Directory API for this use case:

# List users on the domainfrom googleapiclient import discovery
from google.oauth2 import service_account
SCOPES = ("https://www.googleapis.com/auth/admin.directory.group","https://www.googleapis.com/auth/admin.directory.user")
SUBJECT = '[SERVICE_USER@DOMAIN]'
target_key_file = '[YOUR_KEY_FILE.JSON]'
credentials = service_account.Credentials.from_service_account_file(target_key_file)
scoped_credentials = credentials.with_scopes(SCOPES)
delegated_credentials = scoped_credentials.with_subject(SUBJECT)
admin_client = discovery.build('admin', 'directory_v1', credentials=delegated_credentials)
req = admin_client.users().list(domain='[CUSTOMER_DOMAIN]')
resp = req.execute()
users = resp['users']
print users

For a more full-fledged implementation, see this sample application.

Google Sign-In

For those customers for whom an SSO-based solution isn’t appropriate, Google Sign-In provides a simple way to leverage Google’s authentication infrastructure for your SaaS applications. It provides the following password controls:

  • length and strength enforcement
  • rotation enforcement
  • re-use prevention

It also provides strong phishing protection with 2FA enforcement and API-based password reset (sample Python snippet below)

# Reset passwordfrom googleapiclient import discovery
from google.oauth2 import service_account
domain = '[YOUR_DOMAIN]'
delegated_admin = '[YOUR_SERVICE_ADMIN]' # id only (ie. without @domain)
key_file = '[SERVICE_ACCOUNT_JSON_KEY_FILE]'
user = ''.join(['YOUR_USER','@',domain])
password = 'NEW_PASSWORD'
scope = ("https://www.googleapis.com/auth/admin.directory.user",)
subject = ''.join([delegated_admin,'@',domain]);
delegated_credentials = service_account.Credentials.from_service_account_file(key_file, scopes=scope, subject=subject)
authorized_service = discovery.build('admin', 'directory_v1', credentials=delegated_credentials)
req = authorized_service.users().update(userKey=user,body={"password":password, "changePasswordAtNextLogin":True})
resp = req.execute()
print resp

Service Accounts

Service accounts are primarily used to represent applications; this provides a natural mechanism for authorizing your customers via OAuth.

A typical pattern is for either you or your customer to issue a service account, and for the other party to authorize it as a principal. This has several advantages:

  • If your customer issues the service account, they can be wholly responsible for managing access to it so you as a SaaS provider don’t need provide your customer with end-user management or federation capabilities.
  • It supports authorization for joint ventures in which data access is a) time-bound and b) commercial entity rather than user-bound.
  • Google Cloud Platform logging and auditing will reflect the service account, simplifying billing and charge-back.

This pattern also has some limitations:

  • It doesn’t provide a mechanism for authenticating end users
  • Service accounts must be granted and managed at the required level of authorization, billing and charge-back, which can result in service account proliferation and attendant lifecycle management challenges. The proliferation can be mitigated through the Service Account Token Creator role, which enables impersonation of service accounts to create OAuth2 access tokens and sign blobs or JWTs. You can leverage this capability to enable users to mint tokens as required, or to map customer service accounts to your application service accounts.

Service accounts are of course also integral to communication between services of your own SaaS micro-service application (see this article for a sample App Engine implementation).

Authorization

One of the key authorization challenges is in mapping the customers’ user policy to your GCP applications user policy.

There are a couple of approaches here; which one you choose will depend largely on use case.

  • SAML claims: your customer is wholly responsible for managing which users are permitted to access which services and data; you may map these to Admin Console Groups (see below) or service accounts to leverage Cloud IAM’s native support for these.
  • Admin Console Groups or service accounts: you provide a management console through which your customers define user authorization.

SAML Claims

Google Cloud Platform IAM does not support SAML claims directly, so you’ll need to interpret claims in your application or a SAML broker such as Apigee or Auth0.

3rd party SAML AuthN flow for Google Accounts

Apigee supports policy injection for a number of out-of-the-box security policies as well as scripting custom policies (eg. users with the customer=MySecureCustomer attribute in their SAML assertions are allowed to access to APIs with ?customer=MySecureCustomer arguments)

This sample SAML IDP/Service Provider provides decoded response information and is a great testing platform.

Admin Console Groups

Admin Console Groups are managed by the Cloud Identity domain administrators (rather than arbitrary end users), and can be provisioned and configured via API (ignore the legacy G Suite branding; this applies to Cloud Identity as well).

There are two ways to leverage Groups for authorization

  • Grant Cloud Platform IAM roles to Google Groups.
  • Your application can leverage the Admin SDK Groups API (ignore the legacy G Suite branding; this applies to Cloud Identity as well) to discover which users are members of a group, as well as which groups a member belongs to, and the immediate parent groups of a group in a nested group hierarchy (set the userKey to the user or group whose parents you wish to find).

Note that your application only has visibility into Admin Console Groups which belong to its domain, unless additional authority has been explicitly granted through Domain Wide Delegation (see the Isolation article for more on this); ie. your application generally can’t find the parent groups on another domain of which a user on the primary domain is a member.

User Impersonation

You can combine service accounts with Cloud Identities to enable a service account to act on behalf of users on a domain, ie. impersonate the user, via domain-wide delegation of authority (ignore the legacy G Suite branding; this applies to Cloud Identity APIs as well). This is very helpful to address a couple of use cases:

  • Assets (eg. GCS objects) created by your application need to be ACL’d to the customer’s end user. You could manage this manually yourself via the IAM APIs, but user impersonation takes care of it automagically.
  • Your application needs to expose the appropriate assets to your customer’s users based on the their identity. Managing this manually would require that you essentially build an ACL layer within your application; user impersonation makes it happen automagically.

See this article to learn more about this approach and its limitations, as well as for code samples.

What’s next

Try out the APIs in the API Explorer.

Deploy a self-service user provisioning portal.

Configure a sample SAML IDP/Service Provider.

Read the following guides to understand how to implement:

Acknowledgements

Many thanks to Mike McDonald for being a sounding board and advocate for multi-tenant auth.

--

--

Ferris Argyle
Google Cloud - Community

These are my personal writings; the views expressed in these pages are mine alone and not those of my employer, Google.