Node-red login for mobile apps

 string apiUrl = "http://40.87.141.219:1880/ui/"; // API endpoint

 using (HttpClient httpClient = new HttpClient())
 {

     string base64Credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"));
     httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64Credentials);


     HttpResponseMessage responsec = await httpClient.GetAsync(apiUrl);

     await Console.Out.WriteLineAsync("");

     try
     {


         HttpResponseMessage response = await httpClient.GetAsync(apiUrl);
         if (response.IsSuccessStatusCode)
         {


             Device.BeginInvokeOnMainThread(async () =>
             {

                 string content = await response.Content.ReadAsStringAsync();

                 // Create a new WebView to display the downloaded content
                 WebView webView = new WebView
                 {
                     Source = new HtmlWebViewSource { Html = content },
                     VerticalOptions = LayoutOptions.FillAndExpand
                 };

                 // Replace the existing content of the page with the WebView
                 Content = webView;


                 await Task.Delay( 5000);
                 webView.Reload();



             });

         }

         else
         {
         
             Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}");
             kosulum = false;
             await DisplayAlert("Login notttt", "AR" + kosulum, "AR");


         }

     }
     catch (HttpRequestException e)
     {
         Console.WriteLine($"HTTP Request Error: {e.Message}");
         kosulum = false;
     }

    
 }

i try to login with http basic auth , it approves login but

shows somethng like that?

anyone work with that before?

Hi @halukmy

That isn't' going to work.

I'm going to assume you are using .NET MAUI.

All you are doing is fetching the response body, and using it as the content for a HtmlWebViewSource instance, and applying it to the WebView

HtmlWebViewSource is only used to render local HTML content.

Effectively you are just grabbing some HTML, and rendering it to display

  • The WebView has no idea where it actually is (therefore won't load remote resources)
  • It will not open up web socket connections (as needed by dashboard)

If you want to have the WebView actually "navigate" you need to set the Source property to the URI, this will then should start up a real browser session for your URI

WebView webView = new WebView
{
   Source = apiUrl 
};

you are awesome dude!

        HttpResponseMessage response = await httpClient.GetAsync(apiUrl);
        if (response.IsSuccessStatusCode)
        {


            Device.BeginInvokeOnMainThread(async () =>
            {

                string content = await response.Content.ReadAsStringAsync();

                // Create a new WebView to display the downloaded content
                var webView = new HtmlWebViewSource
                {
                    BaseUrl = apiUrl
                 // Source = apiUrl ,//new HtmlWebViewSource { Html = content },
                    //VerticalOptions = LayoutOptions.FillAndExpand
                };

                // Replace the existing content of the page with the WebView


                Content = webView;



            });

        }

i tried this but didnt worked, can you share a code sample ?

Try this.

Note: I have not tested this code, and don't have much xp with WebView (or MAUI in general)
I don't know how WebView handles 401 error (Authentication), so you will need to investigate

string apiUrl = "http://40.87.141.219:1880/ui/"; // API endpoint
WebView webView; // We will use this later in a task

Device.BeginInvokeOnMainThread(() =>
{
    // I'm sure the dashboard  uses cookies 
    CookieContainer cookieContainer = new CookieContainer();

    // Create a new WebView to display the page
    webView = new WebView
    {
        Cookies = cookieContainer,
        Source = new UrlWebViewSource { Url = apiUrl },
        VerticalOptions = LayoutOptions.FillAndExpand
    };

    // Replace the existing content with the WebView
    Content = webView;

    // Don't block the main thread, else you will stop  anything happening during this time
    // await Task.Delay(5000);

    // Instead start a task, and block it internally, then reload the web view on the main thread
    Task.Run(async delegate 
    {
        await Task.Delay(2000)
        Device.BeginInvokeOnMainThread(() =>
        {
            webView.Reload(); // Might be unnecessary?
        });
    });
});

EDIT
I don't actually know if the WebView supports websockets - which is used heavily to drive the dashboard interface

image

i get it again..

username creditintials like;

user

areytechai

Then you may need to subclass WebView to get access to the headers (to set the Basic auth header for dashboard)

  1. Create a custom WebView (see code at bottom)
    See : Add a property on WebView to set additional headers · Issue #7920 · dotnet/maui · GitHub

  2. Use it instead of the default WebView (I have added Username & Password & Url)

string apiUrl = "http://40.87.141.219:1880/ui/"; // API endpoint
AuthenticatedWebView webView; // We will use this later in a task

.... Your other stuff

webView = new AuthenticatedWebView
{
    Username = "Muy Username",
    Password = "My Password",
    Cookies = cookieContainer,
    Url = apiUrl, /* We need to do this */
    Source = new UrlWebViewSource { Url = apiUrl },
    VerticalOptions = LayoutOptions.FillAndExpand
};

The Custom Web View

public class AuthenticatedWebView : WebView
{
	static AuthenticatedWebView()
	{
		Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping(nameof(IWebView.Source), (handler, view) =>
		{
            string base64Credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{webView.Username}:{webView.Password}"));

			if (view is AuthenticatedWebView webView)
			{
				var url = webView.Url!;
#if ANDROID
                var headers = new Dictionary<string, string>
                {
                    ["Authorization"] = $"Basic {base64Credentials}"
                };
                handler.PlatformView.LoadUrl(url, headers);
#elif iOS
                var webRequest = new NSMutableUrlRequest(new NSUrl(url));
                var headerKey = new NSString("Authorization");
                var headerValue = new NSString($"Basic {base64Credentials}");
                var dictionary = new NSDictionary(headerKey, headerValue);
                webRequest.Headers = dictionary;

                handler.PlatformView.LoadRequest(webRequest);
#else
				throw new NotImplementedException();
#endif
			}
		});
	}

	public static readonly BindableProperty UsernameProp = BindableProperty.Create("Username", typeof(string), typeof(AuthenticatedWebView), "");
	public string? Username
	{
		get => GetValue(UsernameProp) as string;
		set => SetValue(UsernameProp, value);
	}

    public static readonly BindableProperty PasswordProp = BindableProperty.Create("Password", typeof(string), typeof(AuthenticatedWebView), "");
	public string? Password
	{
		get => GetValue(PasswordProp) as string;
		set => SetValue(PasswordProp, value);
	}

	public static readonly BindableProperty UrlProp = BindableProperty.Create("Url", typeof(string), typeof(AuthenticatedWebView), "");
	public string? Url
	{
		get => GetValue(UrlProp) as string;
		set => SetValue(UrlProp, value);
	}
}

using System.Net;
using System.Text;

namespace AR_OS;

public partial class Start : ContentPage
{
string apiUrl = "http://40.87.141.219:1880/ui/#!/0?socketid=VFqBMJFjudF6QADXAAAp"; // API endpoint
string username = "user";
string password = "areytechai";
public Start()
{
InitializeComponent();
}
protected override bool OnBackButtonPressed()
{
Application.Current.Quit();
return true;
}
static bool kosulum = false;
WebView webView;
private async void LoginButton_Clicked(object sender, EventArgs e)
{

    ar("user", "areytechai");

    await Console.Out.WriteLineAsync(kosulum.ToString());

    string apiUrl = "http://40.87.141.219:1880/ui/"; // API endpoint


    AuthenticatedWebView webView; // We will use this later in a task


    CookieContainer cookieContainer = new CookieContainer();



    webView = new AuthenticatedWebView
    {
        Username = "Muy Username",
        Password = "My Password",
        Cookies = cookieContainer,
        Url = apiUrl, /* We need to do this */
        Source = new UrlWebViewSource { Url = apiUrl },
        VerticalOptions = LayoutOptions.FillAndExpand
    };
    await Task.Delay(2000);

    Content = webView;

    await Task.Delay(2000);
    Device.BeginInvokeOnMainThread(() =>
    {
        webView.Reload(); // Might be unnecessary?
    });

}

private async void WebView_Navigated(object sender, WebNavigatedEventArgs e)
{
    // HTML formunu otomatik olarak doldurmak için JavaScript kullanabiliriz
    var script = "document.getElementById('login').value = '12345';" +
                 "document.getElementById('pass').value = '55555';";

    await webView.EvaluateJavaScriptAsync(script);


}

async Task<bool> ar(string username, string password)
{
    

    return kosulum;
}
public class AuthenticatedWebView : WebView
{
    static AuthenticatedWebView()
    {
        Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping(nameof(IWebView.Source), (handler, view) =>
        {
            string base64Credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{"user"}:{"areytechai"}"));

            if (view is AuthenticatedWebView webView)
            {
                var url = webView.Url!;

#if ANDROID
var headers = new Dictionary<string, string>
{
["Authorization"] = $"Basic {base64Credentials}"
};
handler.PlatformView.LoadUrl(url, headers);
#elif iOS
var webRequest = new NSMutableUrlRequest(new NSUrl(url));
var headerKey = new NSString("Authorization");
var headerValue = new NSString($"Basic {base64Credentials}");
var dictionary = new NSDictionary(headerKey, headerValue);
webRequest.Headers = dictionary;

            handler.PlatformView.LoadRequest(webRequest);

#else
throw new NotImplementedException();
#endif
}
});
}

    public static readonly BindableProperty UsernameProp = BindableProperty.Create("Username", typeof(string), typeof(AuthenticatedWebView), "");
    public string? Username
    {
        get => GetValue(UsernameProp) as string;
        set => SetValue(UsernameProp, value);
    }

    public static readonly BindableProperty PasswordProp = BindableProperty.Create("Password", typeof(string), typeof(AuthenticatedWebView), "");
    public string? Password
    {
        get => GetValue(PasswordProp) as string;
        set => SetValue(PasswordProp, value);
    }

    public static readonly BindableProperty UrlProp = BindableProperty.Create("Url", typeof(string), typeof(AuthenticatedWebView), "");
    public string? Url
    {
        get => GetValue(UrlProp) as string;
        set => SetValue(UrlProp, value);
    }
}
bool IsCredentialCorrect(string username, string password)
{





    return Username.Text == "admin" && Password.Text == "1234";

}

}

This is code and now i get the page is not loaded

Try this.

I think WebView when it's running as a real browser doesn't like non-encrypted traffic.
I'm not sure where you put this (I don't develop for Android) - maybe in your application XML?

android:usesCleartextTraffic="true"

i used it on managment file, now get unauth , i shared results of vebView results, and i make directly connect to content , totally not get page

is there possible simple maui app file on here ?

Hi @halukmy I'm afraid my knowledge on the matter is exhausted.

This is the problem you face.

  • You need to show the dashboard in a webview
  • Your dashboard is password protected
  • You don't want to prompt for auth in your app

Therefore, you need to somehow get access to the Web Request that the WebView will make, before it's executed to inject any header information to satisfy the auth request.

All my code examples were from searching the web - I'm sure the answer is very close by.

Sorry, i'm not sure what else I can add

still working alot, but couldnt fix ... is there a way to show basic auth login with c#?

i have login but , i cant get details, it says add some nodes or soemthng

Then the webview does not support web sockets (required by dashboard)

IMO - based on your problems, do not use webview, its quite limited obviously, not many here will have the answer.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.