I have a Blazor website that uses MFA loin via Entra and it works fine, what doesn't work is the session time. After 1 hour, the session ends and the user is logged out and forced to log back in. Is there anyway at all to set the session length? I've Google'd myself out trying to find an answer to this.
Below is my code so far in program.cs, some of it is most likely redundent now as I've been adding bits in for testing to see if anything will work! Figured if the session ends after 10 seconds like I'm trying to acheive below, I know I'm onto a winning solution, but it doesnt work.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.EntityFrameworkCore;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
.AddDistributedTokenCaches()
.AddSessionTokenCaches();
builder.Services.AddDistributedMemoryCache();
builder.Services.ConfigureApplicationCookie(x => {
x.ExpireTimeSpan = TimeSpan.FromSeconds(10);
//x.SlidingExpiration = true;
});
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
builder.Services.AddControllers().AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
builder.Services.AddDbContext<DB>(x =>
x.UseSqlServer(builder.Configuration.GetConnectionString("DB"))
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));
builder.Services.AddMvc().AddSessionStateTempDataProvider();
builder.Services.AddSession(x => {
x.Cookie.Expiration = TimeSpan.FromSeconds(10);
x.IdleTimeout = TimeSpan.FromSeconds(10);
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
app.UseWebAssemblyDebugging();
} else {
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllers();
app.MapFallbackToFile("index.html");
app.Run();
According to the documentation, there is a Access Token Lifetime
property, which affect Access tokens, ID tokens, SAML2 tokens, which is 1 hour by default. Note that there are limitations, as the documentation says:
You can specify the lifetime of an access, ID, or SAML token issued by the Microsoft identity platform. You can set token lifetimes for all apps in your organization, for multitenant (multi-organization) applications, or for service principals. We currently don't support configuring the token lifetimes for managed identity service principals.
This page provides information about how a lifetime policy may be defined/changed: https://learn.microsoft.com/en-us/entra/identity-platform/configure-token-lifetimes
It gives this sample code:
Install-Module Microsoft.Graph
Connect-MgGraph -Scopes "Policy.ReadWrite.ApplicationConfiguration","Policy.Read.All","Application.ReadWrite.All"
# Create a token lifetime policy
$params = @{
Definition = @('{"TokenLifetimePolicy":{"Version":1,"AccessTokenLifetime":"4:00:00"}}')
DisplayName = "WebPolicyScenario"
IsOrganizationDefault = $false
}
$tokenLifetimePolicyId=(New-MgPolicyTokenLifetimePolicy -BodyParameter $params).Id
# Display the policy
Get-MgPolicyTokenLifetimePolicy -TokenLifetimePolicyId $tokenLifetimePolicyId
# Assign the token lifetime policy to an app
$params = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/policies/tokenLifetimePolicies/$tokenLifetimePolicyId"
}
$applicationObjectId="aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb"
New-MgApplicationTokenLifetimePolicyByRef -ApplicationId $applicationObjectId -BodyParameter $params
# List the token lifetime policy on the app
Get-MgApplicationTokenLifetimePolicy -ApplicationId $applicationObjectId
# Remove the policy from the app
Remove-MgApplicationTokenLifetimePolicyByRef -ApplicationId $applicationObjectId -TokenLifetimePolicyId $tokenLifetimePolicyId
# Delete the policy
Remove-MgPolicyTokenLifetimePolicy -TokenLifetimePolicyId $tokenLifetimePolicyId
See the AccessTokenLifetime
property in the code in particular.
In the following steps, you'll create a policy that requires users to authenticate less frequently in your web app. Assign the policy to service principal, which sets the lifetime of the access/ID tokens to 8 hours for your web app.
Create a token lifetime policy.
POST https://graph.microsoft.com/v1.0/policies/tokenLifetimePolicies
Content-Type: application/json
{
"definition": [
"{\"TokenLifetimePolicy\":{\"Version\":1,\"AccessTokenLifetime\":\"8:00:00\"}}"
],
"displayName": "Contoso token lifetime policy",
"isOrganizationDefault": false
}
Assign the policy to a service principal.
POST https://graph.microsoft.com/v1.0/servicePrincipals/00001111-aaaa-2222-bbbb-3333cccc4444/tokenLifetimePolicies/$ref
Content-Type: application/json
{
"@odata.id":"https://graph.microsoft.com/v1.0/policies/tokenLifetimePolicies/00aa00aa-bb11-cc22-dd33-44ee44ee44ee"
}
List the policies on the service principal.
GET https://graph.microsoft.com/v1.0/servicePrincipals/00001111-aaaa-2222-bbbb-3333cccc4444/tokenLifetimePolicies
Remove the policy from the service principal.
DELETE https://graph.microsoft.com/v1.0/servicePrincipals/00001111-aaaa-2222-bbbb-3333cccc4444/tokenLifetimePolicies/00aa00aa-bb11-cc22-dd33-44ee44ee44ee/$ref
EDIT
As an alternative to the Powershell-based solution I have quoted from the documentation, @jbmintjb found MSAL, another solution, as we can find here. More information can be found here.