I am developing a ASP.NET MVC 5 website which uses local STS for authentication.
I subclassed the AuthorizeAttribute to customize authentication/authorization process, added MyAuthorizeAttribute to GlobalFilters.
When user came in without authenticated, MyAuthorizeAttribute.OnAuthorize successfully caught it and create a SignInRequest to redirect to STS. That is what I want.
I observed that when user authenticated successfully and STS redirected user back, user's browser POSTed a SAML token embedded in request body to my MVC web application, this is by design, and I expected MyAuthenticateAttribute could catch this request, so I can extract the token from request body, check and validate it, however, MyAuthenticateAttribute.OnAuthorize() function didn't get called this time, it directly went to controller.
So is there anything wrong? Where should i catch and handle the token POSTed from user? Thanks.
You need to decorate your action method with [Authorize] attribute or if you want authorization to happen for all actions in a controller, then set that attribute on the controller itself.
Also take a look at the usage of [AllowAnonymous] at https://www.codeproject.com/Articles/1008731/Insight-of-ASP-NET-MVC-s-Authorize-Attribute
AuthorizeAttribute is both an Attribute and a IAuthorizationFilter. Attributes don't actually do anything, the MVC framework scans for where this attribute is added and registers it as a filter on the fly.
However, rather than decorating controllers or action methods with it, you could add it as a global filter:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new AuthorizationAttribute());
filters.Add(new HandleErrorAttribute());
}
}
By the same token, you can create your own IAuthorizationFilter or subclass AuthorizeAttribute to do whatever you want. If registered globally, it will always run for all actions and then you can use it to do custom authorization of requests globally.
Related
Is good idea to get user identity in ASP.NET Web API controller constructor, for example:
public PagesController(PageValidator pageValidator, PageMapper pageMapper, PagesManager pagesManager, UsersManager usersManager)
:base(usersManager)
{
_pageValidator = pageValidator;
_pageMapper = pageMapper;
_pagesManager = pagesManager;
if (User.Identity.IsAuthenticated)
_pagesManager.UserId = usersManager.GetByEmail(User.Identity.Name).Id;
}
Is always User.Identity was correct populated before this call raise?
This has bitten me a few times. Depending on where/how you are performing your authentication, you need to be careful where you access your identity, particularly in controller constructors.
For example, whilst the controller action is invoked AFTER an IAuthenticationFilter is instantiated, the controller's constructor is called before AuthenticateAsync; meaning any authentication you do in AuthenticateAsync will not be available in your controller's constructor (like in your example).
I typically don't rely on things being available during controller construction (unless handled by DI). Instead access the identity as you need it in your controller actions.
If you are looking at making identity lookup easier (i.e. pulling in your user object based on the User.Identity.Name property) create a base controller class that has a property or method that does it for you, then have your controllers inherit from that...
public User AuthenticatedUser
{
get
{
if (User.Identity.IsAuthenticated)
{
return usersManager.GetByEmail(User.Identity.Name);
}
return null;
}
}
EDIT
See here for a detailed breakdown of the Web.API lifecycle, showing controller creation occurring prior to authentication.
Yes. You can use this property in Controller in any place. ASP.NET has request pipeline: (http://www.dotnetcurry.com/aspnet/888/aspnet-webapi-message-lifecycle).
As you can see Authorization is early stage step in request pipeline.
Controller creation is the latest stage.
I'm looking for some guidance on how to implement authorization security for SignalR on a back end service running in a self-hosted (non-IIS) environment, that is called from a Web application. The backend app is basically a monitor that fires SignalR events back to the HTML based client. This all works fine (amazingly well actually).
However, we need to restrict access to the server for authenticated users from the Web site. So basically if a user is authenticated on the Web site, we need to somehow pick up the crendentials (user name is enough) and validation state in the backend app to decide whether to allow the connection as to avoid unauthorized access.
Can anybody point at some strategies or patterns on how to accomplish this sort of auth forwarding?
I am having similar issues here, as in my web app I use a simple cookie authentication system which uses an AoP style approach to check for any controllers with an attribute, then will get the current context (be it from the static HttpContext.Current or from the target invocation object depending on the type of interceptor) and then verify the cookie exists, it contains right data, then finally verify the token with the db or cache etc.
Anyway this approach can also be used for Signalr, although its a bit more long winded and you are using dependency injection. You would basically wrap the hub calls with the desired attribute, then set up your DI/IoC configuration to intercept these calls, then either get the hub instance within your interceptor and get the cookie (or your custom authentication mechanism) from the request, verify it is all valid or not, and if not then throw a new HttpException("403", "Not authenticated"); which should kick the user out and return back before it even hits your hub method, this way you can put the logic in one place (your interceptor, or a class the interceptor consumes) then just wrap any method that needs to use this authentication using your attribute.
I use Ninject and the interception extension, but most major DI frameworks these days have some form of IoC plugin/extensions, such as Autofac, Windsor, Spring etc.
If you were not happy going down the route of introducing DI and/or AOP to your current project, then maybe you could just create a custom hub instance which contains your authentication logic and then just use that in your hubs, so ok you will still be manually calling some authentication logic from within each hub method you want to protect, but its less code, so something like:
public class AuthorisableHub : Hub
{
private ISomeAuthenticationToken GetSomeAuthenticationTokenFromRequest(Request request) // probably a SignalR specific request object
{
// Get your token from the querystring or cookie etc
}
private bool IsAuthenticationTokenValid(ISomeAuthenticationToken token)
{
// Perform some validation, be it simple or db based and return result
}
protected void PerformUserAuthentication()
{
var token = GetSomeAuthenticationTokenFromRequest(Context.Request);
var isRequestValid = IsAuthenticationTokenValid(token);
if(!isRequestValid)
{ throw new HttpException(403, "<Some forbidden message here>"); }
}
}
public class MyFancyPantsHub : AuthorisableHub
{
public void TellAllClientsSomethingSecret(ISecret secret)
{
PerformUserAuthentication();
// Do stuff with the secret as it should have bombed the user out
// before it reaches here if working correctly
}
}
It is not perfect but would work (I think), also I am sure I once read somewhere that Hubs are newly instantiated for each request, and if this is indeed true, you could possibly just put this logic in your constructor if you want to apply the authentication to every action within the hub.
Hope that helps, or gives you ideas... would be interested in knowing how you did solve it in the end.
SignalR does not provide any additional features for authentication. Instead, it is designed to work with the authentication mechanism of your application.
Hubs
You should do authentication as you normally would and then use the Authorize attribute provided by SignalR to enforce the results of the authentication on the Hubs.
The Authorize attribute can be applied to an entire Hub or particular methods in the Hub. Some examples:
[Authorize] – only authenticated users
[Authorize(Roles = "Admin,Manager")] – only authenticated users in the specified .NET roles
[Authorize(Users = "user1,user2")] – only authenticated users with the specified user names
You can also require all Hubs to require authentication by adding the following method in the Application_Start method:
GlobalHost.HubPipeline.RequireAuthentication();
Persistent Connections
You can use the user object in the request to see if the user is authenticated:
request.User.IsAuthenticated
I need to implement CSRF(Cross Site Request Forgery) Guard in my code (asp.net).
Though I got a library from OWASP, implementing it is a pain since no documentation is given. Can someone provide me an easier way to implement csrf guard in .net, or configure OWASP library correctly ?
Thanks
-Chandan
ASP.NET MVC
If you're using asp.net mvc you can use the anti-forgery token. Basically in your view you would place the following code:
#Html.AntiForgeryToken()
And on your controller you would put this attribute at the top of the controller:
[ValidateAntiForgeryToken]
public ActionResult Foo()
{
// Foo code
}
What this does is ensures that the user cannot submit the form from a remote site, because they are unable to generate the token. You can also create a token with a salt.
ASP.NET WebForms
For asp.net Webforms you can override the OnInit method and set the ViewStateUserKey to the the session id. Web forms will validate the viewstate with a MAC check thereby acting like an anti forgery token. Because an attacker cannot generate a valid viewstate (since they don't have the ability to generate a valid MAC because they can't put the session id in the viewstate) the MAC will fail. You will have to do this on each page, or create a base class that already overrides oninit and does this.
public partial class Default : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.ViewStateUserKey = Session.SessionID;
}
}
I'm just reading about implementing my own HTTP handler for ASP.NET 4.0 and IIS7. This looks really cool. I want special processing for ZIP files and it seems like an HTTP handler is the perfect solution.
However, what's giving me trouble is that the handler must be in a separate assembly. So how can I access the rest of my application from this assembly?
Specifically, I'd like to determine if the user is authenticated and redirect them to the login page if they are not. But User.Identity.IsAuthenticated, etc. will not be available from my handler.
(Yes, I know there are ways to approach this without an HTTP handler but they don't seem appropriate for my specific needs.)
User.Identity.IsAuthenticated, etc. will not be available from my handler.
The ProcessRequest method gives you the current HTTP context from which you could determine if the user is authenticated:
public void ProcessRequest(HttpContext context)
{
if (!context.User.Identity.IsAuthenticated)
{
// the user is not authenticated
}
...
}
I'm building a small app with ASP.NET MVC and I'm using the ASP.NET membership provider for handling users. Hooked this up to the login page of the basic MVC template.
What is the best practice for checking a valid authentication globaly? I basically want to redirect to the front page or the login page if the user's not authenticated on all my pages.
-anders
The way we did it, back in the days of MVC Preview 4 or so, was to create a new "BaseController" class, which every other controller then inherits from. This BaseController class uses the Authorize attribute
[Authorize]
public class BaseController : Controller
{
...
}
The rest of our controllers then inherited from this one
public class HomeController : BaseController
{
...
}
Haven't had to work with MVC for a few months now, so I can't say if this is still applicable, so proceed with caution...
You should just annotate any action you want to authenticate with [Authorize], and optionally with some required roles:
[Authorize()]
public ActionResult Index() {
...
return View();
}
This includes your home page action, if you wish. Unauthorized attempts will be always redirected to the login page.
this may be slightly over complicated, but another approach could be to put a custom HTTP Module in the pipeline to redirect the request if the user isn't authenticated.