I was wondering if there is an easy way to check if the user has access to a specific method, controlling the user permission thru a custom database.
I used to pass the "User" object on every single method, then validate if he does or doesnt has access to that method, just like that
[OperationContract]
public void Foo(UserInformation user, string param1, string param2) {
//Check if the user has permission to run this method
if (!Security.CheckPermission(user,"Foo")) {
...throws an exception or something like that
}
}
I'm sure that there are better ways to do that, one example would be a Role based authorization, but I can't use SQL Server Role provider as my main database is on Oracle and the application already have custom tables where user permissions are stored.
Unafortunatelly, I cant change the database or how users has access to those functions.
I did some research on http://wcfsecurity.codeplex.com but no luck.
Related
I'm building a web app (asp.net mvc),
where i'm using the attribute [Authorize] on GET and Post.
For example:
[Authorize]
public ActionResult EditClient(string id)
{
//Do Stuff
}
I now want to look to ensure that the logged in user, can only access data that belongs to that user\account?
But I'm not sure how to do this, does .Net already provide methods\attributes to use?
For example, this is how I would get a client:
[Authorize]
public ActionResult EditClient(string id)
{
var user= new Token(this.User.Identity.Name);
//user.id
//user.accountId
//So does this Client belong to the same account as the user is in?
//We know the client and user both belong to an account(id)
//Are we allowed to return the below?
var client = _clientService.GetClient(id);
//client.id
//client.accountId
}
As mentioned not to sure what best practice\options I should apply, obviously I know I should apply this kind of logic in most places?
Ideas? Sample?
There are many ways you could achieve this. for example you could create a custom attribute that takes in the parameter and checks the resource belongs to the requesting user. This could get complex as you'd have many different attributes for each type of entity you are accessing.
You probably want other validation rules such as the requested client even exists (i.e. non existing id) I would extract a bunch of rules out such as entity exists, requested entity belongs to authorised user, entity is editable etc etc and inject that into your actions before performing changes or returning said entities, you could throw custom exceptions depending on which validation fails and then send a generic 500, or 400 down to the user with minimal error details (no stack trace). So your action could look something like:
[Authorize]
public ActionResult EditClient(string id)
{
editClientValidator.Validate(id);
var user= new Token(this.User.Identity.Name);
//user.id
//user.accountId
//So does this Client belong to the same account as the user is in?
//We know the client and user both belong to an account(id)
//Are we allowed to return the below?
var client = _clientService.GetClient(id);
//client.id
//client.accountId
}
Where the EditClientValidator class contains your custom rules for editing a client. Alternatively you could create an attribute essentially doing the same thing but only for access (client belongs to the authenticated user)
I am new to MVC and I have very simple problem.
When user login to my application I need to create a specific object (model) for the user for eg UserObject.
This object is unique to current logged in user and should only be disposed when user click on logout.
I don’t know how to maintain the lifetime of the object. As if I create object in Action method of controller class then as soon as the request is finished I lose the reference of the object.
How this should have been done?
The lifetime of your models are only going to be as long as the request. So each time the user goes to another page or refreshes, the MVC framework is going to instantiate a new controller (and model within). Otherwise your server would have a ton of static objects floating around in memory which would use up a lot of resources and wouldn't scale.
In order to manage state, you are going to need to use other methods such as sessions/cookies and a database.
So let's say the user logs in via /User/Login. This routes the request to an action named UserController.Login().
Inside this action, it instantiates a UserModel.
public ActionResult Login(string username, string password) {
var userModel = new UserModel();
if (userModel.Authenticate(username, password)) {
// Setup your session to maintain state
Session["username"] = username;
} else {
return View("Login");
}
return View("LoginComplete");
}
You might want the user model to actually create the session, but I've shown it here for clarity.
The user model authenticates the user, and then you create a session just like you would in a traditional non-MVC site.
Then in subsequent requests, you will want to authorize the user, and use any session data you have to retrieve state information.
public ActionResult SuperSecretPlace() {
var userModel = new UserModel();
string username = Session["username"]
var user = userModel.GetUserByUsername(username);
if (user == null) throw new HttpException(401, "User is not authorized.");
return View("SuperSecretPlace", user);
}
In the action above, the UserModel might do something like query a database to retrieve the user's data so you can pass it in to the corresponding view.
If you want to make life easier, you might want to just use .NET's built in forms authentication:
http://www.codeproject.com/Articles/578374/AplusBeginner-splusTutorialplusonplusCustomplusF
For more info about the lifecycle of MVC:
http://www.dotnet-tricks.com/Tutorial/mvc/TbR0041112-Asp.net-MVC-Request-Life-Cycle.html
http://www.asp.net/mvc/overview/getting-started/lifecycle-of-an-aspnet-mvc-5-application
Actually what you are trying to achieve is passing model from controller to controller which is not possible. When an action is executed the context of the model object is disposed at the view and it can cannot be passed from controller to controller. You have to create a new object repopulate it and use it to achieve the goal in different controller.If you need the data to be persisted you can use sessions but still you need to create an object of the model in every controller.
The following image is for your reference as to see what to use when passing data between model-view-controller. Please feel free to ask if you need more information on this.
As opposed to the other aswers I would not use session as it has quite some disadvantages (scalability, pessimistic concurrency which blocks concurrent calls, app pool recycling...). Why you should not use session is documented in a lot of places like here or here.
Instead, I would store it in a cookie.
However, be sure to not store confidential or sensitive data. Whatever you use (cookies or session), it can be tampered with or stolen. If you are dealing with sensitive information, you need other solutions. Read also more about secure cookie solution here.
I am logging into my service from a c# client like so:
serviceClient.Send<ServiceStack.ServiceInterface.Auth.AuthResponse>(
new ServiceStack.ServiceInterface.Auth.Auth() {
UserName = "xxx",
Password = "yyy" }
);
I would now like to use one of the unused strings in the Auth class to pass some additional information (like a programid). I am using my own subclassed CredentialsAuthProvider. Two questions:
Do you recommend any of the "extra" properties in the Auth class to stuff my programid over any others? I was considering using "State", will that mess anything up if I put a string in there?
Is there a way from within the TryAuthenticate override of my CredentialsAuthProvider to access the Auth class instance that was sent to me (so I can access the programid that I stuck into the State property).
Thank you.
Answered half of my question.
Not sure if any of the properties are better than any other, but I'm using "State" to stuff some extra data. Now that multiple end user programs are accessing the same service, sending a program ID in the State property lets me log the programs attempting to log into the service, along with the users.
If you are authenticating by overriding CredentialsAuthProvider, you can override the Authenticate method to gain access to the Authenticate object that is passed in from the user. From there, you can read the State property (or any other).
Sorry for the basic question, first time with Web MVC4 in C#...
I'm creating a web interface for an application I've written in C#/SQL. I've been able to attach the MVC4 framework to the SQL DB. Now I want to secure what people can do based on group membership in AD. I have the authentication in my web.config set to "Windows" and it properly displays the User.Identity.Name that i'm logged in with. So I know it's pulling up the current logged in user. More over, I need to be able to authenticate a user outside of the active directory domain in the case of an android or ipad device. I haven't gotten that far yet though... for the most part, I'd like to auto authenticate the logged in user if possible then prompt for a username/password if none exists.
Ok, also I already know how to pull group membership for a user in AD. But I need to run that AD query and store that information somewhere that can be accessed on each page. Then on each page how do I access that variable?
For example, I don't want to display a menu option if they don't have access to it so that variable needs to be used to either display or not display the menu option that's being secured. Also, I assume I need to add that security on the webpage as well so that if someone tries to go there manually they cannot.
I assume I don't want to use session variables for security reasons..
In the past with Adobe Flex I used a singleton to manage the session state. I did a search out there and people are saying that it's probably not a good idea in C#. Not many examples of this anyway...
What are you doing to do this?
Here is what I would recommend. Start looking for examples of the ActiveDirectoryMembershipProvider Class. This MembershipProvider combined with Forms Authentication will provide you with a secure system to authenticate users.
Once authenticated, you need to authorize your users to access resources by combining the Active Directory Role Provider(ADRP) (to determine User Groups) with the standard way of Securing your MVC Application.
To get you started I created these simple extension methods when you can extend to use the ADRP (as I haven't used the ADRP).
public static class IPrincipalExtensions
{
private static _adminName = "Administrator";
public static bool IsAnonymous(this IPrincipal instance)
{
return (instance == null);
}
public static bool IsAdminOrInRole(this IPrincipal instance, string role)
{
if (instance == null
|| instance.Identity == null
|| !instance.Identity.IsAuthenticated)
{
return false;
}
bool result = instance.IsInRole(role)
|| instance.IsInRole(IPrincipalExtensions._adminName));
return result;
}
}
Then I also extended the default AuthorizeAttibute to give me an attribute I can use solely for Administrators:
public class AuthorizeAdministratorAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
bool result = false;
IPrincipal user = httpContext.User;
if (user.Identity.IsAuthenticated)
{
result = user.IsAdmin();
}
return result;
}
}
This uses the same extension methods provided in my IPrincipalExtensions so I don't repeat myself. Some might find this overkill as the following two lines are equal:
[Authorize("Administrator")]
[AuthorizeAdministrator]
However, since the first example is using a string, a simple mistype denies access, and if I decided to change the role/group name to "Admins" it becomes more difficult. So using the second one (which I could argue is strongly typed) if the group changes, I only have to change the name in one location.
In the documentation for ServiceStack, it says that the best practice is:
Normally ServiceStack calls the method bool HasPermission(string
permission) in IAuthSession. This method checks if the list
List Permissions in IAuthSession contains the required
permission.
IAuthSession is stored in a cache client as explained above You can
fill this list in the method OnAuthenticated you've overriden in the
first part of this tutorial.
I am integrating with an existing system, and have my custom BasicAuthProvider working (inherited from the base BasicAuthProvider). Authentication is working perfectly, now I am building out the Authorization portion. I plan on using the Permissions list as listed above, but I need access to the Route information to determine if a user has access to a particular resource. I see in the IAuthServiceBase there is an IRequestContext which has the absolute URL, but before going through and parsing that out, I figured there has to be a way to gain access to the ServiceStack Route structure to give me either the class name of the Service being requested, or the DTO the requested service is related to.
Here is the OnAuthenticated method from my BasicAuthProvider class:
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
UserSession sess = (UserSession)session;
Model.User currentUser = UserRepository.GetUserByUsername(session.UserAuthName);
//Fill the IAuthSession with data which you want to retrieve in the app eg:
session.FirstName = currentUser.Person.FirstName;
session.LastName = currentUser.Person.LastName;
session.UserName = currentUser.User1;
sess.CurrentUser = currentUser;
//Important: You need to save the session!
authService.SaveSession(session, TimeSpan.FromDays(1));
}
Under MVC I have used some of the Raw Request Data to get the Controller and Action name before, to determine resource authorization, but this is the first project I am using ServiceStack with.
You may find the [RequiredPermission] attribute or even the implementation of it will help you, e.g. the 3rd parameter passed in a RequestFilter is the Request DTO.
And since a Request DTO maps 1:1 with the service, you can be sure that the request is destined for the IService<TRequest> (or its subclasses e.g. ServiceBase<T>, RestServiceBase<T>).
You can access the type of the service programatically as done in the FilterAttributeCache:
var serviceType = EndpointHost.Metadata.GetServiceTypeByRequest(requestDtoType);
I'm not sure of the exact context/use-case you're trying to support but using the [RequiredPermission] or [RequiredRole] attributes may have what you need which by default validates against the list of roles and permissions available in the built-in UserAuth table.
Externally you can use the /assignroles and /unassignroles web services (as part of the AuthorizationFeature plugin) to assign roles and permissions to users (it requires a user with the Admin role by default).
For more info see the documentation pages on Authentication/Authorization and Validation on the ServiceStack GitHub project wiki.