diff --git a/README.md b/README.md
index a157e2c6..37dd42fc 100644
--- a/README.md
+++ b/README.md
@@ -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
@@ -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.
diff --git a/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Layout/DashboardLayout.razor b/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Layout/DashboardLayout.razor
index fbb8cedb..54c68294 100644
--- a/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Layout/DashboardLayout.razor
+++ b/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Layout/DashboardLayout.razor
@@ -118,85 +118,110 @@
-
- WORKSPACE
+
- PLAYGROUND
-
-
- Demo Store
-
-
-
-
-
-
diff --git a/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Layout/DashboardLayout.razor.css b/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Layout/DashboardLayout.razor.css
index 00097497..efe385e9 100644
--- a/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Layout/DashboardLayout.razor.css
+++ b/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Layout/DashboardLayout.razor.css
@@ -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 {
@@ -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));
}
diff --git a/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Pages/LoginPage.razor b/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Pages/LoginPage.razor
index fc4a05b5..d512cd87 100644
--- a/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Pages/LoginPage.razor
+++ b/apps/identity-lab/CodeBeam.UltimateAuth.IdentityLab/Components/Pages/LoginPage.razor
@@ -107,7 +107,7 @@
-
+
@if (IsLockedOut)
{
@@ -127,10 +127,7 @@
@LockoutCountdown
-
+
Try again after
@@ -187,7 +184,7 @@
MaxLength="256"
Required="true"
RequiredError="Email or username is required."
- Disabled="IsLockedOut"
+ Disabled="@_loginBusy"
Immediate="true" />
-
@(IsLockedOut ? "Temporarily locked" : "Sign In")
-
+
@@ -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()
{
diff --git a/docs/content/migration/index.md b/docs/content/migration/index.md
index 0cd8f9d0..f890b36a 100644
--- a/docs/content/migration/index.md
+++ b/docs/content/migration/index.md
@@ -6,10 +6,84 @@ group: migration
# Migration Guides
-Version-specific instructions for upgrading UltimateAuth applications.
+Keep your UltimateAuth applications up to date with clear, version-specific upgrade guidance.
-Migration guides focus on breaking changes, behavior changes, and required application updates.
+This page provides an overview of stable UltimateAuth releases, their migration impact, and any actions required when upgrading.
-## Available Guides
+**Most updates require little or no application code changes.** When an update requires attention, a dedicated migration guide explains what changed and how to adapt your application.
-- [Migrating to v0.1.1](/docs/migration/v0.1.1) — Blazor route authorization and component lifecycle changes.
+## Version Migration Overview
+
+The table below lists stable releases in descending order, with the newest version first.
+
+Preview and release candidate versions are excluded.
+
+| Version | Migration Impact | What's Changed | Migration Guide |
+|---|---|---|---|
+| **v0.2.0 (In Progress)** | **Medium (Provisional)** | Async authorization APIs, authorization checks, and integration changes | [View Guide](/docs/migration/v0.2.0) |
+| **v0.1.4** | **Low** | CSRF protection, antiforgery integration, and interface changes | [View Guide](/docs/migration/v0.1.4) |
+| **v0.1.3** | **None** | Session deletion, revocation, and refresh consistency fixes | Not required |
+| **v0.1.2** | **None** | Password change transaction and session revocation fixes | Not required |
+| **v0.1.1** | **Low** | Blazor route authorization and component lifecycle changes | [View Guide](/docs/migration/v0.1.1) |
+| **v0.1.0** | **N/A** | Initial stable release | Not applicable |
+
+**Migration impact describes the expected developer effort and affected integration surface, not the size of the code change or the significance of the release.** A small change to a widely used authentication API may have a higher migration impact than a large internal refactor.
+
+> Individual preview and release candidate versions are not listed separately. Migration guidance for an in-progress release may change before its stable release.
+
+Security and reliability fixes may have an impact of **None** while still being strongly recommended.
+
+## Understanding Migration Impact
+
+| Impact | Meaning | Expected Action |
+|---|---|---|
+| **None** | No application code or configuration changes are required for standard integrations. | Update packages and run existing tests. |
+| **Low** | Small, localized changes may be required, typically for specific integrations or customizations. | Review the migration guide and update affected code. |
+| **Medium** | Changes affect commonly used APIs, core integration points, or multiple application areas. Even a small code change is classified as Medium when developers must update functionality they use directly and extensively. | Review the migration guide, update affected integrations, and perform targeted regression testing. |
+| **High** | Significant architectural, API, persistence, or behavioral changes require a planned migration. | Review all migration steps, test thoroughly, and plan deployment carefully. |
+
+Migration impact is evaluated using both **the effort required and how directly the changes affect application developers**.
+
+A change does not qualify as Low simply because it requires only a few lines of code. Breaking changes to frequently used authentication, authorization, session management, or client integration APIs may be classified as Medium even when the implementation changes are relatively small.
+
+Applications using only unaffected functionality may require fewer changes than the stated impact level suggests.
+
+## How to Upgrade
+
+1. **Identify your current version.** Check the installed `CodeBeam.UltimateAuth.*` NuGet packages.
+2. **Review every version between your current and target versions.** Migration requirements are cumulative when skipping releases.
+3. **Follow the linked migration guides.** Apply any required API, configuration, or behavioral changes in version order.
+4. **Update your UltimateAuth packages together.** Keep related packages on compatible versions.
+5. **Build and test your application.** Verify login, logout, refresh, authorization, and session management flows relevant to your integration.
+
+For releases marked **None**, no dedicated migration guide is necessary. You should still review the release notes and run your application tests.
+
+## Available Migration Guides
+
+### [Migrating to v0.1.4](/docs/migration/v0.1.4)
+
+**Impact: Low**
+
+Introduces antiforgery protection for cookie-based authentication flows, updates browser client integration, and changes selected session resolution and browser bridge interfaces.
+
+Applications using the standard UltimateAuth browser client generally receive antiforgery handling automatically.
+
+Custom HTTP clients, manually implemented browser bridges, and custom session resolvers should review the guide.
+
+### [Migrating to v0.1.1](/docs/migration/v0.1.1)
+
+**Impact: Low**
+
+Introduces routing-level enforcement for `[UAuthAuthorize]` and updates the `UAuthComponentBase` lifecycle.
+
+Most applications using the built-in `UAuthApp` router require no changes. Applications with custom routers, component lifecycle overrides, or specialized session requirements should review the guide.
+
+## Release History
+
+For complete release notes, bug fixes, and security updates, visit the [UltimateAuth GitHub Releases](https://github.com/CodeBeamOrg/UltimateAuth/releases) page.
+
+Migration guides focus on changes developers must make to their applications. Release notes provide the complete history of changes in each version.
+
+---
+
+**Upgrading across multiple versions?** Start with the earliest version after your currently installed release and review each migration entry through your target version.
\ No newline at end of file
diff --git a/docs/content/migration/v0.1.4.md b/docs/content/migration/v0.1.4.md
new file mode 100644
index 00000000..c197caea
--- /dev/null
+++ b/docs/content/migration/v0.1.4.md
@@ -0,0 +1,194 @@
+---
+title: Migrating to v0.1.4
+order: 3
+group: migration
+---
+
+# Migrating to v0.1.4
+
+**Migration Impact: Low**
+
+UltimateAuth v0.1.4 introduces antiforgery protection for cookie-based authentication flows and updates several client and server integration interfaces.
+
+The release strengthens protection against Cross-Site Request Forgery (CSRF) while preserving the standard UltimateAuth developer experience.
+
+**Most applications using the built-in UltimateAuth browser client require no application code changes.** Antiforgery token handling is integrated into the client.
+
+Applications using custom HTTP requests, custom browser bridges, or custom session resolvers should review the changes below.
+
+## 1. Antiforgery Protection for Cookie-Based Authentication
+
+UltimateAuth now validates antiforgery tokens for protected operations when cookie-based authentication is applicable.
+
+This includes relevant authentication operations and authenticated state-changing endpoints.
+
+Requests that fail antiforgery validation are rejected with HTTP `400 Bad Request` and the following error:
+
+```json
+{
+ "error": "invalid_antiforgery_token"
+}
+```
+
+### Using the built-in browser client
+
+The UltimateAuth browser client now supports retrieving and submitting antiforgery tokens automatically.
+
+If your application uses the standard UltimateAuth client integration, no additional antiforgery implementation is normally required.
+
+Make sure the server and client packages are updated together.
+
+### Using custom HTTP requests
+
+If your application calls protected UltimateAuth endpoints directly from a browser, you must obtain an antiforgery token and submit it with the request.
+
+The default token endpoint is:
+
+```http
+GET /auth/antiforgery/token
+```
+
+The response contains:
+
+```json
+{
+ "requestToken": "...",
+ "headerName": "X-UAuth-CSRF",
+ "formFieldName": "__RequestVerificationToken"
+}
+```
+
+The endpoint also issues an antiforgery cookie.
+
+For subsequent protected requests:
+
+1. Obtain a token from the configured antiforgery endpoint.
+2. Preserve the associated antiforgery cookie.
+3. Send the request token using the returned `headerName`.
+4. Include the appropriate authentication credentials for the request.
+
+For example:
+
+```http
+POST /auth/logout
+X-UAuth-CSRF:
+Cookie:
+```
+
+The request token and antiforgery cookie must belong to the same antiforgery context.
+
+**Do not hardcode or fabricate antiforgery tokens.** Always obtain them from the server.
+
+The default endpoint path assumes the standard `/auth` base path. Applications using custom routing or multi-tenancy must use their configured endpoint URL.
+
+### Custom server-side integrations
+
+Applications using custom HTTP clients or server-to-server integrations should review whether their requests use cookie-based authentication.
+
+Antiforgery requirements depend on the authentication transport and operation. They are not automatically equivalent for every bearer-token or header-based request.
+
+Do not disable antiforgery validation to resolve an integration failure. Update the affected request flow instead.
+
+## 2. ISessionIdResolver Is Now Asynchronous
+
+The `ISessionIdResolver` interface has changed to support asynchronous session resolution.
+
+If you implement this interface yourself, update the implementation.
+
+**Before (v0.1.3):**
+
+```csharp
+public AuthSessionId? Resolve(HttpContext context)
+{
+ // Resolve the session identifier.
+}
+```
+
+**After (v0.1.4):**
+
+```csharp
+public ValueTask ResolveAsync(HttpContext context, CancellationToken ct = default)
+{
+ ct.ThrowIfCancellationRequested();
+
+ // Resolve the session identifier.
+ return ValueTask.FromResult(null);
+}
+```
+
+Replace the placeholder return with your existing resolution logic.
+
+If your resolver performs asynchronous operations, use an `async ValueTask` implementation and await those operations.
+
+Update any direct calls from `Resolve(...)` to `ResolveAsync(...)` and await the result.
+
+Applications using the built-in session resolver do not need to make this change.
+
+## 3. Custom Browser Bridges
+
+The `IBrowserUAuthBridge` interface now includes:
+
+```csharp
+ValueTask ConfigureAntiforgeryAsync(string tokenUrl, string? trustedOrigin = null);
+```
+
+This allows the UltimateAuth client bootstrapper to configure antiforgery handling for browser requests.
+
+If you provide a custom implementation of `IBrowserUAuthBridge`, implement this new method.
+
+Your implementation must configure the browser-side antiforgery integration using the supplied token endpoint and optional trusted origin.
+
+The exact implementation depends on your browser integration.
+
+**Do not add an empty implementation unless antiforgery handling is already provided by your custom bridge.** Doing so may leave protected browser requests without the required token.
+
+Applications using the built-in UltimateAuth browser bridge do not need to make this change.
+
+## 4. Antiforgery Endpoint Configuration
+
+v0.1.4 introduces a server-side antiforgery configuration section:
+
+```csharp
+options.Antiforgery.TokenEndpoint = "/antiforgery/token";
+```
+
+The client also exposes the corresponding endpoint setting:
+
+```csharp
+options.Endpoints.AntiforgeryToken = "/antiforgery/token";
+```
+
+The default endpoint path is `/antiforgery/token`, resolved under the configured UltimateAuth base path.
+
+No configuration change is required when using the defaults.
+
+If you customize the endpoint, ensure the server and client configurations match.
+
+## 5. Verify Your Application
+
+After upgrading to v0.1.4, verify the following flows where applicable:
+
+- Login and logout using the built-in browser client.
+- Session refresh and validation.
+- Authenticated account and session management operations.
+- Custom requests to UltimateAuth endpoints.
+- Custom session resolver implementations.
+- Custom browser bridge implementations.
+- External Hub and multi-tenant configurations.
+
+For applications using custom browser requests, verify that valid antiforgery tokens allow protected operations and missing or invalid tokens are rejected.
+
+## Migration Checklist
+
+- [ ] Update UltimateAuth packages to compatible v0.1.4 versions.
+- [ ] Update custom `ISessionIdResolver` implementations, if any.
+- [ ] Update custom `IBrowserUAuthBridge` implementations, if any.
+- [ ] Add antiforgery token handling to custom browser HTTP requests, if applicable.
+- [ ] Verify custom antiforgery endpoint configuration, if applicable.
+- [ ] Run authentication, authorization, and session regression tests.
+
+---
+
+**Using the standard UltimateAuth client and built-in session resolution?** No application code changes are normally required. Update your packages and verify your existing authentication flows.
+
+For the complete list of changes, see [UltimateAuth v0.1.4 Release](https://github.com/CodeBeamOrg/UltimateAuth/releases/tag/v0.1.4).
diff --git a/docs/content/migration/v0.2.0.md b/docs/content/migration/v0.2.0.md
new file mode 100644
index 00000000..08c132d9
--- /dev/null
+++ b/docs/content/migration/v0.2.0.md
@@ -0,0 +1,159 @@
+---
+title: Migrating to v0.2.0
+order: 4
+group: migration
+---
+
+# Migrating to v0.2.0
+
+**Migration Impact: Medium — In Progress**
+
+**Latest published prerelease reviewed: v0.2.0-preview.2**
+
+This guide covers migration requirements for the upcoming UltimateAuth v0.2.0 release.
+
+The guide is provisional and will be updated as new preview and release candidate versions become available. The final migration requirements may change before the stable v0.2.0 release.
+
+## 1. Asynchronous Authorization Policies
+
+**Available since preview.1**
+
+Custom implementations of `IAccessPolicy`, `IAccessInvariant`, and `IAccessAuthority` should migrate to `DecideAsync`.
+
+**Before:**
+
+```csharp
+public AccessDecision Decide(AccessContext context)
+{
+ return AccessDecision.Allow();
+}
+```
+
+**After:**
+
+```csharp
+public ValueTask DecideAsync(AccessContext context, CancellationToken ct = default)
+{
+ return ValueTask.FromResult(AccessDecision.Allow());
+}
+```
+
+For `IAccessAuthority`, preserve the existing `runtimePolicies` parameter and add the cancellation token.
+
+Synchronous `Decide` methods are obsolete. Existing synchronous implementations retain compatibility through the interface defaults, but new implementations should use `DecideAsync`.
+
+If your application invokes an authority directly, switch to `DecideAsync` and await the result.
+
+## 2. Authorization Check Results
+
+**Available since preview.1**
+
+`CheckAsync` now returns an explicit authorization decision in the response body.
+
+If your application previously interpreted HTTP `403` as the result of a successful authorization evaluation that denied access, update that handling.
+
+```csharp
+var result = await UAuthClient.Authorization.CheckAsync(request);
+
+if (result.IsSuccess && result.Value is { IsAllowed: true })
+{
+ // Authorized
+}
+```
+
+An HTTP-successful authorization check does not necessarily mean that access was granted.
+
+Inspect the returned authorization decision rather than relying solely on the HTTP status.
+
+## 3. Custom User Lifecycle Integrations
+
+**Available since preview.2**
+
+The `IUserLifecycleIntegration.OnUserCreatedAsync` signature now includes `UAuthClientProfile`.
+
+**Before:**
+
+```csharp
+Task OnUserCreatedAsync(
+ TenantKey tenant,
+ UserKey userKey,
+ object request,
+ CancellationToken ct = default);
+```
+
+**After:**
+
+```csharp
+Task OnUserCreatedAsync(
+ TenantKey tenant,
+ UserKey userKey,
+ object request,
+ UAuthClientProfile clientProfile,
+ CancellationToken ct = default);
+```
+
+Update custom implementations to accept the additional client profile parameter.
+
+Applications using built-in lifecycle integrations do not need to make this change.
+
+## 4. Identifier and Profile Limits
+
+**Available since preview.2**
+
+The reference Users domain now enforces additional identifier and profile safety limits.
+
+The default maximum is 10 active identifiers per user. Applications requiring a different capacity should configure `Identifiers.Behavior.MaxIdentifiersPerUser`.
+
+Existing profile creation and update operations must also respect the new field-length and metadata limits.
+
+If you use EF Core persistence:
+
+1. Review existing profile data for values exceeding the new limits.
+2. Add or apply the appropriate EF Core database migration for your application's DbContext.
+3. Verify that applications handling profile validation errors use the returned error codes.
+
+See [Profile Validation & Limits](/docs/plugin-domains/profile-validation-limits) for the supported limits.
+
+## 5. Password Policies and History
+
+**Available since preview.2**
+
+The reference password credential implementation now applies configurable password policies, with Standard as the default level.
+
+Review custom registration, password-change, and password-reset flows to ensure that they handle server-side password validation errors.
+
+Applications using persistent password-history storage must apply the required database migration before enabling password history.
+
+Password history is disabled by default (`RememberLast = 0`).
+
+See [Password Policy & History](/docs/security/password-policy) for configuration and persistence requirements.
+
+## 6. Rate Limiting
+
+**Available since preview.2**
+
+Built-in endpoint rate limiting is enabled by default when using:
+
+```csharp
+app.UseUltimateAuthWithAspNetCore();
+```
+
+If your application already registers its own rate limiting middleware, avoid installing a duplicate limiter.
+
+To retain application-owned rate limiting:
+
+```csharp
+app.UseUltimateAuthWithAspNetCore(useRateLimiting: false);
+```
+
+Then configure your existing `UseRateLimiter()` middleware in the appropriate pipeline position.
+
+Applications using `UseUltimateAuth()` without the integrated ASP.NET Core helper do not enable UltimateAuth rate limiting by default.
+
+Review custom HTTP clients and authentication flows for HTTP `429 Too Many Requests` handling.
+
+See [Rate Limiting](/docs/security/rate-limiting) for middleware integration and defaults.
+
+---
+
+This page will continue to evolve through the v0.2.0 preview and RC series and will become the stable migration guide when v0.2.0 is released.
diff --git a/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/docs-index.json b/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/docs-index.json
index 0a8a077b..e1c3c2ec 100644
--- a/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/docs-index.json
+++ b/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/docs-index.json
@@ -320,5 +320,19 @@
"Order": 2,
"Group": "migration",
"GroupOrder": 10
+ },
+ {
+ "Title": "Migrating to v0.1.4",
+ "Slug": "migration/v0.1.4",
+ "Order": 3,
+ "Group": "migration",
+ "GroupOrder": 10
+ },
+ {
+ "Title": "Migrating to v0.2.0",
+ "Slug": "migration/v0.2.0",
+ "Order": 4,
+ "Group": "migration",
+ "GroupOrder": 10
}
]
\ No newline at end of file
diff --git a/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/migration/index.json b/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/migration/index.json
index c595f397..8f6b4d5a 100644
--- a/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/migration/index.json
+++ b/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/migration/index.json
@@ -1,14 +1,44 @@
{
"Slug": "migration/index",
"Title": "Migration Guides",
- "Html": "\n\u003Cp\u003EVersion-specific instructions for upgrading UltimateAuth applications.\u003C/p\u003E\n\u003Cp\u003EMigration guides focus on breaking changes, behavior changes, and required application updates.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022available-guides\u0022\u003EAvailable Guides\u003C/h2\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022/docs/migration/v0.1.1\u0022\u003EMigrating to v0.1.1\u003C/a\u003E \u2014 Blazor route authorization and component lifecycle changes.\u003C/li\u003E\n\u003C/ul\u003E\n",
+ "Html": "\n\u003Cp\u003EKeep your UltimateAuth applications up to date with clear, version-specific upgrade guidance.\u003C/p\u003E\n\u003Cp\u003EThis page provides an overview of stable UltimateAuth releases, their migration impact, and any actions required when upgrading.\u003C/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EMost updates require little or no application code changes.\u003C/strong\u003E When an update requires attention, a dedicated migration guide explains what changed and how to adapt your application.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022version-migration-overview\u0022\u003EVersion Migration Overview\u003C/h2\u003E\n\u003Cp\u003EThe table below lists stable releases in descending order, with the newest version first.\u003C/p\u003E\n\u003Cp\u003EPreview and release candidate versions are excluded.\u003C/p\u003E\n\u003Cdiv class=\u0022docs-table-wrapper\u0022\u003E\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003EVersion\u003C/th\u003E\n\u003Cth\u003EMigration Impact\u003C/th\u003E\n\u003Cth\u003EWhat\u0027s Changed\u003C/th\u003E\n\u003Cth\u003EMigration Guide\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\u003Cstrong\u003Ev0.2.0 (In Progress)\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003E\u003Cstrong\u003EMedium (Provisional)\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003EAsync authorization APIs, authorization checks, and integration changes\u003C/td\u003E\n\u003Ctd\u003E\u003Ca href=\u0022/docs/migration/v0.2.0\u0022\u003EView Guide\u003C/a\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\u003Cstrong\u003Ev0.1.4\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003E\u003Cstrong\u003ELow\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003ECSRF protection, antiforgery integration, and interface changes\u003C/td\u003E\n\u003Ctd\u003E\u003Ca href=\u0022/docs/migration/v0.1.4\u0022\u003EView Guide\u003C/a\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\u003Cstrong\u003Ev0.1.3\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003E\u003Cstrong\u003ENone\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003ESession deletion, revocation, and refresh consistency fixes\u003C/td\u003E\n\u003Ctd\u003ENot required\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\u003Cstrong\u003Ev0.1.2\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003E\u003Cstrong\u003ENone\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003EPassword change transaction and session revocation fixes\u003C/td\u003E\n\u003Ctd\u003ENot required\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\u003Cstrong\u003Ev0.1.1\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003E\u003Cstrong\u003ELow\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003EBlazor route authorization and component lifecycle changes\u003C/td\u003E\n\u003Ctd\u003E\u003Ca href=\u0022/docs/migration/v0.1.1\u0022\u003EView Guide\u003C/a\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\u003Cstrong\u003Ev0.1.0\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003E\u003Cstrong\u003EN/A\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003EInitial stable release\u003C/td\u003E\n\u003Ctd\u003ENot applicable\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\u003C/div\u003E\n\u003Cp\u003E\u003Cstrong\u003EMigration impact describes the expected developer effort and affected integration surface, not the size of the code change or the significance of the release.\u003C/strong\u003E A small change to a widely used authentication API may have a higher migration impact than a large internal refactor.\u003C/p\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EIndividual preview and release candidate versions are not listed separately. Migration guidance for an in-progress release may change before its stable release.\u003C/p\u003E\n\u003C/blockquote\u003E\n\u003Cp\u003ESecurity and reliability fixes may have an impact of \u003Cstrong\u003ENone\u003C/strong\u003E while still being strongly recommended.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022understanding-migration-impact\u0022\u003EUnderstanding Migration Impact\u003C/h2\u003E\n\u003Cdiv class=\u0022docs-table-wrapper\u0022\u003E\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003EImpact\u003C/th\u003E\n\u003Cth\u003EMeaning\u003C/th\u003E\n\u003Cth\u003EExpected Action\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\u003Cstrong\u003ENone\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003ENo application code or configuration changes are required for standard integrations.\u003C/td\u003E\n\u003Ctd\u003EUpdate packages and run existing tests.\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\u003Cstrong\u003ELow\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003ESmall, localized changes may be required, typically for specific integrations or customizations.\u003C/td\u003E\n\u003Ctd\u003EReview the migration guide and update affected code.\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\u003Cstrong\u003EMedium\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003EChanges affect commonly used APIs, core integration points, or multiple application areas. Even a small code change is classified as Medium when developers must update functionality they use directly and extensively.\u003C/td\u003E\n\u003Ctd\u003EReview the migration guide, update affected integrations, and perform targeted regression testing.\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\u003Cstrong\u003EHigh\u003C/strong\u003E\u003C/td\u003E\n\u003Ctd\u003ESignificant architectural, API, persistence, or behavioral changes require a planned migration.\u003C/td\u003E\n\u003Ctd\u003EReview all migration steps, test thoroughly, and plan deployment carefully.\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\u003C/div\u003E\n\u003Cp\u003EMigration impact is evaluated using both \u003Cstrong\u003Ethe effort required and how directly the changes affect application developers\u003C/strong\u003E.\u003C/p\u003E\n\u003Cp\u003EA change does not qualify as Low simply because it requires only a few lines of code. Breaking changes to frequently used authentication, authorization, session management, or client integration APIs may be classified as Medium even when the implementation changes are relatively small.\u003C/p\u003E\n\u003Cp\u003EApplications using only unaffected functionality may require fewer changes than the stated impact level suggests.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022how-to-upgrade\u0022\u003EHow to Upgrade\u003C/h2\u003E\n\u003Col\u003E\n\u003Cli\u003E\u003Cstrong\u003EIdentify your current version.\u003C/strong\u003E Check the installed \u003Ccode\u003ECodeBeam.UltimateAuth.*\u003C/code\u003E NuGet packages.\u003C/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EReview every version between your current and target versions.\u003C/strong\u003E Migration requirements are cumulative when skipping releases.\u003C/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EFollow the linked migration guides.\u003C/strong\u003E Apply any required API, configuration, or behavioral changes in version order.\u003C/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EUpdate your UltimateAuth packages together.\u003C/strong\u003E Keep related packages on compatible versions.\u003C/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EBuild and test your application.\u003C/strong\u003E Verify login, logout, refresh, authorization, and session management flows relevant to your integration.\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cp\u003EFor releases marked \u003Cstrong\u003ENone\u003C/strong\u003E, no dedicated migration guide is necessary. You should still review the release notes and run your application tests.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022available-migration-guides\u0022\u003EAvailable Migration Guides\u003C/h2\u003E\n\u003Ch3 class=\u0022mud-scrollspy-section\u0022 id=\u0022migrating-to-v0.1.4\u0022\u003E\u003Ca href=\u0022/docs/migration/v0.1.4\u0022\u003EMigrating to v0.1.4\u003C/a\u003E\u003C/h3\u003E\n\u003Cp\u003E\u003Cstrong\u003EImpact: Low\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003EIntroduces antiforgery protection for cookie-based authentication flows, updates browser client integration, and changes selected session resolution and browser bridge interfaces.\u003C/p\u003E\n\u003Cp\u003EApplications using the standard UltimateAuth browser client generally receive antiforgery handling automatically.\u003C/p\u003E\n\u003Cp\u003ECustom HTTP clients, manually implemented browser bridges, and custom session resolvers should review the guide.\u003C/p\u003E\n\u003Ch3 class=\u0022mud-scrollspy-section\u0022 id=\u0022migrating-to-v0.1.1\u0022\u003E\u003Ca href=\u0022/docs/migration/v0.1.1\u0022\u003EMigrating to v0.1.1\u003C/a\u003E\u003C/h3\u003E\n\u003Cp\u003E\u003Cstrong\u003EImpact: Low\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003EIntroduces routing-level enforcement for \u003Ccode\u003E[UAuthAuthorize]\u003C/code\u003E and updates the \u003Ccode\u003EUAuthComponentBase\u003C/code\u003E lifecycle.\u003C/p\u003E\n\u003Cp\u003EMost applications using the built-in \u003Ccode\u003EUAuthApp\u003C/code\u003E router require no changes. Applications with custom routers, component lifecycle overrides, or specialized session requirements should review the guide.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022release-history\u0022\u003ERelease History\u003C/h2\u003E\n\u003Cp\u003EFor complete release notes, bug fixes, and security updates, visit the \u003Ca href=\u0022https://github.com/CodeBeamOrg/UltimateAuth/releases\u0022\u003EUltimateAuth GitHub Releases\u003C/a\u003E page.\u003C/p\u003E\n\u003Cp\u003EMigration guides focus on changes developers must make to their applications. Release notes provide the complete history of changes in each version.\u003C/p\u003E\n\u003Chr\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpgrading across multiple versions?\u003C/strong\u003E Start with the earliest version after your currently installed release and review each migration entry through your target version.\u003C/p\u003E\n",
"Headings": [
{
- "Id": "available-guides",
- "Text": "Available Guides",
+ "Id": "version-migration-overview",
+ "Text": "Version Migration Overview",
+ "Level": 0
+ },
+ {
+ "Id": "understanding-migration-impact",
+ "Text": "Understanding Migration Impact",
+ "Level": 0
+ },
+ {
+ "Id": "how-to-upgrade",
+ "Text": "How to Upgrade",
+ "Level": 0
+ },
+ {
+ "Id": "available-migration-guides",
+ "Text": "Available Migration Guides",
+ "Level": 0
+ },
+ {
+ "Id": "migrating-to-v0.1.4",
+ "Text": "Migrating to v0.1.4",
+ "Level": 1
+ },
+ {
+ "Id": "migrating-to-v0.1.1",
+ "Text": "Migrating to v0.1.1",
+ "Level": 1
+ },
+ {
+ "Id": "release-history",
+ "Text": "Release History",
"Level": 0
}
],
- "SourceHash": "FA6FAFE02BA9EF2656EBA1C8531CEC3F43A2666D05A61B6E2979BD96B3593D8B",
+ "SourceHash": "DD4CBD449E209E19EED5EE80BEE6DEA683168AF0485EA7C6CF76F5D80A8A3B76",
"BuilderVersion": "1"
}
\ No newline at end of file
diff --git a/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/migration/v0.1.4.json b/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/migration/v0.1.4.json
new file mode 100644
index 00000000..fefe0679
--- /dev/null
+++ b/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/migration/v0.1.4.json
@@ -0,0 +1,54 @@
+{
+ "Slug": "migration/v0.1.4",
+ "Title": "Migrating to v0.1.4",
+ "Html": "\n\u003Cp\u003E\u003Cstrong\u003EMigration Impact: Low\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003EUltimateAuth v0.1.4 introduces antiforgery protection for cookie-based authentication flows and updates several client and server integration interfaces.\u003C/p\u003E\n\u003Cp\u003EThe release strengthens protection against Cross-Site Request Forgery (CSRF) while preserving the standard UltimateAuth developer experience.\u003C/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EMost applications using the built-in UltimateAuth browser client require no application code changes.\u003C/strong\u003E Antiforgery token handling is integrated into the client.\u003C/p\u003E\n\u003Cp\u003EApplications using custom HTTP requests, custom browser bridges, or custom session resolvers should review the changes below.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022antiforgery-protection-for-cookie-based-authentication\u0022\u003E1. Antiforgery Protection for Cookie-Based Authentication\u003C/h2\u003E\n\u003Cp\u003EUltimateAuth now validates antiforgery tokens for protected operations when cookie-based authentication is applicable.\u003C/p\u003E\n\u003Cp\u003EThis includes relevant authentication operations and authenticated state-changing endpoints.\u003C/p\u003E\n\u003Cp\u003ERequests that fail antiforgery validation are rejected with HTTP \u003Ccode\u003E400 Bad Request\u003C/code\u003E and the following error:\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EJSON\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-json\u0022\u003E{\n \u0026quot;error\u0026quot;: \u0026quot;invalid_antiforgery_token\u0026quot;\n}\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Ch3 class=\u0022mud-scrollspy-section\u0022 id=\u0022using-the-built-in-browser-client\u0022\u003EUsing the built-in browser client\u003C/h3\u003E\n\u003Cp\u003EThe UltimateAuth browser client now supports retrieving and submitting antiforgery tokens automatically.\u003C/p\u003E\n\u003Cp\u003EIf your application uses the standard UltimateAuth client integration, no additional antiforgery implementation is normally required.\u003C/p\u003E\n\u003Cp\u003EMake sure the server and client packages are updated together.\u003C/p\u003E\n\u003Ch3 class=\u0022mud-scrollspy-section\u0022 id=\u0022using-custom-http-requests\u0022\u003EUsing custom HTTP requests\u003C/h3\u003E\n\u003Cp\u003EIf your application calls protected UltimateAuth endpoints directly from a browser, you must obtain an antiforgery token and submit it with the request.\u003C/p\u003E\n\u003Cp\u003EThe default token endpoint is:\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EHTTP\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-http\u0022\u003EGET /auth/antiforgery/token\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EThe response contains:\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EJSON\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-json\u0022\u003E{\n \u0026quot;requestToken\u0026quot;: \u0026quot;...\u0026quot;,\n \u0026quot;headerName\u0026quot;: \u0026quot;X-UAuth-CSRF\u0026quot;,\n \u0026quot;formFieldName\u0026quot;: \u0026quot;__RequestVerificationToken\u0026quot;\n}\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EThe endpoint also issues an antiforgery cookie.\u003C/p\u003E\n\u003Cp\u003EFor subsequent protected requests:\u003C/p\u003E\n\u003Col\u003E\n\u003Cli\u003EObtain a token from the configured antiforgery endpoint.\u003C/li\u003E\n\u003Cli\u003EPreserve the associated antiforgery cookie.\u003C/li\u003E\n\u003Cli\u003ESend the request token using the returned \u003Ccode\u003EheaderName\u003C/code\u003E.\u003C/li\u003E\n\u003Cli\u003EInclude the appropriate authentication credentials for the request.\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cp\u003EFor example:\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EHTTP\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-http\u0022\u003EPOST /auth/logout\nX-UAuth-CSRF: \u0026lt;request-token\u0026gt;\nCookie: \u0026lt;authentication-and-antiforgery-cookies\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EThe request token and antiforgery cookie must belong to the same antiforgery context.\u003C/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EDo not hardcode or fabricate antiforgery tokens.\u003C/strong\u003E Always obtain them from the server.\u003C/p\u003E\n\u003Cp\u003EThe default endpoint path assumes the standard \u003Ccode\u003E/auth\u003C/code\u003E base path. Applications using custom routing or multi-tenancy must use their configured endpoint URL.\u003C/p\u003E\n\u003Ch3 class=\u0022mud-scrollspy-section\u0022 id=\u0022custom-server-side-integrations\u0022\u003ECustom server-side integrations\u003C/h3\u003E\n\u003Cp\u003EApplications using custom HTTP clients or server-to-server integrations should review whether their requests use cookie-based authentication.\u003C/p\u003E\n\u003Cp\u003EAntiforgery requirements depend on the authentication transport and operation. They are not automatically equivalent for every bearer-token or header-based request.\u003C/p\u003E\n\u003Cp\u003EDo not disable antiforgery validation to resolve an integration failure. Update the affected request flow instead.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022isessionidresolver-is-now-asynchronous\u0022\u003E2. ISessionIdResolver Is Now Asynchronous\u003C/h2\u003E\n\u003Cp\u003EThe \u003Ccode\u003EISessionIdResolver\u003C/code\u003E interface has changed to support asynchronous session resolution.\u003C/p\u003E\n\u003Cp\u003EIf you implement this interface yourself, update the implementation.\u003C/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EBefore (v0.1.3):\u003C/strong\u003E\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003Epublic AuthSessionId? Resolve(HttpContext context)\n{\n // Resolve the session identifier.\n}\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003E\u003Cstrong\u003EAfter (v0.1.4):\u003C/strong\u003E\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003Epublic ValueTask\u0026lt;AuthSessionId?\u0026gt; ResolveAsync(HttpContext context, CancellationToken ct = default)\n{\n ct.ThrowIfCancellationRequested();\n\n // Resolve the session identifier.\n return ValueTask.FromResult\u0026lt;AuthSessionId?\u0026gt;(null);\n}\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EReplace the placeholder return with your existing resolution logic.\u003C/p\u003E\n\u003Cp\u003EIf your resolver performs asynchronous operations, use an \u003Ccode\u003Easync ValueTask\u0026lt;AuthSessionId?\u0026gt;\u003C/code\u003E implementation and await those operations.\u003C/p\u003E\n\u003Cp\u003EUpdate any direct calls from \u003Ccode\u003EResolve(...)\u003C/code\u003E to \u003Ccode\u003EResolveAsync(...)\u003C/code\u003E and await the result.\u003C/p\u003E\n\u003Cp\u003EApplications using the built-in session resolver do not need to make this change.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022custom-browser-bridges\u0022\u003E3. Custom Browser Bridges\u003C/h2\u003E\n\u003Cp\u003EThe \u003Ccode\u003EIBrowserUAuthBridge\u003C/code\u003E interface now includes:\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003EValueTask ConfigureAntiforgeryAsync(string tokenUrl, string? trustedOrigin = null);\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EThis allows the UltimateAuth client bootstrapper to configure antiforgery handling for browser requests.\u003C/p\u003E\n\u003Cp\u003EIf you provide a custom implementation of \u003Ccode\u003EIBrowserUAuthBridge\u003C/code\u003E, implement this new method.\u003C/p\u003E\n\u003Cp\u003EYour implementation must configure the browser-side antiforgery integration using the supplied token endpoint and optional trusted origin.\u003C/p\u003E\n\u003Cp\u003EThe exact implementation depends on your browser integration.\u003C/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EDo not add an empty implementation unless antiforgery handling is already provided by your custom bridge.\u003C/strong\u003E Doing so may leave protected browser requests without the required token.\u003C/p\u003E\n\u003Cp\u003EApplications using the built-in UltimateAuth browser bridge do not need to make this change.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022antiforgery-endpoint-configuration\u0022\u003E4. Antiforgery Endpoint Configuration\u003C/h2\u003E\n\u003Cp\u003Ev0.1.4 introduces a server-side antiforgery configuration section:\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003Eoptions.Antiforgery.TokenEndpoint = \u0026quot;/antiforgery/token\u0026quot;;\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EThe client also exposes the corresponding endpoint setting:\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003Eoptions.Endpoints.AntiforgeryToken = \u0026quot;/antiforgery/token\u0026quot;;\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EThe default endpoint path is \u003Ccode\u003E/antiforgery/token\u003C/code\u003E, resolved under the configured UltimateAuth base path.\u003C/p\u003E\n\u003Cp\u003ENo configuration change is required when using the defaults.\u003C/p\u003E\n\u003Cp\u003EIf you customize the endpoint, ensure the server and client configurations match.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022verify-your-application\u0022\u003E5. Verify Your Application\u003C/h2\u003E\n\u003Cp\u003EAfter upgrading to v0.1.4, verify the following flows where applicable:\u003C/p\u003E\n\u003Cul\u003E\n\u003Cli\u003ELogin and logout using the built-in browser client.\u003C/li\u003E\n\u003Cli\u003ESession refresh and validation.\u003C/li\u003E\n\u003Cli\u003EAuthenticated account and session management operations.\u003C/li\u003E\n\u003Cli\u003ECustom requests to UltimateAuth endpoints.\u003C/li\u003E\n\u003Cli\u003ECustom session resolver implementations.\u003C/li\u003E\n\u003Cli\u003ECustom browser bridge implementations.\u003C/li\u003E\n\u003Cli\u003EExternal Hub and multi-tenant configurations.\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003EFor applications using custom browser requests, verify that valid antiforgery tokens allow protected operations and missing or invalid tokens are rejected.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022migration-checklist\u0022\u003EMigration Checklist\u003C/h2\u003E\n\u003Cul class=\u0022contains-task-list\u0022\u003E\n\u003Cli class=\u0022task-list-item\u0022\u003E\u003Cinput disabled=\u0022disabled\u0022 type=\u0022checkbox\u0022\u003E Update UltimateAuth packages to compatible v0.1.4 versions.\u003C/li\u003E\n\u003Cli class=\u0022task-list-item\u0022\u003E\u003Cinput disabled=\u0022disabled\u0022 type=\u0022checkbox\u0022\u003E Update custom \u003Ccode\u003EISessionIdResolver\u003C/code\u003E implementations, if any.\u003C/li\u003E\n\u003Cli class=\u0022task-list-item\u0022\u003E\u003Cinput disabled=\u0022disabled\u0022 type=\u0022checkbox\u0022\u003E Update custom \u003Ccode\u003EIBrowserUAuthBridge\u003C/code\u003E implementations, if any.\u003C/li\u003E\n\u003Cli class=\u0022task-list-item\u0022\u003E\u003Cinput disabled=\u0022disabled\u0022 type=\u0022checkbox\u0022\u003E Add antiforgery token handling to custom browser HTTP requests, if applicable.\u003C/li\u003E\n\u003Cli class=\u0022task-list-item\u0022\u003E\u003Cinput disabled=\u0022disabled\u0022 type=\u0022checkbox\u0022\u003E Verify custom antiforgery endpoint configuration, if applicable.\u003C/li\u003E\n\u003Cli class=\u0022task-list-item\u0022\u003E\u003Cinput disabled=\u0022disabled\u0022 type=\u0022checkbox\u0022\u003E Run authentication, authorization, and session regression tests.\u003C/li\u003E\n\u003C/ul\u003E\n\u003Chr\u003E\n\u003Cp\u003E\u003Cstrong\u003EUsing the standard UltimateAuth client and built-in session resolution?\u003C/strong\u003E No application code changes are normally required. Update your packages and verify your existing authentication flows.\u003C/p\u003E\n\u003Cp\u003EFor the complete list of changes, see \u003Ca href=\u0022https://github.com/CodeBeamOrg/UltimateAuth/releases/tag/v0.1.4\u0022\u003EUltimateAuth v0.1.4 Release\u003C/a\u003E.\u003C/p\u003E\n",
+ "Headings": [
+ {
+ "Id": "antiforgery-protection-for-cookie-based-authentication",
+ "Text": "1. Antiforgery Protection for Cookie-Based Authentication",
+ "Level": 0
+ },
+ {
+ "Id": "using-the-built-in-browser-client",
+ "Text": "Using the built-in browser client",
+ "Level": 1
+ },
+ {
+ "Id": "using-custom-http-requests",
+ "Text": "Using custom HTTP requests",
+ "Level": 1
+ },
+ {
+ "Id": "custom-server-side-integrations",
+ "Text": "Custom server-side integrations",
+ "Level": 1
+ },
+ {
+ "Id": "isessionidresolver-is-now-asynchronous",
+ "Text": "2. ISessionIdResolver Is Now Asynchronous",
+ "Level": 0
+ },
+ {
+ "Id": "custom-browser-bridges",
+ "Text": "3. Custom Browser Bridges",
+ "Level": 0
+ },
+ {
+ "Id": "antiforgery-endpoint-configuration",
+ "Text": "4. Antiforgery Endpoint Configuration",
+ "Level": 0
+ },
+ {
+ "Id": "verify-your-application",
+ "Text": "5. Verify Your Application",
+ "Level": 0
+ },
+ {
+ "Id": "migration-checklist",
+ "Text": "Migration Checklist",
+ "Level": 0
+ }
+ ],
+ "SourceHash": "F8FA4FDA0E64B56BADDBA75519538C1ACBFDF88567EF487D30011FAB944B67CC",
+ "BuilderVersion": "1"
+}
\ No newline at end of file
diff --git a/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/migration/v0.2.0.json b/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/migration/v0.2.0.json
new file mode 100644
index 00000000..a0206e85
--- /dev/null
+++ b/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/wwwroot/docs/migration/v0.2.0.json
@@ -0,0 +1,39 @@
+{
+ "Slug": "migration/v0.2.0",
+ "Title": "Migrating to v0.2.0",
+ "Html": "\n\u003Cp\u003E\u003Cstrong\u003EMigration Impact: Medium \u2014 In Progress\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cstrong\u003ELatest published prerelease reviewed: v0.2.0-preview.2\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003EThis guide covers migration requirements for the upcoming UltimateAuth v0.2.0 release.\u003C/p\u003E\n\u003Cp\u003EThe guide is provisional and will be updated as new preview and release candidate versions become available. The final migration requirements may change before the stable v0.2.0 release.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022asynchronous-authorization-policies\u0022\u003E1. Asynchronous Authorization Policies\u003C/h2\u003E\n\u003Cp\u003E\u003Cstrong\u003EAvailable since preview.1\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003ECustom implementations of \u003Ccode\u003EIAccessPolicy\u003C/code\u003E, \u003Ccode\u003EIAccessInvariant\u003C/code\u003E, and \u003Ccode\u003EIAccessAuthority\u003C/code\u003E should migrate to \u003Ccode\u003EDecideAsync\u003C/code\u003E.\u003C/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EBefore:\u003C/strong\u003E\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003Epublic AccessDecision Decide(AccessContext context)\n{\n return AccessDecision.Allow();\n}\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003E\u003Cstrong\u003EAfter:\u003C/strong\u003E\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003Epublic ValueTask\u0026lt;AccessDecision\u0026gt; DecideAsync(AccessContext context, CancellationToken ct = default)\n{\n return ValueTask.FromResult(AccessDecision.Allow());\n}\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EFor \u003Ccode\u003EIAccessAuthority\u003C/code\u003E, preserve the existing \u003Ccode\u003EruntimePolicies\u003C/code\u003E parameter and add the cancellation token.\u003C/p\u003E\n\u003Cp\u003ESynchronous \u003Ccode\u003EDecide\u003C/code\u003E methods are obsolete. Existing synchronous implementations retain compatibility through the interface defaults, but new implementations should use \u003Ccode\u003EDecideAsync\u003C/code\u003E.\u003C/p\u003E\n\u003Cp\u003EIf your application invokes an authority directly, switch to \u003Ccode\u003EDecideAsync\u003C/code\u003E and await the result.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022authorization-check-results\u0022\u003E2. Authorization Check Results\u003C/h2\u003E\n\u003Cp\u003E\u003Cstrong\u003EAvailable since preview.1\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ccode\u003ECheckAsync\u003C/code\u003E now returns an explicit authorization decision in the response body.\u003C/p\u003E\n\u003Cp\u003EIf your application previously interpreted HTTP \u003Ccode\u003E403\u003C/code\u003E as the result of a successful authorization evaluation that denied access, update that handling.\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003Evar result = await UAuthClient.Authorization.CheckAsync(request);\n\nif (result.IsSuccess \u0026amp;\u0026amp; result.Value is { IsAllowed: true })\n{\n // Authorized\n}\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EAn HTTP-successful authorization check does not necessarily mean that access was granted.\u003C/p\u003E\n\u003Cp\u003EInspect the returned authorization decision rather than relying solely on the HTTP status.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022custom-user-lifecycle-integrations\u0022\u003E3. Custom User Lifecycle Integrations\u003C/h2\u003E\n\u003Cp\u003E\u003Cstrong\u003EAvailable since preview.2\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003EThe \u003Ccode\u003EIUserLifecycleIntegration.OnUserCreatedAsync\u003C/code\u003E signature now includes \u003Ccode\u003EUAuthClientProfile\u003C/code\u003E.\u003C/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EBefore:\u003C/strong\u003E\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003ETask OnUserCreatedAsync(\n TenantKey tenant,\n UserKey userKey,\n object request,\n CancellationToken ct = default);\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003E\u003Cstrong\u003EAfter:\u003C/strong\u003E\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003ETask OnUserCreatedAsync(\n TenantKey tenant,\n UserKey userKey,\n object request,\n UAuthClientProfile clientProfile,\n CancellationToken ct = default);\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EUpdate custom implementations to accept the additional client profile parameter.\u003C/p\u003E\n\u003Cp\u003EApplications using built-in lifecycle integrations do not need to make this change.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022identifier-and-profile-limits\u0022\u003E4. Identifier and Profile Limits\u003C/h2\u003E\n\u003Cp\u003E\u003Cstrong\u003EAvailable since preview.2\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003EThe reference Users domain now enforces additional identifier and profile safety limits.\u003C/p\u003E\n\u003Cp\u003EThe default maximum is 10 active identifiers per user. Applications requiring a different capacity should configure \u003Ccode\u003EIdentifiers.Behavior.MaxIdentifiersPerUser\u003C/code\u003E.\u003C/p\u003E\n\u003Cp\u003EExisting profile creation and update operations must also respect the new field-length and metadata limits.\u003C/p\u003E\n\u003Cp\u003EIf you use EF Core persistence:\u003C/p\u003E\n\u003Col\u003E\n\u003Cli\u003EReview existing profile data for values exceeding the new limits.\u003C/li\u003E\n\u003Cli\u003EAdd or apply the appropriate EF Core database migration for your application\u0027s DbContext.\u003C/li\u003E\n\u003Cli\u003EVerify that applications handling profile validation errors use the returned error codes.\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cp\u003ESee \u003Ca href=\u0022/docs/plugin-domains/profile-validation-limits\u0022\u003EProfile Validation \u0026amp; Limits\u003C/a\u003E for the supported limits.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022password-policies-and-history\u0022\u003E5. Password Policies and History\u003C/h2\u003E\n\u003Cp\u003E\u003Cstrong\u003EAvailable since preview.2\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003EThe reference password credential implementation now applies configurable password policies, with Standard as the default level.\u003C/p\u003E\n\u003Cp\u003EReview custom registration, password-change, and password-reset flows to ensure that they handle server-side password validation errors.\u003C/p\u003E\n\u003Cp\u003EApplications using persistent password-history storage must apply the required database migration before enabling password history.\u003C/p\u003E\n\u003Cp\u003EPassword history is disabled by default (\u003Ccode\u003ERememberLast = 0\u003C/code\u003E).\u003C/p\u003E\n\u003Cp\u003ESee \u003Ca href=\u0022/docs/security/password-policy\u0022\u003EPassword Policy \u0026amp; History\u003C/a\u003E for configuration and persistence requirements.\u003C/p\u003E\n\u003Ch2 class=\u0022mud-scrollspy-section\u0022 id=\u0022rate-limiting\u0022\u003E6. Rate Limiting\u003C/h2\u003E\n\u003Cp\u003E\u003Cstrong\u003EAvailable since preview.2\u003C/strong\u003E\u003C/p\u003E\n\u003Cp\u003EBuilt-in endpoint rate limiting is enabled by default when using:\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003Eapp.UseUltimateAuthWithAspNetCore();\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EIf your application already registers its own rate limiting middleware, avoid installing a duplicate limiter.\u003C/p\u003E\n\u003Cp\u003ETo retain application-owned rate limiting:\u003C/p\u003E\n\u003Cdiv class=\u0022docs-code-wrapper\u0022\u003E\u003Cdiv class=\u0022docs-code-header\u0022\u003E\u003Cspan class=\u0022docs-code-language\u0022\u003EC#\u003C/span\u003E\u003Cbutton type=\u0022button\u0022 class=\u0022docs-code-copy\u0022 aria-label=\u0022Copy code\u0022\u003ECopy\u003C/button\u003E\u003C/div\u003E\u003Cpre\u003E\u003Ccode class=\u0022language-csharp\u0022\u003Eapp.UseUltimateAuthWithAspNetCore(useRateLimiting: false);\n\u003C/code\u003E\u003C/pre\u003E\u003C/div\u003E\n\u003Cp\u003EThen configure your existing \u003Ccode\u003EUseRateLimiter()\u003C/code\u003E middleware in the appropriate pipeline position.\u003C/p\u003E\n\u003Cp\u003EApplications using \u003Ccode\u003EUseUltimateAuth()\u003C/code\u003E without the integrated ASP.NET Core helper do not enable UltimateAuth rate limiting by default.\u003C/p\u003E\n\u003Cp\u003EReview custom HTTP clients and authentication flows for HTTP \u003Ccode\u003E429 Too Many Requests\u003C/code\u003E handling.\u003C/p\u003E\n\u003Cp\u003ESee \u003Ca href=\u0022/docs/security/rate-limiting\u0022\u003ERate Limiting\u003C/a\u003E for middleware integration and defaults.\u003C/p\u003E\n\u003Chr\u003E\n\u003Cp\u003EThis page will continue to evolve through the v0.2.0 preview and RC series and will become the stable migration guide when v0.2.0 is released.\u003C/p\u003E\n",
+ "Headings": [
+ {
+ "Id": "asynchronous-authorization-policies",
+ "Text": "1. Asynchronous Authorization Policies",
+ "Level": 0
+ },
+ {
+ "Id": "authorization-check-results",
+ "Text": "2. Authorization Check Results",
+ "Level": 0
+ },
+ {
+ "Id": "custom-user-lifecycle-integrations",
+ "Text": "3. Custom User Lifecycle Integrations",
+ "Level": 0
+ },
+ {
+ "Id": "identifier-and-profile-limits",
+ "Text": "4. Identifier and Profile Limits",
+ "Level": 0
+ },
+ {
+ "Id": "password-policies-and-history",
+ "Text": "5. Password Policies and History",
+ "Level": 0
+ },
+ {
+ "Id": "rate-limiting",
+ "Text": "6. Rate Limiting",
+ "Level": 0
+ }
+ ],
+ "SourceHash": "99DF0B4E30A8578E3B2E809B38606FC0041D6A54F05EECDC98D95E8FD78DCBBA",
+ "BuilderVersion": "1"
+}
\ No newline at end of file
diff --git a/src/client/CodeBeam.UltimateAuth.Client.Blazor/Components/UAuthLoginForm.razor.cs b/src/client/CodeBeam.UltimateAuth.Client.Blazor/Components/UAuthLoginForm.razor.cs
index 7ff71a56..d9c54663 100644
--- a/src/client/CodeBeam.UltimateAuth.Client.Blazor/Components/UAuthLoginForm.razor.cs
+++ b/src/client/CodeBeam.UltimateAuth.Client.Blazor/Components/UAuthLoginForm.razor.cs
@@ -95,6 +95,13 @@ public partial class UAuthLoginForm
[Parameter]
public EventCallback OnTryResult { get; set; }
+ private bool _isSubmitting;
+
+ [Parameter]
+ public EventCallback OnSubmittingChanged { get; set; }
+
+ public bool IsSubmitting => _isSubmitting;
+
private ElementReference _form;
private HubCredentials? _credentials;
@@ -174,16 +181,31 @@ public async Task ReloadAsync()
/// Thrown if the form has not been rendered. Call this method only after the OnAfterRender lifecycle event.
public async Task SubmitAsync()
{
+ if (_isSubmitting)
+ return;
+
if (_form.Context is null)
throw new InvalidOperationException("Form is not yet rendered. Call SubmitAsync after OnAfterRender.");
- if (LoginType == UAuthLoginType.Pkce)
+ _isSubmitting = true;
+
+ try
{
- await SubmitPkceAsync();
+ await OnSubmittingChanged.InvokeAsync(true);
+
+ if (LoginType == UAuthLoginType.Pkce)
+ {
+ await SubmitPkceAsync();
+ }
+ else
+ {
+ await SubmitPasswordAsync();
+ }
}
- else
+ finally
{
- await SubmitPasswordAsync();
+ _isSubmitting = false;
+ await OnSubmittingChanged.InvokeAsync(false);
}
}