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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

---

UltimateAuth is an open-source auth framework with platform-level capabilities that unifies secure session, cookie and token based Auth, modern PKCE flows, Blazor/Maui-ready client experiences - eliminating the complexity of traditional Auth systems while providing a clean, lightweight, extensible and developer-first architecture.
UltimateAuth is an open-source auth framework with platform-level capabilities that unifies secure session, cookie and token based Auth, modern PKCE flows, Blazor/MAUI-ready client experiences - eliminating the complexity of traditional Auth systems while providing a clean, lightweight, extensible and developer-first architecture.

---
## Roadmap
Expand Down Expand Up @@ -70,6 +70,7 @@ UltimateAuth is designed to deliver a simple, consistent developer experience fr

---


### 💜 Join the UltimateAuth Community

UltimateAuth is more than a framework — it's a growing open-source community.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,85 +118,110 @@
<MudIcon Icon="@Icons.Material.Filled.CheckCircle" Color="Color.Success" Size="Size.Small" />
</div>

<MudNavMenu>
<div class="lab-nav-label">WORKSPACE</div>
<div class="lab-sidebar-navigation">
<MudNavMenu>
<div class="lab-nav-label">WORKSPACE</div>

<UAuthStateView Roles="Ladmin">
<MudNavLink Href="/admin" Icon="@Icons.Material.Filled.AdminPanelSettings">
Platform Administration
</MudNavLink>
</UAuthStateView>

<UAuthStateView Roles="Ladmin">
<MudNavLink Href="/admin" Icon="@Icons.Material.Filled.AdminPanelSettings">
Platform Administration
<MudNavLink Href="/dashboard" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Dashboard">
Overview
</MudNavLink>
</UAuthStateView>

<MudNavLink Href="/dashboard" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Dashboard">
Overview
</MudNavLink>
<div class="lab-nav-label">PERSONAL</div>

<div class="lab-nav-label">PERSONAL</div>
<MudNavLink Href="/dashboard/identity" Icon="@Icons.Material.Filled.Badge">
My Identity
</MudNavLink>

<MudNavLink Href="/dashboard/identity" Icon="@Icons.Material.Filled.Badge">
My Identity
</MudNavLink>
<MudNavLink Href="/dashboard/sessions" Icon="@Icons.Material.Filled.Devices">
My Sessions
</MudNavLink>

<MudNavLink Href="/dashboard/sessions" Icon="@Icons.Material.Filled.Devices">
My Sessions
</MudNavLink>
<MudNavLink Href="/dashboard/session-diagnostics" Icon="@Icons.Material.Filled.MonitorHeart">
Session Diagnostics
</MudNavLink>

<MudNavLink Href="/dashboard/session-diagnostics" Icon="@Icons.Material.Filled.MonitorHeart">
Session Diagnostics
</MudNavLink>
<MudNavLink Href="/dashboard/access" Icon="@Icons.Material.Filled.VerifiedUser">
My Access
</MudNavLink>

<MudNavLink Href="/dashboard/access" Icon="@Icons.Material.Filled.VerifiedUser">
My Access
</MudNavLink>
<MudNavLink Href="/dashboard/authorization-lab" Match="NavLinkMatch.All" Icon="@Icons.Material.Outlined.Security">
Authorization Lab
</MudNavLink>

<MudNavLink Href="/dashboard/authorization-lab" Match="NavLinkMatch.All" Icon="@Icons.Material.Outlined.Security">
Authorization Lab
</MudNavLink>
@if (ShowManagement)
{
<div class="lab-nav-label">SANDBOX MANAGEMENT</div>

@if (ShowManagement)
{
<div class="lab-nav-label">SANDBOX MANAGEMENT</div>
<MudNavLink Href="/dashboard/users" Icon="@Icons.Material.Filled.People">
Users
</MudNavLink>

<MudNavLink Href="/dashboard/users" Icon="@Icons.Material.Filled.People">
Users
</MudNavLink>
<MudNavLink Href="/dashboard/authorization" Icon="@Icons.Material.Filled.AdminPanelSettings">
Authorization
</MudNavLink>

<MudNavLink Href="/dashboard/authorization" Icon="@Icons.Material.Filled.AdminPanelSettings">
Authorization
</MudNavLink>
<MudNavLink Href="/dashboard/activity" Icon="@Icons.Material.Filled.History">
Activity
</MudNavLink>

<MudNavLink Href="/dashboard/activity" Icon="@Icons.Material.Filled.History">
Activity
</MudNavLink>
<MudNavLink Href="/dashboard/settings" Icon="@Icons.Material.Filled.Settings">
Settings
</MudNavLink>
}

<MudNavLink Href="/dashboard/settings" Icon="@Icons.Material.Filled.Settings">
Settings
</MudNavLink>
}
<MudNavMenu>
<MudNavLink Icon="@Icons.Material.Filled.Logout" OnClick="LogoutAsync">
Sign Out
</MudNavLink>
</MudNavMenu>

<MudNavMenu>
<MudNavLink Icon="@Icons.Material.Filled.Logout" OnClick="LogoutAsync">
Sign Out
<div class="lab-nav-label">PLAYGROUND</div>

<MudNavLink Href="/dashboard/demo-store" Icon="@Icons.Material.Filled.Storefront">
Demo Store
</MudNavLink>
</MudNavMenu>
</div>

<div class="lab-nav-label">PLAYGROUND</div>

<MudNavLink Href="/dashboard/demo-store" Icon="@Icons.Material.Filled.Storefront">
Demo Store
</MudNavLink>
</MudNavMenu>

<MudSpacer />

<div class="lab-sidebar-bottom">
<MudImage Src="ultimateauth-logo.png" Width="28" Height="28" />
<MudText Typo="Typo.caption">Powered by UltimateAuth</MudText>
<div class="lab-sidebar-footer">
<div class="lab-sidebar-product">
<a href="https://ultimateauth.com"
target="_blank"
rel="noopener noreferrer"
class="lab-sidebar-product-brand">

<span class="lab-sidebar-product-icon">
<MudImage Src="ultimateauth-logo.png" Width="28" Height="28" />
</span>

<span class="lab-sidebar-product-info">
<strong>Powered by UltimateAuth</strong>
<small>Identity Lab</small>
</span>
</a>

<div class="lab-sidebar-product-meta">
<a href="https://github.com/CodeBeamOrg/UltimateAuth/releases"
target="_blank"
rel="noopener noreferrer"
title="UltimateAuth releases">
<MudIcon Icon="@Icons.Material.Outlined.AccountTree" Size="Size.Small" />
<span>@UltimateAuthVersion</span>
</a>

<span class="lab-sidebar-product-runtime">
<MudIcon Icon="@Icons.Material.Outlined.Code" Size="Size.Small" />
<span>.NET @LabVersionInfo.DotNetVersion</span>
</span>
</div>
</div>
</div>
<MudStack Row="true" Justify="Justify.SpaceBetween">
<MudText Typo="Typo.caption">v @UltimateAuthVersion</MudText>
<MudText Typo="Typo.caption">.NET @LabVersionInfo.DotNetVersion</MudText>
</MudStack>
</div>
</MudDrawer>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@
.lab-sidebar-content {
display: flex;
flex-direction: column;
min-height: 100%;
padding: 20px 12px;
height: 100%;
min-height: 0;
padding: 20px 12px 12px;
}

.lab-sidebar-sandbox {
Expand Down Expand Up @@ -117,15 +118,118 @@
font-weight: 650;
}

.lab-sidebar-bottom {

/* Scrollable navigation */

.lab-sidebar-navigation {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: thin;
scrollbar-color: var(--mud-palette-lines-default) transparent;
}

/* Product footer */

.lab-sidebar-footer {
flex-shrink: 0;
padding-top: 12px;
margin-top: 12px;
border-top: 1px solid var(--mud-palette-lines-default);
}

.lab-sidebar-product {
padding: 12px;
border: 1px solid var(--mud-palette-lines-default);
border-radius: 12px;
background: var(--mud-palette-surface);
}

.lab-sidebar-product-brand {
display: flex;
align-items: center;
gap: 9px;
color: var(--mud-palette-text-primary);
text-decoration: none;
min-width: 0;
}

.lab-sidebar-product-icon {
width: 36px;
height: 36px;
flex-shrink: 0;
display: flex;
align-items: center;
gap: 8px;
padding: 18px 12px 4px;
justify-content: center;
border-radius: 9px;
background: var(--mud-palette-primary-hover);
}

.lab-sidebar-product-info {
display: flex;
flex: 1;
flex-direction: column;
gap: 3px;
min-width: 0;
}

.lab-sidebar-product-info strong {
font-size: 0.75rem;
font-weight: 700;
line-height: 1.3;
white-space: nowrap;
}

.lab-sidebar-product-info small {
font-size: 0.66rem;
color: var(--mud-palette-text-secondary);
}

.lab-sidebar-product-external {
flex-shrink: 0;
color: var(--mud-palette-text-secondary);
font-size: .72rem;
opacity: 0.65;
}

.lab-sidebar-product-brand:hover .lab-sidebar-product-external {
color: var(--mud-palette-primary);
opacity: 1;
}

/* Version information */

.lab-sidebar-product-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 6px;
margin-top: 12px;
padding-top: 10px;
border-top: 1px solid var(--mud-palette-lines-default);
}

.lab-sidebar-product-meta a,
.lab-sidebar-product-runtime {
display: inline-flex;
align-items: center;
gap: 4px;
min-width: 0;
color: var(--mud-palette-text-secondary);
font-size: 0.65rem;
white-space: nowrap;
text-decoration: none;
}

.lab-sidebar-product-meta .mud-icon-root {
font-size: 14px;
}

.lab-sidebar-product-meta a:hover {
color: var(--mud-palette-primary);
}


.lab-dashboard-main {
min-height: calc(100vh - var(--mud-appbar-height));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
</Authorized>

<NotAuthorized>
<UAuthLoginForm Identifier="@_identifier" Secret="@_password" ReturnUrl="/dashboard" OnTryResult="HandleLoginResult">
<UAuthLoginForm Identifier="@_identifier" Secret="@_password" ReturnUrl="/dashboard" OnTryResult="HandleLoginResult" OnSubmittingChanged="HandleSubmittingChanged">

@if (IsLockedOut)
{
Expand All @@ -127,10 +127,7 @@
@LockoutCountdown
</MudText>

<MudProgressLinear Value="@LockoutProgress"
Color="Color.Error"
Size="Size.Medium"
Rounded="true" />
<MudProgressLinear Value="@LockoutProgress" Color="Color.Error" Size="Size.Medium" Rounded="true" />

<MudText Typo="Typo.caption" Align="Align.Center">
Try again after
Expand Down Expand Up @@ -187,7 +184,7 @@
MaxLength="256"
Required="true"
RequiredError="Email or username is required."
Disabled="IsLockedOut"
Disabled="@_loginBusy"
Immediate="true" />

<MudPasswordField T="string"
Expand All @@ -198,17 +195,19 @@
MaxLength="256"
Required="true"
RequiredError="Password is required."
Disabled="IsLockedOut"
Disabled="@_loginBusy"
Immediate="true" />

<MudButton ButtonType="ButtonType.Submit"
<MudLoadingButton ButtonType="ButtonType.Submit"
Variant="Variant.Filled"
Color="Color.Primary"
FullWidth="true"
Size="Size.Large"
Loading="@_loginBusy"
AutoDelay="0"
EndIcon="@Icons.Material.Filled.ArrowForward">
@(IsLockedOut ? "Temporarily locked" : "Sign In")
</MudButton>
</MudLoadingButton>

</div>
</UAuthLoginForm>
Expand Down Expand Up @@ -315,8 +314,15 @@
?? AuthState.Identity?.PrimaryUserName
?? "User";

private string? CurrentUserName =>
AuthState.Identity?.PrimaryUserName;
private string? CurrentUserName => AuthState.Identity?.PrimaryUserName;

private bool _loginBusy;

private async Task HandleSubmittingChanged(bool submitting)
{
_loginBusy = submitting;
await InvokeAsync(StateHasChanged);
}

private void ContinueToDashboard()
{
Expand Down
Loading
Loading