Your First Component
Drop in the AuthenticationComponent to add a complete login experience — including OAuth providers,
two-factor authentication, passkeys, and registration — with just a few lines of Razor markup.
Minimal Example
Create a login page using the AuthenticationComponent:
@page "/login"
<AuthenticationComponent
AppId="d6e61c7a-eec5-4164-a004-9b99eb5eb6de"
OnAuthenticationSuccess="@HandleLoginSuccess"
OnAuthenticationError="@HandleLoginError" />
@code {
private async Task HandleLoginSuccess(AuthenticationResponse response)
{
Console.WriteLine($"Welcome, {response.User?.DisplayName}!");
NavigationManager.NavigateTo("/dashboard");
}
private void HandleLoginError(string errorMessage)
{
Console.WriteLine($"Login failed: {errorMessage}");
}
}
import { WildwoodProvider, AuthenticationComponent } from '@wildwood/react';
function LoginPage() {
return (
<WildwoodProvider config={{
baseUrl: 'https://your-api.wildwood.example.com',
appId: 'd6e61c7a-eec5-4164-a004-9b99eb5eb6de',
enableAutoTokenRefresh: true,
}}>
<AuthenticationComponent
appId="d6e61c7a-eec5-4164-a004-9b99eb5eb6de"
onAuthenticationSuccess={(response) => {
console.log(`Welcome, ${response.user?.displayName}!`);
navigate('/dashboard');
}}
onAuthenticationError={(error) => {
console.log(`Login failed: ${error}`);
}}
/>
</WildwoodProvider>
);
}
import { WildwoodProvider, AuthenticationComponent } from '@wildwood/react-native';
function LoginScreen({ navigation }) {
return (
<WildwoodProvider config={{
baseUrl: 'https://your-api.wildwood.example.com',
appId: 'd6e61c7a-eec5-4164-a004-9b99eb5eb6de',
storage: 'asyncStorage',
}}>
<AuthenticationComponent
appId="d6e61c7a-eec5-4164-a004-9b99eb5eb6de"
onAuthenticationSuccess={(response) => {
navigation.navigate('Dashboard');
}}
onAuthenticationError={(error) => {
Alert.alert('Login Failed', error);
}}
/>
</WildwoodProvider>
);
}
import { createAuthMiddleware } from '@wildwood/node';
// Server-side: protect routes with JWT validation
const auth = createAuthMiddleware({
baseUrl: 'https://your-api.wildwood.example.com',
apiKey: process.env.WILDWOOD_API_KEY,
});
app.use('/api', auth);
app.get('/api/profile', (req, res) => {
res.json(req.wildwoodUser);
});
That is all you need. The component handles:
- Rendering the login form (username + password)
- Loading and displaying available OAuth providers (Google, Apple, etc.)
- Passkey/WebAuthn authentication if configured
- Two-factor authentication flow (TOTP, email codes, recovery codes)
- Registration with token-based or open registration
- Forgot password and password reset flows
- CAPTCHA integration if enabled for the app
- Loading spinners, error display, and form validation
AuthenticationComponent Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
AppId |
string? |
null |
The application ID to authenticate against. Determines which providers, captcha, and auth settings are loaded. |
Title |
string? |
null |
Custom title displayed above the form. Defaults to "Sign In" or "Create Account" based on mode. |
ShowPasswordField |
bool |
true |
Whether to show the password field. Automatically set to false if local auth is disabled. |
ShowDetailedErrors |
bool |
true |
Show detailed error messages with stack info. Set to false in production. |
AvailableProviders |
List<AuthProvider>? |
null |
Pre-loaded list of OAuth providers. If null, the component fetches them from the API. |
CaptchaConfig |
CaptchaConfiguration? |
null |
Pre-loaded CAPTCHA configuration. If null, the component fetches it from the API. |
AuthConfig |
AuthenticationConfiguration? |
null |
Pre-loaded authentication configuration. If null, the component fetches it from the API. |
Event Callbacks
| Event | Type | Description |
|---|---|---|
OnAuthenticationSuccess |
EventCallback<AuthenticationResponse> |
Fired when the user successfully authenticates (login, 2FA, or passkey).
The AuthenticationResponse contains the JWT token, refresh token, and user profile.
|
OnAuthenticationError |
EventCallback<string> |
Fired when an authentication error occurs. The string parameter contains the error message. |
OnError |
EventCallback<ComponentErrorEventArgs> |
Inherited from BaseWildwoodComponent. Fired on any component error with full exception details
including Exception, Context, ComponentType, and ComponentId.
|
OnLoadingStateChanged |
EventCallback<bool> |
Inherited from BaseWildwoodComponent. Fired when the component starts or stops loading.
|
Handling the Authentication Response
The OnAuthenticationSuccess callback receives an AuthenticationResponse object.
Here is a more complete example showing what you can do with it:
private async Task HandleLoginSuccess(AuthenticationResponse response)
{
// Access the JWT token for API calls
var token = response.Token;
// Access the refresh token for session management
var refreshToken = response.RefreshToken;
// Access user profile information
var user = response.User;
var displayName = user?.DisplayName;
var email = user?.Email;
var userId = user?.Id;
// Check if the response requires additional steps
if (response.RequiresPasswordReset)
{
// User logged in with a temporary password.
// The component handles this automatically, but you can
// add custom logic here if needed.
return;
}
if (response.RequiresTwoFactor)
{
// Two-factor authentication is required.
// The component handles this automatically.
return;
}
// Store the token for subsequent API calls
// (WildwoodSessionManager handles this if EnableAutoTokenRefresh is on)
// Navigate to the authenticated area of your app
NavigationManager.NavigateTo("/dashboard");
}
The BaseWildwoodComponent Pattern
The AuthenticationComponent — like every WildwoodComponent — inherits from
BaseWildwoodComponent. This base class provides a consistent set of features across the entire library:
Automatic Error Handling
When an exception occurs inside a component, BaseWildwoodComponent catches it, logs it via
ILogger, sets the ErrorMessage property for UI display, and fires the OnError
event callback. You never need to wrap component usage in a try-catch.
<AuthenticationComponent
AppId="@AppId"
EnableErrorHandling="true"
OnError="@HandleComponentError" />
@code {
private void HandleComponentError(ComponentErrorEventArgs args)
{
// args.Exception - the original exception
// args.Context - description of what was happening (e.g., "Processing authentication")
// args.ComponentType - "AuthenticationComponent"
// args.ComponentId - unique 8-char component ID
Logger.LogError(args.Exception, "Error in {Component}: {Context}",
args.ComponentType, args.Context);
}
}
Loading State Management
The base class provides IsLoading and ShowLoadingStates properties. When an async operation
runs through the ExecuteAsync() helper, the component automatically shows a loading spinner
and disables interactive elements:
<!-- Disable the loading spinner if you handle it yourself -->
<AuthenticationComponent
AppId="@AppId"
ShowLoadingStates="false"
OnLoadingStateChanged="@HandleLoading" />
@code {
private bool _isComponentLoading;
private void HandleLoading(bool isLoading)
{
_isComponentLoading = isLoading;
StateHasChanged();
}
}
Theme Integration
Components automatically subscribe to theme changes via IComponentThemeService. When the theme changes,
all components re-render with the new theme's CSS classes. The root element of every component includes dynamic
CSS classes: wildwood-component, the component-specific class, and the current theme class.
Custom CSS Classes
You can pass additional CSS classes and arbitrary HTML attributes to any WildwoodComponent:
<AuthenticationComponent
AppId="@AppId"
CssClass="my-custom-login"
data-testid="login-form"
OnAuthenticationSuccess="@HandleLoginSuccess" />
Safe JavaScript Interop
The base class provides InvokeJSAsync<T>() and InvokeJSVoidAsync() wrappers that catch
JavaScript interop errors and route them through the standard error handling pipeline instead of crashing the component.
What Happens After Login
After a successful authentication, you typically want to:
-
Start session management — If you enabled
EnableAutoTokenRefreshin your options, theIWildwoodSessionManagerautomatically keeps the session alive by refreshing tokens before they expire. -
Navigate to the authenticated area — Use Blazor's
NavigationManagerto redirect the user to a dashboard or home page. -
Use the token for API calls — The JWT from
response.Tokenis used to authenticate requests to WildwoodAPI endpoints.
@inject IWildwoodSessionManager SessionManager
@inject NavigationManager Navigation
@code {
private async Task HandleLoginSuccess(AuthenticationResponse response)
{
await SessionManager.StartSessionAsync(response.Token, response.RefreshToken);
Navigation.NavigateTo("/dashboard");
}
}
import { useSession } from '@wildwood/react';
function LoginPage() {
const { login } = useSession();
const handleSuccess = async (response) => {
await login(response); // Stores tokens, starts auto-refresh
navigate('/dashboard');
};
return <AuthenticationComponent onAuthenticationSuccess={handleSuccess} />;
}
import { useSession } from '@wildwood/react-native';
function LoginScreen({ navigation }) {
const { login } = useSession();
const handleSuccess = async (response) => {
await login(response); // Stores tokens in AsyncStorage
navigation.navigate('Dashboard');
};
return <AuthenticationComponent onAuthenticationSuccess={handleSuccess} />;
}
- Authentication & Session — Deep dive into session management, token refresh, and 2FA
- Component Reference — Full reference for all WildwoodComponents
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Component shows "Authentication is currently disabled" | The app's auth configuration has IsEnabled = false |
Enable authentication in WildwoodAdmin for your AppId |
| No OAuth providers shown | No providers configured for the app, or the API is unreachable | Configure providers in WildwoodAdmin, or check the BaseUrl setting |
| "WildwoodComponents assembly not found" exception | Package not properly referenced | Ensure the NuGet package or project reference is in your .csproj and run dotnet restore |
| Component renders but login fails with network error | BaseUrl is incorrect or the API is not running |
Verify the API is accessible at the configured URL and check CORS settings |
| Styles are missing or component looks unstyled | Theme CSS not included | Add the wildwood-themes.css link to your host page (see Installation) |