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); }
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; } }