Skip to content

[Blazor] Use shared policies for client and server #12391

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

Closed
Herdo opened this issue Jul 20, 2019 · 7 comments
Closed

[Blazor] Use shared policies for client and server #12391

Herdo opened this issue Jul 20, 2019 · 7 comments
Labels
area-blazor Includes: Blazor, Razor Components question
Milestone

Comments

@Herdo
Copy link

Herdo commented Jul 20, 2019

Scenario

In my ASP.NET Core hosted client-side Blazor application, I want to use my policies in both projects.

  • In the server project to secure the API methods.
  • In the client project to appropriately show or hide certain parts of the views.

The current project template creates the following projects:

  • MyProject.Client (.NET Standard 2.0)
  • MyProject.Server (.NET Core 3.0)
  • MyProject.Shared (.NET Standard 2.0)

Problem

The clear approach would be to define the policies in the shared project, once.
However, policies defined in the shared project are not available in the server project.

This is partially due to the changes listed in #3756, as well as the fact that the Microsoft.AspNetCore.Identity.IdentityConstants are not available in the .NET Standard 2.0 project.

Possible options

IMHO, it should be possible to use the same policies for the server and client project, without having to define them twice. Three options I can currently come up with:

  • Make all projects .NET Core 3.0.
  • Define the policies separately in the MyProject.Server and MyProject.Client project (insufficient option).
  • Include the missing classes in .NET Standard (probably the worst option).
@mkArtakMSFT mkArtakMSFT added the area-blazor Includes: Blazor, Razor Components label Jul 22, 2019
@mkArtakMSFT
Copy link
Contributor

Hi. It looks like this is a question about how to use ASP.NET Core. While we do our best to look through all the issues filed here, to get a faster response we suggest posting your questions to StackOverflow using the asp.net-core-blazor tag.

@mkArtakMSFT mkArtakMSFT added this to the Discussions milestone Jul 22, 2019
@Herdo
Copy link
Author

Herdo commented Jul 22, 2019

Added question on StackOverflow: https://stackoverflow.com/questions/57150701/use-same-authorization-policies-for-client-and-server-in-blazor

Those mixed versions and the unknown compability between Microsoft.AspNetCore.App (3.0.0), Microsoft.AspNetCore.Authorization (3.0.0) and Microsoft.AspNetCore.Identity (2.2.0) aren't very obvious, nor comprehensible.

@Herdo
Copy link
Author

Herdo commented Jul 23, 2019

@mkArtakMSFT After further investigation, this is definietly an issue with the Microsoft.AspNetCore.Identity.IdentityConstants class provided by the Microsoft.AspNetCore.Identity (2.2.0) package in the shared project.

That way, shared policies are not possible. Therefore, I'd rather call this issue a bug or feature request, not a question.

The following error is caused by adding the package, causing the client project build to fail:

2>Processing embedded resource linker descriptor: mscorlib.xml
2>Duplicate preserve in resource mscorlib.xml in mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e of System.Threading.WasmRuntime (All).  Duplicate uses (All)
2>Type Mono.ValueTuple has no fields to preserve
2>Type System.Reflection.Assembly has no fields to preserve
2>Fatal error in IL Linker
2>
2>Unhandled Exception: Mono.Linker.MarkException: Error processing method: 'System.Void System.Security.Permissions.PrincipalPermission::Demand()' in assembly: 'System.Security.Permissions.dll' ---> Mono.Cecil.ResolutionException: Failed to resolve System.Security.Principal.IPrincipal System.Threading.Thread::get_CurrentPrincipal()
2>   at Mono.Linker.Steps.MarkStep.HandleUnresolvedMethod(MethodReference reference)
2>   at Mono.Linker.Steps.MarkStep.MarkMethod(MethodReference reference)
2>   at Mono.Linker.Steps.MarkStep.MarkInstruction(Instruction instruction)
2>   at Mono.Linker.Steps.MarkStep.MarkMethodBody(MethodBody body)
2>   at Mono.Linker.Steps.MarkStep.ProcessMethod(MethodDefinition method)
2>   at Mono.Linker.Steps.MarkStep.ProcessQueue()
2>   --- End of inner exception stack trace ---
2>   at Mono.Linker.Steps.MarkStep.ProcessQueue()
2>   at Mono.Linker.Steps.MarkStep.ProcessPrimaryQueue()
2>   at Mono.Linker.Steps.MarkStep.Process()
2>   at Mono.Linker.Steps.MarkStep.Process(LinkContext context)
2>   at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
2>   at Mono.Linker.Pipeline.Process(LinkContext context)
2>   at Mono.Linker.Driver.Run(ILogger customLogger)
2>   at Mono.Linker.Driver.Execute(String[] args, ILogger customLogger)
2>   at Mono.Linker.Driver.Main(String[] args)

Followed up by this cryptic error message:

\.nuget\packages\microsoft.aspnetcore.blazor.build\3.0.0-preview6.19307.2\targets\Blazor.MonoRuntime.targets(439,5): error MSB3073: The command "dotnet "C:\Users\Stefan\.nuget\packages\microsoft.aspnetcore.blazor.mono\0.10.0-preview6.19303.4\build\netstandard1.0\../../tools/illink/illink.dll" -l none --disable-opt unreachablebodies --verbose --strip-security true --exclude-feature com --exclude-feature sre -v false -c link -u link -b true -d "C:\Users\Stefan\.nuget\packages\microsoft.aspnetcore.blazor.mono\0.10.0-preview6.19303.4\build\netstandard1.0\../../tools/mono/bcl/" -d "C:\Users\Stefan\.nuget\packages\microsoft.aspnetcore.blazor.mono\0.10.0-preview6.19303.4\build\netstandard1.0\../../tools/mono/bcl/Facades/" -o "S:\git\hou-units\src\UNITS\UNITS.Client\obj\Debug\netstandard2.0\blazor\linker/" -x "C:\Users\Stefan\.nuget\packages\microsoft.aspnetcore.blazor.build\3.0.0-preview6.19307.2\targets\BuiltInBclLinkerDescriptor.xml" -x "S:\git\hou-units\src\UNITS\UNITS.Client\obj\Debug\netstandard2.0\blazor\linker.descriptor.xml" -a "C:\Users\Stefan\.nuget\packages\jetbrains.annotations\2019.1.3\lib\netstandard2.0\JetBrains.Annotations.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.authentication\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.authentication.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Abstractions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.authentication.cookies\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Cookies.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.authentication.core\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Core.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.aspnetcore.authorization\3.0.0-preview6.19307.2\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.aspnetcore.blazor\3.0.0-preview6.19307.2\lib\netstandard2.0\Microsoft.AspNetCore.Blazor.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.aspnetcore.components\3.0.0-preview6.19307.2\lib\netstandard2.0\Microsoft.AspNetCore.Components.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.aspnetcore.components.browser\3.0.0-preview6.19307.2\lib\netstandard2.0\Microsoft.AspNetCore.Components.Browser.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.cryptography.internal\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.Internal.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.cryptography.keyderivation\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.KeyDerivation.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.dataprotection\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.dataprotection.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.Abstractions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.hosting.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.hosting.server.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.http\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.http.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.http.extensions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.http.features\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.identity\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.aspnetcore.metadata\3.0.0-preview6.19307.2\lib\netstandard2.0\Microsoft.AspNetCore.Metadata.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.webutilities\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.WebUtilities.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.extensions.configuration\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.extensions.configuration.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.extensions.configuration.binder\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.extensions.dependencyinjection\3.0.0-preview6.19304.6\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.extensions.dependencyinjection.abstractions\3.0.0-preview6.19304.6\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.fileproviders.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Abstractions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.hosting.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Hosting.Abstractions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.identity.core\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Identity.Core.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.extensions.logging\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.extensions.logging.abstractions\3.0.0-preview6.19304.6\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.objectpool\2.2.0\lib\netstandard2.0\Microsoft.Extensions.ObjectPool.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.extensions.options\3.0.0-preview6.19304.6\lib\netstandard2.0\Microsoft.Extensions.Options.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.extensions.primitives\3.0.0-preview6.19304.6\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.webencoders\2.2.0\lib\netstandard2.0\Microsoft.Extensions.WebEncoders.dll" -a "C:\Users\Stefan\.nuget\packages\microsoft.jsinterop\3.0.0-preview6.19304.6\lib\netstandard2.0\Microsoft.JSInterop.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.net.http.headers\2.2.0\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.win32.registry\4.5.0\lib\netstandard2.0\Microsoft.Win32.Registry.dll" -a "C:\Users\Stefan\.nuget\packages\mono.webassembly.interop\3.0.0-preview6.19304.6\lib\netstandard2.0\Mono.WebAssembly.Interop.dll" -a "C:\Users\Stefan\.nuget\packages\newtonsoft.json\12.0.2\lib\netstandard2.0\Newtonsoft.Json.dll" -a "C:\Users\Stefan\.nuget\packages\system.buffers\4.5.0\lib\netstandard2.0\System.Buffers.dll" -a "C:\Users\Stefan\.nuget\packages\system.componentmodel.annotations\4.6.0-preview6.19303.8\lib\netstandard2.0\System.ComponentModel.Annotations.dll" -a "C:\Users\Stefan\.nuget\packages\system.memory\4.5.3\lib\netstandard2.0\System.Memory.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.numerics.vectors\4.5.0\lib\netstandard2.0\System.Numerics.Vectors.dll" -a "C:\Users\Stefan\.nuget\packages\system.runtime.compilerservices.unsafe\4.6.0-preview6.19303.8\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.accesscontrol\4.5.0\lib\netstandard2.0\System.Security.AccessControl.dll" -a "C:\Users\Stefan\.nuget\packages\system.security.cryptography.cng\4.4.0\lib\netstandard2.0\System.Security.Cryptography.Cng.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.cryptography.pkcs\4.5.0\lib\netstandard2.0\System.Security.Cryptography.Pkcs.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.cryptography.xml\4.5.0\lib\netstandard2.0\System.Security.Cryptography.Xml.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.permissions\4.5.0\lib\netstandard2.0\System.Security.Permissions.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.principal.windows\4.5.0\lib\netstandard2.0\System.Security.Principal.Windows.dll" -a "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.text.encodings.web\4.5.0\lib\netstandard2.0\System.Text.Encodings.Web.dll" -a "C:\Users\Stefan\.nuget\packages\system.text.json\4.6.0-preview6.19303.8\lib\netstandard2.0\System.Text.Json.dll" -a "C:\Users\Stefan\.nuget\packages\system.threading.tasks.extensions\4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll" -a "S:\git\hou-units\src\UNITS\UNITS.Shared\bin\Debug\netstandard2.0\UNITS.Shared.dll" -a "S:\git\hou-units\src\UNITS\UNITS.Client\obj\Debug\netstandard2.0\UNITS.Client.dll"" exited with code -532462766.

@Herdo
Copy link
Author

Herdo commented Jul 23, 2019

@mkArtakMSFT
Copy link
Contributor

Thanks for all the details, @Herdo .
@javiercn what do you think?

@javiercn
Copy link
Member

Hi @Herdo thanks for contacting us. Is the IdentityConstants the only thing you are using from that assembly? (Seems like it)

I have a few suggestions:

  • I would define the constant in the shared assembly directly, the constant is not going to change, and if you are super worried about it changing in the future, simply write a unit test to check your value against the one in the server. Its a constant, so its gonna be replaced at compile time with the actual value.
  • That form of reuse is hurting you more than you are benefiting from it. You now bring an entire assembly and its dependencies to the client for a single string in the assembly.
  • If you are determined to do this, you can create a custom descriptor and tell the linker to link out anything you don't want and remove dependencies you don't need per https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/blazor/configure-linker?view=aspnetcore-3.0
    • If you ask me, going through all this trouble is not worth it.
  • While we target NETStandard2.0 there are things that naturally aren't going to work in the browser, like many of the ASP.NET Core bits, except for those we specifically create packages for or do work on. (most of them are shared framework in 3.0, so there aren't even packages for them). We plan to do work on the ones we think are useful, like DI, Authorization (which is a package in 3.0 as well as part of the shared framework) but it is unlikely that we do anything for other things like Identity and similar as they only apply on the server.

My final suggestion would be to follow the path of least resistance, while keeping things DRY is a good principle to follow, you need to take into account the price you are paying and the benefit you are getting from it on a per case basis.

Hope this helps.

@Herdo
Copy link
Author

Herdo commented Jul 24, 2019

@javiercn Yes, IdentityConstants is the only thing I'm using, because every guide and tutorial I found points out you should use this class for the authentication schemes.

Not a single one suggest hard-coding Identity.Application into the policies. Which is actually what I did as alternative to reference the Microsoft.AspNetCore.Identity (2.2.0) package. 👍

I know that this re-use is hurting a lot, and after your comment I don't plan to keep it that way, but rather go back to the hard-coded solution.

Thank you very much for your help.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components question
Projects
None yet
Development

No branches or pull requests

3 participants