I have a MAUI app running on localhost and when you start the app, it triggers microsoft login, after the user sucessfull login I catch the ClaimsPrincipal and IsAuthenticated is always false. According to my Main.razor component if the user is not Authenticated it calls the RedirectToLogin Component again and I don't know how to Authorize my logged in user in the app so it might have somethin to do with the IsAuthenticated being false.
I have seen some solutions and they say you have to build ClaimsPrincipal passin the authentication type as parameter to the ClaimsIdentity like this:
new ClaimsPrincipal(new Identity("something"))
The problem is that I get already the ClaimsPrincipal from AAD só I dont know what I should do because I have no way to see the AAD because it is taken care by other team.
This is my Main.razor component:
<Router AppAssembly="@typeof(Main).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<Authorizing>
Authorizing...
</Authorizing>
<NotAuthorized>
<RedirectToLogin />
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
</Router>
This is RedirectToLogin component:
@using Microsoft.AspNetCore.Components.Authorization
@using OfficeManagerApp.Areas.Services.Implementations
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject NavigationManager NavigationManager
<div ><span>Redirecting...</span></div>
@code {
protected override async Task OnInitializedAsync()
{
await ((ExternalAuthStateProvider)AuthenticationStateProvider)
.LogInAsync();
NavigationManager.NavigateTo("/", forceLoad: true);
}
}
and here is where I have the break point to see the CLaimsPrincipal inside the ExternalAuthStateProvider class:
Here are the tutorials I followed for this.
ExternalAuthStateProvider tutorial
I also have a solution using just the PlatformService tutorial with the same problem.
CodePudding user response:
After a while I found the solution!
Basically you receive a ClaimsPrincipal from AAD but you have to create your own ClaimsPrincipal inside the app using the claims from the AAD ClaimsPrincipal.
In ExternalAuthStateProvider.cs, LoginWithExternalProviderAsync() method I did the following:
private async Task<ClaimsPrincipal> LoginWithExternalProviderAsync()
{
var authenticationResult = await _platformService.GetAuthenticationResult();
var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(authenticationResult.ClaimsPrincipal.Claims, "Basic"));
return await Task.FromResult(authenticatedUser);
}
You just need to do this and then it works!!
Extra -----------
To improve the flow login logout, I created a LoginPage.razor:
@page "/login"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using OfficeManagerApp.Areas.Services.Implementations
@attribute [AllowAnonymous]
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject NavigationManager NavigationManager
<button @onclick="Login">Log in</button>
@code
{
public async Task Login()
{
await ((ExternalAuthStateProvider)AuthenticationStateProvider)
.LogInAsync();
NavigationManager.NavigateTo("/");
}
}
Changed the RedirectToLogin,razor:
@inject NavigationManager NavigationManager
<div ><span>Redirecting...</span></div>
@code {
protected override void OnInitialized()
{
NavigationManager.NavigateTo("/login");
}
}
And added a logout method:
private void Logout(){
((ExternalAuthStateProvider)AuthenticationStateProvider)
.Logout();
}
Also did some changes to my Main.razor:
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Main).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<Authorizing>
Authorizing...
</Authorizing>
<NotAuthorized>
@if (!context.User.Identity.IsAuthenticated)
{
<RedirectToLogin />
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
Note don't forget to add to your _Imports.razor:
@using Microsoft.AspNetCore.Components.Authorization