Grant access Keycloack roles to specific subdomains with traefik - azure

My goal
overall goal
I want to serve various applications running on docker containers hosted on the same server, each on a subdomain of company.com. And I want only people from my organization (Microsoft AD azure) to access subdomains, in some cases even only people having specific AD groups.
goal specific to Keycloak
I simply want to have specific realm roles have access to specific subdomains, and nothing else. And this, using only a single realm client (see further for explanation).
what I have achieved to do
I have linked several applications on a server and serving each using traefik on a specific subdomain. For example app1.company.com and app2.company.com.
I have also made a middleware so that all routers using it will make sure users must login. I have used a thomseddon/traefik-forward-auth container that I called oauth. I am using Keycloak and I have successfully linked an Azure Active Directory as identity provider. For this, I enabled a single-tenant application and used its client id & key. I also mapped successfully some AD group to a Keycloak role.
Within oauth configuration, I have added the client id & secret from a single keycloak client rather than from the azure application. I believe this is mandatory if we want to use traefik to redirect trafic.
Now, only people from within my organization can access each app. Success!
Some documentations I used
Homelab Single Sign-On & TLS
How to Configure Microsoft Azure Active Directory as Keycloak Identity Provider to Enable Single Sign-On
what I want to do
Each application has its own subdomain. However I cannot figure out where to make it so that some subdomains are accessible only if a user has a specific realm role (linked automatically depending on a AD group thanks to the above-mentioned mapper).
I thought of adding resources within the Keycloak client, but I don't find how to do it using subdomains.
other alternative is to make one client per subdomain, but this means I need to run one oauth container per subdomain... This seems overkill & a waste of resources without counting maintenance.

The only relatively simple solution I found was to create one Keycloak client per type of permission rules (aka Roles in Keycloak) I wanted.
Then for each type, I had to make a traefik-forward-auth container and connect it to each Keycloak client. I am still using the same Identity provider, so once you've configured it to generate roles, you only need to tell which roles may use which client.
To give an example, you want to have 3 types of permission rules: one for admin, one for trusted users, and one for untrusted user. It could look like this:
admin.example.com
trustedusers.example.com/app1 and trustedusers.example.com/app2
untrustedusers.example.com/app3 and untrustedusers.example.com/app4
You would then have 3 forwardAuth middlewares within traefik.
It is a little bit more cumbersome, but your applications are still connected to your OIDC provider using a single key, then you manage the details using keycloak and these clients.
Of course there is still the solution to have one client per application as is originally planned. This may be unnecessary, and cumbursome if you have a large number of applications (one additional container per application + additional middleware).

Related

How do I configure static multi-tenant authentication in Quarkus

We are using a single Quarkus instance to serve multiple user groups (ADMIN and USER). Up to now we were using one single authentication service so secure our web endpoints (configured in application.properties).
Now requirements changed and we have to authenticate the USER endpoints with a different AS.
Does anybody have an hint how to do this in a simple way. My expectation would be to have some Quarkus config in application.properties like
# user authorisation (default, well documented at Quarkus)
quarkus.oidc.auth-server-url=https://url/to/user-auth
(...)
quarkus.http.auth.permission.app.paths=/admin/*
# admin authorisation (my guess)
quarkus.oidc.ADMIN.auth-server-url=https://url/to/admin-auth
(...)
quarkus.http.ADMIN.auth.permission.app.paths=/admin/*
I know best practice would be to create different service instances but we would like to safe the efforts duplicating the infrastructure and keep things in a single block.

Multi Instance Apps and Azure Authentication Best Practices

We have a multi-instance Saas Application:
Each of our clients is given their own instance and their own subdomain for the site.
Our application (Web app & API) is protected by Azure, currently with the ADAL javascript libraries
We also have a second API for system-level integration that needs to be protected, currently using a second 'native' azure app, but this is likely incorrect and we want to consolidate
Our application reads and writes to the Azure AD both through the AzureAD Graph API and Microsoft Graph API (including password reset calls)
We're looking at Azure AD application configuration options and want to make sure we're building the most sensible and secure Azure AD Application. Here are some of the documentation we've been looking at:
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oauth-client-creds
https://learn.microsoft.com/en-us/azure/architecture/multitenant-identity/
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-compare
We want the application to be multi-tenant to ease configuration, and allow availability in the Gallery; but when looking into doing so we're left with some security questions.
A. Which application version to use
1) v1. Allows access to both Graph API. And as suggested by Microsoft we should use this when we're not concerned with Microsoft Accounts.
2) v2. When looking at the MS Graph API documentation it recommends using v2. Reportedly doesn't work for AzureAD Graph API? Allows the same app to be of multiple types (Web App/API and native), which we may or may not need to protect both our web api and our system api (which we're still trying to model).
B. How to manage the reply URL when our clients have different sub-domains?
I've noted the following options:
1) On the app registry, we add the reply urls for all of our customers. This seems okay because we only need to do it once, but feels odd. Is there a limit to the number of reply urls?
2) Have one reply url, but manage an external tool to route the responses to the correct instance, leveraging the state url parameter. Microsoft seems to be suggesting that in this link: https://learn.microsoft.com/en-us/azure/architecture/multitenant-identity/authenticate I'm not sure if ADAL allows us to set the state for a return subdomain url though. Is this approach common?
3) Is it possible for each ServiceProvider instance in our client's directories to configure the reply url to their own subdomain? I feel like this would be the cleanest approach, but I don't see documentation for it. It would be nice if we could set the replyURL programmatically as well.
C. How to manage authorization to the Graph APIs (AzureAD and Microsoft Graph)
I've noted the following options:
1) Use the client credential flow, with a single application key (used for all clients). As clients subscribe they will admin consent with our app to give the application permission to their directory. Of course we'd do our best to keep that key secure. But if for some reason it was compromised this would put all of our clients at risk, not just the one instance that was compromised.
2) Same as 1, but use a certificate instead of a secret key. I understand this could be a little more secure, but I don't see how it wouldn't suffer from the same issue as 1.
3) Instead of using application permissions, use delegated permissions with an admin user. This would be good, in that it inherently prevents one instance of our app from talking to the wrong directory. However changes to the administrator may interrupt service; and I think it is best audit-wise that our application is responsible for the changes it makes. (Also, do delegated permissions allow for password resetting? I know for app permissions you need to run powershell script to upgrade the application's directory role)
4) Is there some way for the service principal to generate a unique key for it's directory on creation? can this be handed back to our app programmatically? Perhaps during admin consent?
Really good questions. I'll try to answer each to the best of my knowledge, but if someone has other ideas, feel free to comment/add your own answer.
A. Which application version to use
v2 should allow you to call Azure AD Graph API. The documentation you linked shows an example of specifying Azure AD Graph scopes:
GET https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=2d4d11a2-f814-46a7-890a-274a72a7309e&scope=https%3A%2F%2Fgraph.windows.net%2Fdirectory.read%20https%3A%2F2Fgraph.windows.net%2Fdirectory.write
The main decision point if you should use v2 is: Do you need to support Microsoft accounts which are not in an Azure AD? If yes, you need to use v2. Otherwise there is no problem using v1 (well, lack of dynamic permissions).
Since you are using Azure AD Graph to modify things, I'm going to guess pure Microsoft accounts will not work for you. I would recommend sticking with v1.
v2 also has some limits: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-limitations
B. How to manage the reply URL when our clients have different sub-domains?
I could not find documentation on a limit for URLs. It could be that you can add however many you want. But I am not sure :)
If your subdomains look like this: https://customer.product.com, you can configure the reply URL as:
https://*.product.com
It will then allow any subdomain to be specified in the redirect_uri.
Though note that at the time of writing this, wildcard reply URLs are not supported in v2.
C. How to manage authorization to the Graph APIs (AzureAD and Microsoft Graph)
Using multiple keys makes no sense as they are all equal anyway :) Any of them could be used to call another tenant.
You can store the secret/certificate in an Azure Key Vault, and then use Azure AD Managed Service Identity to get it on app startup.
I would prefer using delegated permissions, but if the users of the app won't have the rights to do the things your app needs to do then that does not work.
I would just make sure it is not possible for a customer's instance to call to the APIs with another tenant id. And also make sure token caches are separated in such a way that it is not possible to get another tenant's access token (an in-memory cache on the instance would be good).

Websphere Application Login

I was trying to register an Application Login Module in Websphere but I don´t find any easy example in web.
There are a lot of IBM documents, but too much complex, and I can´t figure out how to register an Application Login Module.
I already have success with a System Login Module bounded to WEB_INBOUND, it works, but affects all my system. I want a Login Module to serve only my applications web, with JAAS authentication.
I´ve tried to bound a login module to existing WSLogin but it doesn´t seems to be working.
Any help ?
tks[]
You need to setup security domains to get the separation you are looking for wrt to the login configurations. The security framework uses the WEB_INBOUND login configuration to authenticate the user for all web applications irrespective of adminConsole or user applications. When you create a security domain and customize the WEB_INBOUND configuration at the server/cluster domain level, it will be used for all the user web applications deployed in those processes. You need to setup the multidomain in a cell topology and assign the domain to the server/cluster where you applications are deployed.
Once you setup the domains, the WEB_INBOUND configuration at the server/cluster domain will be used by the user applications hosted in that server/cluster while the WEB_INBOUND configuration at the admin/global domain will be used for the adminConsole application at the Deploymener Management process where it is deployed.
The application JAAS login configurations are meant to be used by the applications directly. One can create an application login configuration and programmatically use it in the application to perform direct login -
LoginContext lc = new LoginContext("myAppLoginCfg1", callBackHandler);
I asked around and this is the answer that comes from the owner of container security:
The WEB_INBOUND is a JAAS system login that is always configured by default. However, you can specify your own JAAS application login or customize the existing WEB_INBOUND system login. If you want only one application to use a different JAAS login from all your other applications, you can use a security domain that has those different security configurations. The only catch is that application server has to be in a separate server from the other apps. That way, you can map your security domain to that server.
Here's an info center article about security domains:
http://www-01.ibm.com/support/knowledgecenter/#!/SS7K4U_8.5.5/com.ibm.websphere.zseries.doc/ae/tsec_sec_domains_config.html?cp=SS7K4U_8.5.5%2F1-8-2-33-1
And one on application logins:
http://www-01.ibm.com/support/knowledgecenter/#!/SS7K4U_8.5.5/com.ibm.websphere.zseries.doc/ae/rsec_logmod.html?cp=SS7K4U_8.5.5
And system logins:
http://www-01.ibm.com/support/knowledgecenter/#!/SS7K4U_8.5.5/com.ibm.websphere.zseries.doc/ae/usec_sysjaas.html
And here is a much more practical answer that comes from the security dev lead:
So an additional question is - why would you want to do that? Do you want to do anything specific for just one app during login that you do not want for other app logins? (I would think so) You can get the app name in your custom login module and can use that to provide your own app based login requirement in your login module (or skip it) if needed.
Me: Ya, this is what I would do. You can also implement this based on what is in the request. I did one where it would request a SAML token from an STS and put it on the runas subject if I could tell that the request came from WebSeal (and not if it didn't).
If what you need to do for the 'app-specific' case requires skipping what is done in ltpaLoginModule and wsMapDefaultInboundLoginModule (that should run for the other apps), you can't really do that. However, you can modify their behavior.
Read through the task I've given a link to below. Yes, I understand it is a WS-Security task, but its about using APIs. You'll get what I'm talking about if you read closely, particularly the 3rd ("When a caller...") and 5th ("To use a..") paragraphs. The parts that you should be concerned about in the code is the WSCREDENTIAL* stuff.
http://www-01.ibm.com/support/knowledgecenter/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/twbs_config_wssec_caller_no_reg.html

single sign on for multiple nodejs applications

We have 3 nodejs web application running on same domain name on same vps with multiple subdomains and implementing passport authentication for each. We wanted single user be able to access all application with single account and for that we have added accounts.example.com as fourth application solely for purpose of account management. The requirement is - once user is authenticated in accounts.example.com, how to enable user to access rest of the three web application with that session.
you can share your session in redis-server.if you use express,you can try to use connect-redis
https://github.com/visionmedia/connect-redis
Try Hands on CanSecurity... It tops the chart for node.js Single sign on.. Hope this proves fruitful https://github.com/deitch/cansecurity

Azure independent users store and Access Control Service service identities

We have a mobile web platform that we are developing above Azure.
We have a website which is a regular passive authentication scenario and mobile client infront of a web serivce which is active authentication scenario.
We want to create our own users identities store and not base ourselves upon others , currently he are the options we mapped and I have added questions regarding them:
(Correct me if I am wrong or writing something silly).
1.Asp.net membership -Was not originally built for active scenario also will block us in the future if we also want to support OpenId/OAuth providers.
Also , does not support SWT/SAML tokens , so in the future we will need multiple security handlers in our services environment.
Do you know any good way to integrate this with Azure ACS if we need to in the future ?
2.ADFS 2.0 : We can install active direcotry on a virtual machine and manage all users through that , in the future we can integrate this to Azure ACS , supports SWT.
Is Active Directory not an overkill for basic users authentication ? Wont it be an IT overhead (something we desperately want to eliminate) .
3.We can perhaps install other identity management servers - such as Oracle Identity management , again , on a virtual machine and integrate Azure with that as custom STS.
Oracle has designated web access products line :
http://www.oracle.com/technetwork/middleware/id-mgmt/overview/index.html
4.We can use Azure service identities , and simply add users to there. Our main question here is if we can add large amounts of users to this scope (more then several millions).
Regards ,
James
I would suggest making your own STS, but maybe use OpenID or Facebook or someone to do the authentication. Or you could do something like this to store your own usernames, etc:
http://www.soulier.ch/?p=1105&lang=en
But you will run the risk of storing these credentials and have to make sure you don't store it in a way that could be compromised. I don't think service identies would be good for that volume of users.
You may want to check out:
http://identityserver.codeplex.com/
http://garvincasimir.wordpress.com/2011/08/06/azure-acs-plus-asp-net-mvc-memberships/

Resources