Security Impact of GCP session length on OAuth clients

Once you’ve signed in on google.com, the Cloud Console, or any other Google site, your browser session remains valid for multiple days. Not being prompted to sign in over and over again is convenient and at least in typical consumer scenarios, the risk that comes along with keeping the session is limited.

Things can look different in a corporate scenario where users might have access to sensitive data. Keeping sessions alive for 14 days (which is the default) might seem a little risky and might not be in line with an enterprise’s idea of security. G Suite Business and Cloud Identity Premium therefore allow you to change the default session length to a different period such as 8 hours. This setting applies to all Google services, not only GCP.

Recently, Google introduced another way to control session lifetime by allowing you to control the session length for Cloud Console and gcloud sessions.

This feature might look a bit redundant at first considering that you can already adjust the default session length – but there are two important differences:

  • While changing the default session length is a feature that is only available in the G Suite Business and Cloud Identity Premium SKUs, setting the GCP session length works for all SKUs, including Cloud Identity Free.
  • The setting not only affects browser clients, but tools such as gcloud and certain OAuth clients.

The last item is interesting and worth exploring a bit more.

Browser sessions and OAuth clients

When you first use an OAuth client – be it gcloud or some other tool, you have to authorize the client. The works by popping open a browser window (which picks up your existing Google session if present) and then prompting you for your consent. Once authorized, the client can fetch a refresh token which allows it to stay authorized.

The key point to realize is that while the browser session is used to kickstart the OAuth authorization, the lifetimes of the browser session and the refresh token are now disconnected: The browser session might time out after a few hours or days or you might explicitly sign out – but this does not affect the refresh token. The client can keep using the refresh token until one of the following events occur:

  • The user has revoked your app’s access.
  • The refresh token has not been used for six months.
  • The user changed passwords and the refresh token contains Gmail scopes.
  • The user account has exceeded a maximum number of granted (live) refresh tokens.

This explains why merely adjusting the default session length does not affect OAuth clients.

Reacting to expiring sessions

Setting a custom session length for Cloud Console and gcloud sessions not only affects the length of the browser session for the Cloud Console, but also the lifetime of OAuth refresh tokens: If an OAuth client obtained a token for a Google Cloud scope, then the validity of the refresh token is limited to the configured GCP session length. The list of scopes for which this applies includes .../auth/cloud-platform, as well as the more specific scopes such as .../auth/bigquery.readonly. The GCP session length can be set to a value as short as 1 hour.

When a browser session times out, it is pretty clear what should happen next: The user is redirected to the sign-on screen, is prompted for username and password (and hopefully a second factor), and is then sent back to the original URL that he attempted to access. But how should an OAuth client behave in case of a timeout?

As it turns out, the answer depends on the kind of OAuth client. Google distinguishes between first-party clients and third-party clients. First-party clients are administrative tools that Google provides – the most prominent examples are gcloud and gsutil. Third-party clients include any OAuth client that you register in the Cloud Console.

First-party clients

When you use a first-party client such as gcloud and the GCP session timeout expires, you are prompted to re-authenticate. Depending on the configuration that you applied in the Admin Console, you are either prompted to re-enter your username and password or to touch your USB key:

Password prompt

When you look under the hood by observing the network communication of gcloud, you can see that the tool uses a new set of APIs (red) to negotiate the re-authentication before it fetches a new token (green):

Trace

Notably, the prompt and logic to communicate with with those new APIs is implemented by gcloud itself.

When you use OAuth, you usually want to prevent that individual clients ever get to see the user’s credentials. Having a tool like gcloud implement a re-authentication prompt deviates from this idea for the sake of a better user experience – and it should therefore come as no surprise that the new API that gcloud is using is private and can only be used by first-party tools.

Third-party clients

When a third-party client attempts to refresh a token after the GCP session has expired, the OAuth call fails with the following error:

{
  "error": "invalid_grant",
  "error_description": "reauth related error (invalid_rapt)",
  "error_subtype": "invalid_rapt"
}

This error is almost indistinguishable from the error a client receives when the authorization for the client was revoked on myaccount.google.com or when the refresh token expired for a different reason. The only difference is the subtype invalid_rapt which indicates that the actual reason was that the GCP session length has expired.

By responding with a standard error code, Google remains fully OAuth compliant which is an obvious advantage. Also, any well-behaved OAuth client should already be able to deal with invalid_grant errors by re-initiating the OAuth authorization flow.

In practice, many OAuth clients might not be as well-behaved however – it used to be a rare event that a refresh token expired while a user was using the client. And it is certainly not a very common scenario that a user revokes an authorization on myaccount.google.com while still using the client. Chances therefore are that a good percentage of clients either do not handle invalid_grant errors at all, or at least not in a very graceful manner.

Preparing for custom GCP session lengths

Configuring a custom GCP session length means that an event that used to be quite rare turns into an everyday event and OAuth clients need to be prepared to receive invalid_grant errors more often.

As an administrator, it is best to test how commonly used OAuth clients react to expiring sessions before configuring a custom session length. An easy way to do this is to revoke the authorization on myaccount.google.com while running the application and see how it reacts.

As a developer of an application that uses any of the Google Cloud OAuth scopes, you should make sure that the application handles inavlid_token errors properly: If refreshing a token fails, the application should react by reinitiating an OAuth authorization flow. Ideally, the application retries the failed operation once the reauthorization has been completed successfully.

Granted, gracefully handling invalid_grant errors can be challenging, especially in GUI applications. Handling the error requires interacting with the user – but the error could happen at any time and the GUI might not always be in a state where such user interaction is possible.

Any opinions expressed on this blog are Johannes' own. Refer to the respective vendor’s product documentation for authoritative information.
« Back to home