ARTICLE

MAUI Hybrid Blazor Login: JavaScript Interop, Public IP Detection, and Access Control

Flow

๐Ÿงฉ The Problem and Flow

A MAUI Hybrid Blazor login can coordinate browser JavaScript, a public-IP check, server access control, authentication, and module navigation. Click any step to jump to the related implementation.

Page renders
    โ†“
OnAfterRenderAsync(firstRender)
    โ†“
Register JavaScript interop
    โ†“
JavaScript calls Blazor
    โ†“
Fetch public IP
    โ†“
API checks IP access
    โ†“
Enable login controls
    โ†“
Authenticate user
    โ†“
sessionStorage stores non-sensitive context
    โ†“
Navigate to the target module

โš™๏ธ Step 1: OnAfterRenderAsync

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await RegisterJs();
        await Task.Delay(1000);
        isVideoReady = true;
        await InvokeAsync(StateHasChanged);
    }
}

๐Ÿ”— Step 2: Register JavaScript Interop

private DotNetObjectReference<Login_DTVS>? objRef;

protected override void OnInitialized()
{
    objRef = DotNetObjectReference.Create(this);
}

private async Task RegisterJs()
{
    await JS.InvokeVoidAsync("myInterop.register", objRef);
}

public void Dispose()
{
    objRef?.Dispose();
}

โ†”๏ธ Step 3: JavaScript Calls Blazor

window.myInterop = {
    dotNetHelper: null,
    register: function (dotNetHelper) {
        this.dotNetHelper = dotNetHelper;
        window.hasregistered = true;
    },
    callBlazor: function () {
        this.dotNetHelper.invokeMethodAsync(
            "UpdateMessage", "Hello from JavaScript!"
        );
    }
};

๐ŸŒ Step 4: Fetch the Public IP

async function getPublicIP() {
    const response = await fetch('https://api.ipify.org?format=json');
    const data = await response.json();
    return data.ip;
}

string res = await JS.InvokeAsync<string>("getPublicIP");
clientIp = res;

The request is asynchronous, so the C# caller awaits the JavaScript result.

๐Ÿ›ก๏ธ Step 5: API Checks IP Access

var response = await Http.GetFromJsonAsync<AccessResponse>(
    "http://serverip:serverport/Auth/check-access/" + res);

if (response != null)
{
    hasFullAccess = response.HasAccess;
    clientIp = response.IpAddress;
}

โœ… Step 6: Enable Login Controls

<button class="login-btn"
        @onclick="HandleLogin"
        disabled="@isLoading || !@hasFullAccess">
    Sign in
</button>

The UI remains gated until the access decision is available.

๐Ÿ” Step 7: Authenticate the User

var reqq = new AuthApiService.LoginRequest
{
    category = selectedPlant == "1108" ? "E" : "S",
    UserID = username,
    LoginPwd = password,
    IpAddress = clientIp
};

var lr = await AuthService.LoginAsync(reqq);

๐Ÿ’พ Step 8: Store Non-Sensitive Context

await JS.InvokeVoidAsync("sessionStorage.setItem", "PlantCode", selectedPlant);
await JS.InvokeVoidAsync("sessionStorage.setItem", "LoginId", username);
await JS.InvokeVoidAsync("sessionStorage.setItem", "CompCode", selectedPlant);

Keep only non-sensitive context here. Do not store the password in sessionStorage.

โžก๏ธ Step 9: Navigate to the Target Module

if (!string.IsNullOrWhiteSpace(lr.RedirectTo))
{
    await AuthService.AutoRejectPendingApprovalsAsync(selectedPlant);
    Nav.NavigateTo("/" + lr.RedirectTo);
}

๐Ÿšฆ Handling Login Errors

if (!string.IsNullOrWhiteSpace(lr.Error))
{
    ToastMessage = lr.Error;
    ShowToast = true;
    StateHasChanged();
    await Task.Delay(3000);
    ShowToast = false;
    return;
}

๐Ÿง  Why Timing Matters

Browser-dependent JavaScript should be coordinated with the component lifecycle. The first OnAfterRenderAsync call provides a reliable point to register the JavaScript bridge, while the API remains responsible for authentication and authorization decisions.

๐Ÿงน Cleanup

public void Dispose()
{
    objRef?.Dispose();
}

๐Ÿš€ Final Pattern

Blazor owns the UI and orchestration, JavaScript supplies browser capabilities such as public-IP lookup and session storage, and the API handles authentication/access decisions. The interactive flow connects the explanation directly to the relevant code.

NEWSLETTER

Subscribe to the Algolassi newsletter

Get practical .NET, C#, Blazor, SQL Server and developer tips in your inbox. No spam, just useful updates.

๐Ÿค– AlgoLassi Assistant Have a question about this tutorial?

Ask AlgoLassi and get an answer plus the tutorials worth studying next.

Ask a question

๐Ÿ’ฌ Comments

Sign in with Google to publish immediately, or comment anonymously and wait for approval.

Comments will appear here when available.