ASP NET CORE DDD - CurrentUserService in Domain layer - asp.net

I am working on a school project which basically acts like a Messenger with Events etc.
Recently I came across DDD and I decided to try to implement it's concepts in my project.
I ran into a problem, where each time I want to edit an entity I need to check, if a currently logged user has rights for it.
I have CommmunicationChannel entity (AR) which has ICollection<CommunicationChannelMessage>. When I want to edit message I need to load CommunicationChannel entity, find CommunicationChannelMessage in it and then check if currently logged user is the author of the message.
I decided to create DomainService MessageManager, which has method Update(CommunicationChannel channel, string messageId, string newContent).
This method loads the message or throws NotFoundException, after that it check, if user has right to it and if not throws ForbiddenAccessException.
Basically, domain layer now has a responsibility to check if currently logged user has rights to do something. The idea behind this is that there will be no place in code, where I can forget to check permissions of the user. I can only call methods from this manager and they check permissions everytime.
So my question is following. Can a domain service have a reference to ICurrentUserService (returns entity of currently logged user). Shouldn't the check of user permission be application specific concern in Application layer instead of domain layer?
Thank you so much for your answer.

Stricto sensu DDD does not states anything regarding application layering, besides :
domain layer must use object modeling
domain layer is where business rules are implemented
Now the problem must also be split in two different security concepts : authentication (find user identity) and authorization (is user allowed). Authentication is always an application cross cutting concern, usually handled by an asp.net middleware like Kerberos, OIDC, etc ...
You have two approaches possible for your authorization problem : consider the identity verification as a business requirement or a security cross cutting concern.
In case of a business requirement, author must exist in the domain model, at least as a login/username property on message. Add a parameter to your Update() method for actual user identity to be compared with message author. Your controller can pass the user identity from asp net core authentication or any external auth service if a conversion is required.
If you want to make that a cross cutting concern, you don't need to model message author (unless useful for another business requirement). Make a custom middleware, or insert a security layer somewhere in your architecture (a more precise answer would require insights on your actual architecture).

Related

What's the practical workflow using claims for authentication and authorization in a web application?

I just don't still get Claim Based Authentication/Authorization workflow.
The application allows authentication via Facebook.com
After the user is authenticated, an admin can give her/him a claim of having the role of Manager, which creates another claim (where?)
Of course, this claim won't be on the facebook.com server, question 1: where should that claim be stored?
When the user log in again later, I get the claim of facebook.com and I should get the claim from the application. and merge them?
How is the workflow? Trying to understand claims in practical usage.
Basically, Facebook tells me that I'm john#doe.com, and 'field in the blanks' adds a claim that I'm also a manager of domain.com
then I pass those claims to domain.com?
How should I configure in asp.net the application at domain.com to trust Facebook and 'filled in the blank piece' and request claims from both?
I guess I'm using external providers for Authentication and my own provider for Authorization, how this is created on ASP.NET (web API / MVC)?
UPDATE (for clarification)
Let's get backwards. I create a web application where users can register.
'Somehow' there's an trusted ClaimsBased authority somewhere (this should be another application??) where I request the claims for a particular user to see if have particular rights on my application.
So I imagine something like :
/authserver/claims
and my validation checks if X claim is met to do certain operations.
later I add to Facebook. now I have
/facebook/claims
which tells me the user is X
and
/authserver/claims to see if can do operation X on resource Y.
how this is managed on ASP.NET? and where my own claims should be created/exposed/developed.
I think I'm missing something fundamental here.
I think the important thing to understand is the difference between authentication and authorization.
Authentication - the act of confirming the truth of an attribute of a datum or entity.
Authorization - the function of specifying access rights to resources, which is related to information security and computer security in general and to access control in particular.
So, typically for secured system, the workflow starts with Authentication. When a user first connects/uses a system, then are not authenticated (lets say this user is of a type/group Anonymous). The act of the system determining the user is not authenticated is an Authentication in and of it self. Based on being Anonymous, then the act of the system determining what that type of user anonymous has access too is now authorizing what the user can do. For very secure system, the only access anonymous has is to the login screen/page. Once logged in the user is assigned a unique identity and assigned some type of group policy/role (if not already created).
with a web-based application and having a website (#1) authenticate for another website(#2) it becomes a bit more complicated. When I log into StackOverflow(#1), I use my Gmail(#2) account. I get redirected to Google with some special way for Google to know that the page I came from/to go back to. This could be a special key/url combination or for less restrictive access, usually has to do with return url (after I say, yes, where I go back too). Google will create a special authentication token that is specific to the url I am returning to. It is tied to the URL because that means that my token on StackOverflow won't allow me or anyone else to log into say NewEgg for example (in other words someone at StackOverflow with access to the database can't use my token to authenticate as me on some other website, but technically they could log in as me on StackOverflow, but they own the website, so that doesn't really matter). Now I am authenticated on StackOverflow (but technically StackOverflow doesn't even need to know any information about me, just my Token).
On StackOverflow as a new user, a new account is created. This account probably has a one to many relationship to my unique account on Stack Overflow and multiple of logins (and type of logins, OAuth, OpenID or SO Login). Once the account is created, I have whatever access they have setup by default. If I need more or some trigger (lets say based on my Reputation points :) I now have access to Administrative functionality (given some role). That role is tied to my account and indirectly tied to my authentication. This means that I can create additional logins (say a Local SO Login) but keep my Account.
As for each Authentication resource (Google, Facebook, etc) there will be difference schemes for Authentication, but there will always be at least a token (or more than one token) for a website to say who I am (in a generic way).
So website #1 (Stack Overflow) has requested website #2 (Google) to Authenticate me. But only website #1 knows what am I Authorized for.
For role specific functionality, there are a good number of answer on SO dealing with ASP.Net Identity and the Role Manager:
Creating Roles in Asp.net Identity MVC 5
mvc 5 check user role
A much more Indepth look into Identity with MVC - Extending Identity Accounts and Implementing Role-Based Authentication in ASP.NET MVC 5
If you're using ASPNET.Identity (http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity), you can add a Role claim type to the user. It'll be associated with the userlogin, so when the user authenticates with Facebook, these user claims will be added and available in MVC.
See the following code fragment:
var acRes = await UserManager.AddClaimAsync(userId, new Claim(ClaimTypes.Role, "MyRole"));

SignalR on ASP.NET MVC and Multiple User Types

I am currently in the process of sketching-out an application that allows real-time interactions with website visitors.
Therefore, I have two different "User-types":
Unregistered User: these are the visitors
Registered User: these have a (custom) ASP.NET MVC membership
Now, I am persisting "UserNames" and ConnectionIds in a DB so I can freely scale at some point in the future. I do this by accessing Context.Identiy.User.UserName from within the Hub and then query the DB for any existing "sessions".
Here is the problem:
I need two different types of "User"
For one, I want to dynamically generate a GUID - these are the visitors and will be removed from the database after a given amount of inactivity.
These are the admins, they have their proper identities attached to the Context object.
So, how would one go about accessing a "session" from SignalR? It is not really a Session, I just need to get a SessionId from a Cookie on each initial request to the MVC-Controller, that's all. All I need to be able to do is:
Have an auto-generated "SessionId" which I can use to persist visitors across requests
Have a more "extended" identity: I want to use UserId instead of UserName
Anyway, I hope this makes sense but chip in if anything is unclear.
Okay, I just realised that I can use "HttpContext.Current.Request.AnonymousId" and I am linking this up to a Session-database.
Here some relevant documentation: http://msdn.microsoft.com/en-us/library/system.web.httprequest.anonymousid.aspx
This solved my problem in this case. :-)

Benefits of symfony2 security over storing in session variable on own?

How does Symfony's security component work?
Currently, I grab user login data, auth them against a database, and store their info in a session variable to log them in. When a user accesses a page, it checks their session to ensure they have rights to view a specific page. All of this is organized into services.
I've been looking into Symfony's security component but can't figure out exactly how it works. Specifically, is there some extra security benefit (I have an admin panel that I need to have proper security on) that it offers?
I also hate learning framework specific stuff without understanding what's going on, so would appreciate a general breakdown of how the component works.
Thanks
This video is a good resource of how the security component works. The video is from the Symfony live conference in Paris last year. The speaker Johannes Schmitt is the one who has led the development of the security component.
http://www.youtube.com/watch?v=lSxgEK8WKGA
Security is a two-step process whose goal is to prevent a user from accessing a resource that he/she should not have access to.
In the first step of the process, the security system identifies who the user is by requiring the user to submit some sort of identification. This is called authentication, and it means that the system is trying to find out who you are.
Once the system knows who you are, the next step is to determine if you should have access to a given resource. This part of the process is called authorization, and it means that the system is checking to see if you have privileges to perform a certain action.
More information can be found at :
http://symfony.com/doc/current/book/security.html

How do integrate "Users" in my DDD model with authenticating users?

I'm creating my first ASP.NET MVC site and have been trying to follow domain driven development. My site is a project collaboration site where users can be assigned to one or more projects on the site. Tasks are then added to projects, and users with in a project can be assigned to tasks. So a "User" is a fundamental concept of my domain model.
My plan is to have a "User" model object which contains all the information about a user and can be accessed through an IUserRepository. Each user can be identified by a UserId. Although I'm not sure at this point if I want the UserId to be a string or integer.
How should my domain objects User and IUserRepository relate to the more administrative functions of my site like authorizing users and allowing them to login? How would I integrate my domain model with other aspects of ASP.NET such as HttpContext.User, HttpContext.Profile, a custom MemberShipProvider, a custom ProfileProvider, or custom AuthorizeAttribute?
Should I create a custom MembershipProvider and or ProfileProvider which wraps my IUserRepository? Although, I can also foresee why I may want to separate the User information in my domain model from the authorization of a user on my site. For example in the future I may want to switch to windows authentication from forms authentication.
Would it be better to not try and reinvent the wheel and stick with the standard SqlMembershipProvider built into ASP.NET? Each user's profile information would be stored in the domain model (User/IUserRepository), but this would not include their password. I would then use the standard ASP.NET membership stuff to handle creating and authorizing users? So there would need to be some code somewhere that would know to create a profile for a new users in the IUserRepository when their account is created or the first time they login.
Yes - very good question. Like #Andrew Cooper, our team also went through all this.
We went with the following approaches (right or wrong):
Custom Membership Provider
Neither I or the other developer are fans of the built in ASP.NET Membership provider. It's way too bloated for what our site is about (simple, UGC-driven social website). We created a very simple one that does what our application needs, and nothing more. Whereas the built-in membership provider does everything you might need, but most likely won't.
Custom Forms Authentication Ticket/Authentication
Everything in our application uses interface-driven dependency injection (StructureMap). This includes Forms Authentication. We created a very thin interface:
public interface IAuthenticationService
{
void SignIn(User user, HttpResponseBase httpResponseBase);
void SignOut();
}
This simple interface allows easy mocking/testing. With the implementation, we create a custom forms authentication ticket containing: things like the UserId and the Roles, which are required on every HTTP request, do not frequently change and therefore should not be fetched on every request.
We then use an action filter to decrypt the forms authentication ticket (including the roles) and stick it in the HttpContext.Current.User.Identity (for which our Principal object is also interface-based).
Use of [Authorize] and [AdminOnly]
We can still make use of the authorization attributes in MVC. And we also created one for each role. [AdminOnly] simply checks the role for the current user, and throws a 401 (forbidden).
Simple, single table for User, simple POCO
All user information is stored in a single table (with the exception of "optional" user info, such as profile interests). This is mapped to a simple POCO (Entity Framework), which also has domain-logic built into the object.
User Repository/Service
Simple User Repository that is domain-specific. Things like changing password, updating profile, retrieving users, etc. The repository calls into domain logic on the User object i mentioned above. The service is a thin wrapper on top of the repository, which seperates single repository methods (e.g Find) into more specialized ones (FindById, FindByNickname).
Domain seperated from security
Our "domain" the User and his/her's association information. This includes name, profile, facebook/social integration, etc.
Things like "Login", "Logout" are dealing with authentication and things like "User.IsInRole" deals with authorization and therefore do not belong in the domain.
So our controllers work with both the IAuthenticationService and the IUserService.
Creating a profile is a perfect example of domain logic, that is mixed with authentication logic also.
Here's what our's looks like:
[HttpPost]
[ActionName("Signup")]
public ActionResult Signup(SignupViewModel model)
{
if (ModelState.IsValid)
{
try
{
// Map to Domain Model.
var user = Mapper.Map<SignupViewModel, Core.Entities.Users.User>(model);
// Create salt and hash password.
user.Password = _authenticationService.SaltAndHashPassword();
// Signup User.
_userService.Save(user);
// Save Changes.
_unitOfWork.Commit();
// Forms Authenticate this user.
_authenticationService.SignIn(user, Response);
// Redirect to homepage.
return RedirectToAction("Index", "Home", new { area = "" });
}
catch (Exception exception)
{
ModelState.AddModelError("SignupError", "Sorry, an error occured during Signup. Please try again later.");
_loggingService.Error(exception);
}
}
return View(model);
}
Summary
The above has worked well for us. I love having a simple User table, and not that bloated madness that is the ASP.NET Membership provider. It's simple and represents our domain, not ASP.NET's representation of it.
That being said, as i said we have a simple website. If you're working on a banking website then i would be careful about re-inventing the wheel.
My advice to use is create your domain/model first, before you even think about authentication. (of course, this is what DDD is all about).
Then work out your security requirements and choose an authentication provider (off the shelf, or custom) appropriately.
Do not let ASP.NET dictate how your domain should be designed. This is the trap most people fall into (including me, on a previous project).
Good luck!
Let me break down your collection of questions a bit:
Although I'm not sure at this point if I want the UserId to be a string or integer.
It doesn't have to be an integer per say, but definitely use some kind of bit based value here (e.g. int, long or guid). An index operating over a fixed size value is much faster than an index over a string, and in your life time, you will never run out of identifiers for your users.
How should my domain objects User and IUserRepository relate to the more administrative functions of my site like authorizing users and allowing them to login?
Decide if you want to use the built in asp.net membership or not. I recommend not for the reason that it's mostly just bloat and you have to implement most of the features of it yourself anyway, like email verification, which you'd think from looking at the tables generated it would be built in... The template project for ASP.NET MVC 1 and 2 both include a simple membership repository, just rewrite the functions that actually validate the user and you'll be well on your way.
How would I integrate my domain model with other aspects of ASP.NET such as HttpContext.User, HttpContext.Profile, a custom MemberShipProvider, a custom ProfileProvider, or custom AuthorizeAttribute?
Each one of these is worthy of it's own SO question, and each has been asked here before. That being said, HttpContext.User is only useful if you are using the built in FormsAuthentication functionality and I recommend using it in the beginning until you encounter a situation where it is does not do what you want. I like storing the user key in the name when signing in with FormsAuthentication and loading a request bound current user object at the beginning of every request if HttpContext.User.IsAuthenticated is true.
As for the profile, I avoid stateful requests with a passion, and have never used it before, so someone else will have to help you with that one.
All you need to use the built in [Authorize] attribute is to tell FormsAuthentication the user is valdiated. If you want to use the roles feature of the authorize attribute, write your own RoleProvider and it will work like magic. You can find plenty of examples for that on Stack Overflow. HACK: You only have to implement RoleProvider.GetAllRoles(), RoleProvider.GetRolesForUser(string username), and RoleProvider.IsUserInRole(string username, string roleName) in order to have it work. You do not have to implement the entire interface unless you wish to use all of the functionality of the asp.net membership system.
Would it be better to not try and reinvent the wheel and stick with the standard SqlMembershipProvider built into ASP.NET?
The pragmatic answer for every derivation of this question is to not reinvent the wheel until the wheel doesn't do what you need it to do, how you need it to do it.
if (built in stuff works fine) {
use the built in stuff;
} else {
write your own;
}
if (easier to write your own then figure out how to use another tool) {
write your own;
} else {
use another tool;
}
if (need feature not in the system) {
if (time to extend existing api < time to do it yourself) {
extend api;
} else {
do it yourself;
}
}
I know my answer comes a little bit late, but for future references to other colleagues having the same question.
Here is an example of Custom Authentication and Authorization using Roles as well.
http://www.codeproject.com/Articles/408306/Understanding-and-Implementing-ASP-NET-Custom-Form. It's a very good article, very fresh and recent.
In my opinion, you should have this implementation as part of the infrastructure (Just create a new project Security or whatever you want to call it) and implement this example above there. Then call this mechanism from your Application Layer. Remember that the Application layer controls and orchestrate the whole operation in your application. Domain layer should be concern exclusively about business operations, not about access or data persistence, etc.. It's ignorant on how you authenticate people in your system.
Think of a brick and mortar company. The fingerprint access system implemented has nothing to do with this company's operations, but still, it's part of the infrastructure (building). As a matter of fact, it controls who have access to the company, so they can do their respective duties. You don't have two employees, one to scan his fingerprint so the other can walk in and do its job. You have only an Employee with an index finger. For "access" all you need is his finger... So, your repository, if you are going to use the same UserRepository for authentication, should contain a method for authentication. If you decided to use an AccessService instead (this is an application service, not a domain one), you need to include UserRepository so you access that user data, get his finger information (username and password) and compares it with whatever is coming from the form (finger scan). Did I explain myself right?
Most of DDD's situations apply to real life's situations... when it comes to architecture of the software.

Roles for white-label service access

Okay,
I know I'm doing something wrong - but can't figure out a better way.
I am developing a website which is going to allow users to setup their own mini-websites.
Something like Ning.
Also, I have only 1 basic login and access to each mini website is provided (right now) via roles.
So the way I am doing this right now is:
Everytime a new mini website is created - say blah, I create 2 roles in my application.
blah_users and blah_admin
The user creating the mini website is given the role - blah_admin and every other user wanting to join this mini website (or network) is given the role - blah_user.
Anyone can view data from any website. However to add data, one must be a member of that mini site (must have the blah_user role assigned)
The problem that I am facing is that by doing a role based system, I'm having to do loads of stuff manually. Asp.Net 2 controls which work on the User.IsAunthenticated property are basically useless to me now because along with the IsAuthenticated property, I must also check if the user has the proper role.
I'm guessing there is a better way to architect the system but I am not sure how.
Any ideas?
This website is being developed in ASP.Net 2 on IIS 6.
Thanks a tonne!
I afraid standard roles-related stuff of ASP.NET is not what you need. You can try to change authentication module so it will:
Log you in with cookie.
Determine what roles does your visitor have. Perhaps you will use some special table that corresponds user and site.
Make custom principal with user roles enumerated and assign Identity and Principal to the current request.
I also don't think that making special roles for each site is good idea. When you would have hundred sites, you would also have two hundred roles. Pretty unmanageable, I afraid.
When we were solving similar task, we were just not using standard controls. We had single set of roles used on all sites. Membership of concrete user is determined according to current site and his relations to this site.
Addition: Another possibility to investigate is Application that exists in ASP.NET authentication system. Maybe it's possible to isolate each subsite into separate application?
Update: Method that works for our application.
Do not make a lot of cloned roles. Use only two: users and admin. If your sites are public then "users" role could be just global - user on one site doesn't differ from user on another site. If "users" and "everyone" are different roles, then of course "users" should also be bound to a site.
Use standard ASP.NET Membership users, but do not use standard role mechanism.
Make a mechanism for storing relation between site and user. It could be simple table that holds site id, user is and role.
What you have to override is IsInRole method. (Methods to be exact, i'll cover it later). This method is in IPrinciple interface, so you have to make your own principal object. It's quite simple.
Method IsInRole of this type should look take current site (from HttpRequest) look into the site-user table and get roles
Then you have to associate your principal with a request. Do it in PostAuthenticateRequest event.
There is also RoleProvider. Honestly I'm not sure when is it used, but it also have IsInRole method. We can override it in the same way. But other methods of this provider are harder. For example AddUsersToRoles. It accepts array of user names and roles, but to what context (site) should it be added? To current? Not sure, because I don't know when this method is called. So it requires some experiments. I see (Reflector helps) that RopePrincipal by itself uses RoleProvider to fetch list of roles, so maybe it's implement only RoleProvider, using standard principal. For our application this is not a case, so I can't say what problems could be hidden here.

Resources