Authentication filters from Release Notes page
Authentication filters are a new kind of filter in ASP.NET MVC that
run prior to authorization filters in the ASP.NET MVC pipeline and
allow you to specify authentication logic per-action, per-controller,
or globally for all controllers. Authentication filters process
credentials in the request and provide a corresponding principal.
Authentication filters can also add authentication challenges in
response to unauthorized requests.
Can some one provide the practical use of this? Where I can use this AuthenticationFilters exactly?
Earlier I use to manage Access Control List for a action/controller by writing own CustomAttribute: FilterAttribute, IAuthorizationFilter and implement public void OnAuthorization(AuthorizationContext filterContext) . Is it possible to use this AuthenticationFilter here?
As the docs says, the custom authentication filter provides an authentication per-action, per-controller or globally.
An example use is changing the authentication for just few selected controllers. Suppose for example that your whole site uses Forms Authentication where principals are taken from forms cookies.
However, you have a selected controller that acts as OAuth2 Resource Server where requests come from Service Providers (servers) and there are no forms cookies, rather, an OAuth2 access token is provided by the service provider server.
This is where a custom authentication filter comes into play - its task is to translate the token to a principal for the lifetime of current request only, just for the only controller that acts as the resource server endpoint. You don't want the whole site to accept OAuth2 tokens, rather the one particular controller.
The reason to introduce authentication filters is to separate authentication from authorization, where:
authentication is for estabilishing a principal for current request
authorization is to verify whether or not the current principal is permitted to execute current request
This was not clearly separated before authentication filters were introduced. Personally, I used to use authorization filters for this, however having two separate layers of filters in this particular order (authentication first, then authorization) is just cleaner.
Custom authentication can be created by implementing IAuthenticationFilter. It can be used where current user principal is necessary to change for executing certain portion of action of a controller by overriding OnAuthentication method. One can put extra task on request by overriding OnAuthenticationChallenge method.
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.
Background
I have a ASP.NET core (v2.1) project that contains an API. This API is access restricted by JWT bearer.
My server expose an endpoint for login:
POST http://example.com/api/login
After attaching the token to the request, I can call one of the server methods (GET or DELETE:
GET http://example.com/api/1234
or
DELETE http://example.com/api/1234
Target
I want to implement "another type" of token that will allow access only to specific scope. Let's say that we want to give access just for GET method. So, if you have this token - you can GET the resource but not to DELETE it.
Wondering if this is possible with JWT bearer token? If yes, how?
Thanks!
You shouldn't do this with the token itself. The token is used to authenticate that a user is who they claim to be. You should instead look at using the roles to authorise an action and assign different users roles to restrict access to delete verbs.
This article should be able to explain further
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.1
JWT Bearer token should be used for authentication mechanism but what you are talking about is Authorization and thus your approach is wrong seems. You should rather use the Authorization pipeline and implement proper Roles/Policy based authorization which will restrict access to those Api endpoints.
I am working on a asp.net MVC 5-solution where I now need to implement authentication and authorization. The solution has a external service managing the "Heavy work" that will take the username and password on every request, and on successfull verification send back a token with the users permissions(roles) which should be matched against Attributes in the controller.
A request to the external service should be made on every request to my solution. How can I implement this in a simple way in my exising asp.net MVC 5-solution? I have looked at Identity and Owin but they feel overly bloated for what Im trying to achieve. I've also found some info about Forms auth, but it seems to be deprecated?
The workflow I have tried with is something like this:
A user request a controller. The controller is marked with an attribute like "Require(Roles="IT")". I implement the IauthenticationFilter and call my service in the OnAuthentication to verify the users request. From the return I will verify that the user is in fact who he says he is and also if he is permitted to enter the said action on said controller.
Any input is appreciated as I'm having a hard time finding solid info on how to implement a custom auth-solution. Is there any best practice?
Thanks!
MVC builds upon ASP.NET's interfaces IPrincipal and IIdentity. If you implement these interfaces, you can tap into the existing [Authorize] / [AllowAnonymous] attribute functionality of MVC and only extend it if you need some functionality other than users/roles.
I won't repeat the implementation here - there are several posts about how to properly implement these interfaces (which should be set in the Application_PostAuthenticateRequest event in ASP.NET/MVC).
ASP.NET MVC - Set custom IIdentity or IPrincipal
ASP.NET MVC - Custom IIdentity or IPrincipal with Windows Authentication
Implementing IPrincipal and IIdentity in MVC with use of custom membership and role provider
using custom IPrincipal and IIdentity in MVC3
IdentityReboot - open source example of custom security provider
After they type in their password, should I keep a variable in server session storage like Session["loggedIn"] = true that I check when requests are made to pages that require a login, or is there a better/safer way this is traditionally done in ASP.NET?
No, do not keep this in a session variable. In fact, I would argue you should try not to use session for anything. Try to keep the HTTP communication as stateless as possible.
For authentication in ASP.NET MVC, you have 2 alternatives, but ultimately, the both end up working the same way: by writing an encrypted authentication cookie to the browser after you successfully log a user in.
The newer alternative was mentioned in a comment to the OP: Microsoft.AspNet.Identity. To use this, you should be using a newer version of ASP.NET MVC with the OWIN pipeline (though I am not sure if you have to). The older alternative is called Forms Authentication, and can be used with any version of MVC except version 6 (the new vNext / core 1.0 stuff) I believe.
When you have successfully integrated one of these 2 tools into your MVC application, after a user logs on, your Controllers will have a non-null User property of type IPrincipal. You can use this property to determine whether or not a user is authenticated:
// in a controller
bool isThereAUserLoggedIn = this.User != null && this.User.Identity.IsAuthenticated;
If you are using the newer Microsoft.AspNet.Identity, then this IPrincipal User property will be implemented as a ClaimsPrincipal with one or more ClaimsIdentitys. Forms Authentication does not do claims like this, so if you want claims, or social login, etc, use Microsoft.AspNet.Identity.
The way that this is traditionally done in ASP.NET and by my opinion also better and safer is by making use of the ASP.NET Identity package.
ASP.NET Identity handles all aspects around user accounts in a web application:
database for users, including roles and more
user registration and management, like register, email verification, log in, remember me option, forgot my password action and more.
user authentication & authorization
Just to make things more clear, authentication means that the user making the request is actually a valid application user and authorization means that the user has the authority to perform the requested action.
Practically, when a user logs in, Identity automatically keeps that information and makes it available in all controllers and views under User property. So you know at any time which user made the request. Identity also supplies each request with a cookie used for user authentication and authorization.
To check for user authentication you use the User.Identity.IsAuthenticated in a view and the Authorize attribute in a controller:
[Authorize]
public ActionResult Create( ... ){ ... }
The above use of the Authorize attribute will allow only to registered users to request this page.
It is also very common to extend the functionality of your application to include roles for the users and user authorization. Identity creates a "Users" table, a "Roles" table and a many to many relationship between them. After assigning roles to your users you can authorize their requests by using User.Identity.IsInRole("YourRoleName") in a view and in a controller:
[Authorize("YourRoleName")]
public ActionResult Create( ... ){ ... }
The above use of the Authorize attribute will allow only to registered users having the "YourRoleName" role to request this page. In any case if Identity fails to authenticate or authorize the request will prompt to the log in page.
ASP.NET Identity is simple to use, it works and it is easy to extend the membership functionality of your application both by making use the many tools supplied with it and overriding its classes to give them a more specific or complex behaviour.
You will find infinite help on the web on how to use it or a step by step guide.
I'm new to ASP.NET MVC world. I'm building an intranet web application. Authentication and authorization is defined in my case as below:
Authentication: If HttpRequest contains an Header with "USER_ID", user is authenticated.
Authorization: There is one in-house WCF Service, which returns list of roles user is entitled to taking USER_ID as input. I keep the roles required by my application in xml file. If user's required role is in svc response then, she is allowed to use the application.
I'm thinking of implementing it like below:
In Global.asax - > Application_AuthenticateRequest, I'll put code to check http Header. If its non_blank, I'll let user to go through this stage.
In OnAuthorization method of AuthorizeAttribute class, I'll put code to fetch role list and match it against required roles from xml file.
Is there any way that I can use existing authentication,authorization infrastructure?
I see code like this
[Authorize(Roles = "admin")]
public string Index() {
return "only admins!";
}
How can I link Roles property like above to some Xml or Table instead of hard coding?
Please help me to implement this logic in asp.net mvc application.
You should check Windows Identity Foundation (WIF), in particular ClaimsAuthorizationManager and ClaimsPrincipalPermissionAttribute. The later allow you to specify what operation and resource need to be secured, while in ClaimsAuthorizationManager you can check whether the current user can perform the operation on the resource, and that can be read from any source you desire.
For Authorization, I would either:
Create a GenericPrincipal in the global.asax AuthorizeRequest event handler with the appropriate roles, and assign it to both HttpContext.User and Thread.CurrentPrincipal.
Or (better), write a custom RoleProvider that gets the users roles from the xml file. If you configure such a RoleProvider, ASP.NET will assign a suitable RolePrincipal to both HttpContext.User and Thread.CurrentPrincipal.
You can then use the standard AuthorizeAttribute.