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);
        }
        public async Task ValidES256Signature_Unsupported()
        {
            var ex = await Assert.ThrowsAsync <InvalidOperationException>(() => JsonWebSignature.VerifySignedTokenAsync(
                                                                              FakeCertificateCache.Es256ForIap, BuildOptions(new MockClock(FakeCertificateCache.ValidEs256ForIap))));

            Assert.Equal("ES256 signed token verification is not supported in this platform.", ex.Message);
        }
        public async Task Validate_Signature_Time()
        {
            var clockInvalid1 = new MockClock(FakeCertificateCache.BeforeValidJwtGoogleSigned);
            var clockValid1   = new MockClock(FakeCertificateCache.ValidJwtGoogleSigned);
            var clockInvalid2 = new MockClock(FakeCertificateCache.AfterValidJwtGoogleSigned);

            // Test with no tolerance
            Assert.NotNull(await JsonWebSignature.VerifySignedTokenAsync(FakeCertificateCache.JwtGoogleSigned, BuildOptions(clockValid1)));

            var ex1 = await Assert.ThrowsAsync <InvalidJwtException>(() =>
                                                                     JsonWebSignature.VerifySignedTokenAsync(FakeCertificateCache.JwtGoogleSigned, BuildOptions(clockInvalid1)));

            Assert.Equal("JWT is not yet valid.", ex1.Message);

            var ex2 = await Assert.ThrowsAsync <InvalidJwtException>(() =>
                                                                     JsonWebSignature.VerifySignedTokenAsync(FakeCertificateCache.JwtGoogleSigned, BuildOptions(clockInvalid2)));

            Assert.Equal("JWT has expired.", ex2.Message);

            // Test with tolerance
            await Assert.ThrowsAsync <InvalidJwtException>(() =>
                                                           JsonWebSignature.VerifySignedTokenAsync(FakeCertificateCache.JwtGoogleSigned, BuildOptions(clockInvalid1, clockTolerance: TimeSpan.FromSeconds(109))));

            Assert.NotNull(await JsonWebSignature.VerifySignedTokenAsync(FakeCertificateCache.JwtGoogleSigned, BuildOptions(clockInvalid1, clockTolerance: TimeSpan.FromSeconds(111))));
            Assert.NotNull(await JsonWebSignature.VerifySignedTokenAsync(FakeCertificateCache.JwtGoogleSigned, BuildOptions(clockInvalid2, clockTolerance: TimeSpan.FromSeconds(11))));
            await Assert.ThrowsAsync <InvalidJwtException>(() =>
                                                           JsonWebSignature.VerifySignedTokenAsync(FakeCertificateCache.JwtGoogleSigned, BuildOptions(clockInvalid2, clockTolerance: TimeSpan.FromSeconds(9))));
        }
        public async Task ValidAudience()
        {
            var options = BuildOptions(trustedAudiences: new string[] { "233772281425-ab2mcbiqmv8kh0mdnqsrkrod97qk37h0.apps.googleusercontent.com" });
            var payload = await JsonWebSignature.VerifySignedTokenAsync(FakeCertificateCache.JwtGoogleSigned, options);

            Assert.NotNull(payload);
        }
        public async Task InvalidIssuer()
        {
            var options = BuildOptions(trustedIssuers: new string[] { "issuer1", "issuer2" });
            var ex      = await Assert.ThrowsAsync <InvalidJwtException>(() =>
                                                                         JsonWebSignature.VerifySignedTokenAsync(FakeCertificateCache.JwtGoogleSigned, options));

            Assert.Equal("JWT issuer incorrect. Must be one of: 'issuer1', 'issuer2'", ex.Message);
        }
        public async Task InvalidAudience()
        {
            var options = BuildOptions(trustedAudiences: new string[] { "audience1", "audience2" });
            var ex      = await Assert.ThrowsAsync <InvalidJwtException>(() =>
                                                                         JsonWebSignature.VerifySignedTokenAsync(FakeCertificateCache.JwtGoogleSigned, options));

            Assert.Equal("JWT contains untrusted 'aud' claim.", ex.Message);
        }
        public async Task ValidRS256Signature_CustomPayload()
        {
            var payload = await JsonWebSignature.VerifySignedTokenAsync <CustomPayload>(FakeCertificateCache.JwtGoogleSigned, BuildOptions());

            Assert.NotNull(payload);
            Assert.NotNull(payload.AuthorizedParty);
            Assert.NotEmpty(payload.AuthorizedParty);
        }
        public async Task WrongAlgorithm()
        {
            string jwt = $"{UrlSafeBase64Encode("{\"alg\":\"HS256\"}")}.{UrlSafeBase64Encode("{}")}.";
            var    ex  = await Assert.ThrowsAsync <InvalidJwtException>(() =>
                                                                        JsonWebSignature.VerifySignedTokenAsync(jwt, BuildOptions()));

            Assert.Equal("Signing algorithm must be either RS256 or ES256.", ex.Message);
        }
        public async Task InvalidES256Signature_Unsupported()
        {
            // Lets just change the last character of the signed token to break the signature.
            // But Headers and Payload are still valid so we guarantee that the only
            // failure comes from the signature being invalid.
            // The last character was an A, changing for a 4. If at some point the token used in tests changes
            // and the new token ends in anything but a 4, this test will still be valid. If the new token ends in a 4
            // this test will fail and then we'll have to replace the 4 by an A or any other character.
            var invalidToken = FakeCertificateCache.Es256ForIap.Substring(0, FakeCertificateCache.Es256ForIap.Length - 1) + "4";
            var ex           = await Assert.ThrowsAsync <InvalidOperationException>(() =>
                                                                                    JsonWebSignature.VerifySignedTokenAsync(invalidToken, BuildOptions(new MockClock(FakeCertificateCache.ValidEs256ForIap))));

            Assert.Equal("ES256 signed token verification is not supported in this platform.", ex.Message);
        }
        public async Task InvalidRS256Signature()
        {
            // Lets just change the last character of the Google signed token to break the signature.
            // But Headers and Payload are still valid for a Google token so we guarantee that the only
            // failure comes from the signature being invalid.
            // The last character was a Q, changing for a 4. If at some point the token used in tests changes
            // and the new token ends in anything but a 4, this test will still be valid. If the new token ends in a 4
            // this test will fail and then we'll have to replace the 4 by a Q or any other character.
            var invalidToken = FakeCertificateCache.JwtGoogleSigned.Substring(0, FakeCertificateCache.JwtGoogleSigned.Length - 1) + "4";
            var ex           = await Assert.ThrowsAsync <InvalidJwtException>(() =>
                                                                              JsonWebSignature.VerifySignedTokenAsync(invalidToken, BuildOptions()));

            Assert.Equal("JWT invalid, unable to verify signature.", ex.Message);
        }
Example #11
0
    /// <summary>
    /// Verifies a signed jwt token and returns its payload.
    /// </summary>
    /// <param name="signedJwt">The token to verify.</param>
    /// <param name="expectedAudience">The audience that the token should be meant for.
    /// Validation will fail if that's not the case.</param>
    /// <param name="cancellationToken">The cancellation token to propagate cancellation requests.</param>
    /// <returns>A task that when completed will have as its result the payload of the verified token.</returns>
    /// <exception cref="InvalidJwtException">If verification failed. The message of the exception will contain
    /// information as to why the token failed.</exception>
    public async Task <JsonWebSignature.Payload> VerifyTokenAsync(
        string signedJwt, string expectedAudience, CancellationToken cancellationToken = default)
    {
        SignedTokenVerificationOptions options = new SignedTokenVerificationOptions
        {
            // Use clock tolerance to account for possible clock differences
            // between the issuer and the verifier.
            IssuedAtClockTolerance = TimeSpan.FromMinutes(1),
            ExpiryClockTolerance   = TimeSpan.FromMinutes(1),
            TrustedAudiences       = { expectedAudience }
        };

        return(await JsonWebSignature.VerifySignedTokenAsync(signedJwt, options, cancellationToken : cancellationToken));
    }
Example #12
0
        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 NullToken() =>
 await Assert.ThrowsAsync <ArgumentNullException>(() =>
                                                  JsonWebSignature.VerifySignedTokenAsync(null, BuildOptions()));
 public async Task EmptyToken() =>
 await Assert.ThrowsAsync <ArgumentException>(() =>
                                              JsonWebSignature.VerifySignedTokenAsync("", BuildOptions()));
 public async Task ValidES256Signature() =>
 Assert.NotNull(await JsonWebSignature.VerifySignedTokenAsync(
                    FakeCertificateCache.Es256ForIap, BuildOptions(new MockClock(FakeCertificateCache.ValidEs256ForIap))));
 public async Task TwoPartToken() =>
 await Assert.ThrowsAsync <InvalidJwtException>(() =>
                                                JsonWebSignature.VerifySignedTokenAsync("header.payload", BuildOptions()));
 public async Task ValidRS256Signature() =>
 Assert.NotNull(await JsonWebSignature.VerifySignedTokenAsync(
                    FakeCertificateCache.JwtGoogleSigned, BuildOptions()));