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);
Related
I have an ASP.NET MVC API that serves both regular users and admin users. Admin users can do everything regular users can do plus additional functionality.
The HttpContext of requests stores user info which indicates the role of a user. Some endpoints are for use by admin users only. All other endpoints are accessible by all users. Currently, a single controller is being used for both types of user with permissions being used to restrict access accordingly.
However, I'm unsure if this is a good approach because a permission could mistakenly be assigned to the wrong role, or a developer may check the wrong permission for a new endpoint that should be for admin users only.
So, I'm considering two solutions to separate the concerns:
Add a Boolean attribute (e.g., IsAdminUseOnly) to the endpoints. This seems like a quick decision, but would cause code pollution as every endpoint that is for admin use would require true to be specified in the endpoint decorator.
Create a subclass "admin" controller that derives from the regular user controller (in a similar way to described in this question). The parent and child controllers would effectively each have a different Route (e.g., MyController and MyAdminController). The child (admin) controller would inherit all endpoints from the parent controller. Of course, role access would be specified in the child controller as described in this answer using [Authorize(Roles = RolesConvention.Administrator)] for example.
Would either of the above be a suitable solution for this problem, or are there other more suitable methods to achieve the SoC described above?
We have a multi-tenant application. Currently, the tenant is specified with every request as a route parameter:
GET api/Companies/3/Assets
GET api/Companies/5/Groups
The user is authenticated the normal way, but the authorization logic then happens in the Controller, not in an IAuthorizationFilter. As you can imagine, this causes a lot of duplicate code. I have thought of two alternatives, and I'm not sure which one to implement:
Move the company id to the access token
Pros:
Simple to implement, only requires changing how the access token is issued
Company id does not have to be specified in the route
Cons:
Operations across multiple tenants are more complicated, and require two access tokens
A user may follow a link to a resource, but be logged in with the wrong tenant
Update the AuthenticationFilter and AuthorizationFilter to look at the route
Pros:
All the existing endpoints will continue to work as expected
If a user follows a link, they don't have to log out and back in to the right company
Cons:
The authentication filter will be performing some authorization, because it can't make claims about the user's permissions within the company without first verifying that the user belongs to that company
Company id has to be specified in every route
Which of these two alternatives is normally used, and why?
Currently I am about to develop my first REST web API!
I'm currently designing how the system will work yet I am a little confused how things are going to work.
Primarily, a mobile app will consume the Web API, but it must be secure!
For example I wouldn't want an un-authed request handled at all. (Apart from a user registering)
I have found that I can use SSL + Bearer tokens to achieve this user authentication. I am comfortable with this and have tested to see how this would work. And it's suitable.
The problem arises when I wish to retrieve the user details.
In my system a user would log in to the mobile app which would request the token from the server. If all is good, I can log the user into the app. Great! Now, I need to get the information stored about this user to present to them. i.e. name, email, reward points etc...
I am unfamiliar with how to add extra user data AND retrieve it with the Web API. I understand that the token can be used to uniquly identify a user. but how can I extend this data?
Currently I have not much more than a blank WebAPI project with the bearer token authentication implemented. Still using the Entity framework. How can I add more fields of data to a user record?
Furthermore, how can I update these records? For example, a user has gained some reward points, how can update the user data for this?
One final question, Is this suitable for retaining per user data? i.e. can I link other data to a userID or something similar?
Apologies for sounding over-curious, I am very new to MVC
The below code in the IdentityModel.cs would seem like the appropriate place to add user data, but how do I add to this? for example adding a field for reward points? then how would I update upon it?
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
}
How I would do it:
Create ActionFilter that would validate token, it would use your custom class that would leverage DI, it would obviously get the user ID as well
Now that you know that user is authenticated and you know the user ID just do your regular CRUD based on this user ID
Note: Remember to also validate the payload, since if I send you PUT: /user/887/points {points: 999} I could potentially gain unlimited points.
It's not necessary to use ASP .NET Identity for implementing security in your web API project.
If you use Identity you will have to stick on to "ApplicationUser" and Identity tables for user management where you won't be able to complete your requirement.
A solution is to handle user management with your own custom table and implement security using OWIN middleware classes available for .NET, ie, you need to write code for generating and validating tokens rather than using Identity.
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
Just started getting to grips with WCF security. How do I list a user's roles at the service?
E.g.
// Could use declarative security here, i.e. using PrincipalPermission attribute
public string MyService()
{
// Would like some code that does something like:
foreach( Role role in CurrentUser.Roles )
{
}
}
Thanks
When dealing with Windows groups you can use this code:
foreach (IdentityReference idRef in WindowsIdentity.GetCurrent().Groups)
{
Console.WriteLine(idRef.Translate(typeof(NTAccount)).Value);
}
The role-based security infrastructure in .NET (ie IPrincipal) doesn't allow fetching all of a user's roles. You can only inquire whether a user is in a specific role (via IPrincipal.IsInRole("role-name")).
However, there are solutions if you don't mind being tied to a particular authentication/authorization setup. For example, another poster pointed out how to get the user's roles when using Windows authentication.