private string CreateDeviceCodeRequestUriString() { var deviceCodeRequestParameters = new DictionaryRequestParameters(this.resource, this.clientKey); if (this.callState != null && this.callState.CorrelationId != Guid.Empty) { deviceCodeRequestParameters[OAuthParameter.CorrelationId] = this.callState.CorrelationId.ToString(); } if (PlatformPlugin.HttpClientFactory.AddAdditionalHeaders) { IDictionary <string, string> adalIdParameters = AdalIdHelper.GetAdalIdParameters(); foreach (KeyValuePair <string, string> kvp in adalIdParameters) { deviceCodeRequestParameters[kvp.Key] = kvp.Value; } } if (!string.IsNullOrWhiteSpace(extraQueryParameters)) { // Checks for extraQueryParameters duplicating standard parameters Dictionary <string, string> kvps = EncodingHelper.ParseKeyValueList(extraQueryParameters, '&', false, this.callState); foreach (KeyValuePair <string, string> kvp in kvps) { if (deviceCodeRequestParameters.ContainsKey(kvp.Key)) { throw new AdalException(AdalError.DuplicateQueryParameter, string.Format(CultureInfo.CurrentCulture, AdalErrorMessage.DuplicateQueryParameterTemplate, kvp.Key)); } } deviceCodeRequestParameters.ExtraQueryParameter = extraQueryParameters; } return(new Uri(new Uri(this.authenticator.DeviceCodeUri), "?" + deviceCodeRequestParameters).AbsoluteUri); }
/// <summary> /// Creates authentication parameters from the WWW-Authenticate header in response received from resource. This method expects the header to contain authentication parameters. /// </summary> /// <param name="authenticateHeader">Content of header WWW-Authenticate header</param> /// <returns>AuthenticationParameters object containing authentication parameters</returns> public static AuthenticationParameters CreateFromResponseAuthenticateHeader(string authenticateHeader) { if (string.IsNullOrWhiteSpace(authenticateHeader)) { throw new ArgumentNullException("authenticateHeader"); } authenticateHeader = authenticateHeader.Trim(); // This also checks for cases like "BearerXXXX authorization_uri=...." and "Bearer" and "Bearer " if (!authenticateHeader.StartsWith(Bearer, StringComparison.OrdinalIgnoreCase) || authenticateHeader.Length < Bearer.Length + 2 || !char.IsWhiteSpace(authenticateHeader[Bearer.Length])) { var ex = new ArgumentException(AdalErrorMessage.InvalidAuthenticateHeaderFormat, "authenticateHeader"); PlatformPlugin.Logger.Error(null, ex); throw ex; } authenticateHeader = authenticateHeader.Substring(Bearer.Length).Trim(); Dictionary <string, string> authenticateHeaderItems = EncodingHelper.ParseKeyValueList(authenticateHeader, ',', false, null); var authParams = new AuthenticationParameters(); string param; authenticateHeaderItems.TryGetValue(AuthorityKey, out param); authParams.Authority = param; authenticateHeaderItems.TryGetValue(ResourceKey, out param); authParams.Resource = param; return(authParams); }
protected override void UpdateBrokerParameters(IDictionary <string, string> parameters) { Uri uri = new Uri(this.authorizationResult.Code); string query = EncodingHelper.UrlDecode(uri.Query); Dictionary <string, string> kvps = EncodingHelper.ParseKeyValueList(query, '&', false, this.CallState); parameters["username"] = kvps["username"]; }
public override bool ShouldOverrideUrlLoading(WebView view, string url) { Uri uri = new Uri(url); if (url.StartsWith(BrokerConstants.BrowserExtPrefix)) { PlatformPlugin.Logger.Verbose(null, "It is browser launch request"); OpenLinkInBrowser(url, ((Activity)view.Context)); view.StopLoading(); ((Activity)view.Context).Finish(); return(true); } if (url.StartsWith(BrokerConstants.BrowserExtInstallPrefix)) { PlatformPlugin.Logger.Verbose(null, "It is an azure authenticator install request"); view.StopLoading(); this.Finish(view, url); return(true); } if (url.StartsWith(BrokerConstants.ClientTlsRedirect, StringComparison.CurrentCultureIgnoreCase)) { string query = uri.Query; if (query.StartsWith("?")) { query = query.Substring(1); } Dictionary <string, string> keyPair = EncodingHelper.ParseKeyValueList(query, '&', true, false, null); string responseHeader = PlatformPlugin.DeviceAuthHelper.CreateDeviceAuthChallengeResponse(keyPair).Result; Dictionary <string, string> pkeyAuthEmptyResponse = new Dictionary <string, string>(); pkeyAuthEmptyResponse[BrokerConstants.ChallangeResponseHeader] = responseHeader; view.LoadUrl(keyPair["SubmitUrl"], pkeyAuthEmptyResponse); return(true); } if (url.StartsWith(callback, StringComparison.OrdinalIgnoreCase)) { this.Finish(view, url); return(true); } if (!url.Equals("about:blank", StringComparison.CurrentCultureIgnoreCase) && !uri.Scheme.Equals("https", StringComparison.CurrentCultureIgnoreCase)) { UriBuilder errorUri = new UriBuilder(callback); errorUri.Query = string.Format("error={0}&error_description={1}", AdalError.NonHttpsRedirectNotSupported, AdalErrorMessage.NonHttpsRedirectNotSupported); this.Finish(view, errorUri.ToString()); return(true); } return(false); }
private DictionaryRequestParameters CreateAuthorizationRequest(string loginHint) { var authorizationRequestParameters = new DictionaryRequestParameters(this.Resource, this.ClientKey); authorizationRequestParameters[OAuthParameter.ResponseType] = OAuthResponseType.Code; authorizationRequestParameters[OAuthParameter.HasChrome] = "1"; authorizationRequestParameters[OAuthParameter.RedirectUri] = this.redirectUriRequestParameter; if (!string.IsNullOrWhiteSpace(loginHint)) { authorizationRequestParameters[OAuthParameter.LoginHint] = loginHint; } if (this.CallState != null && this.CallState.CorrelationId != Guid.Empty) { authorizationRequestParameters[OAuthParameter.CorrelationId] = this.CallState.CorrelationId.ToString(); } if (this.authorizationParameters != null) { PlatformPlugin.PlatformInformation.AddPromptBehaviorQueryParameter(this.authorizationParameters, authorizationRequestParameters); } if (PlatformPlugin.HttpClientFactory.AddAdditionalHeaders) { IDictionary <string, string> adalIdParameters = AdalIdHelper.GetAdalIdParameters(); foreach (KeyValuePair <string, string> kvp in adalIdParameters) { authorizationRequestParameters[kvp.Key] = kvp.Value; } } if (!string.IsNullOrWhiteSpace(extraQueryParameters)) { // Checks for extraQueryParameters duplicating standard parameters Dictionary <string, string> kvps = EncodingHelper.ParseKeyValueList(extraQueryParameters, '&', false, this.CallState); foreach (KeyValuePair <string, string> kvp in kvps) { if (authorizationRequestParameters.ContainsKey(kvp.Key)) { throw new AdalException(AdalError.DuplicateQueryParameter, string.Format(CultureInfo.CurrentCulture, AdalErrorMessage.DuplicateQueryParameterTemplate, kvp.Key)); } } authorizationRequestParameters.ExtraQueryParameter = extraQueryParameters; } return(authorizationRequestParameters); }
public void ParseAuthorizeResponse(string webAuthenticationResult) { var resultUri = new Uri(webAuthenticationResult); // NOTE: The Fragment property actually contains the leading '#' character and that must be dropped string resultData = resultUri.Query; if (!string.IsNullOrWhiteSpace(resultData)) { // Remove the leading '?' first Dictionary <string, string> response = EncodingHelper.ParseKeyValueList(resultData.Substring(1), '&', true, null); if (response.ContainsKey(TokenResponseClaim.Code)) { this.Code = response[TokenResponseClaim.Code]; } else if (webAuthenticationResult.StartsWith("msauth://", StringComparison.CurrentCultureIgnoreCase)) { this.Code = webAuthenticationResult; } else if (response.ContainsKey(TokenResponseClaim.Error)) { this.Error = response[TokenResponseClaim.Error]; this.ErrorDescription = response.ContainsKey(TokenResponseClaim.ErrorDescription) ? response[TokenResponseClaim.ErrorDescription] : null; this.Status = AuthorizationStatus.ProtocolError; } else { this.Error = AdalError.AuthenticationFailed; this.ErrorDescription = AdalErrorMessage.AuthorizationServerInvalidResponse; this.Status = AuthorizationStatus.UnknownError; } } else { this.Error = AdalError.AuthenticationFailed; this.ErrorDescription = AdalErrorMessage.AuthorizationServerInvalidResponse; this.Status = AuthorizationStatus.UnknownError; } }
public async Task <AuthenticationResultEx> AcquireTokenUsingBroker(IDictionary <string, string> brokerPayload) { if (brokerPayload.ContainsKey("silent_broker_flow")) { throw new AdalSilentTokenAcquisitionException(); } brokerResponse = null; brokerResponseReady = new SemaphoreSlim(0); //call broker string base64EncodedString = Base64UrlEncoder.Encode(BrokerKeyHelper.GetRawBrokerKey()); brokerPayload["broker_key"] = base64EncodedString; brokerPayload["max_protocol_ver"] = "2"; if (brokerPayload.ContainsKey("broker_install_url")) { string url = brokerPayload["broker_install_url"]; Uri uri = new Uri(url); string query = uri.Query; if (query.StartsWith("?")) { query = query.Substring(1); } Dictionary <string, string> keyPair = EncodingHelper.ParseKeyValueList(query, '&', true, false, null); DispatchQueue.MainQueue.DispatchAsync(() => UIApplication.SharedApplication.OpenUrl(new NSUrl(keyPair["app_link"]))); throw new AdalException(AdalErrorIOSEx.BrokerApplicationRequired, AdalErrorMessageIOSEx.BrokerApplicationRequired); } else { NSUrl url = new NSUrl("msauth://broker?" + brokerPayload.ToQueryParameter()); DispatchQueue.MainQueue.DispatchAsync(() => UIApplication.SharedApplication.OpenUrl(url)); } await brokerResponseReady.WaitAsync(); return(ProcessBrokerResponse()); }
private AuthenticationResultEx ResultFromBrokerResponse(IDictionary <string, string> responseDictionary) { TokenResponse response = new TokenResponse(); if (responseDictionary.ContainsKey("error") || responseDictionary.ContainsKey("error_description")) { response = TokenResponse.CreateFromBrokerResponse(responseDictionary); } else { string expectedHash = responseDictionary["hash"]; string encryptedResponse = responseDictionary["response"]; string decryptedResponse = BrokerKeyHelper.DecryptBrokerResponse(encryptedResponse); string responseActualHash = PlatformPlugin.CryptographyHelper.CreateSha256Hash(decryptedResponse); byte[] rawHash = Convert.FromBase64String(responseActualHash); string hash = BitConverter.ToString(rawHash); if (expectedHash.Equals(hash.Replace("-", ""))) { responseDictionary = EncodingHelper.ParseKeyValueList(decryptedResponse, '&', false, null); response = TokenResponse.CreateFromBrokerResponse(responseDictionary); } else { response = new TokenResponse { Error = AdalError.BrokerReponseHashMismatch, ErrorDescription = AdalErrorMessage.BrokerReponseHashMismatch }; } } var dateTimeOffset = new DateTimeOffset(new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)); dateTimeOffset = dateTimeOffset.AddSeconds(response.ExpiresOn); return(response.GetResult(dateTimeOffset)); }
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 = new AuthorizationResult(AuthorizationStatus.ProtocolError) { Error = "Unsupported request", ErrorDescription = "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(new AuthorizationResult(AuthorizationStatus.Success, 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 = EncodingHelper.ParseKeyValueList(query, '&', true, false, null); string responseHeader = PlatformPlugin.DeviceAuthHelper.CreateDeviceAuthChallengeResponse(keyPair).Result; 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 = new AuthorizationResult(AuthorizationStatus.ErrorHttp); result.Error = AdalError.NonHttpsRedirectNotSupported; result.ErrorDescription = AdalErrorMessage.NonHttpsRedirectNotSupported; callbackMethod(result); WebView.DecideIgnore(decisionToken); Close(); } WebView.DecideUse(decisionToken); }
void WebView_NavigateToUrl(object sender, NavigateToUrlEventArgs e) { /*Console.WriteLine(e.Uri); * if (e.Uri.ToString().StartsWith("urn:ietf:wg:oauth:2.0:oob", StringComparison.InvariantCultureIgnoreCase)) * { * Console.WriteLine("MAGICAL SPECIAL HANDLING"); * Application.Invoke(delegate { progressIndicator.Indeterminate = true; progressIndicator.Fraction = 0;}); * }*/ if (e == null) { return; } string requestUrlString = e.Uri.ToString(); if (requestUrlString.StartsWith(BrokerConstants.BrowserExtPrefix, StringComparison.OrdinalIgnoreCase)) { var result = new AuthorizationResult(AuthorizationStatus.ProtocolError) { Error = "Unsupported request", ErrorDescription = "Server is redirecting client to browser. This behavior is not yet defined on Mac OS X." }; callbackMethod(result); webView.StopLoading(); Application.Invoke(delegate { Close(); }); return; } if (requestUrlString.ToLower(CultureInfo.InvariantCulture).StartsWith(callback.ToLower(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase) || requestUrlString.StartsWith(BrokerConstants.BrowserExtInstallPrefix, StringComparison.OrdinalIgnoreCase)) { callbackMethod(new AuthorizationResult(AuthorizationStatus.Success, requestUrlString)); webView.StopLoading(); Application.Invoke(delegate { 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 = EncodingHelper.ParseKeyValueList(query, '&', true, false, null); string responseHeader = PlatformPlugin.DeviceAuthHelper.CreateDeviceAuthChallengeResponse(keyPair).Result; /*var newRequest = WebRequest.CreateHttp(keyPair["SubmitUrl"]); * newRequest.Headers[BrokerConstants.ChallengeResponseHeader] = responseHeader; * var newRequest = (NSMutableUrlRequest)request.MutableCopy(); * newRequest.Url = new NSUrl(keyPair["SubmitUrl"]); * newRequest[BrokerConstants.ChallengeResponseHeader] = responseHeader; * webView.MainFrame.LoadRequest(newRequest); * WebView.DecideIgnore(decisionToken);*/ return; } if (!e.Uri.AbsoluteUri.Equals("about:blank", StringComparison.CurrentCultureIgnoreCase) && !e.Uri.Scheme.Equals("https", StringComparison.CurrentCultureIgnoreCase)) { var result = new AuthorizationResult(AuthorizationStatus.ErrorHttp); result.Error = AdalError.NonHttpsRedirectNotSupported; result.ErrorDescription = AdalErrorMessage.NonHttpsRedirectNotSupported; callbackMethod(result); webView.StopLoading(); Application.Invoke(delegate { Close(); }); } }
public void AcquireToken(IDictionary <string, string> brokerPayload) { if (brokerPayload.ContainsKey("broker_install_url")) { string url = brokerPayload["broker_install_url"]; Uri uri = new Uri(url); string query = uri.Query; if (query.StartsWith("?")) { query = query.Substring(1); } Dictionary <string, string> keyPair = EncodingHelper.ParseKeyValueList(query, '&', true, false, null); PlatformParameters pp = PlatformParameters as PlatformParameters; pp.CallerActivity.StartActivity(new Intent(Intent.ActionView, Android.Net.Uri.Parse(keyPair["app_link"]))); throw new AdalException(AdalErrorAndroidEx.BrokerApplicationRequired, AdalErrorMessageAndroidEx.BrokerApplicationRequired); } Context mContext = Application.Context; AuthenticationRequest request = new AuthenticationRequest(brokerPayload); PlatformParameters platformParams = PlatformParameters as PlatformParameters; // BROKER flow intercepts here // cache and refresh call happens through the authenticator service if (mBrokerProxy.VerifyUser(request.LoginHint, request.UserId)) { PlatformPlugin.Logger.Verbose(null, "It switched to broker for context: " + mContext.PackageName); request.BrokerAccountName = request.LoginHint; // Don't send background request, if prompt flag is always or // refresh_session if (!string.IsNullOrEmpty(request.BrokerAccountName) || !string.IsNullOrEmpty(request.UserId)) { PlatformPlugin.Logger.Verbose(null, "User is specified for background token request"); resultEx = mBrokerProxy.GetAuthTokenInBackground(request, platformParams.CallerActivity); } else { PlatformPlugin.Logger.Verbose(null, "User is not specified for background token request"); } if (resultEx != null && resultEx.Result != null && !string.IsNullOrEmpty(resultEx.Result.AccessToken)) { PlatformPlugin.Logger.Verbose(null, "Token is returned from background call "); readyForResponse.Release(); return; } // Launch broker activity // if cache and refresh request is not handled. // Initial request to authenticator needs to launch activity to // record calling uid for the account. This happens for Prompt auto // or always behavior. PlatformPlugin.Logger.Verbose(null, "Token is not returned from backgroud call"); // Only happens with callback since silent call does not show UI PlatformPlugin.Logger.Verbose(null, "Launch activity for Authenticator"); PlatformPlugin.Logger.Verbose(null, "Starting Authentication Activity"); if (resultEx == null) { PlatformPlugin.Logger.Verbose(null, "Initial request to authenticator"); // Log the initial request but not force a prompt } if (brokerPayload.ContainsKey("silent_broker_flow")) { throw new AdalSilentTokenAcquisitionException(); } // onActivityResult will receive the response // Activity needs to launch to record calling app for this // account Intent brokerIntent = mBrokerProxy.GetIntentForBrokerActivity(request, platformParams.CallerActivity); if (brokerIntent != null) { try { PlatformPlugin.Logger.Verbose(null, "Calling activity pid:" + Android.OS.Process.MyPid() + " tid:" + Android.OS.Process.MyTid() + "uid:" + Android.OS.Process.MyUid()); platformParams.CallerActivity.StartActivityForResult(brokerIntent, 1001); } catch (ActivityNotFoundException e) { PlatformPlugin.Logger.Error(null, e); } } } else { throw new AdalException(AdalErrorAndroidEx.NoBrokerAccountFound, "Add requested account as a Workplace account via Settings->Accounts or set UseBroker=true."); } }
public override void ViewDidLoad() { base.ViewDidLoad(); View.BackgroundColor = UIColor.White; webView = new UIWebView((CGRect)View.Bounds); webView.ShouldStartLoad = (wView, request, navType) => { if (request == null) { return(true); } string requestUrlString = request.Url.ToString(); if (requestUrlString.StartsWith(BrokerConstants.BrowserExtPrefix, StringComparison.OrdinalIgnoreCase)) { DispatchQueue.MainQueue.DispatchAsync(() => CancelAuthentication(null, null)); requestUrlString = requestUrlString.Replace(BrokerConstants.BrowserExtPrefix, "https://"); DispatchQueue.MainQueue.DispatchAsync( () => UIApplication.SharedApplication.OpenUrl(new NSUrl(requestUrlString))); this.DismissViewController(true, null); return(false); } if (requestUrlString.ToLower(CultureInfo.InvariantCulture).StartsWith(callback.ToLower(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase) || requestUrlString.StartsWith(BrokerConstants.BrowserExtInstallPrefix, StringComparison.OrdinalIgnoreCase)) { callbackMethod(new AuthorizationResult(AuthorizationStatus.Success, request.Url.ToString())); this.DismissViewController(true, null); return(false); } if (requestUrlString.StartsWith(BrokerConstants.DeviceAuthChallengeRedirect, StringComparison.CurrentCultureIgnoreCase)) { Uri uri = new Uri(requestUrlString); string query = uri.Query; if (query.StartsWith("?", StringComparison.OrdinalIgnoreCase)) { query = query.Substring(1); } Dictionary <string, string> keyPair = EncodingHelper.ParseKeyValueList(query, '&', true, false, null); string responseHeader = PlatformPlugin.DeviceAuthHelper.CreateDeviceAuthChallengeResponse(keyPair).Result; NSMutableUrlRequest newRequest = (NSMutableUrlRequest)request.MutableCopy(); newRequest.Url = new NSUrl(keyPair["SubmitUrl"]); newRequest[BrokerConstants.ChallengeResponseHeader] = responseHeader; wView.LoadRequest(newRequest); return(false); } if (!request.Url.AbsoluteString.Equals("about:blank", StringComparison.CurrentCultureIgnoreCase) && !request.Url.Scheme.Equals("https", StringComparison.CurrentCultureIgnoreCase)) { AuthorizationResult result = new AuthorizationResult(AuthorizationStatus.ErrorHttp); result.Error = AdalError.NonHttpsRedirectNotSupported; result.ErrorDescription = AdalErrorMessage.NonHttpsRedirectNotSupported; callbackMethod(result); this.DismissViewController(true, null); return(false); } return(true); }; webView.LoadFinished += delegate { // If the title is too long, iOS automatically truncates it and adds ... this.Title = webView.EvaluateJavascript(@"document.title") ?? "Sign in"; }; View.AddSubview(webView); this.NavigationItem.LeftBarButtonItem = new UIBarButtonItem(UIBarButtonSystemItem.Cancel, this.CancelAuthentication); webView.LoadRequest(new NSUrlRequest(new NSUrl(this.url))); // if this is false, page will be 'zoomed in' to normal size //webView.ScalesPageToFit = true; }