Integrating SignalR with existing Authorization - asp.net-mvc

I've been working on a way of integrating SignalR Authorization Attributes with a custom authorization provider (called MVCAuthorization) I went down a few rabbit holes of trying to recreate an Authorization provider for hubs specifically, but that turned out to be far too complicated. So I was wondering, how I can integrate my existing Controller and Action Authorization with my SignalR Hubs and methods?

I figured out that you can retrieve an IAuthorization provider.
If you treat you hub as a controller, and your methods as your actions, all you have to do is create a SignalR Attribute that implements IAuthorizeHubConnection and IAuthorizeHubMethodInvocation
public class HubAuthorizeAttribute : Attribute, IAuthorizeHubConnection,IAuthorizeHubMethodInvocation
{
public virtual bool AuthorizeHubConnection(HubDescriptor hubDescriptor, Microsoft.AspNet.SignalR.IRequest request)
{
IAuthorizationProvider authorizationProvider = DependencyResolver.Current.GetService<IAuthorizationProvider>();
return authorizationProvider.IsAuthorizedController(hubDescriptor.Name);
}
public virtual bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext)
{
IAuthorizationProvider authorizationProvider = DependencyResolver.Current.GetService<IAuthorizationProvider>();
return authorizationProvider.IsAuthorizedAction(hubIncomingInvokerContext.MethodDescriptor.Hub.Name, hubIncomingInvokerContext.MethodDescriptor.Name);
}
}
Then all you have to do is put the attribute on your hub or any methods you want authorized
[HubAuthorize]
public class Message : Hub
{
public void Send(string message)
{
}
}

You should override the existing methods in the pipeline
Check authorize in SignalR attribute
http://www.asp.net/signalr/overview/signalr-20/security/hub-authorization
Overriding AuthorizeHubMethodInvocation will allow you to authorize the request while overriding UserAuthorized with allow you to authenticate (you can check the user's roles etc.
Have your HubAuthorizeAttribute inherit from AuthorizeAttribute and allow the constructor to take in a list of roles
Here's a simple example on how to handle roles http://www.jasonwatmore.com/post/2014/02/18/ASPNET-Web-API-2-Enum-Authorize-Attribute.aspx

Related

Spring Security 4 - Get Authorization mappings

Assuming I have a Spring Application whose requests are being authorized with http.authorizeRequests() and #PreAuthorize
Is there a way to get these mappings programmatically?
Is there an api within Spring where I can retrieve which urls are authorized for the currently authenticated user?
I dont know if there are better ways similar to we pass request header like #RequestHeader("Content-Type")... i would love to see that ...
#PreAuthorize("authorizeAccess(#user,#contentType,)")
public Idea somemethod(#RequestBody User user, #RequestHeader("Content-Type") String contentType )
{..}
But below is definitely an option.
Assuming you know how to write overrride or write your own methods to use in spring security (customised class extending SecurityExpressionRoot). If so if you have a method i.e..authorizeAccess
public boolean authorizeAccess(String mapping)
{
// use mapping to authorize
.. do something
}
Then, we can have all urls in a constant file..
package org.somepackage;
public interface URLMappings {
public static String ADMIN = "/admin";
}
Then pass these urls as constants ..
#RequestMapping(value = URLMappings.ADMIN, method = RequestMethod.POST)
#PreAuthorize("authorizeAccess(T(org.somepackage.URLMappings).ADMIN)")

Authentication with ASP.NET MVC site and ServiceStack API

I am developing a website using ASP.NET MVC with an API using ServiceStack.
Very soon I want to add authentication. The website will have at least two types of users 'service providers' and 'service consumers', although a user could have multiple roles.
I am open to using new MVC Identity, but I want whatever I use to work nicely for both the servicestack API and MVC 'pages' that don't necessarily use the API but should show different content based on login. I do not want to require javascript for login/logout.
I would like the solution to use tokens as I have not used session state anywhere else, but I am open to other options providing they would scale horizontally on a cloud provider (users next request may go to a different instance of back-end).
Anyone have example of an ideal solution?
(N.B: I am not interested in an externally hosted service).
ServiceStack's Authentication can also be used by external ASP.NET Web Frameworks, the ServiceStack and MVC Integration docs shows how you can accept Login credentials from a MVC Controller and register them with ServiceStack:
public ActionResult Login(string userName, string password, string redirect=null)
{
if (ModelState.IsValid)
{
try
{
using (var authService = ResolveService<AuthenticateService>())
{
var response = authService.Authenticate(new Authenticate {
provider = CredentialsAuthProvider.Name,
UserName = userName,
Password = password,
RememberMe = true,
});
// add ASP.NET auth cookie
FormsAuthentication.SetAuthCookie(userName, true);
return Redirect(string.IsNullOrEmpty(redirect) ? "/" : redirect);
}
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
}
return View("Index", GetViewModel());
}
The http://mvc.servicestack.net Live Demo shows an example of calling this controller using a standard MVC HTML Form.
Your MVC Controllers can then inherit ServiceStackController to access the Authenticated Users Session and different ServiceStack providers, here are the API's relating to Session and Authentication:
public class ServiceStackController : Controller
{
//...
ISession SessionBag { get; set; }
bool IsAuthenticated { get; set; }
IAuthSession GetSession(bool reload = true);
TUserSession SessionAs<TUserSession>();
void ClearSession();
}
Enable OAuth Providers
Should you need to you can also enable ServiceStack's different OAuth providers which can optionally callback either directly to a ServiceStack Service or
Further to mythz answer I also needed to know if a user was authenticated in a view and the normal Request.IsAuthenticated does not work when your doing above. So I created a CustomWebViewPage (to use this you will have to change *pageBaseType="Your.NameSpace.CustomWebViewPage" in the View folder's Web.config).
public abstract class CustomWebViewPage : WebViewPage
{
private IServiceStackProvider _serviceStackProvider;
public virtual IServiceStackProvider ServiceStackProvider
{
get
{
return _serviceStackProvider ?? (_serviceStackProvider =
new ServiceStackProvider(new AspNetRequest(base.Context, GetType().Name)));
}
}
public virtual bool IsAuthenticated
{
get { return ServiceStackProvider.IsAuthenticated; }
}
}
public abstract class CustomWebViewPage<TModel> : WebViewPage<TModel>
{
//EXACTLY the same as above method...

Spring Security Rest

I'm having a set of Sping Data Repositories which are all exposed over Rest by using Spring-data-rest project. Now I want to secure the HTTP, so that only registered users can access the http://localhost:8080/rest/ So for this purpose I add #Secured(value = { "ROLE_ADMIN" }) to all the repositories and I also enable the security by specifying the
#EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
So now what happens is I go to the rest and it's all good - i'm asked to authenticate. Next thing I do is I go to my website (which uses all the repositories to access the database) but my request fails with
nested exception is org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
which is correct because i'm browsing my website as anonymous user.
So my question is: is there a way to provide method authentication for the REST layer only? To me it sounds like a new annotation is needed (something like #EnableRestGlobalMethodSecurity or #EnableRestSecurity)
I don't know if this will solve your problem, however I managed to get something similar, working for me by creating an event handler for my specific repository, and then used the #PreAuthorize annotation to check for permissions, say on beforeCreate. For example:
#RepositoryEventHandler(Account.class)
public class AccountEventHandler {
private final Logger logger = LoggerFactory.getLogger(getClass());
#PreAuthorize("isAuthenticated() and (hasRole('ROLE_USER'))")
#HandleBeforeCreate
public void beforeAccountCreate(Account account) {
logger.debug(String.format("In before create for account '%s'", account.getName()));
}
#PreAuthorize("isAuthenticated() and (hasRole('ROLE_ADMIN'))")
#HandleBeforeSave
public void beforeAccountUpdate(Account account) {
logger.debug(String.format("In before update for account '%s'", account.getName()));
//Don't need to add anything to this method, the #PreAuthorize does the job.
}
}

Web API with Forms authentication and roles

I have a MVC4 web application set up, which uses Forms authentication and Web API for interaction. All API controllers use the [Authorize] attribute.
This was working just fine out of the box, until we started adding role support. Instead of implementing a full-fledged RoleProvider, I added a list of roles to the ticket's UserData, and created the following module:
public class SecurityModule : IHttpModule
{
public void Init(HttpApplication context)
{
var roleManager = (RoleManagerModule)context.Modules["RoleManager"];
roleManager.GetRoles += GetRoles;
}
void GetRoles(object sender, RoleManagerEventArgs e)
{
var user = e.Context.User;
if (user.Identity.IsAuthenticated && !(user is MyCustomPrincipal))
{
var roles = GetRolesFromFormsAuthCookie();
if (roles != null)
e.Context.User = new MyCustomPrincipal(user.Identity, roles,
otherData);
}
e.RolesPopulated = true;
}
}
This works flawlessly for MVC calls. For API, however, even though GetRoles gets called, when it reaches the corresponding method, it's back to GenericPrincipal.
How can I make this work with Web API too? Do I have to create a DelegatingHandler?
I'm also storing some custom data in my Principal, which might be a reason not to rely on just a RoleProvider (since I'd end up with a RolePrincipal), although I could just store that in the request context.
Update: I've now added a DelegatingHandler that does the same as the IHttpModule and sets Thread.CurrentPrincipal. Is this a reasonable approach?
Have you tried to set the Thread.CurrentPrincipal in the HttpModule as well ?. You can also use a Katana handler, which will work for both, ASP.NET MVC and ASP.NET Web API.

RIA Services: How can I create custom authentication?

I am working with the Silverlight RIA Services and I want to create custom authentication. This appears to be the only thing that has virtually no documentation (I've read through the entire RIAServicesOverview.docx).
Do you know of a way for me to create a customer authentication service? I don't want to use the default ASP.NET membership model. I don't know what interface or abstract class I need to implement - although I did find System.Web.Ria.ApplicationServices.IAuthentication.
Do I need to implement IAuthentication? If so, could you give me some advice on how to go about doing so? These are the following methods:
public User GetUser();
public User Login(string userName, string password, bool isPersistent, string customData);
public User Logout();
public void UpdateUser(User user);
I don't know how I would implement any of these (except for Login) - how could the service possibly know what user is currently logged in in order for Logout() to work?
I've been scouring the web in search of how to do this for hours, and I can't find anything that describes how to create a simple DomainService that can be used for authenticating a user in an "RIA-linked" Silverlight project.
If someone could shed some light on this, I'd be sincerely grateful.
Thanks,
Charles
[EDIT]
I found the RIA Services page on the MSDN Code Gallery. There's a section called Authentication Samples, which links to some great code samples. Check it out if you want to know more about how authentication works within RIA Services.
If you create a "Silverlight Business Application" you'll see how the template implements authentication. (Or just go here and download the template sample project.)
To simplify, here's the process I used:
First, I create a domain service (FooService) that derives from LinqToEntitiesDomainService where FooContext is my entity model. In it I add all the CRUD operations to access my custom DB table and return user profiles.
Next, create a concrete User class on the serverside by deriving from UserBase:
using System.Web.Ria;
using System.Web.Ria.ApplicationServices;
public class User : UserBase
{}
Finally, derive a class from AuthenticationBase and implement the following four methods:
[EnableClientAccess]
public class AuthenticationService : AuthenticationBase<User>
{
private FooService _service = new FooService();
protected override bool ValidateUser(string username, string password)
{
// Code here that tests only if the password is valid for the given
// username using your custom DB calls via the domain service you
// implemented above
}
protected override User GetAuthenticatedUser(IPrincipal pricipal)
{
// principal.Identity.Name will be the username for the user
// you're trying to authenticate. Here's one way to implement
// this:
User user = null;
if (this._service.DoesUserExist(principal.Identity.Name)) // DoesUserExist() is a call
// added in my domain service
{
// UserProfile is an entity in my DB
UserProfile profile = this._service.GetUserProfile(principal.Identity.Name);
user.Name = profile.UserName;
user.AuthenticationType = principal.Identity.AuthenticationType;
}
return user;
}
public override void Initialize(DomainServiceContext context)
{
this._service.Initialize(context);
base.Initialize(context);
}
protected override void Dispose(bool disposing)
{
if (disposing)
this._service.Dispose();
base.Dispose(disposing);
}
}
Here is a complete official example from MS:
http://code.msdn.microsoft.com/Custom-Authentication-96ca3d20
How about implementing the IAuthorization interface?

Resources