what is the best way to restrict services for certain users - c#

EDIT: reworded and simplified question to be consise...
In my service layer I have something like
GetAllMessages(string userid);
I could have various types of users on my system like Clients / Supplier etc...
This service is only available to all types of users, however what is the best way to implement services only available to selected users e.g.
DeleteAllMessages(string userid); //client only
NewSupplierMessages(string userid); //supplier
Typically these methods will be in one class called MessagesService
NOTE: just to clarify, the user is loggedon and authenticated, however I am wondering if I should write my methods as such:
DeleteAllMessages(ClientUser user); //client only
NewSupplierMessages(SupplierUser userid); //supplier
Basically get the details of the user for every action and call methods in a more strongly typed manner...
EDIT 2:
Note my domain layer is in a seperate class library from my web app, a "client user" will be part of a "client", similarly a "supplier user" will be part of "supplier" - so if I wanted to query my service layer and call the correct code (i.e. retrieve the correct details) - I MUST pass in the user id or a strongly typed class of the user, I cannot see how having a contraint on a DTO object that represents who can access the service as incorrect/ brittle?
Other wise I will have something like this:
GetClientDetails();
The user is handled by asp.net so we know this action can be accessed by the user, however what if there are multiple clients? Surely then we must pass in some some of client id/ if I was to pass in user id I could get the client id from it...
Rather I would say my domain layer is incorrect seeing something like the above signature...
EDIT 3:
The only other alternative I could think off is, when the user authenticates, store the use in a class called UserSession inside the asp.net mvc application as a global state, then inject this using DI (ninject) into my domain service layer, therefore when my signatures can be
GetClientDetails();
The domain service class implementing this interface could be:
public class ClientService : IClientWorkerService
{
private ISession _session;
private IGenericRepo = _repo;
public ClientService(IUserSession _session, IGenericRepo _repo)
{
this._session = _session;
this._repo = _repo;
}
public ClientDetails GetClientDetails()
{
var loggedonuser = _session.GetUser();
if(!loggedonuser.isClient())
throw new NoAccessException()
return _repo.Single<Client>(x=> x.ClientID == loggedonuser.ClientID);
}
}

See MSDN: ASP.NET Authorization
Authorization determines whether an
identity should be granted access to a
specific resource. In ASP.NET, there
are two ways to authorize access to a
given resource:
File authorization
File
authorization is performed by the
FileAuthorizationModule. It checks the
access control list (ACL) of the .aspx
or .asmx handler file to determine
whether a user should have access to
the file. ACL permissions are verified
for the user's Windows identity (if
Windows authentication is enabled) or
for the Windows identity of the
ASP.NET process. For more information,
see ASP.NET Impersonation.
URL authorization
URL authorization
is performed by the
UrlAuthorizationModule, which maps
users and roles to URLs in ASP.NET
applications. This module can be used
to selectively allow or deny access to
arbitrary parts of an application
(typically directories) for specific
users or roles.
An Overview of Authentication and Authorization Options in ASP.NET
Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication
Role-based access control
Custom role based Web Service access

Related

IdentityServer4 + Asp Identity + EF Configure two UsersSet/Providers

Having trouble finding a good lead on this. I have a aspnetcore app with identityserver4 configured to use asp identity with a sql database.
There is a business requirement that all non AD users are stored in this asp identity database.
All AD users are defined on Azure. I can authenticate them with LDAP and receive their data.
The issue comes after authentication. Whenever asp identity tries to call:
var user = await UserManager.FindByNameAsync(userName);
With an AD user, it fails because the user does not exist. This is because it is using EF to query the asp identity database, where those users are not defined.
private DbSet<TUser> UsersSet { get { return Context.Set<TUser>(); } }
I can not store any of the AD information in the asp identity database (business requirement). I am trying to find a way to get the user store to look both at the asp identity tables, as well as Azure (via LDAP).
My current method for getting the AD users when doing initial auth is here:
await GetADUser(queryParams),
It uses LDAP to authenticate and grab the user object.
One additional requirement is that I can not use an external login screen, the login must all be done from the same company facing login UI. AKA no external providers.
As per #mxmissile, abstracting the UserManager out was the correct call. Then you can also abstract out other managers as needed for special functionality. This is in fact the only class in the inheritance layer for this part of the code that is virtual.
There are built in functions that let you register your custom managers:
services.AddIdentity<IdentityUser, IdentityRole>()
.AddUserManager<ApplicationUserManager<IdentityUser>>()
.AddSignInManager<ApplicationSignInManager<IdentityUser>>()
Hopefully this is a little help to any others that have a similar question. I ended up just overriding a couple of the functions from the base user manager and just calling the base method for anything that did not need my new logic. By default it looks like ASP Identity does not try to look up users by email - just fyi.

Global collection for use Web API v2

I would like to create a "Global" dictionary that could be used in my web api v2 project. I would like to collect the usernames of all clients that have authenticated with my API and the time they were authenticated.
Since each client would represent a different HTTP context how could I safely store this data so it can be accessed from other methods in the application? Ideally I would like to add the username and the time they authenticated within m CustomOAuthProvider class as this is where the user authentication occurs.
I would like to avoid using a database as the information is really small and I only need the data while the app is running.
In your Global.asax define a prop public static MyClass MyReference {get; set;}. Then in your method where the user is authorized (logged in), modify this object: Global.MyReference.UpdateMethod(currentUser).

How in ASP.NET MVC do I maintain info about whether a user is "logged in" throughout pages?

After they type in their password, should I keep a variable in server session storage like Session["loggedIn"] = true that I check when requests are made to pages that require a login, or is there a better/safer way this is traditionally done in ASP.NET?
No, do not keep this in a session variable. In fact, I would argue you should try not to use session for anything. Try to keep the HTTP communication as stateless as possible.
For authentication in ASP.NET MVC, you have 2 alternatives, but ultimately, the both end up working the same way: by writing an encrypted authentication cookie to the browser after you successfully log a user in.
The newer alternative was mentioned in a comment to the OP: Microsoft.AspNet.Identity. To use this, you should be using a newer version of ASP.NET MVC with the OWIN pipeline (though I am not sure if you have to). The older alternative is called Forms Authentication, and can be used with any version of MVC except version 6 (the new vNext / core 1.0 stuff) I believe.
When you have successfully integrated one of these 2 tools into your MVC application, after a user logs on, your Controllers will have a non-null User property of type IPrincipal. You can use this property to determine whether or not a user is authenticated:
// in a controller
bool isThereAUserLoggedIn = this.User != null && this.User.Identity.IsAuthenticated;
If you are using the newer Microsoft.AspNet.Identity, then this IPrincipal User property will be implemented as a ClaimsPrincipal with one or more ClaimsIdentitys. Forms Authentication does not do claims like this, so if you want claims, or social login, etc, use Microsoft.AspNet.Identity.
The way that this is traditionally done in ASP.NET and by my opinion also better and safer is by making use of the ASP.NET Identity package.
ASP.NET Identity handles all aspects around user accounts in a web application:
database for users, including roles and more
user registration and management, like register, email verification, log in, remember me option, forgot my password action and more.
user authentication & authorization
Just to make things more clear, authentication means that the user making the request is actually a valid application user and authorization means that the user has the authority to perform the requested action.
Practically, when a user logs in, Identity automatically keeps that information and makes it available in all controllers and views under User property. So you know at any time which user made the request. Identity also supplies each request with a cookie used for user authentication and authorization.
To check for user authentication you use the User.Identity.IsAuthenticated in a view and the Authorize attribute in a controller:
[Authorize]
public ActionResult Create( ... ){ ... }
The above use of the Authorize attribute will allow only to registered users to request this page.
It is also very common to extend the functionality of your application to include roles for the users and user authorization. Identity creates a "Users" table, a "Roles" table and a many to many relationship between them. After assigning roles to your users you can authorize their requests by using User.Identity.IsInRole("YourRoleName") in a view and in a controller:
[Authorize("YourRoleName")]
public ActionResult Create( ... ){ ... }
The above use of the Authorize attribute will allow only to registered users having the "YourRoleName" role to request this page. In any case if Identity fails to authenticate or authorize the request will prompt to the log in page.
ASP.NET Identity is simple to use, it works and it is easy to extend the membership functionality of your application both by making use the many tools supplied with it and overriding its classes to give them a more specific or complex behaviour.
You will find infinite help on the web on how to use it or a step by step guide.

Which layer should be used for user authentication

I'm tying to use Domain Driven Design in one of my applications and have some question about user authentication.
I have an aggregate root called User which has Value Objects like UserCredentials, Password, ActivationToken, etc.
I also have few domain services for managing users.
For example UserRegistration service looks like this:
public interface IUserRegistrationService
{
IEnumerable<string> Register(NewUserRequest request);
}
It checks business rules that are assigned to user registration process and persist user in the database.
Now I want to authenticate user, so I've created UserAuthentication domain service:
public interface UserAuthenticationService
{
IEnumerable<string> Authenticate(AuthRequest request);
}
It takes user from the repository, checks business rules, updates and persists user data changes like LastLoginDate.
But I have some doubts if authentication process belongs to domain itself or it should belong to application service, as for my domain it doesn't matter how user is authenticated.
But on the other hand authentication rules, that are checked inside this service, belong to my domain rules, so they're integral part of my domain.
So where do you put authentication in your DDD based appllications and what is your solution to this issue?
1.Generally, authentication and authorization are su-domains in an application. You'd better build an abstraction in application layer/core domain to isolate them.
public interface OrderingService// application layer
{
void PlaceOder(Order order) {
//delegate to identity subdomain to validate user request
UserAuthenticationService.Authenticate(ExtractFrom(order));
//delegate to booking core domain to handle core business
BookingService.placeOrder(order);
}
}
2.In Identity subdomain, the authentication algorithm could be placed in infrastructure layer:
public class OathUserAuthenticationService:UserAuthenticationService //infrastructure layer
{
IEnumerable<string> Authenticate(AuthRequest request) {
......
}
}
There are excellent discussion and examples in Implementing Domain Driven Design. The author seperate authentication to an identity subdomain.
Following answer is highly depends on my assumptions about your task and environment, so do not beleive me blindly.
I think authentication is a business process. It highly coupled with concepts of User, Registration, UserStatus etc.
If you ask me how to call this business process with the single word, I'd choose UserPolicy. Look at UserPolicy as an aggregate root. It's boundaries includes such entities as: User, RegistrationService, AuthenticationService, UserRepository. All of them must remain consistent. It is easy to achieve, because every action with them is going through their root entity:
IUserPolicy up = container.Resolve<IUserPolicy>();
up.RegisterUser(newUserRequest);
up.AuthUser(authRequest);

ASP.NET MVC 4 : Authentication and Authorization:Intranet Application

I'm new to ASP.NET MVC world. I'm building an intranet web application. Authentication and authorization is defined in my case as below:
Authentication: If HttpRequest contains an Header with "USER_ID", user is authenticated.
Authorization: There is one in-house WCF Service, which returns list of roles user is entitled to taking USER_ID as input. I keep the roles required by my application in xml file. If user's required role is in svc response then, she is allowed to use the application.
I'm thinking of implementing it like below:
In Global.asax - > Application_AuthenticateRequest, I'll put code to check http Header. If its non_blank, I'll let user to go through this stage.
In OnAuthorization method of AuthorizeAttribute class, I'll put code to fetch role list and match it against required roles from xml file.
Is there any way that I can use existing authentication,authorization infrastructure?
I see code like this
[Authorize(Roles = "admin")]
public string Index() {
return "only admins!";
}
How can I link Roles property like above to some Xml or Table instead of hard coding?
Please help me to implement this logic in asp.net mvc application.
You should check Windows Identity Foundation (WIF), in particular ClaimsAuthorizationManager and ClaimsPrincipalPermissionAttribute. The later allow you to specify what operation and resource need to be secured, while in ClaimsAuthorizationManager you can check whether the current user can perform the operation on the resource, and that can be read from any source you desire.
For Authorization, I would either:
Create a GenericPrincipal in the global.asax AuthorizeRequest event handler with the appropriate roles, and assign it to both HttpContext.User and Thread.CurrentPrincipal.
Or (better), write a custom RoleProvider that gets the users roles from the xml file. If you configure such a RoleProvider, ASP.NET will assign a suitable RolePrincipal to both HttpContext.User and Thread.CurrentPrincipal.
You can then use the standard AuthorizeAttribute.

Categories

Resources