1

I try to authorize with swedish BankID from Android and i can't redirect to my app. I use Essentials.WebAuthenticator and from IOS it works perfect, but android can't redirect from final page to my app.

Page after auth

WebAuthenticatorBrowser

internal class WebAuthenticatorBrowser : IBrowser
    {
        private readonly string _callbackUrl;

        public WebAuthenticatorBrowser(string callbackUrl = null)
        {
            _callbackUrl = callbackUrl ?? "";
        }
        public async Task<BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken = default)
        {
            try
            {
                var callbackUrl = string.IsNullOrEmpty(_callbackUrl) ? options.EndUrl : _callbackUrl;
                WebAuthenticatorResult authResult =
                    await WebAuthenticator.AuthenticateAsync(new Uri(options.StartUrl), new Uri(callbackUrl));
                var authorizeResponse = ToRawIdentityUrl(options.EndUrl, authResult);

                return new BrowserResult
                {
                    Response = authorizeResponse
                };
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                return new BrowserResult()
                {
                    ResultType = BrowserResultType.UnknownError,
                    Error = ex.ToString()
                };
            }
        }

        public string ToRawIdentityUrl(string redirectUrl, WebAuthenticatorResult result)
        {
            IEnumerable<string> parameters = result.Properties.Select(pair => $"{pair.Key}={pair.Value}");
            var values = string.Join("&", parameters);

            return $"{redirectUrl}#{values}";
        }
    }

MainActivity

    namespace JAG.Droid
{
    [Activity(Label = "JAG", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize,
        LaunchMode = Android.Content.PM.LaunchMode.SingleInstance)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

            Xamarin.Essentials.Platform.ActivityStateChanged += Platform_ActivityStateChanged;

            LoadApplication(new App());
        }
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

        protected override void OnResume()
        {
            base.OnResume();
            Xamarin.Essentials.Platform.OnResume();
        }

        protected override void OnNewIntent(Intent intent)
        {
            base.OnNewIntent(intent);

            Xamarin.Essentials.Platform.OnNewIntent(intent);
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();

            Xamarin.Essentials.Platform.ActivityStateChanged -= Platform_ActivityStateChanged;
        }

        void Platform_ActivityStateChanged(object sender, Xamarin.Essentials.ActivityStateChangedEventArgs e) =>
            Toast.MakeText(this, e.State.ToString(), ToastLength.Short).Show();
    }

    [Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop)]
    [IntentFilter(new[] { Android.Content.Intent.ActionView }, Categories = new[]
    { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable }, DataScheme = "JAG")]
    public class WebAuthenticatorCallbackActivity : Xamarin.Essentials.WebAuthenticatorCallbackActivity
    {

    }
}

OIDC config

var options = new OidcClientOptions
        {
            Authority = AUTHORITY,
            ClientId = CLIENTID,
            ClientSecret = CLIENTSECRET,
            Scope = SCOPE,
            RedirectUri = REDIRECTURI,
            PostLogoutRedirectUri = LOGOUTREDIRECTURI,
            Browser = new WebAuthenticatorBrowser() 
        };

        options.BackchannelHandler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = (message, certificate, chain, sslPolicyErrors) => true };
        options.Policy.Discovery.RequireHttps = false;
        App.OIDCclient = new OidcClient(options);

Call login

_result = await App.OIDCclient.LoginAsync(new LoginRequest());

            if (_result.IsError)
            {
                Microsoft.AppCenter.AppCenterLog.Error("Error", _result.Error);
                return;
            }

If I close final page I get Exception

A task was canceled.

     at Xamarin.Essentials.WebAuthenticator.PlatformAuthenticateAsync (System.Uri url, System.Uri callbackUrl) [0x001c3] in D:\a\1\s\Xamarin.Essentials\WebAuthenticator\WebAuthenticator.android.cs:94 
  at JAG.Helpers.WebAuthenticatorBrowser.InvokeAsync (IdentityModel.OidcClient.Browser.BrowserOptions options, System.Threading.CancellationToken cancellationToken) [0x00071] in /Users/samoykin/projects/tests/IntroApp/JAG/Helpers/WebAuthenticatorBrowser.cs:25
Andrey
  • 11
  • 1
  • [Authenticator AP](https://devblogs.microsoft.com/xamarin/authentication-xamarin-essentials-aspnet/#web-authenticator-api) contains method AuthenticateAsync which takes two parameters. The url that starts the authentication flow, and the Uri that your app is registered to handle the callback on. The result is a WebAuthenticatorResult which includes any query parameters parsed from the callback URI. Android requires an Intent Filter setup to handle your callback URI. This is easily accomplished by subclassing the WebAuthenticatorCallbackActivity class. – Cherry Bu - MSFT Jul 12 '21 at 08:43
  • 1
    @CherryBu-MSFT Yes, I have WebAuthenticatorCallbackActivity - it is in code above. I think there right DataScheme, an it works with Google auth. In the end I got this url from Identity Service /connect/authorize/callback?response_type=code&nonce=dSe5yD2JZfA8NYfjRe3-VA&state=XFgN-LhqJcIRCdRfdrNrfQ&code_challenge=bZHAHaACBBbz0KtlFC6GUaB5E7E_IiVewrgpWAHRGfU&code_challenge_method=S256&client_id=mobileLogin&scope=openid%20profile&redirect_uri=JAG%3A%2F%2Fintroapp-callback It has redirectUri, but webpage ignore it and stay on page https://myidentityservice/External/Callback – Andrey Jul 12 '21 at 12:33

0 Answers0