Reputation: 519
When attempting to retrieve the name of the user who is currently logged in after being authorized, the User.Identity.Name is null. I do not seem to understand why it is null if I am successfully logged in from IdentityServer
it redirects me back to my blazor project.
In my blazor project I have the following code set up as so:
Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton(sp => new HttpClient { BaseAddress = new Uri("http://localhost:36626") }); // WebApi project
services.AddTransient<IWeatherForecastServices, WeatherForecastServices>();
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.SignOutScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.Authority = "https://localhost:5443"; // IdentityServer Project
options.ClientId = "interactive";
options.ClientSecret = "KEY";
options.ResponseType = "code";
options.Scope.Add("profile"); // default scope
options.Scope.Add("scope2");
options.Scope.Add("roles");
options.Scope.Add("permissions");
options.ClaimActions.MapUniqueJsonKey("role", "role");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
});
services.AddScoped<TokenProvider>();
services.AddCors(options =>
{
options.AddPolicy("Open", builder => builder.AllowAnyOrigin().AllowAnyHeader());
}
);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
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.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors("Open");
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
Index.razor
here variable "Name" is null:
@page "/"
@inject AuthenticationStateProvider GetAuthenticationStateAsync
<AuthorizeView>
<Authorized>
<h3>Welcome, <b>@Name</b></h3>
</Authorized>
<NotAuthorized>
<h3>You are signed out!!</h3>
</NotAuthorized>
</AuthorizeView>
@code{
private string Name;
protected override async Task OnInitializedAsync()
{
var authstate = await GetAuthenticationStateAsync.GetAuthenticationStateAsync();
var user = authstate.User;
var name = user.Identity.Name;
Name = name;
}
}
My Login.cshtml.cs
:
public class LoginModel : PageModel
{
public async Task<IActionResult> OnGetAsync(string redirectUri)
{
// just to remove compiler warning
await Task.CompletedTask;
if (string.IsNullOrWhiteSpace(redirectUri))
{
redirectUri = Url.Content("~/");
}
// If user is already logged in, we can redirect directly...
if (HttpContext.User.Identity.IsAuthenticated)
{
Response.Redirect(redirectUri);
}
return Challenge(
new AuthenticationProperties
{
RedirectUri = redirectUri
},
OpenIdConnectDefaults.AuthenticationScheme);
}
}
My logout.cshtml.cs
:
public class LogoutModel : PageModel
{
public async Task<IActionResult> OnGetAsync() // THIS METHOD DOES NOT DELETE THE AUTH COOKIES NOR REDIRECT YOU BACK TO BLAZOR APP EVEN THOUGH YOU HAVE THE REDIRECT URI OF BLAZOR
{
// just to remove compiler warning
await Task.CompletedTask;
var signOut = SignOut(
new AuthenticationProperties
{
RedirectUri = "https://localhost:5445" // Blazor Project
},
OpenIdConnectDefaults.AuthenticationScheme,
CookieAuthenticationDefaults.AuthenticationScheme);
return signOut;
}
}
Frontend views:
From the start of the projects running :
I click Login, which will redirect me to the identityserver project:
Homepage view, here is where it is supposed to show me the current user logged in, but it does not:
When I hit logout it redirects me to identityserver saying I am logged out:
Is there something that is causing the variable Name
to be null inside of my Index.razor
file?
Upvotes: 4
Views: 1912
Reputation: 45616
Why do you use in your Index component ?
If you use the <AuthorizeView>
, you don't have to create an AuthenticationStateProvider object... you can simply do: @context.User.Identity.Name
, as the CascadingAuthenticationComponent, used in the App component, cascades the AuthenticationState object to children. If you do not have a CascadingAuthenticationComponent in your App component add it.
It is very likely that no authentication state object is created... This imply that both the CascadingAuthenticationComponent and the AuthenticationStateProvider object return null values.
Try the following:
Comment out the following:
options.Scope.Add("profile"); // default scope
options.Scope.Add("scope2");
options.Scope.Add("roles");
options.Scope.Add("permissions");
options.ClaimActions.MapUniqueJsonKey("role", "role");
And use the following instead:
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name"
};
options.UseTokenLifetime = false;
You says that you've created an IdentityServer, right? If so, in your Config file, what value did you give to the ClientId property of the Client object?
This settings in the ConfigureServices method:
options.ClientId = "interactive";
should reflect it.
Here's a code sample for a Client object in the Config.cs file in your IdentityServer4 project:
public static IEnumerable<Client> Clients =>
new Client[]
{
new Client
{
ClientId = "blazor",
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
RequireClientSecret = false,
AllowedCorsOrigins = { "https://localhost:5001" },
AllowedScopes = { "openid", "profile", "email", "weatherapi" },
// where to redirect to after login
RedirectUris = { "https://localhost:5001/authentication/login-callback" },
PostLogoutRedirectUris = { "https://localhost:5001/" },
Enabled = true,
AllowOfflineAccess = true
},
};
Upvotes: 3