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

Blazor Security/Authorization #64

Open
grahamehorner opened this Issue Feb 7, 2018 · 19 comments

Comments

Projects
@grahamehorner

grahamehorner commented Feb 7, 2018

Please consider a claim/policy based client-side authorisation framework where user claims/cookies can be evaluated with in the blazor runtime, to enable/disable application functionality/ui features based on user claims/policy evaluation.

@danroth27 danroth27 added this to the Backlog milestone Feb 7, 2018

@danroth27 danroth27 added this to To Do in Blazor Feb 14, 2018

@richbryant

This comment has been minimized.

richbryant commented Jun 6, 2018

I'm sorry, but doesn't this strike anyone else as inherently insecure and unsafe? The client runs in the user's browser. They can change anything. Put authorisation/authentication in the data source, not on the client.

It might be nice to have for convenience but it would only encourage developers to rely on it when they absolutely shouldn't.

And we can already do this. System.Net.HttpClient can handle the a bearer authentication token without issue.

@grahamehorner

This comment has been minimized.

grahamehorner commented Jun 7, 2018

@richbryant I think your misunderstanding this topic; a claims based policy systems that has nothing to do with authentication; claims would be issued by a claims server/service and digitally secured so that these can't be modified; complied blazor code running in the browser would determine if a claims token has been issued that fulfils the policy required to perform an action. claims tokens are ready in use by any number of browser application in the form of JWT/access token and stored in cookies for Facebook, Twitter, etc.

I'm not saying remove the security on the server/service and place this on the client; I feel that given Blazor is a SPA style application that some parts of the SPA client may need to evaluate a users claims based on the token supplied to see if that user can/should be allowed to perform some action and/or see parts of the UI

however I would defer to @blowdart the security expert for comment if he thinks this would weaken/create security issues?

@blowdart

This comment has been minimized.

Member

blowdart commented Jun 7, 2018

I'm afraid I'm going to lean towards nope, unless the token itself is kept on the client side, and meant for a client app ID (for example using Facebook's javascript SDK so a server is never involved). At which point generally everyone has SDKs for their own tokens, or you parse and validate the JWT yourself. Server side, well, if you start asking a server "Show/Hide X" and you can just use fiddler or dev tools to influence the result then obviously that's not something we should depend on.

Now I take your point that no, this isn't really security, it's UI, but would all our users be that informed? Would they suddenly see claims and think "Hey this is security". I think that from an API design perspective this one will confuse people and ultimately lead to sadness when the confusion happens.

But as Blazor's a preview we haven't undergone any formal security reviews as yet.

@Andrzej-W

This comment has been minimized.

Andrzej-W commented Jun 7, 2018

Let's assume we have a Customers module with a few fields: name, address, credit limit. To edit credit limit field, users have to have special claims. Without special claims credit limit field is displayed as read-only. This is good user experience. Of course malicious user can try to use other tools (for example Postman) to post some data to the server. If you want to create secure application you have to check the same business rules on the server. The same is true in every application type. Here you can read about ASP.NET Core:
https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/validation?view=aspnetcore-2.1#how-validation-works

In Angular you can use route guards (https://angular.io/guide/router#guards) to hide some parts of the application from unauthorized users, for example you can disable link to example.com/customers. Probably you also have WebAPI endpoint: example.com/api/customers. Of course to make application secure you have to authorize all WebAPI requests.

In summary:

  • you can implement business rules on the client to create good user experience
  • you have to implement the same business rules on the server to create secure application
@chassq

This comment has been minimized.

Contributor

chassq commented Jun 7, 2018

There have been ways for years for a dev to place "claims" browser side (see Forms Auth Cookies). These cookies could carry auth info as well as roles/claims. Now these cookies were posted to the server and read server-side but a cookie was exposed to the client with that info (of course encrypted). I guess just saying there is precedence for storing roles/claims browser-side.

Maybe a special type of "read-only" cookie/token with a signature that needs to be validated server-side prior to accessing? IDK I could see this implemented various ways to give the client-side a way to make presentation based decisions? Bottom-line is that whatever checks for allowed features, for example, are placed on the browser-side should be enforced server-side. If there were the shared claims/policy mechanism it would be nice to share it across browser/server side for consistent enforcement.... Sorry for the rambling...

@RemiBou

This comment has been minimized.

Contributor

RemiBou commented Jun 7, 2018

@Andrzej-W I don't agree with "If you want to create secure application you have to check the same business rules on the serve", no you always have to do it on server side, if you want to improve UX you can do it on client side as well but it's not mandatory (just like form validation).

What you need is just an endpoint on your server that send the claims available serialized for the authenticated user, so the cookie reading will only happen on server side.

@chassq

This comment has been minimized.

Contributor

chassq commented Jun 7, 2018

@RemiBou don't think I said what was in your quotes... I do agree all checks should be server side.. My point is only it would be nice to share the same claim policy framework to the point it makes passing and checking the claims seamless and consistent between client and server...

@RemiBou

This comment has been minimized.

Contributor

RemiBou commented Jun 8, 2018

I'm sorry your avatar looks like the one on the comment before yours, I edited.

@vertonghenb

This comment has been minimized.

Contributor

vertonghenb commented Jun 18, 2018

Something like the following?

[Authorize("myPolicy")]
@page "customers"
@robertmclaws

This comment has been minimized.

robertmclaws commented Sep 12, 2018

So I'm working on an authentication system that will be able to handle the various providers. It works completely client-side, uses ClaimsPrincipal, and doesn't expose any secret keys or anything like that.

Now, my question is this: I'm working on the token refresh mechanism, and I need to know: does the HttpClient instance reuses the browser's CookieContainer when it makes requests? I'm hoping it does, because I need to be able to make a GET request to a location I previously redirected to, and I'll need the previous cookie from the Redirect to be available.

Thanks!

@danroth27

This comment has been minimized.

Member

danroth27 commented Sep 14, 2018

@robertmclaws The HttpClient uses JS interop to call into the fetch API (BrowserHttpMessageHandler). We don't introduce a new cookie container.

@shadowmint

This comment has been minimized.

shadowmint commented Sep 15, 2018

At a high level, how does this ticket relate to server-side rendered blazor components?

Isn't that going to require a full authorisation framework to invoke server side code, because it will not happen via the fetch api?

@grahamehorner

This comment has been minimized.

grahamehorner commented Sep 15, 2018

@shadowmint I don't follow? AFAIA the cookie that is supplied to the server-side rendered blazor components would be the claims cookie that was given to the user at sign-in just like and use the standard roles/claims a standard .net core web application?

@shadowmint

This comment has been minimized.

shadowmint commented Sep 15, 2018

@grahamehorner yes, but normally an authorisation policy would be applied, eg. in MVC, at the controller; I don't understand where this would be done in this case?

Or would the component be required to authenticate the user request manually based on the claims? ...in which case, doesn't the client-only blazor need to know about claims?

Perhaps I haven't understood how this is supposed to work; are there any examples of applying an authentication policy using server-side blazor?

@robertmclaws

This comment has been minimized.

robertmclaws commented Sep 15, 2018

So this is going to be interesting to work out.

I'm working on a framework that allows client-side Blazor to authenticate with 3rd party systems like Auth0 through regular C#, not importing JS libraries. It's wired up in Startup.cs, and should feel very familiar to OWIN and ASP.NET Core developers.

I'm working on a blog post about this, but here's the gist of it:
image

The first Action returns a redirect URL so the user can be redirected to the auth page. The second Func processes the return payload into a ClaimsPrincipal. Gluing it all together is a Blazor page that pulls the payload out of the URL and marshalls it back to AppStateBase.
image

So then you can modify MainLayout.cshtml to have login controls, like this:
image

The beauty of this system is that everything responds in real-time, the AppStateBase tracks authentication, but you can easily inherit from that to track other state data that is not specific to your ViewModels.

I'm working now to try to figure out the best way to handle refreshing your tokens, and if it's possible to have an @authorize declaration (or an equivalent) and what happens when you're not authorized. If you have any ideas, please post here, or in the related BlazorEssentials issue.

So that was long-winded, but the interesting part will be how well all this works in Server-Side Blazor. I haven't had a chance to set that up yet and see if what I have now will need to be changed.

Feedback welcome :).

@danroth27 danroth27 changed the title from Blazor Security/Authorisation to Blazor Security/Authorization Oct 15, 2018

@robertsundstrom

This comment has been minimized.

robertsundstrom commented Oct 16, 2018

It would be nice to have an @authorize directive which would turn into an [Authorize] attribute on the Component class. Then making it possible to hook into the authorization logic into the Router like a middleware.

@authorize
@authorize "Operator", "Partner"
@xrkolovos

This comment has been minimized.

xrkolovos commented Oct 22, 2018

@robertmclaws is this sample in github?

@robertmclaws

This comment has been minimized.

@omidSarwary

This comment has been minimized.

omidSarwary commented Oct 29, 2018

Authorization is a real headache especially for beginners like me. It would be really nice if there was a @authorize that would be the same as [authorize].

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