Identity Server - multiple STS - microservices

I have two groups of api applications (group 1: api11, api12; group 2: api21, api22) that are used by two different groups od javascript applications (group 1 and group 2). Each api group has different domain and use different instance of Identity Server (also each identity server has different domain). Business requirement is that user logged in to any application from group 1 can use any app from this group but can't use app or api from group 2.
Under the hood both api1 and api2 often needs to talk to the same microservices. What I want to achive is to make microservices accessible with access tokens issued from any of the identity servers (used by group 1 or group 2 app). Is there any way to achieve this? For one identity server I can use UseIdentityServerBearerTokenAuthentication but as argument I can pass only one Authority there.

It is not directly possible (see this issue)
But you probably need to rethink your architecture. Assuming the business requirement (Business requirement is that user logged in to any application from group 1 can use any app from this group but can't use app or api from group 2.) is non negotiable, what you are trying to achieve may be dangerous if these microservices are handling something very particular to one or the other group (ie, I am talking about multitenancy here)
The right approach in your case would be to have separate instances of microservices, dedicated to different groups, ideally running in their own containers or VMs

So I think this should be possible although whether you really want to do it or not is another question! I haven't tried this but you'd need to do something along the lines of:
Use the same signing certificate from both IdentityServers
To validate your JWTs, use the Microsoft extension "UseJwtBearerAuthentication" instead of using the IdentityServer validator (which is set with the UseIdentityServerAuthentication extension not UseIdentityServerBearerTokenAuthentication - the latter is IdentityServer3 I think). IdentityServer uses the Microsoft validator under the hood anyway, code and docs:
Our authentication middleware serves the same purpose as the above middleware (in fact it uses the Microsoft JWT middleware internally)
The reason for using the Microsoft validator directly is that now you can avoid setting the authority when you set it up, this would normally be used to validate the "iss" (issuer) as part of validating the JWT. Instead you can configure multiple valid issuers (i.e. your two IdentityServers) and point the validator directly at the signing cert that you are using in step 1:
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidIssuers = new[]
{
"http://my_first_IdentityServer/",
"http://my_second_IdentityServer/"
},
IssuerSigningKey = new X509SecurityKey(new X509Certificate2(certLocation))
};
app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
Audience = "http://localhost:5001/",
AutomaticAuthenticate = true,
TokenValidationParameters = tokenValidationParameters
});
The above is adapted from the article here. As it says in the article, you could equally (and preferably) use a certificate store rather than a cert file.
Btw, we're obviously talking authentication here, how you authorise users across the APIs will no doubt add extra complexity.

Related

How to use Multiple Passport Personal Access Clients for different Auth Guards

Passport 10:0
Laravel 9.0
php 8.1
Description
Thankyou in advance. My application has four user types and uses multiple guards for each, i.e, admins, agents, companies, and normal users. All of these guards use API authentication via personal access clients, and tokens are generated for each user type like so;
$user->createToken('TOKEN_NAME')->accessToken;
This worked well, until I ran into an issue where two users of different types, say Admin and Company, having the same id, say 1, could share tokens. The admin user would pass company middleware and vice versa. The issue is discussed in this #Question
The solution proposed in that discussion is to create separate personal access clients for each guard, and to use the different clients to generate access tokens, which makes sense.
To generate access tokens using the different clients, however, i have to clear the resolved ClientRepository instance and register a new singleton instance, like so;
use Laravel\Passport\ClientRepository;
App::clearResolvedInstance(ClientRepository::class);
app()->singleton(ClientRepository::class, function () {
return new ClientRepository(client_id, null); // client secret ignored for this use case
});
$token = $user->createToken('TOKEN-NAME')->accessToken;
Is there a cleaner way of doing this? Is it possible to set or override a ClientRepository property on the Admin::class model such that every call to createToken() by an Admin instance uses the set client?

Can multi-tenancy in Keycloak be done within a single realm?

First, I'm well aware of the multi-realm approach to multi-tenancy in Keycloak. I've taken over a legacy project where nobody thought of multi-tenancy. Now, two years later, suddenly, the customer needs this feature. Actually, the microservices are prepared for this scenario out-of-the-box.
The customer develops a mobile app that authenticates users via API on our keycloak instance with an account number (as username) and a password. Now, he'd like to add an tenant id to the login information.
The customer wants to avoid using several endpoints as a multi-realm solution would demand.
One first idea was to just concatenate tenant-id and account-id on registration. But that's a smelly approach.
So, my thought was that there may be a way to configure Keycloak in a way that I add a custom tenantid field together with username that acts just like a composite primary key in the database world.
Is such a configuration possible? Is there another way to achieve multi-tenancy behaviour using a single realm?
I can't say for sure, but after some research, I found this:
This website lists all of this together with more information:
https://lists.jboss.org/pipermail/keycloak-user/2017-June/010854.html
Check it out, it may help with your data organization in key-cloak.
Late to the party. But maybe for others who are interested. You could try the keycloak extension keycloak-orgs. I am currently building a test stack with it and I am pleased.
A tenant in keycloak-orgs is an organization. You can map organizations and their roles to token claims with a built-in mapper.
"organizations": {
"5aeb9aeb-97a3-4deb-af9f-516615b59a2d" : {
"name": "foo",
"roles": [ "admin", "viewer" ]
}
}
The extension comes w/ an admin interface. From there you can create organizations and assign users to it. There is also a well-documented REST API on the Phase Two homepage (the company who open-sourced the project).
The maintainers provide a keycloak docker image that has the relevant keycloak extensions installed.
If you want a single realm and singe client that serves many tenants, you can just use custom user attribute and e.g. add key(s) "tenant=MyTenant" and then add a client scope and a mapper to include user attributes that has key=tenant
Then the token will carry the user's tenant(s) and you can use that to filter data, add to newly created data etc.
It's only like 4 steps in Keycloak:
Add User attributes using a key-convention.
Add a Client scope that will represent tenants.
Add a mapper to extract the User attributes.
Add Client scope to the Client in use.
Wrote about it here: https://danielwertheim.se/keycloak-and-multi-tenancy-using-single-realm/

Separate access in one app with keycloak

I have the following setup - the Spring SAAS REST service, which allows different companies to manage different events. And there is a rest client (a mobile app) also, shipped separately for each company.
I want to use keycloak for security stuff, and I have a question of how to separate one company from another.
I need companyA to not be able to access companyB event, and also need different roles within the company - some can create events, some can only read it.
First I thought each company will have own realm created in keycloak, but I learned that realm actually specified in the spring boot REST service parameters like
keycloak.realm=demo-realm
Which means it is only one realm per REST application. And I don't want to configure REST service instance per client. I only want one REST rule them all.
Am I trying to use something which really doesn't fit my use case?
Will it be right way to have a keycloack Group configured for each company, and make a logic in such a way that users of one group won't have access to what is created by other group. But then it actually feels wrong, since as I understand group are supposed to be used in a different way - to have admin group and user group, etc, segregating users "vertically" by "privileges", and not "horizontally".
Can you please suggest a right approach for this problem?
I would implement a custom protocol mapper which loads extra user permissions for your application and stores them in a token. This way, you use a single realm and if there are more companies in the future it scales well. Here you've got an example of how to implement it.
Basically, the otherClaims field of the access token is a JSON field that allows a map of properties to be set. You could add a field here such as:
userAccessibleCompanyIds: [1,3,4]
How to load the company ids for the concrete user? You can access your application database from the mapper or get them using the REST API.
Then in your application you need to have a control of what the user accesses. What I do is decode the token and see if the user request suits. If not, return a 403 response.

Web API and .NET 4.5: Claims and rights

Is there a best practice for using claims for right-management?
I am using the new .net 4.5 and the new claim classes.
Currently I do something like that:
new ClaimsIdentity(new List<Claim>
{
new Claim("Username", user.UserName),
new Claim("UserNumber", user.UserNumber.ToString()),
new Claim("Creation_Right", ""),
new Claim("Edit_Right", "")
}
I add the right-claims without a value.
Later I check for the presence of a right. There is no need for a value (like true/false) - if it is present, its implicit 'true'.
Is there a better way to do that?
Perhaps. It looks like what you're doing is merging authentication and authorization together, making an access policy decision at the moment of authentication.
You also have the option of separating your authorization component away from your authentication component. Claims represent a set of information about a user that can be used to make an authorization decision. That is, your autheNtication step produces a set of claims, and whenever your user tries to access something, those claims are fed to the authoriZation component which renders a decision.
This provides some flexibility in that your authorization policy can change and evolve independent of your claims issuance system. For example, you might issue a role claim that identifies someone as an administrator, and you might also issue a authentication method claim that specifies how the user logged on, using a smart card or username and password for example. This gives you power in defining your access policy, you can require just an administrator role for access to some resources, while other more sensitive resources require administrator role AND use of a strong authentication mechanism. It also means you can switch between multiple different access policies depending on context. Your online whiskey store might use an ageOver21 claim on the US, but the Canadian version of your site requires over18 or over19 claims instead. Separating your authZ from your authN allows for this kind of flexibility.

Azure ACS - Best Practice Implementation

We are building an ASP.NET MCV 3 application from scratch running on Windows Azure. About Authentication and Authorization layer we are thinking to use the Access Control Service. I went through some articles about ACS where I got the basic idea but I still have some doubts on it.
My understanding is that using the ACS we outsource the Authentication process to one or more Identity Providers (IP), basically we trust another system (i.e. Microsoft Live ID) to authenticate our users.
The basic process is very straightforward: at authentication stage we redirect (ACS does it) the user to one of our “trusted” IPs, that will redirect the user (with a valid token) to the ACS and eventually to our application.
Here comes a number of questions:
Since we don’t want that all the users with a Live ID account can access to our application, I presume there should be another process to validate that user and checking if he is registered in our application. The question is where? In the ACS or in our application?
I have an idea about this but I don’t know if it’s the right way to do it:
At registration stage, the system (our web app.) asks the user which IP (i.e. Live ID, Google, Facebook, and our app.) he wants to use to authenticate himself in the application. Then the user goes through the authentication process on the IP system and when he comes back, we store his username (IP username) in our DB.
So, next time, at authentication stage we can check if that user is registered in our system.
If the above theory is correct, that means in our app. we need to build our membership provider to store usernames coming from IPs and users that chose our app. as IP.
Am I correct? What is the best practice to design the above process?
Now let’s talk about Authorization and “Roles”. How does it work with ACS? Does ACS manage multiple roles per user?
Again my understanding is that with ACS you can create a number of “Rule groups” related to the IP and not to a single user. If this is correct, how do we manage users in role in our application? Let’s say, for example, that we have multiple roles and our users can be associated to those roles, can we use ASC to manage it?
So the final questions are: Does ACS itself cover the whole Authentication and Authorization process? Do we still need to use the .net Membership Provider? What's the best practice in order to cover our requirements?
For the part of the question about the registration stage, the best thing to use to identify users is the NameIdentifier claim type
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier.
This should be unique for each identity provider and also fixed. If you use the email address claim, it could change for the same user. Technically it could be possible for two identity providers to use the same NameIdentifier (none of the out-of-the-box ones with ACS do) so you could combine the NameIdentifier claim with the IdentityProvider claim type
http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider
to guarantee uniqueness.
For the part about role, I would say using ACS to issue role claims from generic identity like Google would be quite hard to manage using the claim transformation rules in ACS on per user basis. You would have to add a rule for each registered user - probably not feasible. I think the ACS rule groups are more suited to transformation of role claims (e.g. issued by a federated ADFS). Your idea to do it in your application is a better one IMHO. In code, the place to do this using WIF is in a custom ClaimsAuthenticationManager. You override its Authenticate method and based on the NameIdentifier claim from the incoming principle, you look up in your membership datastore and create a new IClaimsPrinciple based on the roles that are in your membership DB (i.e. you add a role claim for each role the user is in).
You then make your authorization decision in a custom ClaimsAuthorizationManager. There are some good samples and info on this around on the web. You can start at
http://msdn.microsoft.com/en-us/library/ee748497.aspx
The user validation process is done with claims.
After you set up an IP with ACS, when users authenticate, ACS will get claims about the authenticated user from the IP. You need to configure rules in ACS to say which claims you want forwarded on to your application. You can also tranlate claims into different types, to normalize the incoming claim set to what your application expects
If you want to implement your role based access with ACS, you can. In this case a role just another claim ACS will issue, and you'll implement your application to give user privileges based on the role claim it receives from ACS.
You can configure ACS rules that map certain IP input claims to role output claims. ACS also has a management service that can change these rules so you can implement a user registration process.
Individual claim rules in ACS relate to identity providers that issue the claim, but rule groups don't. Rule groups associate to RPs (your applications). A rule group is simply a group of claims transformation rules that tell ACS: "for this application, apply this rule group policy when you issue the token".
The ACS docs have lots to say about ACS claim rules configuration, both through the web portal and through the management service::
https://msdn.microsoft.com/library/azure/hh147631.aspx
Expanded response:
Let's say you're using ACS to authenticate to an ASP.NET app that's using WIF. You would configure ACS to issue a Role claim of "Manager" for the google user with email "jdoe#gmail.com".
Now in your ASP.NET app, WIF will see this role claim and it will allow you to control access using either HttpContext.Current.User.IsInRole("Manager"), or the web.config equivalent.
You can manage these ACS rules manually using the web UI, or you can implement a registration process that adds such rules to ACS programatically using the ACS management service. There are some ACS management service samples available at acs.codeplex.com.
Also, the identity developer training kit has some examples on WIF role based access:
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=14347

Resources