RavenDb Authorization + SOA - authorization

The question I have is that of securing documents across services using RavenDb and the Authorization bundle:
I have an 'Account' service which is responsible for managing all things 'user'.
I have a 'Messaging' service which is responsible for all things 'messaging' i.e. wall posts, conversations etc.
To trace who did what in this service, when a new message is posted I create the message and two UserProxy objects (cut down User objects which only have UserId and UserName properties - these are stored as child objects on the WallPost doc so they aren't documents in their own right)
When a user posts something to another users wall i only want to allow:
delete/edit to the original poster, the recipient and admins
view to original poster, recipient, admins and all friends of the recipient
I also have a media service which is responsible for images/video, a MusicEvent service for all things music event - they all need to have a similar setup.
My question is this:
*should the account service store the master User with Roles and Permissions - when it is asked for a user it can send back a dto with the roles and permissions (could get chunky)
*should the Messaging Service maintain it's own copy of a User - with it's own set of roles and permissions?
first is simpler moving forward as it's centralised - but looks a bit dodgy to me
second is probably better but the issue comes when the AccountService changes the username - i can send an event to the esb and have all the relevant services pick it up and take care of the update - but that sounds complicated.
FTR - i'm swaying to option 2 - the non-centralised method.

Personally, I would think about introducing a third service - e.g. IT / Administration service that would be responsible for Roles and Permissions. Its strikes me that these are different business functions / capabilities to those described in Account or Messaging services. A service responsible for that type of functionality would decouple the security aspects of your services from the actual functional areas of Accounts and Messaging. Accounts could still remain the owner of Account information. The messaging service really only needs to identify the user and so using user id / username here is sufficient, unless it nees aditional user information to do its work (email address perhaps). Its ok to duplicate data in this instance, as long as Accounts remains the owner of information.

Ayende answered this for me quite nicely on his blog:
http://ayende.com/Blog/archive/2011/02/17/distributed-authorization-with-ravendb.aspx

Related

How to manage user updates and deletions in OIDC and SPA architecture

i am making a set of applications that share a common oidc provider (in my control), where the users will be created.
One of my applications is a stateless SPA "meeting" app where you can schedule meetings with other users, and you login purely by an OIDC token.
I am having a hard time thinking a strategy about the following
Should the "user" details be stored in the meeting app after a login? So let's say user A exists in the provider, then enters the meeting app. Should i save user A in the meeting app DB?
How to handle change of user details? Let's say user A changes name to User B in the provider. Until he logs in again, all the other users see him as User A still in the "contacts" list. What is the usual practice for solving this?
How to handle deletions in the provider. I need someway to signal that "deleted in provider -> deleted in app". Should i constantly poll the provider and get any missing users, create a push system, or is this just unneeded?
Thanks a lot in advance
That's actually a very good question and rarely explained well in online articles. Hopefully the below detailed notes help you with your solution. I have answered your questions at the end.
OAUTH USER DATA
Typically the core user data such as name, email etc belongs in the Authorization Server. It contains Personally Identifiable Information (PII) and changes are audited there. This is explored in further detail in the Privacy and GDPR article.
DOMAIN SPECIFIC USER DATA
This might include fields like a user's application preferences, and you may end up with data similar to this in your APIs:
Field
Description
id
A database surrogate key for the user
subject
The subject claim from an OAuth access token, which is typically a GUID or something similar
archived
A boolean flag set to true when a user is active in the app
field 1
A domain specific value
field 2
A domain specific value
To get OAuth user data within your applications your APIs can call the Authorization Server's SCIM 2.0 endpoint as described in this User Management article.
AUTHORIZATION AND ROLES
Interestingly, roles and application specific rights could be stored in either of the above data sources. You may want to start by putting roles in the OAuth data, but for cases where they are very domain specific and change often, I have found that storing them in my own API data works best.
DOMAIN SPECIFIC USER DATA AND ACCESS TOKENS
Sometimes you need to include domain specific user data (which might include roles) in access tokens. This Claims Article explains how claims can be looked up from external APIs during token issuance. This typically involves a REST call from the Authorization Server to one or more APIs, providing the subject value for which tokens will be issued.
CONSISTENT USER IDENTITY IN YOUR APPS
A user can potentially authenticate in multiple ways, such as default password / corporate login / social login. You may need to use some custom Account Linking logic to ensure that the subject field in the access token gets the same value in all cases. This prevents you ever creating duplicate users within your application.
USER INFO CHANGES
These are typically made by end users within an application screen, and your APIs then call SCIM endpoints to update the core OAuth data. A common case is when a user changes their name and / or email, eg if the user gets married. Note that the subject value remains the same after this edit.
USER ADMINISTRATION
In scenarios where corporate assets are used, an administrator typically provisions users, either individually or in bulk. This can be done via the SCIM endpoint. In some cases administrator actions may need to save data to both data sources - eg to create a user and set roles + application preferences.
USER INFO EVENTS
Sometimes your application needs to know about a user info event, such as new, deleted or changed users. This can be managed via Event Listeners, where an extension to the Authorization Server calls back your domain specific APIs when a user edit occurs. When a user is deleted in the OAuth user data you might then update the user's application state to archived.
DATA MIGRATIONS
Finally it is worth mentioning that the above also supports migrating to an OAuth architecture or between providers:
Get a combined view of the user data before migration
Insert all existing users into the new OAuth system via SCIM
Update the combined view of the user data with new subject values
Update your domain specific data with new subject values
SUMMARY
So to answer your questions:
Aim to avoid this because it adds complexity, though in some cases you may need to denormalise for performance reasons. The OAuth user data should remain the source of truth and the only place where edits occur to PII data.
Your meeting app would need to join on the OAuth user data and domain specific user data and present a list. This would probably involve caching a combined view of the user data.
See Administrator Events above. Your API should be informed of OAuth user data changes via an event, then your SPA would get current data on the next refresh.
When implemented like this you end up with simple code and a well defined architecture. Some providers may not provide all of these features though, in which case you may need an alternative approach to some areas.

implementation of object level raw permissions inside microservice architecture

I have a bunch of microservices running. I have an api gateway that connect consumers to all these services. Now on some services I need to give permission to certain users ( users are stored in separate Users Service ). For example if I have a blog service I need to give blog 1, blog 2 and blog 3 view permissions only to user 1 and not to user 2 ( the scenario is acl rather than RBAC or ABAC i think, correct me if i am worng ). Now how should i implement the permission system.
For example If store the permission on each entity object inside each microservice as suggested here then each of my service has to know about users also to grant them permissions. this scenario will compel me to synchronize the users data across all microservices ( on users delete update ... ).
Another Solution is to create a separate generic authorization service to manage all services permissions. but this solution will require me to save each microservice schema ( and have to synchronize that schema on change )
Or there is any other solution. please help. how to implement ACL (authorization)
One solution would be to introduce userID into the downstream path from the gateway. So the path
GET /blogs/{blogId}
is exposed on the gateway, but this becomes
GET /blogs/{userId}/{blogId}
on the blogs microservice. The gateway handles the user's bearer token and injects the user's ID into the downstrteam call. The blogs microservice would then return the blog for a "valid" path, or a 404 if the path was not valid.
This is illustrated here:
the backend service maintains which users have access to which blogs?
The blog microservice stores and manages blogs. A blog can have an access list associated with it. That list may contain only the user who is the blog owner, or more than one user. The point is that the ACL is not centralised, but distributed with each blog's data containing it.
if a user is deleted
Then you have two choices. If the user is deleted you publish a UserDeleted event, to which the blogs service is subscribed. Then you can manage all the blogs which have the user in their ACL and remove them. Or, you can do nothing. I would personally choose the latter; one of the features of having a microservice architecture is that some data will not be consistent. If you require absolute consistency then you can have a "caretaker" process which removes deleted users out of blog ACLs. Or don't use microservices.

Setting user notes in Skype for business

I'm looking at building a tool that can set the notes for other users on my company's local Skype for business server, providing automated note updates for participating users in my program.
I've found https://msdn.microsoft.com/en-us/skype/ucwa/setmynoteinformation - which provides guidelines on how to set a user's own personal note. Is there an endpoint that an application (with the appropriate permissions) could access to do something similar for other users?
I see the UCWA documentation for https://msdn.microsoft.com/en-us/skype/ucwa/contactnote_ref - but this appears to be a single user centric API for reading a contact's notes. TrustedApplicationAPI looks to mostly relate to meetings - https://ucwa.skype.com/trustedapplicationapi/reference/Resources.html
Is this something that can be done through a REST interface?
Not with UCWA, which isn't designed for doing operations on-behalf-of user; and so will require you to impersonate the user you want to update the note for.
The only option for you will be running a UCMA instance for the purpose (if you're on-premises), and expose that functionality via a custom REST service

Fiware-Orion: Access control on a per subscription basis

I would like to know if the following scenario is possible:
A Fiware Orion Context Broker instance, to which different data providers connect to publish their data. For each data item (context), the particular data provider should be able to control which application or data consumer is allowed to subscribe to this context. Is this possible with Orion? How can this be done?
I've looked into the multitenant model, but I guess that is not the proper way to do this. Am I right? Are there any alternatives? You can protect the Orion instance with a PEP proxy, but I guess it does not allow access control on a per subscription basis.
Any hints would be highly appreciated.
The scenario that you propose can be implemented, if I understood correctly, with Steelskin PEP Proxy and the multitenant mechanism (but with some concerns).
In your scenario, your whole application would be a service (indicated in all transactions with the fiware-service), and each data-provider would own a dedicated subservice (indicated with the fiwareservicepath header). All the users (both administrator from the data-providers and final user and applications) would be users of that service. Using XACML, different permissions can be assigned to each possible action and user in different roles. E.g.: you can create a dataProvider role with full permissions under its subservice and a dataConsumer role that should be able just to subscribe and read.
This scenario has some problems, mainly concerning who creates the users and roles and assign roles to users. In order to use Steelskin, you have to map services to Keystone Domains and subservices to Keystone Projects; and users belong to the domain. It's the domain (service) administrator the one in charge of creating the users, so, in your case, data providers would not be able to create new users (and probably, even assigning them as subservice customers).
If you need an example on how to connect these pieces together to achieve this, take a look at:
https://github.com/telefonicaid/fiware-pep-steelskin/blob/master/keystoneInstallation.md
Hope it helps

User Auth in EventSourcing applications

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