Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authorization and MAUI Blazor Hybrid #3253

Open
MarkOverstreet opened this issue Feb 13, 2023 · 6 comments
Open

Authorization and MAUI Blazor Hybrid #3253

MarkOverstreet opened this issue Feb 13, 2023 · 6 comments

Comments

@MarkOverstreet
Copy link

Describe the bug
I am trying to create a simple MAUI Blazor Hybrid app using CSLA with authentication and getting an error when the app starts. I used your example code from the MAUI app and it fails when trying to find the Csla.ApplicationContext class.

Version and Platform
CSLA version: 6.2.2
OS: Windows 10
Platform: MAUI Blazor Hybrid

Code that Fails

            var provider = builder.Services.BuildServiceProvider();
            App.ApplicationContext = provider.GetRequiredService<ApplicationContext>();  // this line fails

Stack Trace or Exception Detail
System.InvalidOperationException: 'Unable to resolve service for type 'Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider' while attempting to activate 'Csla.Blazor.WebAssembly.ApplicationContextManager'.'

@rockfordlhotka
Copy link
Member

It is saying that there's no type mapped to the Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider service type.

The CSLA ApplicationContext type needs access to an AuthenticationStateProvider instance, because that's where Blazor stores the current user identity.

The AuthenticationStateProvider service may be mapped in various ways - I'm not sure there's an automatic mapping for a MAUI Blazor Hybrid app type.

@MarkOverstreet
Copy link
Author

After some more analysis I am not sure what to do so let me describe the simple app I am trying to build to prove that CSLA and MAUI Hybrid will work for us. I am trying to build a login component (ex: LoginComponent.razor) that is in a shared class library that can then be used across Server, WASM and MAUI Blazor Hybrid. I currently have it working in WASM but the same component generates the error above in MAUI Blazor Hybrid and I believe it is because we built the shared class library referencing the Csla.Blazor.WebAssembly.

So the question is how in CSLA can I create a shared LoginComponent so that we can use the same login screen and authentication across all 3 platforms?

@rockfordlhotka
Copy link
Member

It might be your component, but the error is saying that in your app startup you aren't mapping a type to the AuthenticationStateProvider service.

So it is also quite possible that your component is fine, and would work if a type was mapped to that service during app startup. Something like this:

  services. AddScoped<AuthenticationStateProvider, yourtype>();

@rockfordlhotka
Copy link
Member

(I've been leaving this as an Issue instead of Discussion b/c maybe there's something we need to add to CSLA to better support the MAUI hybrid scenario)

@MarkOverstreet
Copy link
Author

MarkOverstreet commented Mar 2, 2023

We looked into this further and were able to get a working solution; however, we may not have done it correctly and need your advice. We created a sample project that demonstrates authorization in a WASM project, a Server project and a BlazorHybridMAUI project where we are using a shared UI library and you can see the code here... https://github.com/IgnyteSoftware/CslaBlazorMaui

Essentially, in order to share authorization with all three project types using a shared UI library, we had to add a reference to Csla.Blazor.WebAssembly in each project because this had the CslaAuthorizationStateProvider. Obviously, we can have this reference in the WASM project, but it seems that we shouldn't have it in the Server and MAUI projects. We noticed a commit message (feb1739) that indicated you moved the CslaAuthorizationStateProvider to only build in the WASM project. Why? Is there a reason we can't share this between all 3 projects?

The code below demonstrates a workaround of sorts. Maybe CSLA needs to add a configuration method specific to BlazorHybridMAUI (ex .AddBlazorMaui).

// The following lines were required in the MAUI and Server projects to share the csla authentication state provider
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<CslaAuthenticationStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider>(s => s.GetRequiredService<CslaAuthenticationStateProvider>());
            
// The following lines were required for Maui only, Server is configured differently as you have shown in your standard sample project
builder.Services.AddTransient<HttpClient>();
builder.Services.AddCsla(o => o
  .AddBlazorWebAssembly()  // This was required in the MAUI project to hookup the ViewModel provided by CSLA 
  .DataPortal(dpo => dpo
    .UseHttpProxy(options => options.DataPortalUrl = "https://localhost:7078/api/DataPortal")));

@rockfordlhotka
Copy link
Member

iirc, the change was made because Blazor server provides an ASP.NET Core specific provider that works in the server scenario.

At the time I wasn't thinking about MAUI hybrid - which might benefit from the same CSLA type as wasm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants