Пример #1
0
        private async Task AddBodyParamsAndHeadersAsync(
            IDictionary <string, string> additionalBodyParameters,
            string scopes,
            CancellationToken cancellationToken)
        {
            _oAuth2Client.AddBodyParameter(OAuth2Parameter.ClientId, _requestParams.AppConfig.ClientId);

            if (_serviceBundle.Config.ClientCredential != null)
            {
                await _serviceBundle.Config.ClientCredential.AddConfidentialClientParametersAsync(
                    _oAuth2Client,
                    _requestParams.RequestContext.Logger,
                    _serviceBundle.PlatformProxy.CryptographyManager,
                    _requestParams.AppConfig.ClientId,
                    _requestParams.Authority.GetTokenEndpoint(),
                    _requestParams.SendX5C,
                    cancellationToken).ConfigureAwait(false);
            }

            _oAuth2Client.AddBodyParameter(OAuth2Parameter.Scope, scopes);

            // Add Kerberos Ticket claims if there's valid service principal name in Configuration.
            // Kerberos Ticket claim is only allowed at token request due to security issue.
            // It should not be included for authorize request.
            KerberosSupplementalTicketManager.AddKerberosTicketClaim(_oAuth2Client, _requestParams);

            foreach (var kvp in additionalBodyParameters)
            {
                _oAuth2Client.AddBodyParameter(kvp.Key, kvp.Value);
            }

            foreach (var kvp in _requestParams.AuthenticationScheme.GetTokenRequestParams())
            {
                _oAuth2Client.AddBodyParameter(kvp.Key, kvp.Value);
            }

            _oAuth2Client.AddHeader(
                TelemetryConstants.XClientCurrentTelemetry,
                _serviceBundle.HttpTelemetryManager.GetCurrentRequestHeader(
                    _requestParams.RequestContext.ApiEvent));

            if (!_requestInProgress)
            {
                _requestInProgress = true;

                _oAuth2Client.AddHeader(
                    TelemetryConstants.XClientLastTelemetry,
                    _serviceBundle.HttpTelemetryManager.GetLastRequestHeader());
            }

            //Signaling that the client can perform PKey Auth on supported platforms
            if (DeviceAuthHelper.CanOSPerformPKeyAuth())
            {
                _oAuth2Client.AddHeader(PKeyAuthConstants.DeviceAuthHeaderName, PKeyAuthConstants.DeviceAuthHeaderValue);
            }

            AddExtraHttpHeaders();
        }
        public bool TryCreateDeviceAuthChallengeResponseAsync(HttpResponseHeaders responseHeaders, Uri endpointUri, out string responseHeader)
        {
            responseHeader = string.Empty;
            string           authHeaderTemplate = "PKeyAuth {0}, Context=\"{1}\", Version=\"{2}\"";
            X509Certificate2 certificate        = null;

            if (!DeviceAuthHelper.IsDeviceAuthChallenge(responseHeaders))
            {
                return(false);
            }
            if (!DeviceAuthHelper.CanOSPerformPKeyAuth())
            {
                responseHeader = DeviceAuthHelper.GetBypassChallengeResponse(responseHeaders);
                return(true);
            }

            IDictionary <string, string> challengeData = DeviceAuthHelper.ParseChallengeData(responseHeaders);

            if (!challengeData.ContainsKey("SubmitUrl"))
            {
                challengeData["SubmitUrl"] = endpointUri.AbsoluteUri;
            }

            try
            {
                certificate = FindCertificate(challengeData);
            }
            catch (MsalException ex)
            {
                if (ex.ErrorCode == MsalError.DeviceCertificateNotFound)
                {
                    responseHeader = DeviceAuthHelper.GetBypassChallengeResponse(responseHeaders);
                    return(true);
                }
            }

            DeviceAuthJWTResponse responseJWT = new DeviceAuthJWTResponse(challengeData["SubmitUrl"],
                                                                          challengeData["nonce"], Convert.ToBase64String(certificate.GetRawCertData()));

            CngKey key = NetDesktopCryptographyManager.GetCngPrivateKey(certificate);

            byte[] sig = null;
            using (Native.RSACng rsa = new Native.RSACng(key))
            {
                rsa.SignatureHashAlgorithm = CngAlgorithm.Sha256;
                sig = rsa.SignData(responseJWT.GetResponseToSign().ToByteArray());
            }

            string signedJwt = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", responseJWT.GetResponseToSign(),
                                             Base64UrlHelpers.Encode(sig));
            string authToken = string.Format(CultureInfo.InvariantCulture, " AuthToken=\"{0}\"", signedJwt);

            responseHeader = string.Format(CultureInfo.InvariantCulture, authHeaderTemplate, authToken,
                                           challengeData["Context"],
                                           challengeData["Version"]);

            return(true);
        }
        public void CheckIfResponseIsDeviceAuthChallenge()
        {
            //Act
            bool successResponse = DeviceAuthHelper.IsDeviceAuthChallenge(s_httpResponse.Headers);
            bool failedResponse  = DeviceAuthHelper.IsDeviceAuthChallenge((new HttpResponse()).Headers);

            //Assert
            Assert.IsTrue(successResponse);
            Assert.IsFalse(failedResponse);
        }
        private void AddBodyParamsAndHeaders(IDictionary <string, string> additionalBodyParameters, string scopes)
        {
            _oAuth2Client.AddBodyParameter(OAuth2Parameter.ClientId, _requestParams.AppConfig.ClientId);
            _oAuth2Client.AddBodyParameter(OAuth2Parameter.ClientInfo, "1");


            if (_requestParams.ClientCredential != null)
            {
                Dictionary <string, string> ccBodyParameters = ClientCredentialHelper.CreateClientCredentialBodyParameters(
                    _requestParams.RequestContext.Logger,
                    _serviceBundle.PlatformProxy.CryptographyManager,
                    _requestParams.ClientCredential,
                    _requestParams.AppConfig.ClientId,
                    _requestParams.Endpoints,
                    _requestParams.SendX5C);

                foreach (var entry in ccBodyParameters)
                {
                    _oAuth2Client.AddBodyParameter(entry.Key, entry.Value);
                }
            }

            _oAuth2Client.AddBodyParameter(OAuth2Parameter.Scope, scopes);
            _oAuth2Client.AddBodyParameter(OAuth2Parameter.Claims, _requestParams.ClaimsAndClientCapabilities);

            foreach (var kvp in additionalBodyParameters)
            {
                _oAuth2Client.AddBodyParameter(kvp.Key, kvp.Value);
            }

            foreach (var kvp in _requestParams.AuthenticationScheme.GetTokenRequestParams())
            {
                _oAuth2Client.AddBodyParameter(kvp.Key, kvp.Value);
            }

            _oAuth2Client.AddHeader(
                TelemetryConstants.XClientCurrentTelemetry,
                _serviceBundle.HttpTelemetryManager.GetCurrentRequestHeader(
                    _requestParams.RequestContext.ApiEvent));

            if (!_requestInProgress)
            {
                _requestInProgress = true;

                _oAuth2Client.AddHeader(
                    TelemetryConstants.XClientLastTelemetry,
                    _serviceBundle.HttpTelemetryManager.GetLastRequestHeader());
            }

            //Signaling that the client can perform PKey Auth on supported platforms
            if (DeviceAuthHelper.CanOSPerformPKeyAuth())
            {
                _oAuth2Client.AddHeader(PKeyAuthConstants.DeviceAuthHeaderName, PKeyAuthConstants.DeviceAuthHeaderValue);
            }
        }
        public void ParsePKeyAuthChallengeData()
        {
            //Act
            var result = DeviceAuthHelper.ParseChallengeData(s_httpResponse.Headers);

            //Assert
            Assert.AreEqual(result["Version"], "1.0");
            Assert.AreEqual(result["CertThumbprint"], "thumbprint");
            Assert.AreEqual(result["Context"], "context");
            Assert.AreEqual(result["Nonce"], "nonce");
        }
        public bool TryCreateDeviceAuthChallengeResponseAsync(HttpResponseHeaders headers, Uri endpointUri, out string responseHeader)
        {
            responseHeader = string.Empty;
            Certificate certificate        = null;
            string      authHeaderTemplate = "PKeyAuth {0}, Context=\"{1}\", Version=\"{2}\"";

            if (!DeviceAuthHelper.IsDeviceAuthChallenge(headers))
            {
                return(false);
            }
            if (!DeviceAuthHelper.CanOSPerformPKeyAuth())
            {
                responseHeader = DeviceAuthHelper.GetBypassChallengeResponse(headers);
                return(false);
            }

            IDictionary <string, string> challengeData = DeviceAuthHelper.ParseChallengeData(headers);

            if (!challengeData.ContainsKey("SubmitUrl"))
            {
                challengeData["SubmitUrl"] = endpointUri.AbsoluteUri;
            }

            try
            {
                certificate = Task.FromResult(FindCertificateAsync(challengeData)).Result.Result;
            }
            catch (MsalException ex)
            {
                if (ex.ErrorCode == MsalError.DeviceCertificateNotFound)
                {
                    responseHeader = DeviceAuthHelper.GetBypassChallengeResponse(headers);
                    return(true);
                }
            }

            DeviceAuthJWTResponse responseJWT = new DeviceAuthJWTResponse(challengeData["SubmitUrl"],
                                                                          challengeData["nonce"], Convert.ToBase64String(certificate.GetCertificateBlob().ToArray()));
            IBuffer input = CryptographicBuffer.ConvertStringToBinary(responseJWT.GetResponseToSign(),
                                                                      BinaryStringEncoding.Utf8);
            CryptographicKey keyPair =
                Task.FromResult(PersistedKeyProvider.OpenKeyPairFromCertificateAsync(certificate, HashAlgorithmNames.Sha256, CryptographicPadding.RsaPkcs1V15)).Result.GetResults();

            IBuffer signed = Task.FromResult(CryptographicEngine.SignAsync(keyPair, input)).Result.GetResults();

            string signedJwt = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", responseJWT.GetResponseToSign(),
                                             Base64UrlHelpers.Encode(signed.ToArray()));
            string authToken = string.Format(CultureInfo.InvariantCulture, " AuthToken=\"{0}\"", signedJwt);

            responseHeader = string.Format(CultureInfo.InvariantCulture, authHeaderTemplate, authToken, challengeData["Context"], challengeData["Version"]);
            return(true);
        }
        public void GetDeviceAuthBypassChallengeResponse()
        {
            //Arrange
            Dictionary <string, string> pKeyAuthHeaders = new Dictionary <string, string>();

            pKeyAuthHeaders.Add("Context", "context");
            pKeyAuthHeaders.Add("Version", "1.0");

            //Act
            var result1 = DeviceAuthHelper.GetBypassChallengeResponse(s_httpResponse.Headers);
            var result2 = DeviceAuthHelper.GetBypassChallengeResponse(pKeyAuthHeaders);

            //Assert
            Assert.AreEqual(result1, TestConstants.PKeyAuthResponse);
            Assert.AreEqual(result2, TestConstants.PKeyAuthResponse);
        }
        private async Task <T> HandleDeviceAuthChallenge <T>(IHttpWebResponse response)
        {
            IDictionary <string, string> responseDictionary = this.ParseChallengeData(response);

            if (!responseDictionary.ContainsKey("SubmitUrl"))
            {
                responseDictionary["SubmitUrl"] = RequestUri;
            }

            string responseHeader = await DeviceAuthHelper.CreateDeviceAuthChallengeResponse(responseDictionary)
                                    .ConfigureAwait(false);

            IRequestParameters rp = this.Client.BodyParameters;

            this.Client = new HttpClientWrapper(CheckForExtraQueryParameter(responseDictionary["SubmitUrl"]),
                                                this.CallState);
            this.Client.BodyParameters           = rp;
            this.Client.Headers["Authorization"] = responseHeader;
            return(await this.GetResponseAsync <T>(false).ConfigureAwait(false));
        }
        void DecidePolicyForNavigation(WebView webView, NSDictionary actionInformation, NSUrlRequest request, WebFrame frame, NSObject decisionToken)
        {
            if (request == null)
            {
                WebView.DecideUse(decisionToken);
                return;
            }

            string requestUrlString = request.Url.ToString();

            if (requestUrlString.StartsWith(BrokerConstants.BrowserExtPrefix, StringComparison.OrdinalIgnoreCase))
            {
                var result = AuthorizationResult.FromStatus(
                    AuthorizationStatus.ProtocolError,
                    "Unsupported request",
                    "Server is redirecting client to browser. This behavior is not yet defined on Mac OS X.");
                _callbackMethod(result);
                WebView.DecideIgnore(decisionToken);
                Close();
                return;
            }

            if (requestUrlString.ToLower(CultureInfo.InvariantCulture).StartsWith(_callback.ToLower(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase) ||
                requestUrlString.StartsWith(BrokerConstants.BrowserExtInstallPrefix, StringComparison.OrdinalIgnoreCase))
            {
                _callbackMethod(AuthorizationResult.FromUri(request.Url.ToString()));
                WebView.DecideIgnore(decisionToken);
                Close();
                return;
            }

            if (requestUrlString.StartsWith(BrokerConstants.DeviceAuthChallengeRedirect, StringComparison.CurrentCultureIgnoreCase))
            {
                var    uri   = new Uri(requestUrlString);
                string query = uri.Query;
                if (query.StartsWith("?", StringComparison.OrdinalIgnoreCase))
                {
                    query = query.Substring(1);
                }

                Dictionary <string, string> keyPair = CoreHelpers.ParseKeyValueList(query, '&', true, false, null);
                string responseHeader = DeviceAuthHelper.GetBypassChallengeResponse(keyPair);

                var newRequest = (NSMutableUrlRequest)request.MutableCopy();
                newRequest.Url = new NSUrl(keyPair["SubmitUrl"]);
                newRequest[BrokerConstants.ChallengeResponseHeader] = responseHeader;
                webView.MainFrame.LoadRequest(newRequest);
                WebView.DecideIgnore(decisionToken);
                return;
            }

            if (!request.Url.AbsoluteString.Equals("about:blank", StringComparison.CurrentCultureIgnoreCase) &&
                !request.Url.Scheme.Equals("https", StringComparison.CurrentCultureIgnoreCase))
            {
                var result = AuthorizationResult.FromStatus(
                    AuthorizationStatus.ErrorHttp,
                    MsalError.NonHttpsRedirectNotSupported,
                    MsalErrorMessage.NonHttpsRedirectNotSupported);

                _callbackMethod(result);
                WebView.DecideIgnore(decisionToken);
                Close();
            }

            WebView.DecideUse(decisionToken);
        }
 public void CanOSPerformDeviceAuth()
 {
     Assert.IsFalse(DeviceAuthHelper.CanOSPerformPKeyAuth());
 }
 public void CanOSPerformDeviceAuth()
 {
     Assert.IsFalse(DeviceAuthHelper.CanOSPerformPKeyAuth());
     //Check one additinal time for cache
     Assert.IsFalse(DeviceAuthHelper.CanOSPerformPKeyAuth());
 }