public async Task JwtCache_Scoped_CachesOne() { var clock = new MockClock(new DateTime(2016, 1, 1, 0, 0, 0, DateTimeKind.Utc)); var initializer = new ServiceAccountCredential.Initializer("some-id") { UseJwtAccessWithScopes = true, Scopes = new[] { "scope1", "scope2" }, Clock = clock }.FromPrivateKey(PrivateKey); var cred = new ServiceAccountCredential(initializer); Assert.True(cred.HasExplicitScopes); // Must be true for the remainder of this test to be valid. Assert.True(cred.UseJwtAccessWithScopes); // Check that only one JWT is cached var jwt0 = await cred.GetAccessTokenForRequestAsync("uri0"); for (int i = 0; i < ServiceAccountCredential.JwtCacheMaxSize; i++) { await cred.GetAccessTokenForRequestAsync($"uri{i}"); // Check jwt is retrieved from cache. var jwt0Cached = await cred.GetAccessTokenForRequestAsync("uri0"); Assert.Same(jwt0, jwt0Cached); } // Add one more JWT to cache that should remove jwt0 from the cache. await cred.GetAccessTokenForRequestAsync("uri_too_much"); var jwt0Uncached = await cred.GetAccessTokenForRequestAsync("uri0"); // Scoped credential cache just one token regardless of authUri. Assert.Same(jwt0, jwt0Uncached); }
public async Task JwtCache_Size() { var clock = new MockClock { UtcNow = new DateTime(2016, 1, 1, 0, 0, 0, DateTimeKind.Utc) }; var initializer = new ServiceAccountCredential.Initializer("some-id") { Clock = clock }.FromPrivateKey(PrivateKey); var cred = new ServiceAccountCredential(initializer); Assert.False(cred.HasScopes); // Must be false for the remainder of this test to be valid. // Check JWTs removed from cache once cache fills up. var jwt0 = await cred.GetAccessTokenForRequestAsync("uri0"); for (int i = 0; i < ServiceAccountCredential.JwtCacheMaxSize; i++) { await cred.GetAccessTokenForRequestAsync($"uri{i}"); // Check jwt is retrieved from cache. var jwt0Cached = await cred.GetAccessTokenForRequestAsync("uri0"); Assert.Same(jwt0, jwt0Cached); } // Add one more JWT to cache that should remove jwt0 from the cache. await cred.GetAccessTokenForRequestAsync("uri_too_much"); var jwt0Uncached = await cred.GetAccessTokenForRequestAsync("uri0"); Assert.NotSame(jwt0, jwt0Uncached); }
private void SendData(string json) { var msgBytes = Encoding.UTF8.GetBytes(json); string token; lock (m_syncCredential) { token = m_credential.GetAccessTokenForRequestAsync().GetAwaiter().GetResult(); } var request = WebRequest.Create(Endpoint); request.Method = "POST"; request.ContentType = "application/json"; request.ContentLength = msgBytes.Length; request.Headers.Add(HttpRequestHeader.Authorization, $"Bearer {token}"); using (var stream = request.GetRequestStream()) { stream.Write(msgBytes, 0, msgBytes.Length); } using (var res = request.GetResponse()) { return; } }
private async Task Run() { GoogleCredential credential = await GoogleCredential.GetApplicationDefaultAsync(); if (credential.IsCreateScopedRequired) { credential = credential.CreateScoped(new string[] { "https://www.googleapis.com/auth/userinfo.email" }); } String uc = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync(); Console.WriteLine("Done UserCredential " + uc); string CREDENTIAL_FILE_JSON = "/home/srashid/gcp_misc/certs/GCPNETAppID-e65deccae47b.json"; //Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", CREDENTIAL_FILE_JSON); using (var stream = new FileStream(CREDENTIAL_FILE_JSON, FileMode.Open, FileAccess.Read)) { ServiceAccountCredential svc_credential = GoogleCredential.FromStream(stream) .CreateScoped(new string[] { "https://www.googleapis.com/auth/userinfo.email" }) .UnderlyingCredential as ServiceAccountCredential; String sc = await svc_credential.GetAccessTokenForRequestAsync(); Console.WriteLine("Done ServiceAccountCredential " + sc); //https://github.com/google/google-api-dotnet-client/blob/master/Src/Support/Google.Apis.Auth/GoogleJsonWebSignature.cs //var certs = await GoogleJsonWebSignature.GetGoogleCertsAsync(SystemClock.Default, false, null); //var validPayload = await GoogleJsonWebSignature.ValidateAsync(jwt); } }
/// <summary> /// Gets the access token for service account. /// </summary> /// <exception cref="ArgumentNullException">Thrown if one of the following /// OAuth2 parameters are empty: ServiceAccountEmail, JwtPrivateKey, Scope /// </exception> public void GenerateAccessTokenForServiceAccount() { // Mark the usage. featureUsageRegistry.MarkUsage(FEATURE_ID); long timestamp = config.UnixTimestamp; long expiry = timestamp + DEFAULT_EXPIRY_PERIOD; ValidateOAuth2Parameter("ServiceAccountEmail", ServiceAccountEmail); ValidateOAuth2Parameter("JwtPrivateKey", JwtPrivateKey); ValidateOAuth2Parameter("Scope", Scope); ServiceAccountCredential credential = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(ServiceAccountEmail) { Scopes = new[] { Scope }, HttpClientFactory = this.HttpClientFactory, Clock = this.Clock }.FromPrivateKey(JwtPrivateKey) ); credential.GetAccessTokenForRequestAsync().Wait(); this.AccessToken = credential.Token.AccessToken; ExpiresIn = (int)credential.Token.ExpiresInSeconds.GetValueOrDefault(); UpdatedOn = DateTime.UtcNow; if (this.OnOAuthTokensObtained != null) { this.OnOAuthTokensObtained(this); } }
/// <summary> /// Gets the access token in service account flow. /// </summary> /// <returns>The token response.</returns> protected virtual TokenResponse GetAccessTokenForServiceAccount() { ServiceAccountCredential credential = this.GetServiceAccountCredential(); Task <string> task = credential.GetAccessTokenForRequestAsync(); task.Wait(); return(credential.Token); }
public async Task JwtCache_Expiry() { var clock = new MockClock(new DateTime(2016, 1, 1, 0, 0, 0, DateTimeKind.Utc)); var initializer = new ServiceAccountCredential.Initializer("some-id") { Clock = clock }.FromPrivateKey(PrivateKey); var cred = new ServiceAccountCredential(initializer); Assert.False(cred.HasExplicitScopes); // Must be false for the remainder of this test to be valid. // Check JWTs are only cached until the expiry minus the expiry window. var jwt0 = await cred.GetAccessTokenForRequestAsync("uri"); clock.UtcNow += ServiceAccountCredential.JwtLifetime - ServiceAccountCredential.JwtCacheExpiryWindow - TimeSpan.FromSeconds(1); var jwt0Cached = await cred.GetAccessTokenForRequestAsync("uri"); Assert.Same(jwt0, jwt0Cached); clock.UtcNow += TimeSpan.FromSeconds(2); var jwt0Uncached = await cred.GetAccessTokenForRequestAsync("uri"); Assert.NotSame(jwt0, jwt0Uncached); }
private async Task <string> CreateAccessTokenAsync(CancellationToken cancellationToken) { // Execute the Request: var accessToken = await credential .GetAccessTokenForRequestAsync(cancellationToken : cancellationToken) .ConfigureAwait(false); if (accessToken == null) { throw new Exception("Failed to obtain Access Token for Request"); } return(accessToken); }
public async Task ValidLocallySignedAccessToken_FromPrivateKey() { const string dummyServiceAccountCredentialFileContents = @"{ ""private_key_id"": ""PRIVATE_KEY_ID"", ""private_key"": ""-----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJJM6HT4s6btOsfe 2x4zrzrwSUtmtR37XTTi0sPARTDF8uzmXy8UnE5RcVJzEH5T2Ssz/ylX4Sl/CI4L no1l8j9GiHJb49LSRjWe4Yx936q0Xj9H0R1HTxvjUPqwAsTwy2fKBTog+q1frqc9 o8s2r6LYivUGDVbhuUzCaMJsf+x3AgMBAAECgYEAi0FTXsu/zRswAUGaViQiHjrL uU65BSHXNVjV/2fLNEKnGWGqpli68z1IXY+S2nwbUak7rnGsq9/0F6jtsW+hZbLk KXUOuuExpeC5Kd6ngWX/f2jqmhlUabiQijU9cVk7pMq8EHkRtvlosnMTUAEzempu QUPwn1PZHhmJkBvZ4lECQQDCErrxl+e3BwUDcS0yVEEmCNSG6xdXs2878b8rzbe7 3Mmi6SuuOLi3PU92J+j+f/MOdtYrk13mEDdYmd5dhrt5AkEAwPvDEsDT/W4y4h5n gv1awGBA5aLFE1JNWM/Gwn4D1cGpEDHKFREaBtxMDCASpHJuw8r7zUywpKhmBZcf GS37bwJANdSAKfbafLfjuhqwUJ9yGpykZm/a36aTmerp/bpn1iHdg+RtCzwMcDb/ TWSwibbvsflgWmHbz657y4WSWhq+8QJAWrpCNN/ZCk2zuGDo80lfUBAwkoVat8G6 wWU1oZyS+vzIGef+hLb8kHsjeZPej9eIwZ39kcBbT54oELrCkRjwGwJAQ8V2A7lT ZUp8AsbVqF6rbLiiUfJMo2btGclQu4DEVyS+ymFA65tXDLUuR9EDqJYdqHNZJ5B8 4Z5p2prkjWTLcA== -----END PRIVATE KEY-----"", ""client_email"": ""CLIENT_EMAIL"", ""client_id"": ""CLIENT_ID"", ""type"": ""service_account""}"; var credentialParameters = NewtonsoftJsonSerializer.Instance.Deserialize <JsonCredentialParameters>(dummyServiceAccountCredentialFileContents); var initializer = new ServiceAccountCredential.Initializer(credentialParameters.ClientEmail) { Clock = new MockClock { UtcNow = new DateTime(2016, 1, 1, 0, 0, 0, DateTimeKind.Utc) } }; var cred = new ServiceAccountCredential(initializer.FromPrivateKey(credentialParameters.PrivateKey)); Assert.False(cred.Scopes?.Any()); // HasScopes must be false for the type of access token we want to test. string accessToken = await cred.GetAccessTokenForRequestAsync("http://authurl/"); string expectedToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJDTElFTlRfRU1BSUwiLCJz" + "dWIiOiJDTElFTlRfRU1BSUwiLCJhdWQiOiJodHRwOi8vYXV0aHVybC8iLCJleHAiOjE0N" + "TE2MTAwMDAsImlhdCI6MTQ1MTYwNjQwMH0.WLljSaAqxMVZnAxFA2SvpA3n2WRlQW71Nb" + "CUkbN-ZI-EWoL-HhgiV_3ISrXMvbDHYhBR0vvtXE0PcRcsMEf51Y0jV4DXZ8hf-QJFq7O" + "Hrepwe93dnDE6uNVnbj41_0phuy1WKwae29Qp2aPI2Y8E8Z2tXQlF87E_MdgjXVeTF8k"; Assert.Equal(expectedToken, accessToken); }
public async Task JwtAccessToken_Http() { // See: https://developers.google.com/identity/protocols/oauth2/service-account#jwt-auth ServiceAccountCredential credential = Helper.GetServiceCredential().CreateScoped().UnderlyingCredential as ServiceAccountCredential; string token = await credential.GetAccessTokenForRequestAsync("https://bigtableadmin.googleapis.com/"); using HttpClient client = new HttpClient(); HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); request.RequestUri = new Uri($"https://bigtableadmin.googleapis.com/v2/projects/{Helper.GetProjectId()}/instances"); HttpResponseMessage response = await client.SendAsync(request); Assert.Equal(HttpStatusCode.OK, response.StatusCode); }
public async Task Jwt_WithUser_AccessToken(bool useJwtAccessWithScopes) { var clock = new MockClock(new DateTime(2016, 1, 1, 0, 0, 0, DateTimeKind.Utc)); var handler = new FetchesTokenMessageHandler(); var initializer = new ServiceAccountCredential.Initializer("some-id") { UseJwtAccessWithScopes = useJwtAccessWithScopes, Clock = clock, User = "******", HttpClientFactory = new MockHttpClientFactory(handler) }.FromPrivateKey(PrivateKey); var cred = new ServiceAccountCredential(initializer); Assert.False(cred.HasExplicitScopes); // Must be false for the remainder of this test to be valid. var token = await cred.GetAccessTokenForRequestAsync("uri0"); Assert.Equal("a", token); }
public async Task JwtScopes_UseAud(bool useJwtAccessWithScopes) { var clock = new MockClock(new DateTime(2016, 1, 1, 0, 0, 0, DateTimeKind.Utc)); var initializer = new ServiceAccountCredential.Initializer("some-id") { UseJwtAccessWithScopes = useJwtAccessWithScopes, Clock = clock }.FromPrivateKey(PrivateKey); var cred = new ServiceAccountCredential(initializer); Assert.False(cred.HasExplicitScopes); // Must be false for the remainder of this test to be valid. var jwt0 = await cred.GetAccessTokenForRequestAsync("uri0"); byte[] decoded = TokenEncodingHelpers.Base64UrlDecode(jwt0.Split(new char[] { '.' })[1]); string payload = System.Text.Encoding.UTF8.GetString(decoded); Assert.Contains("\"aud\":\"uri0\"", payload); Assert.DoesNotContain("scope", payload); }
static async Task <string> GetGoogleOAuthTokenAsync() { //setup ouath //string serviceAccountEmail = "*****@*****.**"; //pls dev service account - 1 string serviceAccountEmail = "*****@*****.**"; //service-oauth string O_AUTH_EMAIL_SCOPE = "https://www.googleapis.com/auth/devstorage.read_write"; var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.Exportable); ServiceAccountCredential credential = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(serviceAccountEmail) { Scopes = new[] { O_AUTH_EMAIL_SCOPE } }.FromCertificate(certificate)); //var done = await credential.RequestAccessTokenAsync(new System.Threading.CancellationToken()); return(await credential.GetAccessTokenForRequestAsync()); }
public async Task ValidLocallySignedAccessToken_FromX509Certificate() { #if NETCOREAPP1_0 || NETCOREAPP1_1 || NETCOREAPP2_0 const string sPfx = @" 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"; var x509Cert = new X509Certificate2(Convert.FromBase64String(sPfx)); #elif NET452 || NET46 const string sPrivateKey = @" -----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALQoMIfUT93VMvb5 4U5dsJLXD1D6z4o/VuVlNUaf5xH01qAv8Egpxe6f5frLB/p1eNyDjNIZ3QitD6aN 9Vfh4ifg6txBuBJtIMfSDvRJITNZ2SjKJREbflZuBk0HINKYQk2H+3TIzUbE/pN4 Cu6Mids5L/oVOnRWIe3bEC+PHR7ZAgMBAAECgYBI1qrwb+2ukeFeK59lcMnQRLVD l3RLv9ohOy80E7h38RbJgzhR5NnK5ck1AduC7vXjqihIVf6g4F+ghmq4knI94KPQ 2fOyQGVV6jVeRVqMusx7tP9V1H26yABiK6TPklcCsWwADFmexfOxfIgbBGSmlbAd N2/ad1Xog1xDebrbEQJBAO+2qSIDX1ahfxUyvvcMaix6Mrh/OYKb5aH1Y/7MfAav lpbQavQHNvak2147aPNxy0ZvWdJ2HVA7hUMkgysYWSUCQQDAZalkZMSrve+Onh55 U+w5xjLklhh8PhYxx8plT8ae9VG75dGvWSz/W81B3ILg2lrNU6o08NKBJdZsJYmc BeKlAkBtJh3zF9gEaTqlW1rqwKNjpyyLJ5r3JqczzLmAXnmmzbLi7vmULejP+5bL XH/YQZtOcgtTMmb8jm2Kegijyc1lAkANGt+e5v4+dIGMxVhuCzlb9hQhXdftHo2E dodivzxYN32Jvu25c+mMu0QP6GVBy53Dvp8pW/36rgkc9LGa3wvBAkEA7dGAl95T UeNFVfuzkYNtQppcSgrx1oTcpTHoNgcvk8AgBf4yDdJJyo0IUONmgJCVffc1aTWn nf/8cW9YC+0icQ== -----END PRIVATE KEY-----"; const string sCert = @" MIICNDCCAZ2gAwIBAgIJAKl3qU1+NsuuMA0GCSqGSIb3DQEBCwUAMDMxCzAJBgNV BAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRlMQ8wDQYDVQQKDAZHb29nbGUwHhcN MTYwODEwMTQwOTQ2WhcNNDMxMjI3MTQwOTQ2WjAzMQswCQYDVQQGEwJHQjETMBEG A1UECAwKU29tZS1TdGF0ZTEPMA0GA1UECgwGR29vZ2xlMIGfMA0GCSqGSIb3DQEB AQUAA4GNADCBiQKBgQC0KDCH1E/d1TL2+eFOXbCS1w9Q+s+KP1blZTVGn+cR9Nag L/BIKcXun+X6ywf6dXjcg4zSGd0IrQ+mjfVX4eIn4OrcQbgSbSDH0g70SSEzWdko yiURG35WbgZNByDSmEJNh/t0yM1GxP6TeArujInbOS/6FTp0ViHt2xAvjx0e2QID AQABo1AwTjAdBgNVHQ4EFgQUMqzJi099PA8ML5CV1OSiHgiTGoUwHwYDVR0jBBgw FoAUMqzJi099PA8ML5CV1OSiHgiTGoUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B AQsFAAOBgQBQ9cMInb2rEcg8TTYq8MjDEegHWLUI9Dq/IvP/FHyKDczza4eX8m+G 3buutN74pX2/GHRgqvqEvvUUuAQUnZ36k6KjTNxfzNLiSXDPNeYmy6PWsUZy4Rye /Van/ePiXdipTKMiUyl7V6dTjkE5p/e372wNVXUpcxOMmYdWmzSMvg=="; var x509Cert = new X509Certificate2(Convert.FromBase64String(sCert)); RSAParameters rsaParameters = Pkcs8.DecodeRsaParameters(sPrivateKey); var privateKey = new System.Security.Cryptography.RSACryptoServiceProvider(); privateKey.ImportParameters(rsaParameters); x509Cert.PrivateKey = privateKey; #else #error Unsupported target #endif Assert.True(x509Cert.HasPrivateKey); var initializer = new ServiceAccountCredential.Initializer("some-id") { Clock = new MockClock { UtcNow = new DateTime(2016, 1, 1, 0, 0, 0, DateTimeKind.Utc) } }; var cred = new ServiceAccountCredential(initializer.FromCertificate(x509Cert)); Assert.False(cred.Scopes?.Any()); // HasScopes must be false for the type of access token we want to test. string accessToken = await cred.GetAccessTokenForRequestAsync("http://authurl/"); string expectedToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzb21lLWlkIiwic3ViIjoi" + "c29tZS1pZCIsImF1ZCI6Imh0dHA6Ly9hdXRodXJsLyIsImV4cCI6MTQ1MTYxMDAwMCwia" + "WF0IjoxNDUxNjA2NDAwfQ.GfpDHgrFi4ZlGC5LuJEarLU4_eTrT5PVa-S40YtkdB2E1f3" + "4naYG2ItcfBEFg7Gbdkr1cIAyipuhEd2yLfPmWGwhOwVcBRNyK_J5w8RodS44mxNJwau0" + "jKy4x1K20ybLqcnNgzE0wag6fi5GHwdNIB0URdHDTiC88CRYdl1CIdk"; Assert.Equal(expectedToken, accessToken); }