public async Task FetchesOidcToken() { // A little bit after the tokens returned from OidcTokenFakes were issued. var clock = new MockClock(new DateTime(2020, 5, 13, 15, 0, 0, 0, DateTimeKind.Utc)); var messageHandler = new OidcTokenResponseSuccessMessageHandler(); var initializer = new ServiceAccountCredential.Initializer("MyId", "http://will.be.ignored") { Clock = clock, ProjectId = "a_project_id", HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var credential = new ServiceAccountCredential(initializer.FromPrivateKey(PrivateKey)); // The fake Oidc server returns valid tokens (expired in the real world for safety) // but with a set audience that lets us know if the token was refreshed or not. var oidcToken = await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("will.be.ignored")); var signedToken = SignedToken <Header, Payload> .FromSignedToken(await oidcToken.GetAccessTokenAsync()); Assert.Equal("https://first_call.test", signedToken.Payload.Audience); // Move the clock some but not enough that the token expires. clock.UtcNow = clock.UtcNow.AddMinutes(20); signedToken = SignedToken <Header, Payload> .FromSignedToken(await oidcToken.GetAccessTokenAsync()); Assert.Equal("https://first_call.test", signedToken.Payload.Audience); // Only the first call should have resulted in a request. The second time the token hadn't expired. Assert.Equal(1, messageHandler.Calls); }
protected override CredentialsRefreshState GenerateNewCredentials() { var configuredRegion = AWSConfigs.AWSRegion; var region = string.IsNullOrEmpty(configuredRegion) ? DefaultSTSClientRegion : RegionEndpoint.GetBySystemName(configuredRegion); Amazon.SecurityToken.Model.Credentials cc = null; try { var stsConfig = ServiceClientHelpers.CreateServiceConfig(ServiceClientHelpers.STS_ASSEMBLY_NAME, ServiceClientHelpers.STS_SERVICE_CONFIG_NAME); stsConfig.RegionEndpoint = region; var stsClient = new AmazonSecurityTokenServiceClient(new AnonymousAWSCredentials()); OidcToken oidcToken = SourceCredentials.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(TargetAudience).WithTokenFormat(OidcTokenFormat.Standard)).Result; TargetAssumeRoleRequest.WebIdentityToken = oidcToken.GetAccessTokenAsync().Result; AssumeRoleWithWebIdentityResponse sessionTokenResponse = stsClient.AssumeRoleWithWebIdentityAsync(TargetAssumeRoleRequest).Result; cc = sessionTokenResponse.Credentials; _logger.InfoFormat("New credentials created for assume role that expire at {0}", cc.Expiration.ToString("yyyy-MM-ddTHH:mm:ss.fffffffK", CultureInfo.InvariantCulture)); return(new CredentialsRefreshState(new ImmutableCredentials(cc.AccessKeyId, cc.SecretAccessKey, cc.SessionToken), cc.Expiration)); } catch (Exception e) { var msg = "Error exchanging Google OIDC token for AWS STS "; var exception = new InvalidOperationException(msg, e); Logger.GetLogger(typeof(GoogleCompatCredentials)).Error(exception, exception.Message); throw exception; } }
public async Task OidcTokenProvider_ComputeCredential() { // This test only executes on GCE so we are certain to have a ComputeCredential. GoogleCredential credential = GoogleCredential.FromComputeCredential(); OidcToken token = await credential.GetOidcTokenAsync( OidcTokenOptions.FromTargetAudience("https://this.is.a.test")); // Check an access token (really id_token) is available. Assert.NotNull(await token.GetAccessTokenAsync()); // If IdToken is set and AccessToken is not, AccessToken is set to // IdToken, so we can always check here that AccessToken is not null. Assert.NotNull(token.TokenResponse.AccessToken); // The enpoint does not send an expiry, bu we set it to the id_token // expiry. Assert.NotNull(token.TokenResponse.ExpiresInSeconds); var verificationOptions = new SignedTokenVerificationOptions(); verificationOptions.TrustedAudiences.Add("https://this.is.a.test"); var payload = await JsonWebSignature.VerifySignedTokenAsync(await token.GetAccessTokenAsync(), verificationOptions); Assert.NotNull(payload); Assert.Contains("https://this.is.a.test", payload.AudienceAsList); }
/// <summary> /// Authenticates using the client id and credentials, then fetches /// the uri. /// </summary> /// <param name="iapClientId">The client id observed on /// https://console.cloud.google.com/apis/credentials. </param> /// <param name="credentialsFilePath">Path to the credentials .json file /// downloaded from https://console.cloud.google.com/apis/credentials. /// </param> /// <param name="uri">HTTP uri to fetch.</param> /// <returns>The http response body as a string.</returns> public async Task <string> InvokeRequestAsync(string iapClientId, string credentialsFilePath, string uri) { // Read credentials from the credentials .json file. ServiceAccountCredential saCredential; using (var fs = new FileStream(credentialsFilePath, FileMode.Open, FileAccess.Read)) { saCredential = ServiceAccountCredential.FromServiceAccountData(fs); } // Request an OIDC token for the Cloud IAP-secured client ID. OidcToken oidcToken = await saCredential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(iapClientId)).ConfigureAwait(false); // Always request the string token from the OIDC token, the OIDC token will refresh the string token if it expires. string token = await oidcToken.GetAccessTokenAsync().ConfigureAwait(false); // Include the OIDC token in an Authorization: Bearer header to // IAP-secured resource using (var httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); string response = await httpClient.GetStringAsync(uri).ConfigureAwait(false); return(response); } }
public async Task RefreshesOidcToken() { // A little bit after the tokens returned from OidcTokenFakes were issued. var clock = new MockClock(new DateTime(2020, 5, 21, 9, 20, 0, 0, DateTimeKind.Utc)); var messageHandler = new OidcComputeSuccessMessageHandler(); var initializer = new ComputeCredential.Initializer("http://will.be.ignored", "http://will.be.ignored") { Clock = clock, HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var credential = new ComputeCredential(initializer); // The fake Oidc server returns valid tokens (expired in the real world for safty) // but with a set audience that lets us know if the token was refreshed or not. var oidcToken = await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("will.be.ignored")); var signedToken = SignedToken <Header, Payload> .FromSignedToken(await oidcToken.GetAccessTokenAsync()); Assert.Equal("https://first_call.test", signedToken.Payload.Audience); // Move the clock so that the token expires. clock.UtcNow = clock.UtcNow.AddHours(2); signedToken = SignedToken <Header, Payload> .FromSignedToken(await oidcToken.GetAccessTokenAsync()); Assert.Equal("https://subsequent_calls.test", signedToken.Payload.Audience); // Two calls, because the second time we tried to get the token, the first one had expired. Assert.Equal(2, messageHandler.Calls); }
public async Task FromUserCredential_OidcTokenFails() { var stream = new MemoryStream(Encoding.UTF8.GetBytes(DummyUserCredentialFileContents)); var credential = GoogleCredential.FromStream(stream); await Assert.ThrowsAsync <InvalidOperationException>( () => credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("audience"))); }
public void WithInvalidTokenFormat() { Assert.Throws <ArgumentException>( () => OidcTokenOptions .FromTargetAudience("dummy_target_audience") .WithTokenFormat((OidcTokenFormat)5)); }
public void FromTargetAudience() { var options = OidcTokenOptions.FromTargetAudience("dummy_target_audience"); Assert.Equal("dummy_target_audience", options.TargetAudience); Assert.Equal(OidcTokenFormat.Full, options.TokenFormat); }
public async Task RefreshesOidcToken() { // A little bit after the tokens returned from OidcTokenFakes were issued. var clock = new MockClock(new DateTime(2020, 5, 13, 15, 0, 0, 0, DateTimeKind.Utc)); var messageHandler = new OidcTokenResponseSuccessMessageHandler(); var initializer = new ServiceAccountCredential.Initializer("MyId", "http://will.be.ignored") { Clock = clock, ProjectId = "a_project_id", HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var credential = new ServiceAccountCredential(initializer.FromPrivateKey(PrivateKey)); var oidcToken = await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("audience")); var signedToken = SignedToken <Header, Payload> .FromSignedToken(await oidcToken.GetAccessTokenAsync()); Assert.Equal("https://first_call.test", signedToken.Payload.Audience); // Move the clock so that the token expires. clock.UtcNow = clock.UtcNow.AddHours(2); signedToken = SignedToken <Header, Payload> .FromSignedToken(await oidcToken.GetAccessTokenAsync()); Assert.Equal("https://subsequent_calls.test", signedToken.Payload.Audience); // Two calls, because the second time we tried to get the token, the first one had expired. Assert.Equal(2, messageHandler.Calls); }
/// <summary> /// Obtains an OIDC token for authentication an IAP request. /// </summary> /// <param name="iapClientId">The client ID observed on /// https://console.cloud.google.com/apis/credentials. </param> /// <param name="cancellationToken">The token to propagate operation cancel notifications.</param> /// <returns>The HTTP response message.</returns> public async Task <OidcToken> GetOidcTokenAsync(string iapClientId, CancellationToken cancellationToken) { // Obtain the application default credentials. GoogleCredential credential = await GoogleCredential.GetApplicationDefaultAsync(cancellationToken); // Request an OIDC token for the Cloud IAP-secured client ID. return(await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(iapClientId), cancellationToken)); }
public async Task GetOidcTokenAsync_Failure() { var credential = CreateImpersonatedCredentialWithErrorResponse(); var oidcToken = await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("will.be.ignored")); var ex = await Assert.ThrowsAsync <TokenResponseException>(() => oidcToken.GetAccessTokenAsync()); Assert.Equal(ErrorResponseContent, ex.Error.Error); }
public async Task GetOidcTokenAsync() { var credential = CreateImpersonatedCredentialWithIdTokenResponse(); var oidcToken = await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("will.be.ignored")); var token = await oidcToken.GetAccessTokenAsync(); Assert.Equal(674146, oidcToken.TokenResponse.ExpiresInSeconds); Assert.Equal(OidcComputeSuccessMessageHandler.FirstCallToken, token); }
/// <summary> /// Obtains an OIDC token for authentication an IAP request. /// </summary> /// <param name="iapClientId">The client ID observed on /// https://console.cloud.google.com/apis/credentials. </param> /// <param name="credentialsFilePath">Path to the credentials .json file /// downloaded from https://console.cloud.google.com/apis/credentials. /// </param> /// <param name="cancellationToken">The token to propagate operation cancel notifications.</param> /// <returns>The HTTP response message.</returns> public async Task <OidcToken> GetOidcTokenAsync(string iapClientId, string credentialsFilePath, CancellationToken cancellationToken) { // Read credentials from the credentials .json file. GoogleCredential credential = await GoogleCredential .FromFileAsync(credentialsFilePath, cancellationToken).ConfigureAwait(false); // Request an OIDC token for the Cloud IAP-secured client ID. return(await credential .GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(iapClientId), cancellationToken).ConfigureAwait(false)); }
public void WithTokenFormat() { var options = OidcTokenOptions .FromTargetAudience("dummy_target_audience") .WithTokenFormat(OidcTokenFormat.Standard); var newOptions = options.WithTokenFormat(OidcTokenFormat.FullWithLicences); Assert.NotSame(options, newOptions); // Original unchanged. Assert.Equal("dummy_target_audience", options.TargetAudience); Assert.Equal(OidcTokenFormat.Standard, options.TokenFormat); // New only changes token format. Assert.Equal("dummy_target_audience", newOptions.TargetAudience); Assert.Equal(OidcTokenFormat.FullWithLicences, newOptions.TokenFormat); }
public async Task FromComputeCredential_FetchesOidcToken() { var clock = new MockClock { UtcNow = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) }; var messageHandler = new OidcTokenSuccessMessageHandler(clock); var initializer = new ComputeCredential.Initializer("http://will.be.ignored", "http://will.be.ignored") { Clock = clock, HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var computeCredential = new ComputeCredential(initializer); var googleCredential = GoogleCredential.FromComputeCredential(computeCredential); var oidcToken = await googleCredential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("audience")); Assert.Equal("very_fake_access_token_1", await oidcToken.GetAccessTokenAsync()); }
public static async Task <OidcToken> getGoogleOIDCToken(string targetAudience, string credentialsFilePath) { //GoogleCredential gCredential; ServiceAccountCredential saCredential; //ComputeCredential cCredential; using (var fs = new FileStream(credentialsFilePath, FileMode.Open, FileAccess.Read)) { saCredential = ServiceAccountCredential.FromServiceAccountData(fs); } //cCredential = new ComputeCredential(); //gCredential = await GoogleCredential.GetApplicationDefaultAsync(); OidcToken oidcToken = await saCredential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(targetAudience).WithTokenFormat(OidcTokenFormat.Standard)).ConfigureAwait(false); return(oidcToken); }
public async Task FetchesOidcToken_WithDefaultOptions() { // A little bit after the tokens returned from OidcTokenFakes were issued. var clock = new MockClock(new DateTime(2020, 5, 21, 9, 20, 0, 0, DateTimeKind.Utc)); var messageHandler = new OidcComputeSuccessMessageHandler(); var initializer = new ComputeCredential.Initializer("http://will.be.ignored", "http://will.be.ignored") { Clock = clock, HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var credential = new ComputeCredential(initializer); var oidcToken = await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("any_audience")); await oidcToken.GetAccessTokenAsync(); Assert.Equal("?audience=any_audience&format=full", messageHandler.LatestRequest.RequestUri.Query); }
public async Task FetchesOidcToken_WithDefaultOptions() { var clock = new MockClock { UtcNow = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) }; var messageHandler = new OidcTokenSuccessMessageHandler(clock); var initializer = new ComputeCredential.Initializer("http://will.be.ignored", "http://will.be.ignored") { Clock = clock, HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var credential = new ComputeCredential(initializer); var oidcToken = await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("any_audience")); await oidcToken.GetAccessTokenAsync(); Assert.Equal("?audience=any_audience&format=full", messageHandler.LatestRequest.RequestUri.Query); }
public async Task FromServiceAccountCredential_FetchesOicdToken() { var clock = new MockClock { UtcNow = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) }; var messageHandler = new OidcTokenSuccessMessageHandler(clock); var initializer = new ServiceAccountCredential.Initializer("MyId", "http://will.be.ignored") { Clock = clock, ProjectId = "a_project_id", HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var serviceAccountCredential = new ServiceAccountCredential(initializer.FromPrivateKey(ServiceAccountCredentialTests.PrivateKey)); var googleCredential = GoogleCredential.FromServiceAccountCredential(serviceAccountCredential); var oidcToken = await googleCredential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("audience")); Assert.Equal("very_fake_access_token_1", await oidcToken.GetAccessTokenAsync()); }
public async Task <string> Run(string targetAudience, string credentialsFilePath, string uri) { ServiceAccountCredential saCredential; using (var fs = new FileStream(credentialsFilePath, FileMode.Open, FileAccess.Read)) { saCredential = ServiceAccountCredential.FromServiceAccountData(fs); } OidcToken oidcToken = await saCredential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(targetAudience).WithTokenFormat(OidcTokenFormat.Standard)).ConfigureAwait(false); string token = await oidcToken.GetAccessTokenAsync().ConfigureAwait(false); using (var httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); string response = await httpClient.GetStringAsync(uri).ConfigureAwait(false); Console.WriteLine(response); return(response); } }
public async Task FromComputeCredential_FetchesOidcToken() { // A little bit after the tokens returned from OidcTokenFakes were issued. var clock = new MockClock(new DateTime(2020, 5, 21, 9, 20, 0, 0, DateTimeKind.Utc)); var messageHandler = new OidcComputeSuccessMessageHandler(); var initializer = new ComputeCredential.Initializer("http://will.be.ignored", "http://will.be.ignored") { Clock = clock, HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var computeCredential = new ComputeCredential(initializer); var googleCredential = GoogleCredential.FromComputeCredential(computeCredential); // The fake Oidc server returns valid tokens (expired in the real world for safty) // but with a set audience that lets us know if the token was refreshed or not. var oidcToken = await googleCredential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("will.be.ignored")); var signedToken = SignedToken <Header, Payload> .FromSignedToken(await oidcToken.GetAccessTokenAsync()); Assert.Equal("https://first_call.test", signedToken.Payload.Audience); }
public async Task FetchesOidcToken() { var clock = new MockClock { UtcNow = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) }; var messageHandler = new OidcTokenSuccessMessageHandler(clock); var initializer = new ComputeCredential.Initializer("http://will.be.ignored", "http://will.be.ignored") { Clock = clock, HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var credential = new ComputeCredential(initializer); var oidcToken = await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("audience")); Assert.Equal("very_fake_access_token_1", await oidcToken.GetAccessTokenAsync()); // Move the clock some but not enough that the token expires. clock.UtcNow = clock.UtcNow.AddMinutes(20); Assert.Equal("very_fake_access_token_1", await oidcToken.GetAccessTokenAsync()); // Only the first call should have resulted in a request. The second time the token hadn't expired. Assert.Equal(1, messageHandler.Calls); }
public async Task RefreshesOidcToken() { var clock = new MockClock { UtcNow = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) }; var messageHandler = new OidcTokenSuccessMessageHandler(clock); var initializer = new ComputeCredential.Initializer("http://will.be.ignored", "http://will.be.ignored") { Clock = clock, HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var credential = new ComputeCredential(initializer); var oidcToken = await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("audience")); Assert.Equal("very_fake_access_token_1", await oidcToken.GetAccessTokenAsync()); // Move the clock so that the token expires. clock.UtcNow = clock.UtcNow.AddHours(2); Assert.Equal("very_fake_access_token_2", await oidcToken.GetAccessTokenAsync()); // Two calls, because the second time we tried to get the token, the first one had expired. Assert.Equal(2, messageHandler.Calls); }
public async Task FetchesOidcToken_CorrectPayloadSent() { var clock = new MockClock { UtcNow = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) }; var messageHandler = new OidcTokenSuccessMessageHandler(clock); var initializer = new ServiceAccountCredential.Initializer("MyId", "http://will.be.ignored") { Clock = clock, ProjectId = "a_project_id", HttpClientFactory = new MockHttpClientFactory(messageHandler) }; var credential = new ServiceAccountCredential(initializer.FromPrivateKey(PrivateKey)); var expectedPayload = new JsonWebSignature.Payload { Issuer = "MyId", Subject = "MyId", Audience = GoogleAuthConsts.OidcAuthorizationUrl, IssuedAtTimeSeconds = (long)(clock.UtcNow - UnixEpoch).TotalSeconds, ExpirationTimeSeconds = (long)(clock.UtcNow.Add(JwtLifetime) - UnixEpoch).TotalSeconds, TargetAudience = "any_audience" }; var serializedExpectedPayload = NewtonsoftJsonSerializer.Instance.Serialize(expectedPayload); var urlSafeEncodedExpectedPayload = UrlSafeBase64Encode(serializedExpectedPayload); var oidcToken = await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("any_audience")); await oidcToken.GetAccessTokenAsync(); var requestFormDict = messageHandler.LatestRequestContent.Split('&') .ToDictionary(entry => entry.Split('=')[0], entry => entry.Split('=')[1]); var assertion = requestFormDict["assertion"]; // Assertion format shoould be headers.payload.signature var encodedPayload = assertion.Split('.')[1]; Assert.Contains(urlSafeEncodedExpectedPayload, encodedPayload); }
public async Task <string> Run(string targetAudience, string credentialsFilePath, string uri) { ServiceAccountCredential saCredential; using (var fs = new FileStream(credentialsFilePath, FileMode.Open, FileAccess.Read)) { saCredential = ServiceAccountCredential.FromServiceAccountData(fs); } OidcToken oidcToken = await saCredential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(targetAudience).WithTokenFormat(OidcTokenFormat.Standard)).ConfigureAwait(false); string token = await oidcToken.GetAccessTokenAsync().ConfigureAwait(false); // the following snippet verifies an id token. // this step is done on the receiving end of the oidc endpoint // adding this step in here as just as a demo on how to do this //var options = SignedTokenVerificationOptions.Default; SignedTokenVerificationOptions options = new SignedTokenVerificationOptions { IssuedAtClockTolerance = TimeSpan.FromMinutes(1), ExpiryClockTolerance = TimeSpan.FromMinutes(1), TrustedAudiences = { targetAudience }, CertificatesUrl = "https://www.googleapis.com/oauth2/v3/certs" // default value }; var payload = await JsonWebSignature.VerifySignedTokenAsync(token, options); Console.WriteLine("Verified with audience " + payload.Audience); // end verification // use the token using (var httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); string response = await httpClient.GetStringAsync(uri).ConfigureAwait(false); Console.WriteLine(response); return(response); } }
public async Task FromAccessToken_OidcTokenFails() { var credential = GoogleCredential.FromAccessToken("fake_access_token"); await Assert.ThrowsAsync <InvalidOperationException>( () => credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience("audience"))); }