Applicazione di esempio
Consulta la applicazione di esempio per i dettagli di implementazione.
Installazione
Installa il pacchetto NuGet ITfoxtec.Identity.BlazorWebAssembly.OpenidConnect tramite il gestore pacchetti di Visual Studio.
Oppure installa via PowerShell usando il comando seguente.
Install-Package ITfoxtec.Identity.BlazorWebAssembly.OpenidConnect
Oppure tramite CLI.
dotnet add package ITfoxtec.Identity.BlazorWebAssembly.OpenidConnect
Configurazione e setup
Registra OpenidConnectPkce, HttpClient e IHttpClientFactory nel file Program.cs.
private static void ConfigureServices(IServiceCollection services, WebAssemblyHostConfiguration configuration, IWebAssemblyHostEnvironment hostEnvironment)
{
services.AddHttpClient("BlazorWebAssemblyOidcSample.API", client => client.BaseAddress = new Uri(hostEnvironment.BaseAddress))
.AddHttpMessageHandler<AccessTokenMessageHandler>();
services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("BlazorWebAssemblyOidcSample.API"));
services.AddOpenidConnectPkce(settings =>
{
configuration.Bind("IdentitySettings", settings);
});
}
Aggiungi appsettings.json e gli eventuali appsettings.Development.json sotto wwwroot con la configurazione IdentitySettings. Lo scope è aggiunto come elenco di valori separati da spazi.
{
"IdentitySettings": {
"Authority": "https://...some authority.../",
"ClientId": "...client id...",
"Scope": "...some scope..."
}
}
Aggiungi lo spazio dei nomi della libreria @using ITfoxtec.Identity.BlazorWebAssembly.OpenidConnect a Imports.razor.
Chiamate API verso un altro dominio
La configurazione può essere estesa per supportare chiamate API verso domini diversi dal dominio base. Gli AuthorizedUris attendibili nella configurazione IdentitySettings sono configurati su AccessTokenMessageHandler.
private static void ConfigureServices(IServiceCollection services, WebAssemblyHostConfiguration configuration, IWebAssemblyHostEnvironment hostEnvironment)
{
services.AddHttpClient("BlazorWebAssemblyOidcSample.API", client => client.BaseAddress = new Uri(hostEnvironment.BaseAddress))
.AddHttpMessageHandler(sp =>
{
var handler = sp.GetService<AccessTokenMessageHandler>();
configuration.Bind("IdentitySettings", handler);
return handler;
});
services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("BlazorWebAssemblyOidcSample.API"));
services.AddOpenidConnectPkce(settings =>
{
configuration.Bind("IdentitySettings", settings);
});
}
Aggiungi domini attendibili come AuthorizedUris nella configurazione IdentitySettings.
{
"IdentitySettings": {
"Authority": "https://...some authority.../",
"ClientId": "...client id...",
"Scope": "...some scope...",
"Resources": [ "...resource..." ],
"AuthorizedUris": [ "...authorized api Uri..." ]
}
}
Validazione periodica del token di accesso
Imposta SessionValidationIntervalSeconds in IdentitySettings (predefinito 300; imposta 0 per disabilitare).
Quando abilitato, OidcAuthenticationStateProvider chiama periodicamente l'endpoint UserInfo tramite OidcHelper.ValidateAccessTokenWithUserInfoEndpoint.
Se la validazione fallisce, il provider cancella la sessione e genera l'evento di logout così la UI può chiedere all'utente di accedere di nuovo.
Aggiungi pagina di callback
Aggiungi una pagina di callback Authentication.razor nella cartella Pages con il seguente contenuto.
@page "/authentication/{action}"
@inherits AuthenticationPageBase
Autorizza le view
Aggiorna App.razor per includere AuthorizeRouteView/NotAuthorized con l'elemento OidcRedirectToLogin. OidcRedirectToLogin avvia il flusso di login se l'utente non ha accesso.
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<OidcRedirectToLogin />
</NotAuthorized>
<Authorizing>
<h1>Authentication in progress</h1>
<p>Only visible while authentication is in progress.</p>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<h1>Sorry</h1>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
</Router>
In questo modo sono supportati sia l'attributo Authorize sia AuthorizeView.
Menu login/logout
Aggiungi LoginDisplay.razor con un menu di login/logout con il seguente contenuto.
@inject OpenidConnectPkce oenidConnectPkce
<AuthorizeView>
<Authorized>
Hello, @context.User.Identity.Name!
<button class="nav-link btn btn-link" @onclick="LogoutAsync">Logout</button>
</Authorized>
<NotAuthorized>
<button class="nav-link btn btn-link" @onclick="LoginAsync">Login</button>
</NotAuthorized>
</AuthorizeView>
@code{
private async Task LoginAsync(MouseEventArgs args)
{
await oenidConnectPkce.LoginAsync();
}
private async Task LogoutAsync(MouseEventArgs args)
{
await oenidConnectPkce.LogoutAsync();
}
}
LoginDisplay può essere aggiunto a MainLayout.razor così.
@inherits LayoutComponentBase
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
<LoginDisplay />
</div>
<div class="content px-4">
@Body
</div>
</div>