This page explains how to use Credential Access Boundaries to create an OAuth 2.0 access token with downscoped Cloud Storage permissions.
The process for creating a token with downscoped permissions includes the following steps:
- Grant the appropriate IAM roles to a user or service account.
- Define a Credential Access Boundary that sets an upper bound on the permissions that are available to the user or service account.
- Create an OAuth 2.0 access token for the user or service account.
- Exchange the OAuth 2.0 access token for a new token that respects the Credential Access Boundary.
You can then use the new downscoped OAuth 2.0 access token to authenticate requests to Cloud Storage.
Before you begin
Before you use Credential Access Boundaries, make sure you meet the following requirements:
You need to downscope permissions only for Cloud Storage, not for other Google Cloud services.
If you need to downscope permissions for additional Google Cloud services, you can create multiple service accounts and grant a different set of roles to each service account.
You can use OAuth 2.0 access tokens for authentication. Other types of short-lived credentials don't support Credential Access Boundaries.
Also, you must enable the required APIs:
-
Enable the IAM and Security Token Service APIs.
Grant IAM roles
A Credential Access Boundary sets an upper bound on the available permissions for a resource. It can subtract permissions from a principal, but it can't add permissions that the principal does not already have.
As a result, you must also grant roles to the principal that provide the permissions they need, either on a Cloud Storage bucket or on a higher-level resource, such as the project.
For example, suppose you need to create a downscoped short-lived credential that allows a service account to create objects in a bucket:
- At a minimum, you must grant a role to the service account that includes the
storage.objects.create
permission, such as the Storage Object Creator role (roles/storage.objectCreator
). The Credential Access Boundary must also include this permission. - You can also grant a role that includes more permissions, such as the Storage
Object Admin role (
roles/storage.objectAdmin
). The service account can use only the permissions that appear in both the role grant and the Credential Access Boundary.
To learn about predefined roles for Cloud Storage, see Cloud Storage roles.
Define the Credential Access Boundary
A Credential Access Boundary is an object that contains a list of access boundary rules. The rules are made up of parameters that specify the upper bound of the permissions that are available to the user or service account. To define a Credential Access Boundary, create a JSON object that lists the access boundary rules and their parameters.
The following is an example of a Credential Access Boundary:
{
"accessBoundary": {
"accessBoundaryRules": [
{
"availablePermissions": [
"inRole:ROLE_ID"
],
"availableResource": "//storage.googleapis.com/projects/_/buckets/BUCKET_NAME"
"availabilityCondition": {
"expression" : "CONDITION"
}
]
}
}
Replace the following:
ROLE_ID
: The ID of a predefined or custom role that defines the upper bound on the available permissions for the resource. For example,roles/storage.objectViewer
. To specify multiple roles, add a new line with aninRole:
prefix followed by the role ID. Only the permissions in the specified roles will be available.BUCKET_NAME
: The name of the Cloud Storage bucket that the rule applies to.CONDITION
: Optional. A condition expression that specifies the Cloud Storage objects where permissions are available. For example, the following condition makes permissions available for objects whose name starts withcustomer-a
:resource.name.startsWith('projects/_/buckets/example-bucket/objects/customer-a')
To learn more about how to create and customize credential access boundaries, see Components of a Credential Access Boundary.
For examples of potential use cases for Credential Access Boundaries, see Examples of Credential Access Boundaries.
Create an OAuth 2.0 access token
Before you create a downscoped short-lived credential, you must create a normal
OAuth 2.0 access token. You can then exchange the normal credential for a
downscoped credential. When you create the access token, use the OAuth 2.0 scope
https://www.googleapis.com/auth/cloud-platform
.
To create an access token for a service account, you can complete the server-to-server OAuth 2.0 flow, or you can use the Service Account Credentials API to generate an OAuth 2.0 access token.
To create an access token for a user, see Obtaining OAuth 2.0 access tokens. You can also use the OAuth 2.0 Playground to create an access token for your own Google Account.
Exchange the OAuth 2.0 access token
After you create an OAuth 2.0 access token, you can exchange the access token for a downscoped token that respects the Credential Access Boundary. This process typically involves a token broker and a token consumer:
The token broker is responsible for defining the Credential Access Boundary and exchanging an access token for a downscoped token.
The token broker can use a supported authentication library to exchange access tokens automatically, or it can call the Security Token Service to exchange tokens manually.
The token consumer requests a downscoped access token from the token broker, then uses the downscoped access token to perform another action.
The token consumer can use a supported authentication library to automatically refresh access tokens before they expire. Alternatively, it can refresh tokens manually, or it can allow tokens to expire without refreshing them.
There are two ways to exchange the access token for a downscoped token:
Client-side token exchange (recommended): Clients obtain cryptographic materials from the Security Token Service API server. The cryptographic materials allow clients to generate downscoped tokens with varying Credential Access Boundary rules independently on the client side for a set duration (for example, 1 hour). This approach reduces latency and improves efficiency, especially for clients requiring frequent Credential Access Boundary rule updates. It's also more efficient for applications that need to generate many unique downscoped tokens. This is the recommended approach because it provides better performance, scalability, and future feature compatibility.
Server-side token exchange: Clients request a new downscoped token from the Security Token Service API server whenever a Credential Access Boundary rule changes. This approach is straightforward but requires a round trip to the Security Token Service API server for each downscoped token request. This approach is recommended only for customers who require a client library that doesn't support client-side token exchange, due to the round trip to the Security Token Service API for each downscoped token request.
Client-side token exchange
If you create the token broker and token consumer with the following language, you can use Google's authentication library to exchange and refresh tokens automatically through the client-side approach.
Java
For Java, you can exchange and refresh tokens automatically with version 1.32.1
or later of the
com.google.auth:google-auth-library-cab-token-generator
artifact.
To check your artifact version, run the following Maven command in your application directory:
mvn dependency:list -DincludeArtifactIds=google-auth-library-cab-token-generator
The following example shows how a token broker can generate downscoped tokens:
The following example shows how a token consumer can use a refresh handler to automatically obtain and refresh downscoped tokens:
Server-side token exchange
This section describes the following methods that you can use to exchange tokens through the service side approach:
Exchange and refresh the access token automatically using server-side approach
If you create the token broker and token consumer with one of the following languages, you can use Google's authentication library to exchange and refresh tokens automatically using the server-side token generation approach:
Go
For Go, you can exchange and refresh tokens automatically with version
v0.0.0-20210819190943-2bc19b11175f or later of the
golang.org/x/oauth2
package.
To check your package version, run the following command in your application directory:
go list -m golang.org/x/oauth2
The following example shows how a token broker can generate downscoped tokens:
The following example shows how a token consumer can use a refresh handler to automatically obtain and refresh downscoped tokens:
Java
For Java, you can exchange and refresh tokens automatically with version 1.1.0
or later of the
com.google.auth:google-auth-library-oauth2-http
artifact.
To check your artifact version, run the following Maven command in your application directory:
mvn dependency:list -DincludeArtifactIds=google-auth-library-oauth2-http
The following example shows how a token broker can generate downscoped tokens:
The following example shows how a token consumer can use a refresh handler to automatically obtain and refresh downscoped tokens:
Node.js
For Node.js, you can exchange and refresh tokens automatically with version
7.9.0 or later of the google-auth-library
package.
To check your package version, run the following command in your application directory:
npm list google-auth-library
The following example shows how a token broker can generate downscoped tokens:
The following example shows how a token consumer can provide a refresh handler that automatically obtains and refreshes downscoped tokens:
Python
For Python, you can exchange and refresh tokens automatically with version 2.0.0
or later of the google-auth
package.
To check your package version, run the following command in the environment where the package is installed:
pip show google-auth
The following example shows how a token broker can generate downscoped tokens:
The following example shows how a token consumer can provide a refresh handler that automatically obtains and refreshes downscoped tokens:
Exchange and refresh the access token manually
A token broker can use the Security Token Service API to exchange an access token for a downscoped access token. It can then provide the downscoped token to a token consumer.
To exchange the access token, use the following HTTP method and URL:
POST https://sts.googleapis.com/v1/token
Set the Content-Type
header in the request to
application/x-www-form-urlencoded
. Include the following fields in the request
body:
Fields | |
---|---|
grant_type |
Use the value
|
options |
A JSON-formatted Credential Access Boundary, encoded with percent encoding. |
requested_token_type |
Use the value
|
subject_token |
The OAuth 2.0 access token that you want to exchange. |
subject_token_type |
Use the value
|
The response is a JSON object that contains the following fields:
Fields | |
---|---|
access_token |
A downscoped OAuth 2.0 access token that respects the Credential Access Boundary. |
expires_in |
The amount of time until the downscoped token expires, in seconds. This field is included only if the original access token represents a service account. When this field is not included, the downscoped token has the same time to expire as the original access token. |
issued_token_type |
Contains the value
|
token_type |
Contains the value |
For example, if a JSON-formatted Credential Access Boundary is stored in the file
./access-boundary.json
, you can use the following
curl
command to exchange the access token. Replace
original-token
with the original access token:
curl -H "Content-Type:application/x-www-form-urlencoded" \ -X POST \ https://sts.googleapis.com/v1/token \ -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token_type=urn:ietf:params:oauth:token-type:access_token&requested_token_type=urn:ietf:params:oauth:token-type:access_token&subject_token=original-token" \ --data-urlencode "options=$(cat ./access-boundary.json)"
The response is similar to the following example:
{
"access_token": "ya29.dr.AbCDeFg-123456...",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600
}
When a token consumer requests a downscoped token, the token broker responds with both the downscoped token and the number of seconds until it expires. If the token has expired, the server rejects the request. To refresh the downscoped token, the consumer can request a downscoped token from the broker before the existing token expires.
What's next
- Learn about access control for Cloud Storage.
- Create a short-lived service account credential.
- Create an OAuth 2.0 access token for a service account with one of the following methods:
- Create an OAuth 2.0 access token for a user.
- See the permissions in each predefined role.
- Learn about custom roles.