Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Returning an issuer claim on request errors #656

Merged
merged 9 commits into from May 17, 2021
Expand Up @@ -609,7 +609,10 @@ public boolean isRequired(HttpResponse response) {
response = request.execute();
} catch (IOException e) {
throw new IOException(
String.format("Error getting access token for service account: %s", e.getMessage()), e);
String.format(
"Error getting access token for service account: %s, iss: %s",
e.getMessage(), getIssuer()),
e);
}

GenericData responseData = response.parseAs(GenericData.class);
Expand Down Expand Up @@ -648,7 +651,16 @@ public IdToken idTokenWithAudience(String targetAudience, List<Option> options)
HttpRequestFactory requestFactory = transportFactory.create().createRequestFactory();
HttpRequest request = requestFactory.buildPostRequest(new GenericUrl(tokenServerUri), content);
request.setParser(new JsonObjectParser(jsonFactory));
HttpResponse response = request.execute();
HttpResponse response;
try {
response = request.execute();
} catch (IOException e) {
throw new IOException(
String.format(
"Error getting id token for service account: %s, iss: %s",
e.getMessage(), getIssuer()),
e);
}

GenericData responseData = response.parseAs(GenericData.class);
String rawToken = OAuth2Utils.validateString(responseData, "id_token", PARSE_ERROR_PREFIX);
Expand Down Expand Up @@ -755,6 +767,10 @@ public final URI getTokenServerUri() {
return tokenServerUri;
}

private String getIssuer() {
return this.clientEmail;
}

@VisibleForTesting
int getLifetime() {
return lifetime;
Expand Down Expand Up @@ -787,7 +803,7 @@ public byte[] sign(byte[] toSign) {
@Override
public JwtCredentials jwtWithClaims(JwtClaims newClaims) {
JwtClaims.Builder claimsBuilder =
JwtClaims.newBuilder().setIssuer(clientEmail).setSubject(clientEmail);
JwtClaims.newBuilder().setIssuer(getIssuer()).setSubject(clientEmail);
return JwtCredentials.newBuilder()
.setPrivateKey(privateKey)
.setPrivateKeyId(privateKeyId)
Expand Down Expand Up @@ -862,7 +878,7 @@ String createAssertion(JsonFactory jsonFactory, long currentTime, String audienc
header.setKeyId(privateKeyId);

JsonWebToken.Payload payload = new JsonWebToken.Payload();
payload.setIssuer(clientEmail);
payload.setIssuer(getIssuer());
payload.setIssuedAtTimeSeconds(currentTime / 1000);
payload.setExpirationTimeSeconds(currentTime / 1000 + this.lifetime);
payload.setSubject(serviceAccountUser);
Expand Down Expand Up @@ -898,7 +914,7 @@ String createAssertionForIdToken(
header.setKeyId(privateKeyId);

JsonWebToken.Payload payload = new JsonWebToken.Payload();
payload.setIssuer(clientEmail);
payload.setIssuer(getIssuer());
payload.setIssuedAtTimeSeconds(currentTime / 1000);
payload.setExpirationTimeSeconds(currentTime / 1000 + this.lifetime);
payload.setSubject(serviceAccountUser);
Expand Down
Expand Up @@ -1189,6 +1189,37 @@ public void fromStream_noClientEmail_throws() throws IOException {
testFromStreamException(serviceAccountStream, "client_email");
}

@Test
public void getIdTokenWithAudience_badEmailError_issClaimTraced() throws IOException {
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
MockTokenServerTransport transport = transportFactory.transport;
transport.setError(new IOException("Invalid grant: Account not found"));
ServiceAccountCredentials credentials =
ServiceAccountCredentials.fromPkcs8(
CLIENT_ID,
CLIENT_EMAIL,
PRIVATE_KEY_PKCS8,
PRIVATE_KEY_ID,
SCOPES,
transportFactory,
null);

String targetAudience = "https://bar";
IdTokenCredentials tokenCredential =
IdTokenCredentials.newBuilder()
.setIdTokenProvider(credentials)
.setTargetAudience(targetAudience)
.build();

String expectedErrorMessage = String.format("iss: %s", CLIENT_EMAIL);

try {
tokenCredential.refresh();
} catch (IOException expected) {
assertTrue(expected.getMessage().contains(expectedErrorMessage));
}
}

@Test
public void fromStream_noPrivateKey_throws() throws IOException {
InputStream serviceAccountStream =
Expand Down