I have a Blazor server-side app and in Startup.cs
I have the following:
services.AddSingleton<ITicketStore, CookieMemoryTicketStore>();services.AddOptions<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme) .Configure<ITicketStore>((options, store) => { options.ExpireTimeSpan = TimeSpan.FromDays(14); options.SlidingExpiration = true; options.SessionStore = store; });
I use a ITicketStore
implementation to store the cookies using MemoryCache
. and then the authentication set up:
services.AddAuthentication(options =>{ options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme).AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>{ options.Authority = "authority"; options.ClientId = "clientid"; options.ClientSecret = "clientsecret"; options.ResponseType = OpenIdConnectResponseType.Code; options.ResponseMode = OpenIdConnectResponseMode.FormPost; options.GetClaimsFromUserInfoEndpoint = true; options.MapInboundClaims = false; options.SaveTokens = true; options.UseTokenLifetime = false; options.UseSecurityTokenValidator = true; options.Scope.Add(OpenIdConnectScope.OpenIdProfile); options.Scope.Add(OpenIdConnectScope.Email); options.Scope.Add(OpenIdConnectScope.OfflineAccess); options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name", RoleClaimType = "role" };});services.AddAuthorizationCore();
And in my _Host.cshtml
I do:
var tokens = new InitialApplicationState{ AccessToken = await HttpContext.GetTokenAsync(Token.Access), IdToken = await HttpContext.GetTokenAsync(Token.Id), RefreshToken = await HttpContext.GetTokenAsync(Token.Refresh),};
And the InitialApplicationState
is then used in App.razor
.
And during my login process (on login redirect from the auth provider), I start with:
var oidcOptions = new OidcClientOptions{ Authority = "issuer", ClientId = "clientid", LoadProfile = false, Scope = StandardScopes.OpenId};var client = new OidcClient(oidcOptions);var state = await client.GetUserInfoAsync(tokenProvider.AccessToken, ct);
Using the above everything works fine for a few hours. Then all of a sudden, when the user is automatically authenticated (his authenication cookies are still stored in the browser), the call to GetUserInfoAsync
fails with an exception because tokenProvider.AccessToken
is null
.
The only workaround so far is to delete all the site cookies and then authentication/authorization works again.
Has anyone encountered this problem? Is the above code missing some steps?