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

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.

Related

How to handle different action with same route and different authorize attribute in asp .net core

I'm developing some Web-API project with ASP.Net Core 2 using some custom middleware which is translating the authorization info that it gets from a 3rd party service into a new Claim Identity and adds it to http context user claim principal. I also have implemented some custom authorization policy provider which checks the added claim identity for required permissions and roles.
Now I wanna have two actions like below on same controller with same route:
[Route("api/[controller]")]
public class StatesController : Controller
{
[Authorize("PaiedUser")]
[HttpGet(Name = "GetStates")]
public IActionResult GetStatesPaied(StateHttpRequestParameter requestResourceParameter)
{ //some code here to handle the paied user request}
[Authorize("FreeUser")]
[HttpGet(Name = "GetStates")]
public IActionResult GetStatesFree(StateHttpRequestParameter requestResourceParameter)
{ //some code here to handle the free user request}
}
On the runtime I got this exception,
Microsoft.AspNetCore.Mvc.Internal.AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:
SaMonitoring.API.Controllers.StatesController.GetStatesFree(SaMonitoring.API)
SaMonitoring.API.Controllers.StatesController.GetStatesPaied(SaMonitoring.API)
How can I achieve this behavior ?
I think the problem here is that the roles are not mutually exclusive as far as MVC is concerned. Someone could fall into both conditions which is what makes it ambiguous. I think you'd be better off checking the user's role inside a single function and providing results appropriately.

Authorization on Dynamic Web API Controllers

How to use AbpAuthorize or AbpAllowAnonymous attributes?
What's the default behaviour for these controllers?
Could not find in docs.
AbpAuthorize is just used to check for permissions. This for example:
[AbpAuthorize("Administration.UserManagement.CreateUser")]
public void CreateUser(CreateUserInput input)
{
//A user can not execute this method if he is not granted for "Administration.UserManagement.CreateUser" permission.
}
Checks if he has the Administration.UserManagement.CreateUserpermission. Before allowing the user to execute the method.
AbpAuthorize, if left without parameters just checks if the user is logged in.
[AbpAuthorize]
public void SomeMethod(SomeMethodInput input)
{
//A user can not execute this method if he did not login.
}
This for example, will check if the user is logged in before he can execute the method.
Try reading here for more detailed stuff:
https://aspnetboilerplate.com/Pages/Documents/Authorization#DocCheckPermission
It will explain it better than me.
You can add these attributes to your Application Services or Controllers derived from AbpController. Basically it uses interception and checks the current user has the required permission or not. (Hence an authenticated user is needed to check a permission). So first you have to authenticate the user to dive into these permissions.

Role-based authorization in ASP.NET Web API - how to set roles on the principal?

I am using recipe 10-3 in the newly released book ASP.NET Web Api 2 Recipes to support basic authentication in my Web API. This recipe utilizes a 3rd party library from Thinktecture. As seen from the below code, I am authentication the user against my own account service.
using Thinktecture.IdentityModel.WebApi.Authentication.Handler;
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
var authenticationConfiguration = new AuthenticationConfiguration();
var accountService = ServiceLocator.Get<AccountService>();
authenticationConfiguration.AddBasicAuthentication((userName, password) => accountService.Authenticate(userName, password));
config.MessageHandlers.Add(new AuthenticationHandler(authenticationConfiguration));
...
}
}
Now I want to make role-based authorization in my controllers using the Authorize attribute:
[Authorize(Roles="administrator")]
public IHttpActionResult Get()
{
...
}
My account service obviously knows about the users and their assigned roles, but this information is not available to the Authorize attibute (the roles are not set on the principal).
How do I accomplish this? Can the Thinktecture authentication handler be configured to set the roles on the principal? Or should I make my own custom Authorize attribute (deriving from the Authorize attribute)? And if so, should I override the OnAuthorization method to create and set the principal using my account service? Or maybe override the IsAuthorized method directly? Or maybe something else...
The AuthenticationHandler only does authentication. You'd need to set the roles in a separate step (e.g. in a delegating handler).
If you are on Web API v2 - I'd rather recommend switching to the basic auth OWIN middleware
https://github.com/thinktecture/Thinktecture.IdentityModel/tree/master/source/Thinktecture.IdentityModel.Owin.BasicAuthentication
This gives you full control over the principal that gets created.
https://github.com/thinktecture/Thinktecture.IdentityModel/blob/master/samples/OWIN/AuthenticationTansformation/KatanaAuthentication/Startup.cs
There is also a nuget.
I found out that the AddBasicAutentication method actually has an overload that takes a delegate for providing the roles. This is exactly what I was looking for. So now the call to AddBasicAuthentication looks like this, and everything works like a charm:
authenticationConfiguration.AddBasicAuthentication((userName, password) => accountService.Authenticate(userName, password), (username) => accountService.GetRoles(username));

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.

How to handle authorisation failure in MVC3

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>

Resources