Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion UltimateAuth.slnx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Solution>
<Folder Name="/Samples/">
<Project Path="samples/blazor-server/UltimateAuth.BlazorServer/UltimateAuth.BlazorServer.csproj" />
<Project Path="samples/blazor-server/UltimateAuth.Sample.BlazorServer/UltimateAuth.Sample.BlazorServer.csproj" />
<Project Path="samples/blazor-standalone-wasm/UltimateAuth.Sample.BlazorStandaloneWasm/UltimateAuth.Sample.BlazorStandaloneWasm.csproj" Id="27bd3c4d-65a9-4c70-a6c9-4178b1897730" />
</Folder>
<Folder Name="/Solution Items/">
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@inherits LayoutComponentBase
@inject ISnackbar Snackbar

<UAuthClientProvider />
<UAuthClientProvider OnReauthRequired="HandleReauth" />

<MudThemeProvider />
<MudPopoverProvider />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using MudBlazor;

namespace UltimateAuth.Sample.BlazorServer.Components.Layout
{
public partial class MainLayout
{
private void HandleReauth()
{
Snackbar.Add("Reauthentication required. Please log in again.", Severity.Warning);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
@page "/"
@page "/login"
@using CodeBeam.UltimateAuth.Client
@using CodeBeam.UltimateAuth.Client.Diagnostics
@using CodeBeam.UltimateAuth.Core.Abstractions
@using CodeBeam.UltimateAuth.Core.Runtime
@using CodeBeam.UltimateAuth.Server.Abstractions
@using CodeBeam.UltimateAuth.Server.Cookies
@using CodeBeam.UltimateAuth.Server.Infrastructure
@inject IUAuthFlowService<UserId> Flow
@inject ISnackbar Snackbar
@inject ISessionQueryService<UserId> SessionQuery
@inject ICredentialResolver CredentialResolver
@inject IClock Clock
@inject IUAuthCookieManager CookieManager
@inject IHttpContextAccessor HttpContextAccessor
@inject IUAuthClient UAuthClient
@inject NavigationManager Nav
@inject IUAuthProductInfoProvider ProductInfo
@inject AuthenticationStateProvider AuthStateProvider
@inject UAuthClientDiagnostics Diagnostics


<div class="uauth-page d-flex align-center justify-center">
<MudStack Class="uauth-stack">
<UALoginForm @ref="_form" Identifier="@_username" Secret="@_password">
<MudStack>
<MudText Typo="Typo.h4">Welcome to UltimateAuth!</MudText>
<MudTextField @bind-Value="@_username" Variant="Variant.Outlined" Label="Username" Immediate="true" HelperText="Default: Admin" />
<MudPasswordField @bind-Value="@_password" Variant="Variant.Outlined" Label="Password" Immediate="true" HelperText="Default: Password!" />
<MudButton Variant="Variant.Filled" Color="Color.Primary" ButtonType="ButtonType.Submit">Login</MudButton>
</MudStack>
</UALoginForm>

<MudStack Class="mud-width-full" Row="true">
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="ValidateAsync">Validate</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Secondary" OnClick="LogoutAsync">Logout</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="RefreshAsync">Refresh</MudButton>
</MudStack>

<MudStack Class="mud-width-full">
<MudButton Variant="Variant.Filled" Color="Color.Info" OnClick="ProgrammaticLogin">Programmatic Login</MudButton>
</MudStack>

<MudStack Spacing="0">
<MudText><b>@ProductInfo.Get().ProductName</b> v @ProductInfo.Get().Version</MudText>
<MudText>Client Profile: @ProductInfo.Get().ClientProfile.ToString()</MudText>
</MudStack>

<MudStack Spacing="0">
<MudText>State of Authentication:</MudText>
<MudText>@(_authState?.User?.Identity?.IsAuthenticated == true ? "Authenticated" : "Not Authenticated") - UserId:@(_authState?.User?.Identity?.Name)</MudText>
<AuthorizeView>
<Authorized>
<MudText>Authorized context is shown.</MudText>
</Authorized>
<NotAuthorized>
<MudText>Not Authorized context is shown.</MudText>
</NotAuthorized>
</AuthorizeView>
</MudStack>

<MudStack>
<MudPaper Class="pa-4 mt-4">
<MudText Typo="Typo.h6">UltimateAuth Client Diagnostics</MudText>

<MudDivider Class="my-2" />

<MudText>Started: @Diagnostics.StartCount - @Diagnostics.StartedAt</MudText>
<MudText>Stopped: @Diagnostics.StopCount - @Diagnostics.StoppedAt</MudText>
<MudText>Terminated: @Diagnostics.TerminatedCount - @Diagnostics.TerminatedAt (@Diagnostics.TerminationReason.ToString())</MudText>

<MudDivider Class="my-2" />

<MudText>Refresh Attempts: @Diagnostics.RefreshAttemptCount</MudText>
<MudText>Auto: @Diagnostics.AutomaticRefreshCount</MudText>
<MudText>Manual: @Diagnostics.ManualRefreshCount</MudText>

<MudText Color="Color.Success">
Touched Success: @Diagnostics.RefreshTouchedCount
</MudText>
<MudText Color="Color.Success">
No-Op Success: @Diagnostics.RefreshNoOpCount
</MudText>
<MudText Color="Color.Warning">
ReauthRequired: @Diagnostics.RefreshReauthRequiredCount
</MudText>
<MudText Color="Color.Warning">
Unknown: @Diagnostics.RefreshUnknownCount
</MudText>
</MudPaper>
</MudStack>
</MudStack>

</div>
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using CodeBeam.UltimateAuth.Client;
using CodeBeam.UltimateAuth.Core.Contracts;
using CodeBeam.UltimateAuth.Core.Domain;
using Microsoft.AspNetCore.Components.Authorization;
using MudBlazor;

namespace UltimateAuth.BlazorServer.Components.Pages
namespace UltimateAuth.Sample.BlazorServer.Components.Pages
{
public partial class Home
{
Expand All @@ -12,6 +12,19 @@ public partial class Home

private UALoginForm _form = null!;

private AuthenticationState _authState = null!;

protected override async Task OnInitializedAsync()
{
Diagnostics.Changed += OnDiagnosticsChanged;
_authState = await AuthStateProvider.GetAuthenticationStateAsync();
}

private void OnDiagnosticsChanged()
{
InvokeAsync(StateHasChanged);
}

private async Task ProgrammaticLogin()
{
var request = new LoginRequest
Expand All @@ -20,51 +33,16 @@ private async Task ProgrammaticLogin()
Secret = "Password!",
};
await UAuthClient.LoginAsync(request);
_authState = await AuthStateProvider.GetAuthenticationStateAsync();
}

private async Task ValidateAsync()
{
var httpContext = HttpContextAccessor.HttpContext;

if (httpContext is null)
{
Snackbar.Add("HttpContext not available", Severity.Error);
return;
}

var credential = CredentialResolver.Resolve(httpContext);

if (credential is null)
{
Snackbar.Add("No credential found", Severity.Error);
return;
}

if (!AuthSessionId.TryCreate(credential.Value, out var sessionId))
{
Snackbar.Add("Invalid session id", Severity.Error);
return;
}
var result = await UAuthClient.ValidateAsync();

var result = await SessionQuery.ValidateSessionAsync(
new SessionValidationContext
{
TenantId = credential.TenantId,
SessionId = sessionId,
Device = credential.Device,
Now = Clock.UtcNow
});

if (result.IsValid)
{
Snackbar.Add("Session is valid ✅", Severity.Success);
}
else
{
Snackbar.Add(
$"Session invalid ❌ ({result.State})",
Severity.Error);
}
Snackbar.Add(
result.IsValid ? "Session is valid ✅" : $"Session invalid ❌ ({result.State})",
result.IsValid ? Severity.Success : Severity.Error);
}

private async Task LogoutAsync()
Expand All @@ -76,7 +54,6 @@ private async Task LogoutAsync()
private async Task RefreshAsync()
{
await UAuthClient.RefreshAsync();
//Snackbar.Add("Logged out", Severity.Success);
}

protected override void OnAfterRender(bool firstRender)
Expand Down Expand Up @@ -114,5 +91,10 @@ private void ClearQueryString()
Nav.NavigateTo(clean, replace: true);
}

public void Dispose()
{
Diagnostics.Changed -= OnDiagnosticsChanged;
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Components.Authorization;

namespace CodeBeam.UltimateAuth.Client.BlazorServer;

internal sealed class UAuthAuthenticationStateProvider : AuthenticationStateProvider
{
private readonly AuthenticationStateProvider _inner;

public UAuthAuthenticationStateProvider(AuthenticationStateProvider inner)
{
_inner = inner;

_inner.AuthenticationStateChanged += s => NotifyAuthenticationStateChanged(s);
}

public override Task<AuthenticationState> GetAuthenticationStateAsync() => _inner.GetAuthenticationStateAsync();

/// <summary>
/// Call this after login/logout navigation
/// </summary>
public void NotifyStateChanged() => NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<CascadingAuthenticationState>
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
</CascadingAuthenticationState>
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using UltimateAuth.BlazorServer
@using UltimateAuth.BlazorServer.Components
@using UltimateAuth.Sample.BlazorServer
@using UltimateAuth.Sample.BlazorServer.Components

@using CodeBeam.UltimateAuth.Core.Abstractions
@using CodeBeam.UltimateAuth.Core.Domain
Expand Down
Loading
Loading