Recap of Post 1
Post 1 showed you to set up Keycloak, your DNS, an Azure External Identity Provider and how to invite internal B2B guest users.
Recap of Post 2
Post 2 showcased keycloak_to_azure.py
, a way to automate user and group sync from Keycloak to Azure AD utilizing Microsoft Graphs REST API via HTTP and the python-keycloak package.
Using a different email domain in Azure AD and Keycloak
Here at B1 Systems, we had the challenge of already existing Azure AD users. They used our main email domain as their UPN suffix and the domain is a custom DNS verified domain. These “verified domains” cannot be used with SAML-Fed IdP federation, so we have to set up the federation with an “unverified domain”.
Example Setup with a hitch
Your ACME company owns acme.com
and uses it for all its main activities, e.g. hosting your website and sending/receiving your mail. acme.com
is registered as a custom DNS verified domain in Azure AD. You have your admin users inside this domain (and you don’t want to change that). You are also using this domain for users and their email addresses inside your Keycloak. Keycloak is your one and only Identity and Access Management. Remember: The user’s domain part is the criterion for the user federation to Keycloak. Again, the acme.com
domain cannot be used with SAML-Fed IdP federation, as it is a “verified domain”. To work around this, you are now using acme.corp
(also owned by your company) as the domain for your staff’s users and establish an IdP federation for this very domain inside Azure AD (see Post 1).
Problem as seen in the login process
When you now login to your Azure tenant by visiting https://portal.azure.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/ you will be forwarded to your Keycloak instance and presented with a login window, as usual. After a successful login, you will be presented with an Azure error message resembling something like “user cannot be found”. If you analyze the login process with a tool like SAML-tracer, you would see that the needed SAML Attribute http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
sadly is a user from the acme.com
domain. This is of course “correct”, as the user entry in Keycloak includes the email
attribute from our main email domain acme.com
.
How to solve this …
We would need a different answer from Keycloak for the email
attribute. The answer has to include our SAML-federated domain acme.corp
and not the real acme.com
domain.
- A simple solution would be to add an additional attribute, e.g.
email_azure
to every user and just using this in the “User Attribute Mapper” from Post 1.- This would have to be maintained/automated somehow.
- If you’re using LDAP integration inside Keycloak, this could even be added as an LDAP attribute.
- This would have to be maintained/automated somehow.
- Can we just “overwrite” this inside Keycloak?
Overwrite email
attribute in Keycloak
Keycloak <= v16 (old WildFly Distribution) -> you should not run this anymore
Keycloak <= v16 had a “Javascript Mapper” which could be used to achieve hacks like this pretty easy:
Client -> Client scopes -> *-dedicated -> Mappers -> Add mapper -> By Configuration -> javascript Mapper
:
protocol: saml
name: email_com
Mapper Type: javascript Mapper
Script:
input = user.email;
username = input.split("@")[0];
domain = input.split("@")[1];
output = username + "@acme.corp";
Single Value Attribute: ON
Friendly Name: email_com
SAML Attribute Name: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
SAML Attribute NameFormat: URI Reference
Keycloak >= v17 (Quarkus Distribution)
Keycloak v17 introduced Quarkus as the new default distribution and got rid of old clutter like the “Javascript Mapper”.
Overwriting the email
attribute is a bit more challenging here.
keycloak-custom-email-domain-mapper
One approach could be to use or write a custom provider using the Service Provider Interface (SPI) or to be more precise, a custom protocol mapper that changes our email
attribute.
The code
mschwartau/keycloak-custom-protocol-mapper-example is a great starting point of achieving this and similar goals. Kudos!
I forked mschwartau’s repo and created yeoldegrove/keycloak-custom-email-domain-mapper for the sole purpose of rewriting the email
user attribute and using it as the http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
SAML attribute.
Explaining the whole mapper would be “too much” and a bit boring I guess. So let’s just quickly explain how to use it. If you’re interested in the boring details, it is open source 😉
Installing the Mapper
You have to ship the *.jar
file (containing the mapper), which can be build by running mvn clean package
, to your Keycloak instance. Custom providers can just be placed inside /opt/keycloak/providers
and will be automatically loaded during startup. If you are using a containerized setup, the easiest way would be to just use the provided Dockerfile
and spinning up the container with command: start
(or adapting the CMD
line iside the Dockerfile). Also have a look at Running Keycloak in a container for more details on how you can adapt the image.
To check that the provider is loaded, have a look at e.g. Provider info – https://auth.acme.com/auth/admin/acme/console/#/acme/providers and look for saml-custom-email-domain-mapper
.
Using the Mapper
After you have added saml-custom-email-domain-mapper
to your Keycloak instance, you can use it like any other mapper.
Client -> Client scopes -> *-dedicated -> Mappers -> Add mapper -> By Configuration -> Custom Email Domain Mapper
:
Be sure to set acme.corp
as Email Domain
.
protocol: saml
Mapper Type: Custom Email Domain Mapper
Name: email
Email Domain: acme.corp
SAML Attribute Statement: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
SAML Attribute NameFormat: urn:oasis:names:tc:SAML:2.0:attrname-format:uri
Recap and Conclusion – A working setup with different email domains in Azure AD and Keycloak
After following all the steps above, let’s shortly recap what your setup now looks like:
acme.com
is registered as a custom DNS verified domain in Azure ADacme.com
domain cannot be used with SAML-Fed IdP federation, as it is a “verified domain”.- you have set up IdP-federation for
acme.corp
- you have set up IdP-federation for
acme.corp
is used to login to the Azure portal- you are forwarded to Keycloak due to IdP-federation for
acme.corp
- Keycloak answers with an
email
user attribute that includesacme.com
saml-custom-email-domain-mapper
overwrites theemail
attribute and adds thehttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
SAML attribute to theacme.corp
domain
- you are forwarded to Keycloak due to IdP-federation for
- Azure AD accepts the
acme.corp
SAML answer and your users can login successfully now.
Congratulations! You’re now using different email domains in Azure AD and Keycloak and the login is working.
Next Steps
This is where our 3-part Azure and Keycloak series comes to an end. If your’re interested in a similar setup or even want a B1 Consultant to set it up four you, feel free to reach out. We’re glad to help you.