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); }
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); }
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 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 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")); 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() { 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 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); }