Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
package com.google.auth.oauth2;

import static com.google.auth.oauth2.OAuth2Utils.JSON_FACTORY;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpHeaders;
Expand Down Expand Up @@ -140,7 +139,6 @@ private ExternalAccountAuthorizedUserCredentials(Builder builder) {
*/
public static ExternalAccountAuthorizedUserCredentials fromStream(InputStream credentialsStream)
throws IOException {
checkNotNull(credentialsStream);
return fromStream(credentialsStream, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
}

Expand All @@ -162,17 +160,24 @@ public static ExternalAccountAuthorizedUserCredentials fromStream(InputStream cr
*/
public static ExternalAccountAuthorizedUserCredentials fromStream(
InputStream credentialsStream, HttpTransportFactory transportFactory) throws IOException {
checkNotNull(credentialsStream);
checkNotNull(transportFactory);

JsonObjectParser parser = new JsonObjectParser(OAuth2Utils.JSON_FACTORY);
GenericJson fileContents =
parser.parseAndClose(credentialsStream, StandardCharsets.UTF_8, GenericJson.class);
try {
return fromJson(fileContents, transportFactory);
} catch (ClassCastException | IllegalArgumentException e) {
throw new CredentialFormatException("Invalid input stream provided.", e);
Preconditions.checkNotNull(transportFactory);
GenericJson fileContents = parseJsonInputStream(credentialsStream);
String fileType = extractFromJson(fileContents, "type");
if (fileType.equals(
GoogleCredentialsInfo.EXTERNAL_ACCOUNT_AUTHORIZED_USER_CREDENTIALS.getFileType())) {
try {
return fromJson(fileContents, transportFactory);
} catch (ClassCastException | IllegalArgumentException e) {
throw new CredentialFormatException("Invalid input stream provided.", e);
}
}

throw new IOException(
String.format(
"Error reading credentials from stream, 'type' value '%s' not recognized."
+ " Expecting '%s'.",
fileType,
GoogleCredentialsInfo.EXTERNAL_ACCOUNT_AUTHORIZED_USER_CREDENTIALS.getFileType()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,17 @@

import com.google.api.client.http.HttpHeaders;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.util.Data;
import com.google.auth.RequestMetadataCallback;
import com.google.auth.http.HttpTransportFactory;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.math.BigDecimal;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -387,17 +386,22 @@ public static ExternalAccountCredentials fromStream(InputStream credentialsStrea
*/
public static ExternalAccountCredentials fromStream(
InputStream credentialsStream, HttpTransportFactory transportFactory) throws IOException {
checkNotNull(credentialsStream);
checkNotNull(transportFactory);

JsonObjectParser parser = new JsonObjectParser(OAuth2Utils.JSON_FACTORY);
GenericJson fileContents =
parser.parseAndClose(credentialsStream, StandardCharsets.UTF_8, GenericJson.class);
try {
return fromJson(fileContents, transportFactory);
} catch (ClassCastException | IllegalArgumentException e) {
throw new CredentialFormatException("An invalid input stream was provided.", e);
Preconditions.checkNotNull(transportFactory);
GenericJson fileContents = parseJsonInputStream(credentialsStream);
String fileType = extractFromJson(fileContents, "type");
if (fileType.equals(GoogleCredentialsInfo.EXTERNAL_ACCOUNT_CREDENTIALS.getFileType())) {
try {
return fromJson(fileContents, transportFactory);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zhumin8 Talked with Sai and ExternalAccountCredential.fromStream() branching off to creating the subtypes is fine to keep.

} catch (ClassCastException | IllegalArgumentException e) {
throw new CredentialFormatException("An invalid input stream was provided.", e);
}
}

throw new IOException(
String.format(
"Error reading credentials from stream, 'type' value '%s' not recognized."
+ " Expecting '%s'.",
fileType, GoogleCredentialsInfo.EXTERNAL_ACCOUNT_CREDENTIALS.getFileType()));
}

/**
Expand All @@ -417,9 +421,6 @@ public static ExternalAccountCredentials fromStream(
@SuppressWarnings("unchecked")
static ExternalAccountCredentials fromJson(
Map<String, Object> json, HttpTransportFactory transportFactory) {
checkNotNull(json);
checkNotNull(transportFactory);

String audience = (String) json.get("audience");
String subjectTokenType = (String) json.get("subject_token_type");
String tokenUrl = (String) json.get("token_url");
Expand Down
53 changes: 53 additions & 0 deletions oauth2_http/java/com/google/auth/oauth2/GdchCredentials.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.UrlEncodedContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.json.webtoken.JsonWebSignature;
Expand Down Expand Up @@ -99,6 +100,58 @@ public class GdchCredentials extends GoogleCredentials {
this.name = GoogleCredentialsInfo.GDCH_CREDENTIALS.getCredentialName();
}

/**
* Returns credentials defined by a GdchCredentials key file in JSON format from the Google
* Developers Console.
*
* <p>Important: If you accept a credential configuration (credential JSON/File/Stream) from an
* external source for authentication to Google Cloud Platform, you must validate it before
* providing it to any Google API or library. Providing an unvalidated credential configuration to
* Google APIs can compromise the security of your systems and data. For more information, refer
* to {@see <a
* href="https://cloud.google.com/docs/authentication/external/externally-sourced-credentials">documentation</a>}.
*
* @param credentialsStream the stream with the credential definition.
* @return the credential defined by the credentialsStream.
* @throws IOException if the credential cannot be created from the stream.
*/
public static GdchCredentials fromStream(InputStream credentialsStream) throws IOException {
return fromStream(credentialsStream, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
}

/**
* Returns credentials defined by a GdchCredentials key file in JSON format from the Google
* Developers Console.
*
* <p>Important: If you accept a credential configuration (credential JSON/File/Stream) from an
* external source for authentication to Google Cloud Platform, you must validate it before
* providing it to any Google API or library. Providing an unvalidated credential configuration to
* Google APIs can compromise the security of your systems and data. For more information, refer
* to {@see <a
* href="https://cloud.google.com/docs/authentication/external/externally-sourced-credentials">documentation</a>}.
*
* @param credentialsStream the stream with the credential definition.
* @param transportFactory HTTP transport factory, creates the transport used to get access
* tokens.
* @return the credential defined by the credentialsStream.
* @throws IOException if the credential cannot be created from the stream.
*/
public static GdchCredentials fromStream(
InputStream credentialsStream, HttpTransportFactory transportFactory) throws IOException {
Preconditions.checkNotNull(transportFactory);
GenericJson fileContents = parseJsonInputStream(credentialsStream);
String fileType = extractFromJson(fileContents, "type");
if (fileType.equals(GoogleCredentialsInfo.GDCH_CREDENTIALS.getFileType())) {
return fromJson(fileContents, transportFactory);
}

throw new IOException(
String.format(
"Error reading credentials from stream, 'type' value '%s' not recognized."
+ " Expecting '%s'.",
fileType, GoogleCredentialsInfo.GDCH_CREDENTIALS.getFileType()));
}

/**
* Create GDCH service account credentials defined by JSON.
*
Expand Down
32 changes: 24 additions & 8 deletions oauth2_http/java/com/google/auth/oauth2/GoogleCredentials.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
package com.google.auth.oauth2;

import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.util.Preconditions;
import com.google.api.core.ObsoleteApi;
Expand Down Expand Up @@ -235,6 +234,29 @@ public static GoogleCredentials fromStream(InputStream credentialsStream) throws
return fromStream(credentialsStream, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
}

/**
* Parses the Credential InputStream into JSON for each credential subclass to consume. The
* Credential InputStream must be non-null and valid.
*/
static GenericJson parseJsonInputStream(InputStream credentialsStream) throws IOException {
Preconditions.checkNotNull(credentialsStream);
JsonObjectParser parser = new JsonObjectParser(OAuth2Utils.JSON_FACTORY);
return parser.parseAndClose(credentialsStream, StandardCharsets.UTF_8, GenericJson.class);
}

/**
* Internal helper method to try and extract a field from the json stream and throw an exception
* if it doesn't exist.
*/
static String extractFromJson(Map<String, Object> json, String field) throws IOException {
String fileType = (String) json.get(field);
if (fileType == null) {
throw new IOException(
"Error reading credentials from stream, '" + field + "' field not specified.");
}
return fileType;
}

/**
* This method is obsolete because of a potential security risk. Use the credential specific load
* method instead
Expand Down Expand Up @@ -276,14 +298,8 @@ public static GoogleCredentials fromStream(InputStream credentialsStream) throws
"This method is obsolete because of a potential security risk. Use the credential specific load method instead")
public static GoogleCredentials fromStream(
InputStream credentialsStream, HttpTransportFactory transportFactory) throws IOException {
Preconditions.checkNotNull(credentialsStream);
Preconditions.checkNotNull(transportFactory);

JsonFactory jsonFactory = OAuth2Utils.JSON_FACTORY;
JsonObjectParser parser = new JsonObjectParser(jsonFactory);
GenericJson fileContents =
parser.parseAndClose(credentialsStream, StandardCharsets.UTF_8, GenericJson.class);

GenericJson fileContents = parseJsonInputStream(credentialsStream);
String fileType = (String) fileContents.get("type");
if (fileType == null) {
throw new IOException("Error reading credentials from stream, 'type' field not specified.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import com.google.api.client.http.HttpResponse;
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.CredentialTypeForMetrics;
Expand All @@ -55,6 +56,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.text.DateFormat;
import java.text.ParseException;
Expand Down Expand Up @@ -360,6 +362,59 @@ public byte[] sign(byte[] toSign) {
}
}

/**
* Returns credentials defined by a ImpersonatedCredential key file in JSON format from the Google
* Developers Console.
*
* <p>Important: If you accept a credential configuration (credential JSON/File/Stream) from an
* external source for authentication to Google Cloud Platform, you must validate it before
* providing it to any Google API or library. Providing an unvalidated credential configuration to
* Google APIs can compromise the security of your systems and data. For more information, refer
* to {@see <a
* href="https://cloud.google.com/docs/authentication/external/externally-sourced-credentials">documentation</a>}.
*
* @param credentialsStream the stream with the credential definition.
* @return the credential defined by the credentialsStream.
* @throws IOException if the credential cannot be created from the stream.
*/
public static ImpersonatedCredentials fromStream(InputStream credentialsStream)
throws IOException {
return fromStream(credentialsStream, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
}

/**
* Returns credentials defined by a ImpersonatedCredential key file in JSON format from the Google
* Developers Console.
*
* <p>Important: If you accept a credential configuration (credential JSON/File/Stream) from an
* external source for authentication to Google Cloud Platform, you must validate it before
* providing it to any Google API or library. Providing an unvalidated credential configuration to
* Google APIs can compromise the security of your systems and data. For more information, refer
* to {@see <a
* href="https://cloud.google.com/docs/authentication/external/externally-sourced-credentials">documentation</a>}.
*
* @param credentialsStream the stream with the credential definition.
* @param transportFactory HTTP transport factory, creates the transport used to get access
* tokens.
* @return the credential defined by the credentialsStream.
* @throws IOException if the credential cannot be created from the stream.
*/
public static ImpersonatedCredentials fromStream(
InputStream credentialsStream, HttpTransportFactory transportFactory) throws IOException {
Preconditions.checkNotNull(transportFactory);
GenericJson fileContents = parseJsonInputStream(credentialsStream);
String fileType = extractFromJson(fileContents, "type");
if (fileType.equals(GoogleCredentialsInfo.IMPERSONATED_CREDENTIALS.getFileType())) {
return fromJson(fileContents, transportFactory);
}

throw new IOException(
String.format(
"Error reading credentials from stream, 'type' value '%s' not recognized."
+ " Expecting '%s'.",
fileType, GoogleCredentialsInfo.IMPERSONATED_CREDENTIALS.getFileType()));
}

/**
* Returns impersonation account credentials defined by JSON using the format generated by gCloud.
* The source credentials in the JSON should be either user account credentials or service account
Expand All @@ -380,7 +435,6 @@ public byte[] sign(byte[] toSign) {
@SuppressWarnings("unchecked")
static ImpersonatedCredentials fromJson(
Map<String, Object> json, HttpTransportFactory transportFactory) throws IOException {

checkNotNull(json);
checkNotNull(transportFactory);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpResponseException;
import com.google.api.client.http.UrlEncodedContent;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.json.webtoken.JsonWebSignature;
Expand Down Expand Up @@ -485,14 +486,18 @@ public static ServiceAccountCredentials fromStream(InputStream credentialsStream
*/
public static ServiceAccountCredentials fromStream(
InputStream credentialsStream, HttpTransportFactory transportFactory) throws IOException {
ServiceAccountCredentials credential =
(ServiceAccountCredentials)
GoogleCredentials.fromStream(credentialsStream, transportFactory);
if (credential == null) {
throw new IOException(
"Error reading credentials from stream, ServiceAccountCredentials type is not recognized.");
Preconditions.checkNotNull(transportFactory);
GenericJson fileContents = parseJsonInputStream(credentialsStream);
String fileType = extractFromJson(fileContents, "type");
if (fileType.equals(GoogleCredentialsInfo.SERVICE_ACCOUNT_CREDENTIALS.getFileType())) {
return fromJson(fileContents, transportFactory);
}
return credential;

throw new IOException(
String.format(
"Error reading credentials from stream, 'type' value '%s' not recognized."
+ " Expecting '%s'.",
fileType, GoogleCredentialsInfo.SERVICE_ACCOUNT_CREDENTIALS.getFileType()));
}

/** Returns whether the scopes are empty, meaning createScoped must be called before use. */
Expand Down
16 changes: 3 additions & 13 deletions oauth2_http/java/com/google/auth/oauth2/UserCredentials.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import com.google.api.client.http.HttpResponseException;
import com.google.api.client.http.UrlEncodedContent;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.util.GenericData;
import com.google.api.client.util.Preconditions;
Expand Down Expand Up @@ -173,19 +172,10 @@ public static UserCredentials fromStream(InputStream credentialsStream) throws I
*/
public static UserCredentials fromStream(
InputStream credentialsStream, HttpTransportFactory transportFactory) throws IOException {
Preconditions.checkNotNull(credentialsStream);
Preconditions.checkNotNull(transportFactory);

JsonFactory jsonFactory = JSON_FACTORY;
JsonObjectParser parser = new JsonObjectParser(jsonFactory);
GenericJson fileContents =
parser.parseAndClose(credentialsStream, StandardCharsets.UTF_8, GenericJson.class);

String fileType = (String) fileContents.get("type");
if (fileType == null) {
throw new IOException("Error reading credentials from stream, 'type' field not specified.");
}
if (GoogleCredentialsInfo.USER_CREDENTIALS.getFileType().equals(fileType)) {
GenericJson fileContents = parseJsonInputStream(credentialsStream);
String fileType = extractFromJson(fileContents, "type");
if (fileType.equals(GoogleCredentialsInfo.USER_CREDENTIALS.getFileType())) {
return fromJson(fileContents, transportFactory);
}
throw new IOException(
Expand Down
Loading