IdenityServer in an enterprise environment - Resolve user information across multiple databases - asp.net-web-api

We use the IdentityServer3 as our central authentication provider. Now I have a general question about the IdenityServer in an enterprise environment. I try to explain it with the following example:
If a user was successfully authenticated, he get a token from the provider. The token includes the unique ID of the user.
The authenticated user send a request to a WebApi, to create a new item (e.g a new product).
The WebApi extract the unique ID from the token and creates the new product in the database. Additionally the new product was linked with the unique user ID (e.g as creationUserId).
An other user send a request to the WebApi to get all available products.
The WebApi create a database query to retrieve all products. Additionally the WebApi wants to convert the creationUserId of each product to the correlating username. But that is not possible, because username is stored in the identity database which is an other database one than the application database (e.g for the products). Are there some best practices to solve this requirement?
Many thanks for your help!
Regards

Thank you for your answers. I see only one way to realize my requirements:
--> I store the username with the userId in the application database, because a API for translating is to slow.

Related

How to choose the best strategy to configure role-based authorization using AWS Cognito User pools?

I'm building an Angular 11 app with AWS Amplify as the backend which uses Appsync, dynamodb and a managed GraphQL API. I'm using the cognito user pools to authenticate. Authentication works neatly, but I am really confused about how to go about doing role-based authorization. I haven't done this using cognito before but I have a strategy in mind that should theoretically work out. I would like advice on if there is a better way to do this:-
Requirements:-
The app will be used by members of organisations that we are partnering with. Every member will be tied to an organisation. So organisations have their own table and so do members. Members of an organisation can only access content related to their organisation. So right after authentication, the client app has to get the id of the organisation the current user belongs to and also the role they play in that organisation to show/hide UI resources and filter data. Which UI resources they can access depends on the role they play in that organisation and of course the data they see there has to be restricted to what is related to their organisation.
This is a controlled beta release of our application, so Cognito user pools uses email and password to login. No other login option is provided for the sake of keeping things simple. User sign up is not possible. Only admins can add new users for now.
How I plan to do this:-
Cognito API is integrated to the client and the admin will add the
new members from the client UI and the client will add them to the
cognito user pool via the Cognito API
While adding the new members, the admin will specify which
organisation they belong to and what role they play in it. But the
organisation and role are not details that are stored within the
user pools. There is a separate dynamodb table called "members"
which stores these information because these can change frequently
and need to be flexible.
Additions made to the Cognito user pool trigger a lambda function
that automatically syncronizes the "members" table in the amplify
backend in a dynamoDB table with the new additions to the user pool.
So when the admin adds a new user from the client UI, they
fill out a form with the email ID, name, organisation and role of
the new user, and the client UI will create that user with the name
and email ID in the user pool via the cognito API. Once that request
returns the user's ID (remember it will also trigger the creation of
a record in the member's table via the lambda funciton), we create a
mutation to the member's table adding the organisation and the role to the user's record in the member table.
Cognito user pool only has the email ID, name and user ID and
nothing else, all other information is stored in the members table,
which also has the ID, and name (for human reference) but not the
Email ID. We will not be holding the same information in
these two tables to avoid redundancy.
Updates to the email ID can be made by individual users via the
client app which will do it in the cognito user pool via the cognito
API. And no updates need to be made to the member table after email
update since the member table doesn't have the email ID. All other
member details can be made to the members table via the client app.
When the user logs in, as soon as the cognito UI authenticates the
user and sends over the email ID and user id, we fetch the member
details from the member table using the user ID and get details such as their name,
organisation they belong to and their role. And using the
information on their role, we can restrict UI resources using flags
in the UI Code. To achieve this, there will be a separate table that
will let the admin user modify access to the UI resources for each
role. So we'll need to fetch the role and the associated UI tags
right after authentication as well.
And as for how data is filtered as per the organisation, I am not
sure yet, but I would like to use an authorizer that will be
specified using a function in the graphql schema itself, that will
get the organisation ID with each request and use that to filter the
data before returning to the client.
Not sure if this process is solid, but this is what I was able to fathom. Please let me know if I am doing this in a sensible way or if there are better ways to achieve what I am doing.

How to handle authorization for a non-user based Laravel API?

I have a Laravel web application for a restaurant with its own user base.
I have another web application for a bookstore with its own different user base.
I would like to create a third application (mostly API, probably using Lumen) that can create accounting records from both the restaurant and the bookstore on every transaction that is made (i.e. when I sell any food, make a POST request to this API to insert a record, and do the same if I sell a book).
How can I guarantee that only authorized users from my web apps (any user) can make requests to my API, without asking them for any additional password?
This is a typical use case for the client credentials grant tokens oauth flow.
From the laravel passport documentation:
The client credentials grant is suitable for machine-to-machine authentication. For example, you might use this grant in a scheduled job which is performing maintenance tasks over an API. 
You can create an api-key for each user that has to be present in the post request's header. There should be a table in the API that has these keys stored with the corresponding user_id.
As such you can identify each user based on the given api-key.

MVC Multi Tennat Application how to add sub site

I have an intranet application for which the URL is as follows
http:\\ServerName]\RunLog\
I am adding another department/tenant/group of users which will utilize the same instance of the application and same database. Their data will be different from the existing users. I am planning to add new column foreign key in each table to identify the specific tenant. I authenticate users windows authentication. I am thinking that the access to the application will be as follows
http:\[ServerName]\Platform1\RunLog
http:\[ServerName]\Platform2\RunLog
So for the above URL, how could I go about achieving that in the Application? I know how to make the table changes in SQL server, Updating the Entities, Updating the linq code in the controllers to pull up respective tennant data. Any help to get me started would be appriciated.
Kindly note that as you have given in your post, it is possible to identify the tenant's based on their URL. The table that contains the tenant details will also contain their url. So you will identify the tenant based on the URL. After identifying the tenant, we can authenticate the user's using the found tenant id / tenant code, get the tenant's configuration or settings using the same tenant id / tenant code.
I hope that you could have all the other entities of the application with a column called as TenantId. This will help you to fetch the data based on tenant. Your only change will be in the data access layer where you will filter the data that you retrieve from the Database.
Let me know if you have any other clarifications regarding the other specifics of this implementation.

Extending WSO2 Identity Server JDBCUserStoreManager to fit external user database

We have a requirement to authenticate users of a web application deployed in WSO2 Application Server against an existing external database. We are trying using WSO2 Identity Server for this.
Our db table containing users has two columns which make a username unique, clientid and usercode. i.e. usercode is not unique by itself but clientid+usercode is unique. Also our passwords are salted with PBKDF2. So I have extended the JDBCUserStoreManager to talk to our database and am able to store and retrieve passwords in PBKDF2.
But I cant figure out how I can get the client id from the login page to our extended JDBCUserStoreManager. i.e how can I access clientid stored in users session, from inside our custom JDBCUserStoreManager? If I can get the clientid from the session in there, I can use it in the sql queries to do the needful.
Any help in figuring this out is much appreciated..
You can enter the combination "clientid+usercode" as the username at the login page. Then the authenticator will pass that combination as the username to the doAuthenticate() method of your custom userstore manager. There you can split the client id and usercode from the username.

ASP.NET MVC3 / User registration, membership, roles and privilege

In my application I need to register users. The users can be any of three: admin, client and general. They have different attributes (Admin may have only name, client may have company address and so on). The default MVC membership scheme is okay but how can it be extended to register more information during registration time? Or should I use custom membership?
I need to have a record of clients and general users with clientID or generalID.
The default MVC membership scheme is okay but how can it be extended
to register more information during registration time? Or should I use
custom membership?
I think too many people, yourself included, are expecting to get too much from the default ASP.NET Membership Provider. It was never designed to handle application-specific things, like what company your customer works for, your admin's name, and so on. It's main purpose is storing passwords for authentication.
Sure, the password needs to be linked to a username, so that there can be a 2-key authentication pair. Sometimes you also need the user's email address, when it is different from their username, in order to contact the user regarding their password. But don't store anything else about your users in the membership store. Store it in your application database.
In order to join data between your application and the membership provider, use the membership provider's UserName or ProviderKey as a column in one of your database tables. You end up with 2 entities which are not explicitly related. You can even have your SqlMembershipProvider implemented in a separate database from your application database. Even if they are in the same database, avoid having a foreign key between any of the provider tables and your application tables. This muddies the waters between what you own, and what you "outsource" to the membership provider.
You end up with 2 physically isolated representations of your user. One is the MembershipProvider, which contains a password for your user. The other is your application, which contains other business-specific details. The two are only logically associated within your application. After you authenticate a user with the membership API, their UserName and/pr ProviderKey become available to your application. You can then use that piece of data to query your app database and get the additional details. This is where you might put something like the clientID or generalID you mentioned.
If you look at the System.Web.Security.Member* API, this should make things clearer. It does one thing really well -- associating your users with passwords and other information related to password resetting (like the email address, question and answer, etc). So outsource just the password provider, and rely on your application to do the important stuff.
You could customise the default profile provider or create your own... Follow this reference
http://msdn.microsoft.com/en-us/library/8zs47k7y
You can add new properties to the profile for anything in the web.config too
I highly suggest creating your own membership roles. It's dead simple and nothing can beat the flexibility of having your own implementation.
Here's a video I made a while back showing you step by step how to achieve this:
http://www.youtube.com/watch?v=BsxUsyMSGeA
The gist of it is, you create your own AuthorizeAttribute and create your own roles; protecting each controller or even individual Action methods along the way.
The one drawback of this approach is that you can determine what Role a user has in your system, but not what a Role can do in your system. Does that make sense?
There are other choices if you need to edit what a role can do at runtime.

Resources