Beispiel #1
0
        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;
        }
        public override string ToString()
        {
            StringBuilder messageBuilder = new StringBuilder();

            foreach (KeyValuePair <string, string> kvp in this)
            {
                EncodingHelper.AddKeyValueString(messageBuilder, EncodingHelper.UrlEncode(kvp.Key), EncodingHelper.UrlEncode(kvp.Value));
            }

            if (this.ExtraQueryParameter != null)
            {
                messageBuilder.Append('&' + this.ExtraQueryParameter);
            }

            return(messageBuilder.ToString());
        }
        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))
            {
                CallState.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
                bool hasAccountNameOrUserId = !string.IsNullOrEmpty(request.BrokerAccountName) || !string.IsNullOrEmpty(request.UserId);
                if (string.IsNullOrEmpty(request.Claims) && hasAccountNameOrUserId)
                {
                    CallState.Logger.Verbose(null, "User is specified for background token request");
                    resultEx = mBrokerProxy.GetAuthTokenInBackground(request, platformParams.CallerActivity);
                }
                else
                {
                    CallState.Logger.Verbose(null, "User is not specified for background token request");
                }

                if (resultEx != null && resultEx.Result != null && !string.IsNullOrEmpty(resultEx.Result.AccessToken))
                {
                    CallState.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.
                CallState.Logger.Verbose(null, "Token is not returned from backgroud call");

                // Only happens with callback since silent call does not show UI
                CallState.Logger.Verbose(null, "Launch activity for Authenticator");
                CallState.Logger.Verbose(null, "Starting Authentication Activity");
                if (resultEx == null)
                {
                    CallState.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
                    {
                        CallState.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)
                    {
                        CallState.Logger.Error(null, e);
                    }
                }
            }
            else
            {
                throw new AdalException(AdalErrorAndroidEx.NoBrokerAccountFound, "Add requested account as a Workplace account via Settings->Accounts or set UseBroker=true.");
            }
        }
Beispiel #4
0
        private async Task <T> GetResponseAsync <T>(bool respondToDeviceAuthChallenge)
        {
            T typedResponse = default(T);
            IHttpWebResponse response;

            try
            {
                if (PlatformPlugin.HttpClientFactory.AddAdditionalHeaders)
                {
                    IDictionary <string, string> adalIdHeaders = AdalIdHelper.GetAdalIdParameters();
                    foreach (KeyValuePair <string, string> kvp in adalIdHeaders)
                    {
                        this.Client.Headers[kvp.Key] = kvp.Value;
                    }
                }

                //add pkeyauth header
                this.Client.Headers[DeviceAuthHeaderName] = DeviceAuthHeaderValue;
                using (response = await this.Client.GetResponseAsync().ConfigureAwait(false))
                {
                    typedResponse = EncodingHelper.DeserializeResponse <T>(response.ResponseString);
                }
            }
            catch (HttpRequestWrapperException ex)
            {
                if (ex.InnerException is TaskCanceledException)
                {
                    Resiliency = true;
                    PlatformPlugin.Logger.Information(this.CallState, "Network timeout - " + ex.InnerException.Message);
                }

                if (!this.isDeviceAuthChallenge(ex.WebResponse, respondToDeviceAuthChallenge))
                {
                    AdalServiceException serviceEx;
                    if (ex.WebResponse != null)
                    {
                        TokenResponse tokenResponse = TokenResponse.CreateFromErrorResponse(ex.WebResponse);
                        string[]      errorCodes    = tokenResponse.ErrorCodes ?? new[] { ex.WebResponse.StatusCode.ToString() };
                        serviceEx = new AdalServiceException(tokenResponse.Error, tokenResponse.ErrorDescription,
                                                             errorCodes, ex);

                        if (ex.WebResponse.StatusCode == HttpStatusCode.BadRequest && tokenResponse.Error == AdalError.InteractionRequired)
                        {
                            throw new AdalClaimChallengeException(tokenResponse.Error, tokenResponse.ErrorDescription, tokenResponse.Claims);
                        }

                        if ((int)ex.WebResponse.StatusCode >= 500 && (int)ex.WebResponse.StatusCode < 600)
                        {
                            PlatformPlugin.Logger.Information(this.CallState, "HttpStatus code: " + ex.WebResponse.StatusCode + " - " + ex.InnerException.Message);
                            Resiliency = true;
                        }
                    }

                    else
                    {
                        serviceEx = new AdalServiceException(AdalError.Unknown, ex);
                    }

                    if (Resiliency)
                    {
                        if (RetryOnce)
                        {
                            await Task.Delay(DelayTimePeriodMilliSeconds).ConfigureAwait(false);

                            RetryOnce = false;
                            PlatformPlugin.Logger.Information(this.CallState, "Retrying one more time..");
                            return(await this.GetResponseAsync <T>(respondToDeviceAuthChallenge).ConfigureAwait(false));
                        }

                        PlatformPlugin.Logger.Information(this.CallState,
                                                          "Retry Failed - " + ex.InnerException.Message);
                    }

                    PlatformPlugin.Logger.Error(CallState, serviceEx);
                    throw serviceEx;
                }
                else
                {
                    response = ex.WebResponse;
                }
            }
            //check for pkeyauth challenge
            if (this.isDeviceAuthChallenge(response, respondToDeviceAuthChallenge))
            {
                return(await HandleDeviceAuthChallenge <T>(response).ConfigureAwait(false));
            }

            return(typedResponse);
        }
        private StringBuilder ToStringBuilder()
        {
            StringBuilder messageBuilder = new StringBuilder();

            if (this.stringBuilderParameter != null)
            {
                messageBuilder.Append(this.stringBuilderParameter);
            }

            foreach (KeyValuePair <string, string> kvp in this)
            {
                EncodingHelper.AddKeyValueString(messageBuilder, EncodingHelper.UrlEncode(kvp.Key), EncodingHelper.UrlEncode(kvp.Value));
            }

            this.AddSecureParametersToMessageBuilder(messageBuilder);

            if (this.ExtraQueryParameter != null)
            {
                messageBuilder.Append('&' + this.ExtraQueryParameter);
            }

            return(messageBuilder);
        }