MAUI BlazorWebView fails to establish WebRTC connection on Android due to insecure host (https://0.0.0.0)
Description
Description: When creating a MAUI Blazor Hybrid app in .NET 8.0 and setting up a WebRTC connection between devices, the getUserMedia function in JavaScript works as expected on iOS and Windows platforms, allowing the video stream to be set up successfully.
However, on Android, the connection fails despite the necessary permissions being requested and assigned to the app. The issue arises because the BlazorWebView on Android requests access to the device through the host https://0.0.0.0, which Android treats as insecure, causing the connection to be blocked.
For multi-platform apps that require messaging and communication, this makes MAUI currently unsuitable on Android. There is no clear way to signal to Android that this is a secure connection, nor is there an option to override the default host when calling from the BlazorWebView.
Why this is a bug: This is not a feature request but a bug because the WebRTC setup works perfectly on iOS and Windows out of the box. WebRTC is a widely used standard, and MAUI needs to support it consistently across all platforms, including Android.
Expected Behavior:
The getUserMedia function should be able to request the device's media securely on Android, just as it does on iOS and Windows. MAUI should either treat the BlazorWebView as secure on Android or provide a way to override the default host (https://0.0.0.0) used in the WebRTC request.
Steps to Reproduce
Steps to Reproduce:
Create a new MAUI Blazor Hybrid app in .NET 8.0. Implement WebRTC using the getUserMedia function in JavaScript. Test the app on iOS, Windows, and Android devices. Observe that the connection works on iOS and Windows but fails on Android due to the insecure host issue. Environment:
.NET version: 8.0 MAUI version: (insert version) Platform: Android (failing), iOS and Windows (working)
Link to public reproduction project repository
No response
Version with bug
8.0.82 SR8.2
Is this a regression from previous behavior?
No, this is something new
Last version that worked well
Unknown/Other
Affected platforms
Android
Affected platform versions
14 and up
Did you find any workaround?
No workarounds currently work.
Relevant log output
14:03:20:299 [CameraManagerGlobal] Connecting to camera service
14:03:20:299 [VendorTagDescriptor] addVendorDescriptor: vendor tag id 11706189966126095484 added
14:03:20:299 [VendorTagDescriptor] addVendorDescriptor: vendor tag id 15055940602041719656 added
14:03:20:366 [CameraManagerGlobal] Camera 0 facing CAMERA_FACING_BACK state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 1 facing CAMERA_FACING_FRONT state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 2 facing CAMERA_FACING_BACK state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 20 facing CAMERA_FACING_BACK state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 21 facing CAMERA_FACING_BACK state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 23 facing CAMERA_FACING_BACK state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 3 facing CAMERA_FACING_FRONT state now CAMERA_STATE_CLOSED for client com.samsung.android.smartface API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 4 facing CAMERA_FACING_FRONT state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 52 facing CAMERA_FACING_BACK state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 56 facing CAMERA_FACING_BACK state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [DeviceStateManager] handleDeviceStateInfoChanged state=0, baseState=0
14:03:20:366 [CameraManagerGlobal] Camera 58 facing CAMERA_FACING_BACK state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 71 facing CAMERA_FACING_FRONT state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 73 facing CAMERA_FACING_FRONT state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:366 [CameraManagerGlobal] Camera 90 facing CAMERA_FACING_FRONT state now CAMERA_STATE_CLOSED for client android.system API Level 2 User Id 0
14:03:20:422 [chromium] [INFO:CONSOLE(58)] "Error initializing camera: [object DOMException]", source: https://0.0.0.0/js/jsMessage.js (58)
Hi I'm an AI powered bot that finds similar issues based off the issue title.
Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!
Closed similar issues:
- [regression/8.0.3] BlazorWebView does not initialize properly on Android platform (#19013), similarity score: 0.75
- Blazor MAUI - Camera/Microphone Android - NotAllowedError: Permission denied (#3694), similarity score: 0.73
- .NET MAUI Blazor UWP doesn't not allow camera access through javascript library or functions. (#10176), similarity score: 0.71
- [iOs] MAUI Blazor Hybrid '//' urls not treated as secure (#19297), similarity score: 0.71
- Can't connect to secure websocket(wss) with android 8 (#8952), similarity score: 0.70
Note: You can give me feedback by thumbs upping or thumbs downing this comment.
Hi I'm an AI powered bot that finds similar issues based off the issue title.
Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!
Closed similar issues:
- [regression/8.0.3] BlazorWebView does not initialize properly on Android platform (#19013), similarity score: 0.75
- Blazor MAUI - Camera/Microphone Android - NotAllowedError: Permission denied (#3694), similarity score: 0.73
- .NET MAUI Blazor UWP doesn't not allow camera access through javascript library or functions. (#10176), similarity score: 0.71
- [iOs] MAUI Blazor Hybrid '//' urls not treated as secure (#19297), similarity score: 0.71
- Can't connect to secure websocket(wss) with android 8 (#8952), similarity score: 0.70
Note: You can give me feedback by thumbs upping or thumbs downing this comment.
These are either not the same issue or have poor workarounds that have since been removed by losing access to various overloads.
Could you provide us with a sample project so we can investigate it further? Looking forward to your reply!
Please find attached project to test.
Run in Windows mode it will work, deploy to iPhone and it will also work, try deploying to Android phone you will get the error. https://0.0.0.0 is trying to get access to camera and fail.
@steveo555 How do you know that the use of https://0.0.0.0 is the root issue here?
Running your sample, I looked at that object DOMException and it's a NOT ALLOWED permission error. Your app does request permissions, but that's for the App itself. The webview itself needs to have those permissions set, which should be, I think, done in WebChromeClient (https://github.com/dotnet/maui/blob/b2c1d25f7a71197666c2053c1e40dbdea6049cc7/src/BlazorWebView/src/Maui/Android/BlazorWebChromeClient.cs#L15-L98) which isn't happening.
So I think there's a bug here in MAUI with its Blazor Webview, but it seems like a permission error, unrelated to the host. Do you have a way to verify your claim?
Hi Thanks for getting back to me.
@steveo555 How do you know that the use of https://0.0.0.0 is the root issue here?
Running your sample, I looked at that
object DOMExceptionand it's aNOT ALLOWEDpermission error. Your app does request permissions, but that's for the App itself. The webview itself needs to have those permissions set, which should be, I think, done inWebChromeClient(https://github.com/dotnet/maui/blob/b2c1d25f7a71197666c2053c1e40dbdea6049cc7/src/BlazorWebView/src/Maui/Android/BlazorWebChromeClient.cs#L15-L98
) which isn't happening. So I think there's a bug here in MAUI with its Blazor Webview, but it seems like a permission error, unrelated to the host. Do you have a way to verify your claim?
Thanks for the reply. Did you try adding this to the sample I gave and got it to work? I still get the error. Also I have collated the following....
"Android restricts access to certain web APIs, including those for camera access, to secure origins only."
Source: Chromium Security FAQ
"Certain web platform features are restricted to secure contexts. For example, the geolocation API and the getUserMedia API (for accessing the microphone and camera) are only available to secure origins."
Chromium Security FAQ
Android Developers Documentation "For apps targeting Android 6.0 (API level 23) and later, the system considers your app's activities to be secure by default, and secure origins are required for secure content."
https://developer.android.com/guide/webapps/security
Explanation: Android's WebView is based on Chromium and inherits its security policies. Both platforms restrict access to sensitive APIs like the camera to secure origins to protect user privacy and security.
"This means that web pages must be served over HTTPS with a valid certificate from a recognized Certificate Authority (CA)."
Source: W3C Secure Contexts Specification
"A context is considered secure when it is delivered securely and all the resources it loads are also delivered securely."
https://www.w3.org/TR/secure-contexts/#secure-context
MDN Web Docs on getUserMedia() For security reasons, getUserMedia() can only be used from a secure origin (HTTPS or localhost).
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
Explanation: Secure origins are typically defined as HTTPS connections using valid SSL/TLS certificates issued by recognized CAs. This ensures encrypted communication and verified server identity.
"Using an insecure origin like https://0.0.0.0 will result in Android refusing permission requests for sensitive features like the camera."
Source: IANA Special-Purpose Address Registry "0.0.0.0/8 — This block denotes invalid or unknown addresses."
IANA IPv4 Special-Purpose Address Registry Let's Encrypt Documentation "Let's Encrypt can't issue certificates for 'localhost' or for IP addresses such as '127.0.0.1'." Let's Encrypt - Certificates for localhost
Explanation: The IP address 0.0.0.0 is non-routable and cannot have a valid SSL/TLS certificate issued to it. As a result, any HTTPS connection to 0.0.0.0 is considered insecure, and Android will deny permission requests from such origins. Additional References:
Google Developers on Secure Contexts:
"Starting with Chrome 47, getUserMedia() (for camera and microphone access) is only available from secure origins." Google Developers - Avoiding the Not Secure Warning in Chrome
Web Fundamentals - What is Considered a Secure Context?
"A context is considered secure when it is delivered securely and all the resources it loads are also delivered securely." Web Fundamentals - Secure Contexts
So from API 23 and above Andriod will also black https://0.0.0.0 from access to the camera.
That's why we need another mechanism to serve pages in the blazorwebview that allows either a certificate or localhost as the host.
Let me know what you think.
@steveo555 The Android link link you posted above 404s, and I couldn't find it on the Internet Archive.
Yes, by enabling the permissions to go through at the Android WebView level, I could get it to run:
https://github.com/drasticactions/maui/commit/16f9587099ef6a9ef2b9afce4a0e3bae8f740a51
This is because, as I wrote, the Android webview itself (As in, the actual Android WebView) is asking for permissions that would normally need to be handled by the developer with the web view. So you need two levels of permissions, for the app and for the WebView.
The MAUI WebView and Blazor WebView wrapper don't handle this event. With the MAUI WebView (The regular one with no direct Blazor Hybrid support), you can override the handler to pass in your own WebChromeClient, that can handle this event and allow the permissions through. You can't with the Blazor WebView since it's private.
There are conversations about changing 0.0.0.0 to something else, but I believe that's not your issue here. It would work if you were able to handle this event... that said, the code I wrote above is wrong. That, AFAIK, will allow all permission requests to go through, which you would never want to do (And 100% not want in the platform code itself).
So that would require coming up with a way to pass that event up the chain so you, the developer, can handle it. The right thing to do here is let you handle this event so you can see which webpage (since you could have IFrames or other content trying to get access for permissions) to then allow them to go through or not.
So in short:
- I think this is a bug in MAUI and not your code
- It involves you not being able to handle permissions in the Blazor/MAUI WebView for Android
- It is unrelated to 0.0.0.0 (although that should be changed)
- It would probably require a new API to surface this event (Which, AFAIK, is only in Android) within the MAUI/Blazor WebView.
@Eilon What do you think?
I concur with your points and understand the implications. I apologize for any confusion caused earlier. The key issue is that using 0.0.0.0 as a host is not considered secure, and this approach will need to change if we aim to future-proof any permission-based APIs that Android may leverage in the future.
Ideally, the permissions that have been requested, approved, and applied to the native application should be propagated to the WebView component, as they are on Windows and iOS platforms. Alternatively, there should be an efficient method to obtain the necessary permissions within the WebView context without excessive complexity.
My immediate challenge is that I have an upcoming deadline for the Android version of my project, and I need to find an effective workaround for this issue. It does not create a positive impression to inform users that certain functionality is available only on iOS devices, with Android support "coming soon." Consequently, I may need to temporarily disable the iOS web call functionality to ensure consistency across platforms until a proper solution is implemented.
@drasticactions - Would you be able to modify the sample project I upload with the code you mentioned gets it working please?
Moving to the Backlog as a feature request. Specifically, we will consider adding ability to override this behavior in the WebView.
Any news guys? I need to get this functionality out to the Android test group. I've added the
public override void OnPermissionRequest(PermissionRequest? request)
{
request?.Grant(request.GetResources());
}
but its still the same error.
Cheers
any work around for this issue? thanks
any work around for this issue? thanks
Not yet as far as I am aware. .NET 9 preview has same issue.
Any news on this. There is still no workaround or way to get it working in Android. iOS still works fine.
@mkArtakMSFT anything here? This still exists in .net core 9
@drasticactions @steveo555 Hey guys, just so I'm completely clear... it's not possible for WebRTC to function with MAUI Blazor currently?
Just to be clear, it was working in iOS builds but not Android.
HOWEVER, in .NET 9.0 Release, it is now possible. I think they have changed the WebView to use 0.0.0.1 which, for now, the OS is allowing to access permissions as long as you override the WebView and have a custom handler to handle permission requests.
Like this:
#if IOS
using Foundation;
using WebKit;
using Microsoft.AspNetCore.Components.WebView.Maui;
using Microsoft.Maui.Handlers;
namespace ThePathfinderApp.Platforms.iOS;
public class CustomBlazorWebViewHandler : BlazorWebViewHandler
{
protected override WKWebView CreatePlatformView()
{
var webView = base.CreatePlatformView();
if (webView.Configuration != null)
{
webView.Configuration.AllowsInlineMediaPlayback = true;
webView.Configuration.MediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypes.None;
}
webView.AllowsBackForwardNavigationGestures = true;
webView.ScrollView.Bounces = false;
webView.AutoresizingMask = UIKit.UIViewAutoresizing.FlexibleDimensions;
// Disable safe area
webView.InsetsLayoutMarginsFromSafeArea = false;
webView.LayoutMargins = new UIKit.UIEdgeInsets(0, 0, 0, 0);
webView.ScrollView.ContentInsetAdjustmentBehavior = UIKit.UIScrollViewContentInsetAdjustmentBehavior.Never;
return webView;
}
}
#endif
And in your MainProgram.cs:
builder.UseMauiApp<App>().ConfigureMauiHandlers(handlers =>
{
#if ANDROID handlers.AddHandler<BlazorWebView, CustomBlazorWebViewHandler>();
#endif
});
Then, as long as the user has granted permission, it will work. You'll need a TURN server for video because mobile devices mess around with DNS and ports, but once you set that up, it will work at last.
It's not a long-term solution — we really need the ability to set the WebView to have a secure context with our app's proper address and certificate — but it's a start, I guess.
I hope that helps you. It's taken me a year to get it working 👍
@steveo555 Thank you, I appreciate your thorough write up!
Hi, good day. Any updates on this? I need to implement WebRTC in MAUI BlazorWebView on Android. @mkArtakMSFT @jfversluis @jamesmontemagno
Just to be clear, it was working in iOS builds but not Android.
HOWEVER, in .NET 9.0 Release, it is now possible. I think they have changed the WebView to use 0.0.0.1 which, for now, the OS is allowing to access permissions as long as you override the WebView and have a custom handler to handle permission requests.
Like this:
#if IOS using Foundation; using WebKit; using Microsoft.AspNetCore.Components.WebView.Maui; using Microsoft.Maui.Handlers;
namespace ThePathfinderApp.Platforms.iOS;
public class CustomBlazorWebViewHandler : BlazorWebViewHandler { protected override WKWebView CreatePlatformView() { var webView = base.CreatePlatformView();
if (webView.Configuration != null) { webView.Configuration.AllowsInlineMediaPlayback = true; webView.Configuration.MediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypes.None; } webView.AllowsBackForwardNavigationGestures = true; webView.ScrollView.Bounces = false; webView.AutoresizingMask = UIKit.UIViewAutoresizing.FlexibleDimensions; // Disable safe area webView.InsetsLayoutMarginsFromSafeArea = false; webView.LayoutMargins = new UIKit.UIEdgeInsets(0, 0, 0, 0); webView.ScrollView.ContentInsetAdjustmentBehavior = UIKit.UIScrollViewContentInsetAdjustmentBehavior.Never; return webView; }} #endif
And in your MainProgram.cs:
builder.UseMauiApp<App>().ConfigureMauiHandlers(handlers => { #if ANDROID handlers.AddHandler<BlazorWebView, CustomBlazorWebViewHandler>(); #endif }); Then, as long as the user has granted permission, it will work. You'll need a TURN server for video because mobile devices mess around with DNS and ports, but once you set that up, it will work at last.
It's not a long-term solution — we really need the ability to set the WebView to have a secure context with our app's proper address and certificate — but it's a start, I guess.
I hope that helps you. It's taken me a year to get it working 👍
Yes mate, see this 👆🏻