I'm using a custom AuthenticationHandler and only some of my controller methods have the [Authorize] attribute. I log on Info level and it creates a log entry for any method call. Now I can't tell apart if somebody actually tried accessing a method that requires authorization and failed or if it's a call to a method that doesn't even need authorization and it fails because it's supposed to.
Is there a way to tell them apart or preferably to keep MVC from calling HandleAuthenticateAsync when it's not needed?
It sounds like you might be misusing the AuthenticationHandler. You are not supposed to immediately reject access if the user fails to authenticate. If you do so, it doesn't even reach the MVC context in the pipeline.
Unless you intentionally want to reject any access to unauthenticated users, you should only either authenticate or pass it through as anonymous user. After that at some point AuthorizeAttribute will kick in and check whether user has access to the requested resource or not. If he is not authenticated, the authorization will reject the request.
Related
I have been trying to wrap my head around this concept but have many questions and unfortunately, all official documents and tutorials are based on Visual Studio templates with individual user accounts.
My goal is pretty straightforward I believe. I have a web application which will only support external provider logins (namely: Facebook, Twitter, and LinkedIn). I do not want to support cookie authentication since there won't be a support for custom username/password.
My first problem is to define a default AuthenticationScheme. Below is my startup.cs:
services.AddAuthentication()
.AddFacebook(/* options */)
.AddTwitter(/* options */)
If I define a controller action with Authorize attribute I get no default authentication scheme defined error when I hit that route. However, I want users to be redirected to my login route if they are unauthorized. If I modify startup.cs like below it all works but then I think I support cookie (old forms authentication?) authentication which I don't want to.
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie()
.AddFacebook(/* options */)
My other issue is that I don't know what happens under the hood of AddFacebook() call. If I set up my middleware this way and log in with Facebook I magically get all the necessary tokens, claims and suddenly I have an application cookie set and my fb_login callback route can access to Facebook's token! When I check the network requests I see there is a hit to the signin-facebook route -which I didn't define- and I guess under the hood it calls HttpContext.SignInAsync() etc... but if I refresh my fb-login callback and check if
HttpContext.AuthenticateAsync(FacebookDefaults.AuthenticationScheme)
returns Success = true no! it returns false! But it was true just one second ago?
Also, when should I be using methods like AuthenticateAsync() and SignInAsync()?
Long story short I need a tutorial or documentation that explains this middleware without asp.net Identity framework, EntityFramework and templates.
I want to understand how a simple AddFacebook() call binds everything, and if I want to manually do that (say with AddOauth) how can I achieve the same functionality?
I'm not a fan of "automagically working" code so if someone can explain what's going on here I'd be very appreciated.
Cookie auth is used to persist the authenticated state between the requests. There is no substitute for this, and no it's not the same as forms auth, though cookies are used in both cases. The reason for that is simply that cookies are what makes state work over the HTTP protocol, which is itself stateless. If exclude the use of cookies, then there is no other mechanism to maintain state.
Using something like the Facebook auth scheme directly authorizes the initial request, but again, because there is no state, the next request is no longer authenticated without going through the Facebook OAuth flow again.
Long and short, the other auth schemes are there for things like APIs, where each request is typically authenticated individually via something like the Authorization header. A web browser doesn't work this way, and instead relies on cookies handle subsequent authorization. No cookies, no auth.
I have few BL functions that checking who is invoking a method by reading the data from httpContext.User property. It works great when the user really SignIn to the system.
I would like to allow users to schedule an action to be run on a later time. Once the user asks to send an email later, i am writing the request to the DB and the automation service i developed will execute it on the right time by making an http call like: https://mysystem.lan/SendEmail/?Requestid=122d8f273465.
since the automation process not happens in the client side, the user is not logged in to the system so the action SendEmail will not run because the httpContext.User property will be null.
Thanks to the parameter Requestid in the url, i can resolve the UserId who created the request and i want to mock the ASP.NET Identity to be the identity of that user and that the GetUserId() extension method will work too (since mocking not affects that kind of methods).
All the answers i saw here explaining how to mock the identity by creating an instance of the controller for unit testing but this situation is different because i need to mock the identity inside inside the controller action when the server is getting the request https://mysystem.lan/SendEmail/?Requestid=122d8f273465.
Can you suggest how to do that?
I've been using Authorize to verify that the user has logged in but I was told in a previous post that it was used to make sure their role has access to that method.
Does that mean I should be using something else to allow/disallow access to a web page or is using Authorize the right way?
I have a handful of pages that I want to prevent users who are not logged in from getting to.
What is the right way of checking this and can it be done at class level?
Thanks!
Authorization and Authentication are two different things. It sounds like you are trying to use the AuthorizeAttribute to authenticate which should actually be happening by your membership provider.
So in short, authentication is a way for you to identify who your users are and authorization is how you identify what access a user has, identified or not.
One thing to mention from the docs on AuthorizeAttribute:
"When you mark an action method with AuthorizeAttribute, access to that action method is restricted to users who are both authenticated and authorized. If you mark a controller with the attribute, all action methods in the controller are restricted."
So it isn't performing the authentication for you but checking it.
I have a ServiceHost that implements many Contacts on various endpoints and bindings ((http & https) x (rest & soap) with Anonymous Access, Windows, or Custom authentication, as bound depending on the Contract) & nettcp with Windows authentication. Custom authentication is embedded in the http or soap headers. Each endpoint and contract has its purpose. It should all be manageable on a single ServiceHost - I don't want to split it up.
I've gotten it to the point where all the endpoints work and serve their content correctly, but the authentication/authorization isn't integrated into the WCF stack. I have been using a MessageInspector to handle validation of the authentication header and allowing it if the token was valid.
Now I want to integrate the authentication/authorization into the WCF stack. I want to be able to access the identity and check the claims in each Operation's implementation. And perhaps basic claims can be authorized centrally, like "are these claims authorizing anything at all in this contract?" (by contract type).
In the case of custom authentication, I have a signed/secure token that includes a custom implementation of identity and property claims which I can properly extract and convert into WCF claims upon receipt (even if I don't know exactly where to put them once I've got them). For Windows authentication, I just need access to the default Windows identity stuff.
I can set the ServiceAuthenticationManager and ServiceAuthorizationManager each to custom values, but it's not doing anything I want it to and I'm getting totally lost.
For example, the ReadOnlyCollection<IAuthorizationPolicy> authPolicy coming into Authenticate() seems to be inconsistent - sometimes it's empty, sometimes it has one UnconditionalPolicy and sometimes it has 2 or more (4?) of my custom IAuthorizationPolicy already there. Meanwhile IAuthorizationPolicy.Evaluate() gets executed anywhere from 0 to ~9 times per request. Sometimes, within IAuthorizationPolicy.Evaluate(), OperationContext.Current is null! And sometimes the evaluationContext.ClaimSets already has my claimset. Yet state is always null even when I give it a value in a previous enactment.
Rather than tackling these problems individually, I think it'd be better to step back and ask for some high-level explanation of what I should do/expect to see.
Authentication: When a request comes into the ServiceHost, it needs to get Authenticated. At this point in the pipeline, I don't need to know what they can do, just who they are. If a client submits both Windows credentials and a custom authentication ticket to a Contract/Binding on which I require just a custom authentication ticket, the service shouldn't be tricked into evaluating the wrong one. But perhaps at this stage in the WCF pipeline, the Contract hasn't been resolved so perhaps during this stage, all found identities/claims/tokens should be captured and selected among later. Is this right? How is this done?
Message Inspection: I have a custom MessageInspector which I'll still need for CORS support and OPTIONS request processing on some of the endpoints. I believe this happens after authentication and before authorization. In the case of OPTIONS, I set ref message to null and skip the Operation entirely, jumping straight to the BeforeSendReply. Clients don't send the auth-token on a CORS OPTIONS preflight request and so I allow these requests unconditionally.
Authorization: Depending on the Contract, I want to require certain authentication mechanisms and ignore others. I believe some setup needs to prepare the Thread Principal and Operation Context principal to the correct value. It seems that multiple Authorization policies can be in play at once. How do they interact?
Operation: I want to be able to implement each operation assuming that the identity of the caller is authenticated using a supported authentication (by Contract, which I'm OK maintaining hard-coded somewhere ONCE) and get the validated caller identity and assert simple permissions checks againsts the verified Claims.
How do I achieve this (code preferred over config xml)?
Thanks!
I'm currently trying to implement the MembershipProvider class, but my user repository isn't typical to most of the examples I'm finding on the net. Instead of retrieving a user, we simply check the user's identity against an auth server for the requested URL:
User attempts to "POST" to ws.example.com/jobA
Attribute validates the user with the auth server to see if they have access to this action/url
Rejects or accepts the request
A couple other posts pointed me in this direction for implementing a custom membership provider. The way I figure it, in order to make this work, I need to be able to see what the requested URL was, and be able to look at their cookies. In Filters, i have access to the HttpRequestMessage. How do I get at the info i need in this context??
[Despite this thread is not specifically about SharePoint Membership Providers, I will just leave this solution here because I couldn't find it anywhere else, and kept being redirect to this thread while looking for solutions on Google. I hope it helps someone]
For SharePoint Membership Providers, we have the Security Token Service, which is a WCF Service. In this case, System.Web.HttpContext.Current is always null, but you can get the actual Request URL using this property:
System.ServiceModel.OperationContext.Current.RequestContext