User Auth in EventSourcing applications - authentication

I'm looking into crafting an app with DDD+CQRS+EventSourcing, and I have some trouble figuring out how to do user auth.
Users are intrinsically part of my domain, as they are responsible for clients. I'm using ASP.NET MVC 4, and I was looking to just use the SimpleMembership. Since logging in and authorising users is a synchronous operation, how is this tackled in an eventually consistent architecture?
Will I have to roll my own auth system where I keep denormalized auth tables on the read side? How to handle the security of this? Will I end up storing password hashes in both my event store and my view tables?
So many questions, if anyone can shed some light, I would be very thankful :)
tldr; How do you do User Auth in EventSource-applications?

Not every "Domain" or business component has to use DDD or CQRS. In most cases, user information is really cruddy, so you can usually not use DDD for that. Other domains don't really depend on the actual user. There's usually a correlation id (UserId) that gets shared by the various domains.
If using messaging in your system, one option is to register and manage users without CQRS, then send a command (RegisterUser { UserId } ). This would publish an event User Registered. Other domains can listen to this event to kick-off any workflows or ARs that are needed.

For our MVC CQRS app, we originally started off keeping all the user related information in the domain, and, like somebody mentioned, there was a RegisterUserCommand and a UserRegisteredEvent. After storing the user information in the domain, that event got published and picked up on the read side, which also created a user and generated all the password hashes, etc. We then done the authentication on the read side: the controller would make a call out to a 'read model authentication service' to authenticate against.
Later on down the road, we ended up completely refactoring this. It turned out that we needed access to the user related information to build in security for authorising our commands, which we done on the command processing side (our app is a distributed app that sends 'fire and forget' asynchronous commands to a queue, with an autonomous listener on the other side). The security component then needed a reference to our domain to go and get the user profile, which led to cumbersome referencing issues.
We decided to put the user security stuff into a separate database that we considered to be more of a central component, rather than belonging to the domain or read model. We still maintain user profile related information in the domain and read models (e.g. job title, twitter account URL etc.), but all the security related stuff, like password hashes, are stored in this central database. That's then accessible with a service, that's available to both MVC and the command authoriser.
We didn't actually have to change anything in the UI for this refactor, as we just called the service to register the users from the register user command handler. If you're going to do it that way, you need to be careful here to make your user service related operations idempotent. This is so that you can give your commands the opportunity to be retried without side effects, because you're updating 2 sources of information (the ES and the user database).
Finally, you could of course use the membership providers for this central component, but there can be pitfalls with that. We ended up just writing our own - it's pretty simple to do. That article links to this, which provides a good example of how to implement it.

You should consider creating separate entities like: visitor (just visited your site), user (registered), customer (bought something), etc. Try to split your system in this way, even if it causes a little bit of data redundancy. Disk space is not an issue but ability to modify different components of the system independently is usually very critical.
People create denormalized auth tables only for the purpose of scaling and only if your auth read side is a performance bottleneck. If not - usual 3rd normal form is a way to go.
In SimpleMembership scenario all tables created by SimpleMembership can be viewed as snapshot of "user" aggregate. And yes, they will duplicate some data in your event store.
You may have events like: UserCreated, UserUpdated, UserAssignedToRole, etc.
And don't be tricked by the name of that membership provider. It's not so simple and usually has lots of things that you can easily live without (depends on your domain). So, maybe you can use something like this: https://gist.github.com/Kayli/fe73769f19fdff40c3a7

Related

Is it better to handle user and authentication logic separated or together?

I am currently developing a codebase for all mobile projects developed by our team.
One of the main services I'm working on is the authentication service, but I am unsure about whether to treat authentication and the user together or separated, understanding authentication as all the process of obtaining and storing the authentication token (sign in, sign up and sign out), and user as the instance of that user, all its data and all the methods linked to it (CRUD of the user and related content).
You really want to think about authentication and authorization separately if you can. For small enough project's it's worth consolidating, but the more separation you can include the better for the future.
Just to baseline:
Authentication => Who are you?
Authorization => What can you do?
Authentication paradigms are almost always (these days) external, from SAML, to FIDO2, to whatever comes next... It's going to be a moving target, and you DON'T want your authorization scheme tightly tied to it. Authorization is almost always an internal concern, and should not be tied to the flavor of the week that is authentication. Not to mention the fact that it is a near certainty that you will soon be supporting multiple authentication protocols simultaneously (you aren't already?), and embedding roles based on that auth is a messy thing at best.
Also, you are at some point going to need to do something horrible, like dumping your user database and moving to a new provider. Don't make that even messier by putting all your authorization logic in there.
Finally, testing is immensely easier when you can mock authorization without authentication. Test cases will dramatically simplify if you can "impersonate" a different role on demand.
In any reasonably large/complex product you will have multiple domain views onto a user.
Each of these views will translate into separately stored data and logic/services for each view. The key being separation of concerns.
In order to make sure the different views can be connected it is useful to have a common identifier for a user that you may want to pass between services. But you may not need to pass a lot of additional information across the services. For example the domain services do not need to know about passwords etc.
Even in your question an authentication service may be separate from an authorization service may be separate from anything else, etc.

Restrict access of a connected app (Salesforce)

What is the best way to restrict the scope of a connected app to a set of objects? My current solution is to use the Manage user data via APIs scope but that still grants more access than required.
A solution I see frequently is to create a user with a restricted profile and connect with that user but then you lose context of actions made by users in the connected app so this solution doesn't work
Tricky, you typically don't. (consider posting on https://salesforce.stackexchange.com/, there might be a clever way I didn't think of).
You can flip the connected app from "all users can self authorise" to "admin-approved users are preauthorised" and then allow only certain profiles / permission sets to use the app. But the bulk of it is "just" enabling the connection via API and cutting it to say Chatter only or OpenId identifiers. And that's already an improvement compared to SOAP APIs where you don't have scopes and the app can completely impersonate the user, do everything they can do in UI.
Profiles/permission sets/sharing rules are "the" way even in not immediately obvious situations like Lighting Connect Salesforce to Salesforce or Named Credentials access to another org.
If you can't restrict the visibility with profiles and access to all tables user can see is not acceptable...
you could create series of Apex classes exposing certain queries, updates etc and grant profile access to these classes - but without full api access? You could even let them pass any SOQL (evil) but use with sharing, WITH SECURITY_ENFORCED, stripInaccessible + custom restriction on tables before returning results
you could look into https://developer.salesforce.com/docs/atlas.en-us.238.0.apexref.meta/apexref/apex_class_Auth_ConnectedAppPlugin.htm although I suspect it's run only on connect, not on every request. So at best you could deny access if user has right to see some sensitive data, not great
if there are few objects you need to block updates if done via app - Quiddity might be the way to go. Throw error in a trigger if action started from REST context?
give the Transaction Security trailhead a go. If it looks promising (there's way to check "application" and "queried entities" according to this) - might be a solution. You'll likely have to cough up $ though, last time I checked the cool bits of event monitoring & transaction security were hidden behind an extra paid addon (standalone or bundled with platform encryption and Field Audit Track into Salesforce Shield solution)
2 logins? dedicated user for querying stuff but inserts/updates running as your end user?

Does it make sense to split user identity and profile?

While writing a solution from scratch based on microservice approach (more specifically it is Azure Service Fabric) I came to an idea of splitting the user Identity (which is login credentials, claims, etc.) and user profile (which may contain some social info like avatar, links to social networks, birthday, etc.).
For the identity, I'm going to use IdentityServer4 (stateless ASP.Net Core) and for storing all these data I'm thinking of an Entity Framework + SQL. The profile will be managed and stored on different microservice (stateless as well) with a connection to Cosmos DB (via Mongo DB API), thus making it a NoSQL storage.
Are there any disadvantages of such an approach I'm not aware of?
You're conflating a bunch of things here. First, you have your actual "user" entity persisted to the database. There is no good reason to split a "profile" from this, as it's all just data about the user. If you're using Identity to manage users, roles and such, it was designed to be extensible from the ground up, meaning put user data on the user entity. A separate profile entity only serves to necessitate an join for no purpose.
At a higher level, once the user has been authenticated (via Identity Server), you have a principal. That principal is basically just a set of claims tied to a particular "identity" (i.e. the authenticated user). The claims come from multiple places, it could be data on the user record, roles, or even third-party claims such as when an external login account is utilized. Where the claims come from is mostly inconsequential.
Long and short, there's no reason for a separate profile entity and especially no reason for an entirely different service to work with profiles. That profile service would inevitably have to utilize a user service, so there's a hard dependency between the two: a clear sign that it's no a true separate service. In fact, this only makes the rest of your app that much more complicated as then you're having to work with both a user service and profile service depending on what piece of the user you're after.

GunDB user authentication and data storage among users

I have been following your project for quite some time now and am intrigued by the functionality of gunDB where it doesn't require a database in between and keeps security in check.
However, I've got some questions about GunDB which I've been thinking about for quite some time now before I can give Gun a go with a project I'm currently working on. In this project it is necessary that data is safe but should also be shareable once a group has been setup. The project is a mobile app project and ata is mostly stored on the device in a SQLite database.
I have been looking into Gun as it allows for better usage of the app in sense of collaboration. The questions I have, however, are:
User authentication
How is user authentication handled through private keys? So how can a user "register" with, for example, a username and password to login to the service.
For authentication I am currently using Firebase where it is possible to use username/password authentication and I would like to know how Gun approaches this case and how it's implemented.
Data storage
In the documentation and on the website it's stated that data is stored locally with every client and can be stored on a "node" or server using either a local hard drive or the Amazon S3 storage option.
What I am curious about is what data is actually stored at the client? Is this only the data he/she has access to or is this a copy of the whole dataset where the client can only access whatever he/she is granted to have access to?
Maintaining your data
When I've got a production system running with a lot of data, how will I be able to manage my data flows and/or help out my clients with issues they have in the system?
In other words, how can I make sure I can keep up with the system if I want to throw in an update and/or service my clients with data issues.
My main concern is the ability to synchronize their local storage correctly.
Those are all my questions for now.
Thank you very much in advance for providing some clarity on these subjects.
Best regards,
(Answered by Mark Nadal on Github: https://github.com/amark/gun/issues/398#issuecomment-320418285)
#sleever great to hear from you! Thanks for finally jumping into the discussion! :D
User Authentication,
this is currently in alpha. If you haven't already seen these links, check them out:
https://github.com/amark/gun/wiki/auth
http://gun.js.org/explainers/data/security.html
https://github.com/amark/gun/blob/master/sea.js#L23-L43
https://github.com/BrockAtkinson/login-riot-gun
If you have already, would love to either (A) get you to alpha test and help push things forward or (B) hear any specific questions you have about it. This thread is also a more at length discussion about alternative security API ideas: #321 .
Data storage.
Browser peers by default store the data that they subscribe to, not the full data set. You could ask it to store everything, but the browser wouldn't like that. Meanwhile NodeJS peers, especially if hooked up to S3 or others, would store all data and act as a backup.
Does this make data insecure? No, encryption should keep it secure, even if anybody/everybody stores it, the encryption makes it safe. (See [insert link to (1)] for more information).
Maintenance.
You would service your customers by deploying an update to your app code. It would not be ideal for your customers if you could meddle with their data directly. If they wanted you to do that, my recommendation would be that they change their password, give the new password to you, and you login and make any necessary changes. Why? Because if you have admin access to their data, their privacy is fundamentally violated.

Where should I put CAS session checking code in a CakePHP application?

I work for a department of a university that uses CAS to provide single-sign-on authentication, and am writing a CakePHP application that needs to use this CAS service. I need to write code that:
Checks with the CAS server to see if the user is logged in
Pulls some credentials from the server if so
Checks the credentials against an internal ACL, as the set of people who can access the application is a subset of the set that can log into the CAS service.
Provides some mechanism for admin users, either by creating special admin users outside the CAS system (with all the headaches that would entail) or by promoting certain CAS users (with the different headaches that would entail).
As a relative newcomer to CakePHP, I frequently struggle with where to stick code that "doesn't belong". The best I can figure is that this code ought to go in the beforeFilter method of the App Controller, but I wonder, is this the best place for it? Also, is it too low in the stack to take advantage of admin routing?
Lastly, I know that CakePHP provides both Auth and ACL components, but when I looked into using them they did not appear amenable to interfacing with outside authentication services. Am I wrong, and would either of these be a good fit for what I need to do?
Thanks!
If you take a look at the Cake's core components you can see that your CAS requirement fits with the type of things components are typically used for (ie. auth/session).
I would recommend creating a CasAuthComponent. There is some information on extending AuthComponent, in a previous answer of mine, which may prove useful if you wish to build on top of the existing core AuthComponent.
A component (essentially reusable controller code) can interact with models, use other components (such as Session) and control user flow (redirects for example)
Note that, the core AuthComponent actually retrieves information from a model (the User model by default), so you could do something similar.
The CasAuthComponent you create could $use an external user model (CasUser maybe) which is responsible for CRUD operations on the data (retrieving users mainly).
You could take this one step further and abstract CAS interactions into a datasource used by this model, but it isn't strictly neccessary if you don't plan on reusing the code in other models.
The end result could be packaged into a plugin:
CasAuthComponent (app/plugins/cas/controllers/components/cas_auth.php)
CasUser (app/plugins/cas/models/cas_user.php)
CasSource (app/plugins/cas/models/datasources/cas_source.php) [optional]
And used in your application by putting the following in your app_controller:
public $components = array('Cas.CasAuthComponent');
If you wish to be able to administer the users from Cake, you can also include a controller and views in your plugin, which allow the user to interact with the CasUser model (ie. $this->CasUser->save()).