How to handle authorisation failure in MVC3 - asp.net-mvc-3

I'm building an internal (intranet) MVC3 application using Windows Authentication and a custom role provider. The authentication and role provider work okay, as long as the the user has the role requested.
For example, I have a UserContoller which allows the user of the application to manage user accounts within the application. Obviously i want to restrict access to this controller.
If I do this:
[Authorize]
public class UserController : Controller
{
...
}
then the Windows Authentication works fine, and the user is transparently logged in. However, I want to restrict the controller to a specific group of users. So I do this:
[Authorize(Roles="UserAdmin")]
public class UserController : Controller
{
...
}
If the list of roles returned by my role provider includes "UserAdmin", then everything is fine and the user gets access to the controller.
However, if the user is not in the role then the browser (tested on IE8 and FF10) prompts for credentials. If that is cancelled then the server returns a 401 error page.
So my question after all of that is, how do I handle the situation where the user is not in the requested role, and return him to the application's home action, or some other action to provide a user-friendly message?

You could also create an custom attribute which inherits from AuthorizeAttribute
Override the HandleUnauthorizedRequest method

You could specify in the web.config an url to show on the 401 case.
<customErrors mode="RemoteOnly" defaultRedirect="/Error/">
<error statusCode="401" redirect="/AuthorizationFailed"/>
</customErrors>

Related

Does the [Authorize] attribute on a hub apply to the OnConnection() method?

Does the authorize attribute on a hub apply to the OnConnection() method?
I ask, because if I apply the [Authorize] attribute to my hub, non-authorized users can still call this method.
Am I supposed to perform manual authorization on this method?
SignalR provides the Authorize attribute to specify which users or roles have access to a hub or method. This attribute is located in the "Microsoft.AspNet.SignalR" namespace. You apply the Authorize attribute to either a hub or particular methods in a hub. When you apply the Authorize attribute to a hub class, the specified authorization requirement is applied to all of the methods in the hub. Without the Authorize attribute, a connected client can access any public method on the hub.
If you have defined a role named "Admin" in your web application, you could specify that only users in that role can access a hub with the following code.
[Authorize(Roles = "Admin")]
public class AdminAuthHub : Hub
{
}
Or, you can specify that a hub contains one method that is available to all users, and a second method that is only available to authenticated users, as shown below.
public class SampleHub : Hub
{
public void UnrestrictedSend(string message){ . . . }
[Authorize]
public void AuthenticatedSend(string message){ . . . }
}
The following examples address different authorization scenarios:
[Authorize] – only authenticated users
[Authorize(Roles = "Admin,Manager")] – only authenticated users in the specified roles
[Authorize(Users = "user1,user2")] – only authenticated users with the specified user names
[Authorize(RequireOutgoing=false)] – only authenticated users can invoke the hub,
but calls from the server back to clients are not limited by authorization, such as, when only
certain users can send a message but all others can receive the message.
The RequireOutgoing property can only be applied to the entire hub, not on individuals methods within the hub. When RequireOutgoing is not set to false, only users that meet the authorization requirement are called from the server.
You can get more details in this article
Hope this helps.
I've just realised why the method was being called for non-authorized users.
It was because I had the following on my hub:
[Authorize(RequireOutgoing=false)]
And not just simply:
[Authorize]
The RequireOutgoing named parameter causes the OnConnection() method to be called for non-authorized users.

Spring Security Recommended Design To Request User Login to Different User With Different Role

I have the following use case and need recommendations on the proper implementation. To be clear can this be done through configuration or do I need to implement new code?
Business Use Case
The business wants to allow a user to login via social media sites and access some of their pages. But in order to access pages that deal with $$ the user must login via the applications local account.
Technical Use Case
Allow users to login via Facebook or other provider and provide role USER_PARTIAL_RIGHTS
If user accesses a page with role USER_FULL_RIGHTS prompt the user to login to an account that is a local JDBC stored account.
This authentication must also ensure that the page is protected by USER_FULL_RIGHTS role and not other roles.
I am using grail spring security plugin, but I am expecting to have to customize the plugin.
So what are recommendations for doing this? A couple of ideas that I have are:
Technical Ideas
custom spring access denied handler
custom access denied controller instead of the stock jsp page
From what i understand from your question, here is my suggestion.
For login via Facebook use Spring Social. Here is the documentation. The implementations are straightforward. Write a custom signin method and set the authorities for partial rights, something like this:
public void signin(String userId) {
authorities = new ArrayList<GrantedAuthority>();
//set your partial rights authority
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(userId, null, authorities));
}
And do a method level security implementation using the #secured annotation to access the page that needs full rights. Something like this
#Secured("USER_FULL_RIGHTS ")
yourMethod(){
//code
}
This would prompt for a login where can use authentication from applications local account.
What we ended up implementing is a controller that looks at the role and redirects the user to the correct landing page. Kinda messy, but it works.
Collection<GrantedAuthority> inferred = SpringSecurityUtils.findInferredAuthorities(SpringSecurityUtils.getPrincipalAuthorities());
if(ifAnyGranted('ROLE_FOO', inferred)) {
redirect(controller: 'foo',action: 'home')
return
}

Correct Event to check user authentication in BaseController class

I'm in the process of converting a web application of mine to an MVC application. I think it will benefit from it but I'm a newb and a half at MVC. I want all of my controllers to inherent from a base controller and the first thing I want to do is redirect the User to the Login view if they are not authenticated. The method already written basically looks for a Cookie and if it doesn't find it does a Response.Redirect() to the login screen. I want to move this method to the BaseController but I'm not positive what's the best way to go about it. So in essence what BaseController Event should I invoke to check for authentication before loading the page?
Thanks
The MVC way to handle this is to decorate controller actions with the AuthorizationAttribute.
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.
The Authorize attribute lets you indicate that authorization is restricted to predefined roles or to individual users. This gives you a high degree of control over who is authorized to view any page on the site.
If an unauthorized user tries to access a method that is marked with the Authorize attribute, the MVC framework returns a 401 HTTP status code. If the site is configured to use ASP.NET forms authentication, the 401 status code causes the browser to redirect the user to the login page.

Using AuthorizeAttribute in ASP.NET Web API

I have used the [Authorize] attribute in an ASP.NET Web API method
[Authorize]
public IEnumerable<User> GetAllUsers()
From the application I can access this method without a problem as my user is already authenticated. However, is there any way that I can specify the username, password to this method when calling so that I can implement a REST API? This is when calling from a standalone application or the browser.
I didn't entirely understand your question but System.Web.Http.AuthorizeAttribute checks against Thread.CurrentPrincipal to see if the user is authorized or not.
You can specifically give user permissions if you want as below:
[Authorize(Users = "User1")]
public IEnumerable<User> GetAllUsers()
But the Authentication process is entirely up to you. I would recommend authenticating the user through a message handler and then populating the Thread.CurrentPrincipal there. Then, use the AuthorizeAttribute as you see fit for your application.

my own view after denied acces

I have created a controler for Admin only and I add:
[Authorize(Roles = "Admin")]
before class definition. When I try get sites for Admin as a User I'm redirected to LogOn site. How can I change redirect to LogOn or add a extra information to logon site?
Bouncing users to the LogOn page when they're logged in but don't have access to a page is one of the downsides of using the out-of-the-box AuthorizeAttribute. You have two options:
Create a custom authorize attribute (See: Redirecting unauthorized controller in ASP.NET MVC)
Change the "loginUrl" attribute of your "forms" element in the web.config to point to an action method that handles redirection based on whether you're logged in or not. You can check in the action method to see if the user is logged in. If they are, you can display an unauthorized access view, and if they aren't you can send them on to the log in page. e.g. <authentication mode="Forms"><forms loginUrl="~/error/unauthorized" timeout="2880"></authentication>

Resources