# Node-red login for mobile apps

**URL:** https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984
**Category:** General
**Tags:** node-red-dashboard
**Created:** [12 October 2023 21:36 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984 "2023-10-12T21:36:07Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![halukmy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/halukmy/32/31192_2.png) [@halukmy](https://discourse.nodered.org/u/halukmy)
#### Post date: [12 October 2023 21:36 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/1 "2023-10-12T21:36:07Z")

</div>

```
 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

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/5/250298388ecad665d6e00f16fbee1539cc28a567.png)

shows somethng like that?

anyone work with that before?

---

<div class="post-metadata">

### Author: ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)
#### Post date: [13 October 2023 09:03 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/2 "2023-10-13T09:03:56Z")

</div>

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

```csharp
WebView webView = new WebView
{
   Source = apiUrl 
};

```

---

<div class="post-metadata">

### Author: ![halukmy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/halukmy/32/31192_2.png) [@halukmy](https://discourse.nodered.org/u/halukmy)
#### Post date: [13 October 2023 22:02 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/3 "2023-10-13T22:02:03Z")

</div>

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 ?

---

<div class="post-metadata">

### Author: ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)
#### Post date: [14 October 2023 08:42 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/4 "2023-10-14T08:42:17Z")

</div>

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

```csharp
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

---

<div class="post-metadata">

### Author: ![halukmy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/halukmy/32/31192_2.png) [@halukmy](https://discourse.nodered.org/u/halukmy)
#### Post date: [14 October 2023 09:27 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/5 "2023-10-14T09:27:21Z")

</div>

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/b/5bbf2c93085aea136d05655d19db16d230c05d97.png)

i get it again..

username creditintials like;

user

areytechai

---

<div class="post-metadata">

### Author: ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)
#### Post date: [14 October 2023 10:34 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/6 "2023-10-14T10:34:06Z")

</div>

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](https://github.com/dotnet/maui/issues/7920)

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

```auto
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

```auto
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);
	}
}

```

---

<div class="post-metadata">

### Author: ![halukmy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/halukmy/32/31192_2.png) [@halukmy](https://discourse.nodered.org/u/halukmy)
#### Post date: [15 October 2023 13:09 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/7 "2023-10-15T13:09:46Z")

</div>

> [@halukmy](#):
>
> `webView`

using [System.Net](http://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](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

 ![WhatsApp Image 2023-10-15 at 16.09.43_a04ec555](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/0/c05fa555b6fce7abef7b4c5e4508082b0681732b.jpeg)

---

<div class="post-metadata">

### Author: ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)
#### Post date: [15 October 2023 14:14 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/8 "2023-10-15T14:14:44Z")

</div>

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?

```auto
android:usesCleartextTraffic="true"

```

---

<div class="post-metadata">

### Author: ![halukmy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/halukmy/32/31192_2.png) [@halukmy](https://discourse.nodered.org/u/halukmy)
#### Post date: [15 October 2023 15:19 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/9 "2023-10-15T15:19:43Z")

</div>

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

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/7/d7034a5df4393de8b3e762f6ac2484abe347e85d.png)

is there possible simple maui app file on here ?

---

<div class="post-metadata">

### Author: ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)
#### Post date: [15 October 2023 15:30 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/10 "2023-10-15T15:30:28Z")

</div>

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

---

<div class="post-metadata">

### Author: ![halukmy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/halukmy/32/31192_2.png) [@halukmy](https://discourse.nodered.org/u/halukmy)
#### Post date: [21 October 2023 19:02 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/11 "2023-10-21T19:02:57Z")

</div>

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

---

<div class="post-metadata">

### Author: ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)
#### Post date: [21 October 2023 19:35 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/12 "2023-10-21T19:35:44Z")

</div>

> [@halukmy](#):
>
> 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.

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [20 December 2023 19:36 UTC](https://discourse.nodered.org/t/node-red-login-for-mobile-apps/81984/13 "2023-12-20T19:36:23Z")

</div>

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