Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Non-HTTPS Redirect failed Android maui #4994

Open
Swodah opened this issue Nov 14, 2024 · 3 comments
Open

[Bug] Non-HTTPS Redirect failed Android maui #4994

Swodah opened this issue Nov 14, 2024 · 3 comments
Assignees
Labels
needs attention Delete label after triage public-client untriaged Do not delete. Needed for Automation

Comments

@Swodah
Copy link

Swodah commented Nov 14, 2024

Library version used

4.66.2

.NET version

both .net 8 and .net 9.

Scenario

PublicClient - mobile app

Is this a new or an existing app?

This is a new app or experiment

Issue description and reproduction steps

Hello, the company I work for is making an integration to another company's integration to our national authentication broker (MitID (MyID)), and I am having issues getting MSAL to work the same on android as on ios and windows.

The case is that it works on ios but not android because - if my understanding is right - android doesn't allow the embedded msal window to open the app through a redirect.

The flow is that we connect to the broker used by "partner company" and they then redirect us to the national login method, which will ask us to open the app on the same device or another device.
If we open it on another device we will have to scan a qr code on the device we opened the authentication window, meaning the user would effectively need 2 devices on hand.
If we use the option to open on the same device it removes the need to scan (it isn't enough to just open the app manually it has to use the redirect info).

Below is the error:

{MSAL.Xamarin.Android.4.66.2.0.MsalServiceException:
ErrorCode: non_https_redirect_failed
Microsoft.Identity.Client.MsalServiceException: Non-HTTPS URL redirect is not supported in a web view. This error happens when the authorization flow, which collects user credentials, gets redirected to a page that is not supported, for example if the redirect occurs over http. This error does not trigger for the final redirect, which can be http://localhost, but for intermediary redirects.Mitigation: This usually happens when using a federated directory which is not setup correctly. - intent://appswitchmitid.page.link/?link=https://appswitch.mitid.dk?ticket"ticketid"returnUrl%3DChrome&apn=dk.mitid.app.android&afl=https://appswitch.mitid.dk#Intent;package=com.google.android.gms;action=com.google.firebase.dynamiclinks.VIEW_DYNAMIC_LINK;scheme=https;S.browser_fallback_url=https://appswitch.mitid.dk;end;
at Microsoft.Identity.Client.Internal.AuthCodeRequestComponent.VerifyAuthorizationResult(AuthorizationResult authorizationResult, String originalState)
at Microsoft.Identity.Client.Internal.AuthCodeRequestComponent.FetchAuthCodeAndPkceInternalAsync(IWebUI webUi, CancellationToken cancellationToken)
at Microsoft.Identity.Client.Internal.AuthCodeRequestComponent.FetchAuthCodeAndPkceVerifierAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.Internal.Requests.InteractiveRequest.GetTokenResponseAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.Internal.Requests.InteractiveRequest.ExecuteAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<>c__DisplayClass11_1.<b__1>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.Identity.Client.Utils.StopwatchService.MeasureCodeBlockAsync(Func`1 codeBlock)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.ApiConfig.Executors.PublicClientExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenInteractiveParameters interactiveParameters, CancellationToken cancellationToken)
at KMDStudicaApp.Services.AzureAuth.SignInAsync(String domainHint, String mail) in D:\Projects\KMDStudicaApp\Services\AzureAuth.cs:line 148
at KMDStudicaApp.Utility.GlobalMethods.DoLogin(String Username) in D:\Projects\KMDStudicaApp\Utility\GlobalMethods.cs:line 63
at KMDStudicaApp.Login.LoginTypePage.LoginUniLogin(Object sender, EventArgs e) in D:\Projects\KMDStudicaApp\Pages\Login\LoginTypePage.xaml.cs:line 24
StatusCode: 0
ResponseBody:
Headers: }

I have tried various work arounds:

  1. putting the WithUseEmbeddedWebView() option to false so it opens in browser, this allows the browser to open the app and the flow continues fine, until I have to return to the app, as the app is open on what looks like an msal windows without getting the response of data from the window opened in the system browser. - I have tried adding any code i could find that should be need for this workaround, including around 100 questions to github copilot to help generate what i might have forgotten.

  2. I have tried overwritting the maui webviewhandler:

x.AddHandler<WebView, Platforms.Android.AndroidWebViewHandler>();

The handler looking like this.

public class AndroidWebViewHandler : WebViewHandler
{
protected override void ConnectHandler(global::Android.Webkit.WebView platformView)
{
platformView.Settings.SetSupportMultipleWindows(false);
platformView.Settings.JavaScriptCanOpenWindowsAutomatically = true;

        platformView.Settings.JavaScriptEnabled = true;
        platformView.Settings.MixedContentMode = global::Android.Webkit.MixedContentHandling.AlwaysAllow;
        base.ConnectHandler(platformView);
    }
}

If this is working as intended i'd hope to hear a workaround.

Relevant code snippets

Relevant part of "InitializePublicClientAppAsync"

      var builder = PublicClientApplicationBuilder.Create(ClientID)
         .WithRedirectUri("msauth."apppackage"://auth")      .WithAuthority("https://logicidentityprod.b2clogin.com/tfp/logicidentityprod.onmicrosoft.com/B2C_1A_signup_signin");

android manifest line to catch the redirect back to our app: 
	<data android:scheme="msauth."apppackage"" android:host="auth" />

below is SignInAsync:

await InitializePublicClientAppAsync();

if (string.IsNullOrWhiteSpace(domainHint))
{
    var hint = await GetDomainHint(mail);
    domainHint = hint.hint;
}

try
{
    var accounts = await pca.GetAccountsAsync();
    var firstAccount = accounts.FirstOrDefault();
    var authResult = await pca.AcquireTokenSilent(Scopes, firstAccount).ExecuteAsync();
    AccessToken = authResult.AccessToken;
    GlobalConfig.SetEnviroment(Endpoints.baseUrl);
    GlobalConfig.SetDomainHint(domainHint);
    return authResult;
}
catch (MsalUiRequiredException)
{
    var dic = new Dictionary<string, string>
    {
        { "domain_hint", domainHint }
    };

    // This means we need to login again through the MSAL window.
    var builder = pca.AcquireTokenInteractive(Scopes)
        .WithExtraQueryParameters(dic)
        .WithPrompt(Prompt.ForceLogin)
        ;

    if (DeviceInfo.Platform == DevicePlatform.Android)
    {
        builder = builder.WithParentActivityOrWindow(ParentWindow);
        builder.WithUseEmbeddedWebView(true);
    }
    else
    {
    builder.WithUseEmbeddedWebView(true);
    }

    try
    {
        var authResult = await builder.ExecuteAsync();
        AccessToken = authResult.AccessToken;
        GlobalConfig.SetEnviroment(Endpoints.baseUrl);
        GlobalConfig.SetDomainHint(domainHint);
        return authResult;
    }
    catch (MsalClientException ex)
    {
        if (ex.ErrorCode.Equals("authentication_canceled", StringComparison.OrdinalIgnoreCase))
        {
            throw new UMS.UMSException(ex.Message, UMS.UMSExceptionCode.Unauthorized);
        }
        else
        {
            throw new UMS.UMSException(ex.Message, UMS.UMSExceptionCode.UnexpectedError);
        }
    }
}

Expected behavior

I expected android and iOS to handle the redirect to the MitID app without issue and then getting the clear in the window and continueing the flow.

Identity provider

Other

Regression

No response

Solution and workarounds

No response

@iulico-1
Copy link
Contributor

iulico-1 commented Nov 27, 2024

@Swodah, the main intent of MSAL auth libraries is to allow/support app integration with Microsoft Identity services - Entra ID. Are you authenticating with Entra ID in your scenario or you are using a different IDPs?

Currently the check you are hitting is by design MSAL.net library doesn't allow redirection to non HTTPS URIs.

If you are attempting to authenticate to Entra ID using .WithBroker() option will provide you with a more robust and secure solution.

@iulico-1 iulico-1 self-assigned this Nov 27, 2024
@Swodah
Copy link
Author

Swodah commented Nov 28, 2024

@iulico-1 I am not 100% sure, since i am a bit unsure on the jargon and the receiving sides setup.
As far as i understand it we contact an azure authentication service that redirects to the national idp "mitid". Then get returned back and the flow is supposed to continue and we should get a token.
step 1: contact the 3rd party partner for msal authentication.
step 2: redirect to mitid staying in the same msal window.
step 3: after authentication redirect back get token from 3rd party.
above doesn't work for us, though i have since been told that they are reconsidering their mitid integration as it may be halfbaked.

We have another app where my company controls most of the flow and we use another company for the contact to mitid, still using MSAL, where the redirect feature, though we open it in a browser there and the redirect link we get from the service is intercepted and handled.
Step 1: Use http api to contact our server to create a transaction request at mitid broker. and send link to app for mitid broker login.
Step 2: Open received link with msal and do a login (redirect that opens app works). redirect to app.
Step 3: App handles redirect and uses http api to contact our server again. Server checks the result of the login transaction with the broker. Server sends login token to app.

For now i'll await more news from the other company on their mitid integration if the msal contributors think it works as intended.

@espenrl
Copy link

espenrl commented Dec 19, 2024

Our MAUI app experiences this. Sentry collects reports regarding Microsoft 2-factor authentication. On Android only.

Uri: microsoft-authenticator://activatemfa/?code=<redacted>&url=https%3A%2F%2Fmobileappcommunicator.auth.microsoft.com%2Factivatev2%2F<redacted>

Microsoft.Identity.Client.MsalServiceException: Non-HTTPS URL redirect is not supported in a web view. This error happens when the authorization flow, which collects user credentials, gets redirected to a page that is not supported, for example if the redirect occurs over http. This error does not trigger for the final redirect, which can be http://localhost, but for intermediary redirects.Mitigation: This usually happens when using a federated directory which is not setup correctly. 
- microsoft-authenticator://activatemfa/?code=<redacted>&url=https%3A%2F%2Fmobileappcommunicator.auth.microsoft.com%2Factivatev2%2F<redacted>
  ?, in void AuthCodeRequestComponent.VerifyAuthorizationResult(AuthorizationResult authorizationResult, string originalState)
  ?, in async Task<Tuple<AuthorizationResult, string>> AuthCodeRequestComponent.FetchAuthCodeAndPkceInternalAsync(IWebUI webUi, CancellationToken cancellationToken)
  ?, in async Task<Tuple<AuthorizationResult, string>> AuthCodeRequestComponent.FetchAuthCodeAndPkceVerifierAsync(CancellationToken cancellationToken)
  ?, in async Task<MsalTokenResponse> InteractiveRequest.GetTokenResponseAsync(CancellationToken cancellationToken)
  ?, in async Task<AuthenticationResult> InteractiveRequest.ExecuteAsync(CancellationToken cancellationToken)
  ?, in async Task<AuthenticationResult> RequestBase.RunAsync(CancellationToken cancellationToken)+(?) => { }
  ?, in async Task<MeasureDurationResult> StopwatchService.MeasureCodeBlockAsync(Func<Task> codeBlock)
  ?, in async Task<AuthenticationResult> RequestBase.RunAsync(CancellationToken cancellationToken)
  ?, in async Task<AuthenticationResult> PublicClientExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenInteractiveParameters interactiveParameters, CancellationToken cancellationToken)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs attention Delete label after triage public-client untriaged Do not delete. Needed for Automation
Projects
None yet
Development

No branches or pull requests

3 participants