diff --git a/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java b/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java index 6e79f9f43..4fa7d8cc4 100644 --- a/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java +++ b/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java @@ -42,6 +42,7 @@ import com.google.api.client.util.GenericData; import com.google.auth.ServiceAccountSigner; import com.google.auth.http.HttpTransportFactory; +import com.google.common.annotations.Beta; import com.google.common.base.MoreObjects; import java.io.IOException; import java.io.InputStream; @@ -50,6 +51,7 @@ import java.net.UnknownHostException; import java.util.Collections; import java.util.Date; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.logging.Level; @@ -62,7 +64,8 @@ * *

These credentials use the IAM API to sign data. See {@link #sign(byte[])} for more details. */ -public class ComputeEngineCredentials extends GoogleCredentials implements ServiceAccountSigner { +public class ComputeEngineCredentials extends GoogleCredentials + implements ServiceAccountSigner, IdTokenProvider { private static final Logger LOGGER = Logger.getLogger(ComputeEngineCredentials.class.getName()); @@ -157,6 +160,45 @@ public AccessToken refreshAccessToken() throws IOException { return new AccessToken(accessToken, new Date(expiresAtMilliseconds)); } + /** + * Returns a Google ID Token from the metadata server on ComputeEngine + * + * @param targetAudience the aud: field the IdToken should include + * @param options list of Credential specific options for the token. For example, an IDToken for a + * ComputeEngineCredential could have the full formatted claims returned if + * IdTokenProvider.Option.FORMAT_FULL) is provided as a list option. Valid option values are: + *
+ * IdTokenProvider.Option.FORMAT_FULL
+ * IdTokenProvider.Option.LICENSES_TRUE
+ * If no options are set, the defaults are "&format=standard&licenses=false" + * @throws IOException if the attempt to get an IdToken failed + * @return IdToken object which includes the raw id_token, JsonWebSignature + */ + @Beta + @Override + public IdToken idTokenWithAudience(String targetAudience, List options) + throws IOException { + GenericUrl documentUrl = new GenericUrl(getIdentityDocumentUrl()); + if (options != null) { + if (options.contains(IdTokenProvider.Option.FORMAT_FULL)) { + documentUrl.set("format", "full"); + } + if (options.contains(IdTokenProvider.Option.LICENSES_TRUE)) { + // license will only get returned if format is also full + documentUrl.set("format", "full"); + documentUrl.set("license", "TRUE"); + } + } + documentUrl.set("audience", targetAudience); + HttpResponse response = getMetadataResponse(documentUrl.toString()); + InputStream content = response.getContent(); + if (content == null) { + throw new IOException("Empty content from metadata token server request."); + } + String rawToken = response.parseAsString(); + return IdToken.create(rawToken); + } + private HttpResponse getMetadataResponse(String url) throws IOException { GenericUrl genericUrl = new GenericUrl(url); HttpRequest request = @@ -243,6 +285,11 @@ public static String getServiceAccountsUrl() { + "/computeMetadata/v1/instance/service-accounts/?recursive=true"; } + public static String getIdentityDocumentUrl() { + return getMetadataServerUrl(DefaultCredentialsProvider.DEFAULT) + + "/computeMetadata/v1/instance/service-accounts/default/identity"; + } + @Override public int hashCode() { return Objects.hash(transportFactoryClassName); diff --git a/oauth2_http/java/com/google/auth/oauth2/IamUtils.java b/oauth2_http/java/com/google/auth/oauth2/IamUtils.java index d4675c963..58ba91f97 100644 --- a/oauth2_http/java/com/google/auth/oauth2/IamUtils.java +++ b/oauth2_http/java/com/google/auth/oauth2/IamUtils.java @@ -37,6 +37,7 @@ import com.google.api.client.http.HttpStatusCodes; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.json.JsonHttpContent; +import com.google.api.client.json.GenericJson; import com.google.api.client.json.JsonObjectParser; import com.google.api.client.util.GenericData; import com.google.auth.Credentials; @@ -54,6 +55,8 @@ class IamUtils { private static final String SIGN_BLOB_URL_FORMAT = "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s:signBlob"; + private static final String ID_TOKEN_URL_FORMAT = + "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s:generateIdToken"; private static final String PARSE_ERROR_MESSAGE = "Error parsing error message response. "; private static final String PARSE_ERROR_SIGNATURE = "Error parsing signature response. "; @@ -138,4 +141,74 @@ private static String getSignature( GenericData responseData = response.parseAs(GenericData.class); return OAuth2Utils.validateString(responseData, "signedBlob", PARSE_ERROR_SIGNATURE); } + + /** + * Returns an IdToken issued to the serviceAccount with a specified targetAudience + * + * @param serviceAccountEmail the email address for the service account to get an ID Token for + * @param credentials credentials required for making the IAM call + * @param transport transport used for building the HTTP request + * @param targetAudience the audience the issued ID token should include + * @param additionalFields additional fields to send in the IAM call + * @return IdToken issed to the serviceAccount + * @throws IOException if the IdToken cannot be issued. + * @see + * https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateIdToken + */ + static IdToken getIdToken( + String serviceAccountEmail, + Credentials credentials, + HttpTransport transport, + String targetAudience, + boolean includeEmail, + Map additionalFields) + throws IOException { + + String idTokenUrl = String.format(ID_TOKEN_URL_FORMAT, serviceAccountEmail); + GenericUrl genericUrl = new GenericUrl(idTokenUrl); + + GenericData idTokenRequest = new GenericData(); + idTokenRequest.set("audience", targetAudience); + idTokenRequest.set("includeEmail", includeEmail); + for (Map.Entry entry : additionalFields.entrySet()) { + idTokenRequest.set(entry.getKey(), entry.getValue()); + } + JsonHttpContent idTokenContent = new JsonHttpContent(OAuth2Utils.JSON_FACTORY, idTokenRequest); + + HttpCredentialsAdapter adapter = new HttpCredentialsAdapter(credentials); + HttpRequest request = + transport.createRequestFactory(adapter).buildPostRequest(genericUrl, idTokenContent); + + JsonObjectParser parser = new JsonObjectParser(OAuth2Utils.JSON_FACTORY); + request.setParser(parser); + request.setThrowExceptionOnExecuteError(false); + + HttpResponse response = request.execute(); + int statusCode = response.getStatusCode(); + if (statusCode >= 400 && statusCode < HttpStatusCodes.STATUS_CODE_SERVER_ERROR) { + GenericData responseError = response.parseAs(GenericData.class); + Map error = + OAuth2Utils.validateMap(responseError, "error", PARSE_ERROR_MESSAGE); + String errorMessage = OAuth2Utils.validateString(error, "message", PARSE_ERROR_MESSAGE); + throw new IOException( + String.format("Error code %s trying to getIDToken: %s", statusCode, errorMessage)); + } + if (statusCode != HttpStatusCodes.STATUS_CODE_OK) { + throw new IOException( + String.format( + "Unexpected Error code %s trying to getIDToken: %s", + statusCode, response.parseAsString())); + } + InputStream content = response.getContent(); + if (content == null) { + // Throw explicitly here on empty content to avoid NullPointerException from + // parseAs call. + // Mock transports will have success code with empty content by default. + throw new IOException("Empty content from generateIDToken server request."); + } + + GenericJson responseData = response.parseAs(GenericJson.class); + String rawToken = OAuth2Utils.validateString(responseData, "token", PARSE_ERROR_MESSAGE); + return IdToken.create(rawToken); + } } diff --git a/oauth2_http/java/com/google/auth/oauth2/IdToken.java b/oauth2_http/java/com/google/auth/oauth2/IdToken.java new file mode 100644 index 000000000..4d7e88eea --- /dev/null +++ b/oauth2_http/java/com/google/auth/oauth2/IdToken.java @@ -0,0 +1,125 @@ +/* + * Copyright 2019, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.google.auth.oauth2; + +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.webtoken.JsonWebSignature; +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Date; +import java.util.Objects; + +/** Represents a temporary IdToken and its JsonWebSignature object */ +@Beta +public class IdToken extends AccessToken implements Serializable { + + private static final long serialVersionUID = -8514239465808977353L; + + private transient JsonWebSignature jsonWebSignature; + + /** + * @param tokenValue String representation of the ID token. + * @param jsonWebSignature JsonWebSignature as object + */ + private IdToken(String tokenValue, JsonWebSignature jsonWebSignature) { + super(tokenValue, new Date(jsonWebSignature.getPayload().getExpirationTimeSeconds() * 1000)); + this.jsonWebSignature = jsonWebSignature; + } + + /** + * Creates an IdToken given the encoded Json Web Signature. + * + * @param tokenValue String representation of the ID token. + * @return returns com.google.auth.oauth2.IdToken + */ + public static IdToken create(String tokenValue) throws IOException { + return create(tokenValue, OAuth2Utils.JSON_FACTORY); + } + + /** + * Creates an IdToken given the encoded Json Web Signature and JSON Factory + * + * @param jsonFactory JsonFactory to use for parsing the provided token. + * @param tokenValue String representation of the ID token. + * @return returns com.google.auth.oauth2.IdToken + */ + public static IdToken create(String tokenValue, JsonFactory jsonFactory) throws IOException { + return new IdToken(tokenValue, JsonWebSignature.parse(jsonFactory, tokenValue)); + } + + /** + * The JsonWebSignature as object + * + * @return returns com.google.api.client.json.webtoken.JsonWebSignature + */ + public JsonWebSignature getJsonWebSignature() { + return jsonWebSignature; + } + + @Override + public int hashCode() { + return Objects.hash( + super.getTokenValue(), jsonWebSignature.getHeader(), jsonWebSignature.getPayload()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("tokenValue", super.getTokenValue()) + .add("JsonWebSignature", jsonWebSignature) + .toString(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IdToken)) { + return false; + } + IdToken other = (IdToken) obj; + return Objects.equals(super.getTokenValue(), other.getTokenValue()) + && Objects.equals(this.jsonWebSignature.getHeader(), other.jsonWebSignature.getHeader()) + && Objects.equals(this.jsonWebSignature.getPayload(), other.jsonWebSignature.getPayload()); + } + + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.writeObject(this.getTokenValue()); + } + + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + String signature = (String) ois.readObject(); + this.jsonWebSignature = JsonWebSignature.parse(OAuth2Utils.JSON_FACTORY, signature); + } +} diff --git a/oauth2_http/java/com/google/auth/oauth2/IdTokenCredentials.java b/oauth2_http/java/com/google/auth/oauth2/IdTokenCredentials.java new file mode 100644 index 000000000..6b827c5f9 --- /dev/null +++ b/oauth2_http/java/com/google/auth/oauth2/IdTokenCredentials.java @@ -0,0 +1,198 @@ +/* + * Copyright 2019, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.google.auth.oauth2; + +import com.google.api.client.util.Preconditions; +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; +import java.io.IOException; +import java.util.List; +import java.util.Objects; + +/** + * IdTokenCredentials provides a Google Issued OpenIdConnect token.
+ * Use an ID token to access services that require presenting an ID token for authentication such as + * Cloud Functions or Cloud Run.
+ * The following Credential subclasses support IDTokens: ServiceAccountCredentials, + * ComputeEngineCredentials, ImpersonatedCredentials. + * + *

For more information see
+ * Usage:
+ * + *

+ * String credPath = "/path/to/svc_account.json";
+ * String targetAudience = "https://example.com";
+ *
+ * // For Application Default Credentials (as ServiceAccountCredentials)
+ * // export GOOGLE_APPLICATION_CREDENTIALS=/path/to/svc.json
+ * GoogleCredentials adcCreds = GoogleCredentials.getApplicationDefault();
+ * if (!adcCreds instanceof IdTokenProvider) {
+ *   // handle error message
+ * }
+ *
+ * IdTokenCredentials tokenCredential = IdTokenCredentials.newBuilder()
+ *     .setIdTokenProvider(adcCreds)
+ *     .setTargetAudience(targetAudience).build();
+ *
+ * // for ServiceAccountCredentials
+ * ServiceAccountCredentials saCreds = ServiceAccountCredentials.fromStream(new FileInputStream(credPath));
+ * saCreds = (ServiceAccountCredentials) saCreds.createScoped(Arrays.asList("https://www.googleapis.com/auth/iam"));
+ * IdTokenCredentials tokenCredential = IdTokenCredentials.newBuilder()
+ *     .setIdTokenProvider(saCreds)
+ *     .setTargetAudience(targetAudience).build();
+ *
+ * // for ComputeEngineCredentials
+ * ComputeEngineCredentials caCreds = ComputeEngineCredentials.create();
+ * IdTokenCredentials tokenCredential = IdTokenCredentials.newBuilder()
+ *     .setIdTokenProvider(caCreds)
+ *     .setTargetAudience(targetAudience)
+ *     .setOptions(Arrays.asList(ComputeEngineCredentials.ID_TOKEN_FORMAT_FULL))
+ *     .build();
+ *
+ * // for ImpersonatedCredentials
+ * ImpersonatedCredentials imCreds = ImpersonatedCredentials.create(saCreds,
+ *     "impersonated-account@project.iam.gserviceaccount.com", null,
+ *     Arrays.asList("https://www.googleapis.com/auth/cloud-platform"), 300);
+ * IdTokenCredentials tokenCredential = IdTokenCredentials.newBuilder()
+ *     .setIdTokenProvider(imCreds)
+ *     .setTargetAudience(targetAudience)
+ *     .setOptions(Arrays.asList(ImpersonatedCredentials.INCLUDE_EMAIL))
+ *     .build();
+ *
+ * // Use the IdTokenCredential in an authorized transport
+ * GenericUrl genericUrl = new GenericUrl("https://example.com");
+ * HttpCredentialsAdapter adapter = new HttpCredentialsAdapter(tokenCredential);
+ * HttpTransport transport = new NetHttpTransport();
+ * HttpRequest request = transport.createRequestFactory(adapter).buildGetRequest(genericUrl);
+ * HttpResponse response = request.execute();
+ *
+ * // Print the token, expiration and the audience
+ * System.out.println(tokenCredential.getIdToken().getTokenValue());
+ * System.out.println(tokenCredential.getIdToken().getJsonWebSignature().getPayload().getAudienceAsList());
+ * System.out.println(tokenCredential.getIdToken().getJsonWebSignature().getPayload().getExpirationTimeSeconds());
+ * 
+ */ +@Beta +public class IdTokenCredentials extends OAuth2Credentials { + + private static final long serialVersionUID = -2133257318957588431L; + + private IdTokenProvider idTokenProvider; + private String targetAudience; + private List options; + + private IdTokenCredentials(Builder builder) { + this.idTokenProvider = Preconditions.checkNotNull(builder.getIdTokenProvider()); + this.targetAudience = Preconditions.checkNotNull(builder.getTargetAudience()); + this.options = builder.getOptions(); + } + + @Override + public AccessToken refreshAccessToken() throws IOException { + return this.idTokenProvider.idTokenWithAudience(targetAudience, options); + } + + public IdToken getIdToken() { + return (IdToken) getAccessToken(); + } + + @Override + public int hashCode() { + return Objects.hash(options, targetAudience); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).toString(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IdTokenCredentials)) { + return false; + } + IdTokenCredentials other = (IdTokenCredentials) obj; + return Objects.equals(this.idTokenProvider, other.idTokenProvider) + && Objects.equals(this.targetAudience, other.targetAudience); + } + + public Builder toBuilder() { + return new Builder() + .setIdTokenProvider(this.idTokenProvider) + .setTargetAudience(this.targetAudience) + .setOptions(this.options); + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static class Builder extends OAuth2Credentials.Builder { + + private IdTokenProvider idTokenProvider; + private String targetAudience; + private List options; + + protected Builder() {} + + public Builder setIdTokenProvider(IdTokenProvider idTokenProvider) { + this.idTokenProvider = idTokenProvider; + return this; + } + + public IdTokenProvider getIdTokenProvider() { + return this.idTokenProvider; + } + + public Builder setTargetAudience(String targetAudience) { + this.targetAudience = targetAudience; + return this; + } + + public String getTargetAudience() { + return this.targetAudience; + } + + public Builder setOptions(List options) { + this.options = options; + return this; + } + + public List getOptions() { + return this.options; + } + + public IdTokenCredentials build() { + return new IdTokenCredentials(this); + } + } +} diff --git a/oauth2_http/java/com/google/auth/oauth2/IdTokenProvider.java b/oauth2_http/java/com/google/auth/oauth2/IdTokenProvider.java new file mode 100644 index 000000000..fe3b0f667 --- /dev/null +++ b/oauth2_http/java/com/google/auth/oauth2/IdTokenProvider.java @@ -0,0 +1,86 @@ +/* + * Copyright 2019, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.google.auth.oauth2; + +import com.google.common.annotations.Beta; +import java.io.IOException; +import java.util.List; + +/** Interface for an Google OIDC token provider. This type represents a google issued OIDC token. */ +@Beta +public interface IdTokenProvider { + + /** + * Enum of various credential-specific options to apply to the token. + * + *

ComputeEngineCredentials + * + *

    + *
  • FORMAT_FULL + *
  • LICENSES_TRUE + *
+ * + *
+ * ImpersonatedCredential + * + *
    + *
  • INCLUDE_EMAIL + *
+ */ + public enum Option { + FORMAT_FULL("formatFull"), + LICENSES_TRUE("licensesTrue"), + INCLUDE_EMAIL("includeEmail"); + + private String option; + + private Option(String option) { + this.option = option; + } + + public String getOption() { + return option; + } + } + + /** + * Returns a Google OpenID Token with the provided audience field. + * + * @param targetAudience List of audiences the issued ID Token should be valid for. targetAudience + * accepts a single string value (multiple audiences are not supported) + * @param options List of Credential specific options for for the token. For example, an IDToken + * for a ComputeEngineCredential can return platform specific claims if + * "ComputeEngineCredentials.ID_TOKEN_FORMAT_FULL" is provided as a list option. + * @return IdToken object which includes the raw id_token, expiration and audience. + */ + IdToken idTokenWithAudience(String targetAudience, List