public async Task PopTest_ExternalWilsonSigning_Async()
        {
            var confidentialApp = ConfidentialClientApplicationBuilder
                                  .Create(PublicCloudConfidentialClientID)
                                  .WithExperimentalFeatures()
                                  .WithAuthority(PublicCloudTestAuthority)
                                  .WithClientSecret(s_publicCloudCcaSecret)
                                  .Build();

            // Create an RSA key Wilson style (SigningCredentials)
            var key            = CreateRsaSecurityKey();
            var popCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256);

            var popConfig = new PoPAuthenticationConfiguration()
            {
                PopCryptoProvider = new SigningCredentialsToPopCryptoProviderAdapter(popCredentials, true),
                SignHttpRequest   = false,
            };

            var result = await confidentialApp.AcquireTokenForClient(s_keyvaultScope)
                         .WithProofOfPossession(popConfig)
                         .ExecuteAsync(CancellationToken.None)
                         .ConfigureAwait(false);

            Assert.AreEqual("pop", result.TokenType);
            Assert.AreEqual(
                TokenSource.IdentityProvider,
                result.AuthenticationResultMetadata.TokenSource);

            SignedHttpRequestDescriptor signedHttpRequestDescriptor =
                new SignedHttpRequestDescriptor(
                    result.AccessToken,
                    new IdentityModel.Protocols.HttpRequestData()
            {
                Uri    = new Uri(ProtectedUrl),
                Method = HttpMethod.Post.ToString()
            },
                    popCredentials);
            var    signedHttpRequestHandler = new SignedHttpRequestHandler();
            string req = signedHttpRequestHandler.CreateSignedHttpRequest(signedHttpRequestDescriptor);

            await VerifyPoPTokenAsync(
                PublicCloudConfidentialClientID,
                ProtectedUrl,
                HttpMethod.Post,
                req, "pop").ConfigureAwait(false);

            var result2 = await confidentialApp.AcquireTokenForClient(s_keyvaultScope)
                          .WithProofOfPossession(popConfig)
                          .ExecuteAsync(CancellationToken.None)
                          .ConfigureAwait(false);

            Assert.AreEqual(
                TokenSource.Cache,
                result2.AuthenticationResultMetadata.TokenSource);
        }
示例#2
0
        public async Task Roundtrips(RoundtripSignedHttpRequestTheoryData theoryData)
        {
            var context = TestUtilities.WriteHeader($"{this}.Roundtrips", theoryData);

            try
            {
                var handler = new SignedHttpRequestHandler();
                var signedHttpRequestDescriptor = new SignedHttpRequestDescriptor(theoryData.AccessToken, theoryData.HttpRequestData, theoryData.SigningCredentials, theoryData.SignedHttpRequestCreationParameters);
                signedHttpRequestDescriptor.CnfClaimValue = theoryData.CnfClaimValue;
                var signedHttpRequest     = handler.CreateSignedHttpRequest(signedHttpRequestDescriptor);
                var cryptoProviderFactory = signedHttpRequestDescriptor.SigningCredentials.CryptoProviderFactory ?? signedHttpRequestDescriptor.SigningCredentials.Key.CryptoProviderFactory;
                if (cryptoProviderFactory.CryptoProviderCache.TryGetSignatureProvider(
                        signedHttpRequestDescriptor.SigningCredentials.Key,
                        signedHttpRequestDescriptor.SigningCredentials.Algorithm,
                        signedHttpRequestDescriptor.SigningCredentials.Key is AsymmetricSecurityKey ? typeof(AsymmetricSignatureProvider).ToString() : typeof(SymmetricSignatureProvider).ToString(),
                        true,
                        out _))
                {
                    context.Diffs.Add(LogHelper.FormatInvariant("SignedHttpRequest cached SignatureProvider (Signing), Key: '{0}', Algorithm: '{1}'", signedHttpRequestDescriptor.SigningCredentials.Key, signedHttpRequestDescriptor.SigningCredentials.Algorithm));
                }


                var signedHttpRequestValidationContext = new SignedHttpRequestValidationContext(signedHttpRequest, theoryData.HttpRequestData, theoryData.TokenValidationParameters, theoryData.SignedHttpRequestValidationParameters);
                var result = await handler.ValidateSignedHttpRequestAsync(signedHttpRequestValidationContext, CancellationToken.None).ConfigureAwait(false);

                if (cryptoProviderFactory.CryptoProviderCache.TryGetSignatureProvider(
                        signedHttpRequestDescriptor.SigningCredentials.Key,
                        signedHttpRequestDescriptor.SigningCredentials.Algorithm,
                        signedHttpRequestDescriptor.SigningCredentials.Key is AsymmetricSecurityKey ? typeof(AsymmetricSignatureProvider).ToString() : typeof(SymmetricSignatureProvider).ToString(),
                        false,
                        out _))
                {
                    context.Diffs.Add(LogHelper.FormatInvariant("SignedHttpRequest cached SignatureProvider (Validate), Key: '{0}', Algorithm: '{1}'", signedHttpRequestDescriptor.SigningCredentials.Key, signedHttpRequestDescriptor.SigningCredentials.Algorithm));
                }

                IdentityComparer.AreBoolsEqual(result.IsValid, theoryData.IsValid, context);

                if (result.Exception != null)
                {
                    throw result.Exception;
                }

                Assert.NotNull(result);
                Assert.NotNull(result.SignedHttpRequest);
                Assert.NotNull(result.ValidatedSignedHttpRequest);
                Assert.NotNull(result.AccessTokenValidationResult);

                theoryData.ExpectedException.ProcessNoException(context);
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex, context);
            }

            TestUtilities.AssertFailIfErrors(context);
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            try
            {
                // Give application opportunity to find from a different location, adjust, or reject token
                var messageReceivedContext = new SignedHttpRequestMessageReceivedContext(Context, Scheme, Options);

                // event can set the token
                //await Events.MessageReceived(messageReceivedContext);
                if (messageReceivedContext.Result != null)
                {
                    return(messageReceivedContext.Result);
                }

                // If application retrieved token from somewhere else, use that.
                string signedHttpRequest = messageReceivedContext.Token;

                if (string.IsNullOrEmpty(signedHttpRequest))
                {
                    string authorization = Request.Headers[HeaderNames.Authorization];

                    // If no authorization header found, nothing to process further
                    if (string.IsNullOrEmpty(authorization))
                    {
                        return(AuthenticateResult.NoResult());
                    }

                    if (authorization.StartsWith(SignedHttpRequestConstants.AuthorizationHeaderSchemeName, StringComparison.OrdinalIgnoreCase))
                    {
                        signedHttpRequest = authorization.Substring((SignedHttpRequestConstants.AuthorizationHeaderSchemeName + " ").Length).Trim();
                    }

                    // If no token found, no further work possible
                    if (string.IsNullOrEmpty(signedHttpRequest))
                    {
                        return(AuthenticateResult.NoResult());
                    }
                }

                if (_configuration == null && Options.ConfigurationManager != null)
                {
                    _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
                }

                var validationParameters = Options.AccessTokenValidationParameters.Clone();
                if (_configuration != null)
                {
                    var issuers = new[] { _configuration.Issuer };
                    validationParameters.ValidIssuers = validationParameters.ValidIssuers?.Concat(issuers) ?? issuers;

                    validationParameters.IssuerSigningKeys = validationParameters.IssuerSigningKeys?.Concat(_configuration.SigningKeys)
                                                             ?? _configuration.SigningKeys;
                }

                var signedHttpRequestHandler = new SignedHttpRequestHandler();

                Request.EnableBuffering();

                byte[] body = null;
                // Only extract the body if it will be validated.
                if (Options.SignedHttpRequestValidationParameters.ValidateB)
                {
                    using (var ms = new MemoryStream(2048))
                    {
                        await Request.Body.CopyToAsync(ms);

                        body = ms.ToArray();  // returns base64 encoded string JSON result
                    }
                }

                Request.Body.Position = 0;

                Dictionary <string, IEnumerable <string> > headers = new Dictionary <string, IEnumerable <string> >();

                // Only extract the headers if they will be validated.
                if (Options.SignedHttpRequestValidationParameters.ValidateH)
                {
                    foreach (var keyValuePair in Request.Headers)
                    {
                        headers.Add(keyValuePair.Key, keyValuePair.Value.AsEnumerable());
                    }
                }

                var httpRequestData = new HttpRequestData()
                {
                    Method  = Request.Method,
                    Uri     = new Uri(UriHelper.GetEncodedUrl(Request)),
                    Body    = body,
                    Headers = headers
                };

                var signedHttpRequestValidationContext = new SignedHttpRequestValidationContext(signedHttpRequest, httpRequestData, validationParameters, Options.SignedHttpRequestValidationParameters);
                SignedHttpRequestValidationResult signedHttpRequestValidationResult = null;


                signedHttpRequestValidationResult = await signedHttpRequestHandler.ValidateSignedHttpRequestAsync(signedHttpRequestValidationContext, CancellationToken.None).ConfigureAwait(false);


                if (!signedHttpRequestValidationResult.IsValid)
                {
                    Logger.TokenValidationFailed(signedHttpRequestValidationResult.Exception);
                    // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the event.
                    if (Options.RefreshOnIssuerKeyNotFound && Options.ConfigurationManager != null &&
                        signedHttpRequestValidationResult.Exception is SecurityTokenSignatureKeyNotFoundException)
                    {
                        Options.ConfigurationManager.RequestRefresh();
                    }

                    var authenticationFailedContext = new SignedHttpRequestAuthenticationFailedContext(Context, Scheme, Options)
                    {
                        Exception = signedHttpRequestValidationResult.Exception
                    };

                    //await Events.AuthenticationFailed(authenticationFailedContext);
                    if (authenticationFailedContext.Result != null)
                    {
                        return(authenticationFailedContext.Result);
                    }

                    return(AuthenticateResult.Fail(authenticationFailedContext.Exception));
                }

                Logger.TokenValidationSucceeded();

                var principal = new ClaimsPrincipal(signedHttpRequestValidationResult.AccessTokenValidationResult.ClaimsIdentity);

                Request.HttpContext.Items[typeof(SignedHttpRequestValidationResult)] = signedHttpRequestValidationResult;
                var tokenValidatedContext = new SignedHttpRequestValidatedContext(Context, Scheme, Options)
                {
                    Principal = principal,
                    SignedHttpRequestValidationResult = signedHttpRequestValidationResult,
                };

                //await Events.TokenValidated(tokenValidatedContext);
                if (tokenValidatedContext.Result != null)
                {
                    return(tokenValidatedContext.Result);
                }

                tokenValidatedContext.Success();
                return(tokenValidatedContext.Result);
            }
            catch (Exception ex)
            {
                Logger.ErrorProcessingMessage(ex);

                var authenticationFailedContext = new SignedHttpRequestAuthenticationFailedContext(Context, Scheme, Options)
                {
                    Exception = ex
                };

                //await Events.AuthenticationFailed(authenticationFailedContext);
                if (authenticationFailedContext.Result != null)
                {
                    return(authenticationFailedContext.Result);
                }

                throw;
            }
        }