<div dir="ltr"><p dir="ltr">You can implement a dynamic keycloak config resolver that can work with realms not known in advance.  <span style="font-size:12.8px">I&#39;ve just been doing exactly the same thing.  My requirement was to use the host name to identify a realm, so</span><span style="font-size:12.8px"> </span><a href="http://tenanta.mydomain.com/my-client" target="_blank" style="font-size:12.8px">tenanta.mydomain.com/my-client</a><span style="font-size:12.8px"> </span><span style="font-size:12.8px">would use realm &quot;tenanta&quot;,</span><a href="http://tenantb.mydomain.com/my-client" target="_blank" style="font-size:12.8px">tenantb.mydomain.com/my-client</a><span style="font-size:12.8px"> </span><span style="font-size:12.8px">would use &quot;tenantb&quot; etc and realms could be created dynamically and my-client would immediately work with those new realms without requiring a reboot or re-configuration.   </span><span style="font-size:12.8px">There are different KeycloakConfigResolver implementations you can use to do this, depending on your client configuration.</span></p><p dir="ltr"><span style="font-size:12.8px">If the client is configured as public (no client secret) or if the client secret for the application is the same in each realm, then you can use a keycloak template for configuration.  So you could</span><span style="font-size:12.8px"> deploy a WEB-INF/keycloak-template.json file which looks something like this...</span></p><div dir="ltr" style="font-size:12.8px"><div><span style="color:rgb(51,51,51);font-family:Consolas,Menlo,&quot;Liberation Mono&quot;,Courier,monospace;font-size:12px;line-height:1.4;white-space:pre-wrap">{</span><br></div><div><pre style="white-space:pre-wrap;margin-top:0px;margin-bottom:0px;padding:0px;font-family:Consolas,Menlo,&quot;Liberation Mono&quot;,Courier,monospace;font-size:12px;line-height:1.4;color:rgb(51,51,51)"><a name="m_-8955023691950085650_glomex-multi-tenant-keycloak.json-2" style="color:rgb(53,114,176)"></a>  <span style="color:navy">&quot;realm&quot;</span>: <span style="color:rgb(187,136,68)">&quot;tenantA&quot;</span>,
<a name="m_-8955023691950085650_glomex-multi-tenant-keycloak.json-3" style="color:rgb(53,114,176)"></a>  <span style="color:navy">&quot;realm-public-<span class="">key</span>&quot;</span>: <span style="color:rgb(187,136,68)">&quot;MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA07H+1raA8G5lU9II9GwQ1r2yXzSeBpEC6Lz822iB+oZGi36KC6caVOyi1IVIWB/ZnxxoC8AHsn4ASYJnYUMNTjRvK9nwHCP825LD3nHFBHyQ0gUHBELRi6ZvmOu3TnyiIlnR2SCxwmND5ifgtDfKwldcdCTNWqJG5MkcOimhDEiZYLOrShH5pCcEkPE5JBj0GDGYs9AcUT8/OrJEvInVAfnMMxvzZfXhJQlXnq0HbkGPNL2LMq66bmfI7OTzWKpIIoa24DOcxvu5FEqnnfhEZ+RkhfrVVe876T7Jx9f128xOTAYgi98515+xeFGei1Qer1IJCtnE5vICKKVtDdJg1wIDAQAB&quot;</span>,
<a name="m_-8955023691950085650_glomex-multi-tenant-keycloak.json-4" style="color:rgb(53,114,176)"></a>  <span style="color:navy">&quot;auth-server-url&quot;</span>: <span style="color:rgb(187,136,68)">&quot;<a href="https://keycloak.mydomain.com/auth" target="_blank">https://keycloak.mydomain.com/auth</a>&quot;</span>,
<a name="m_-8955023691950085650_glomex-multi-tenant-keycloak.json-5" style="color:rgb(53,114,176)"></a>  <span style="color:navy">&quot;ssl-required&quot;</span>: <span style="color:rgb(187,136,68)">&quot;none&quot;</span>,
<a name="m_-8955023691950085650_glomex-multi-tenant-keycloak.json-6" style="color:rgb(53,114,176)"></a>  <span style="color:navy">&quot;resource&quot;</span>: <span style="color:rgb(187,136,68)">&quot;my-client&quot;</span>,
<a name="m_-8955023691950085650_glomex-multi-tenant-keycloak.json-7" style="color:rgb(53,114,176)"></a>  <span style="color:navy">&quot;public-client&quot;</span>: <span style="font-weight:700">true</span>
<a name="m_-8955023691950085650_glomex-multi-tenant-keycloak.json-8" style="color:rgb(53,114,176)"></a>}</pre><div><br><div><div>The <span class="">KeycloakConfigResolver</span> would use this template for each realm and just overwrite the &quot;realm&quot; and &quot;realm-public-<span class="">key</span>&quot; values with the real values.  To get those real values, the <span class="">KeycloakConfigResolver</span> would first work out the realm name.  In my case, I derive the realm name from the hostname, so <a href="http://tenanta.mydomain.com/" target="_blank">tenanta.mydomain.com</a> would indicate &quot;tenanta&quot; was being used.  Once you have derived the realm name, then you can do a http get request to http://&lt;keycloak_url&gt;/auth/realms/&lt;tenantname&gt; (eg. <a href="https://keycloak.mydomain.com/auth/realms/tenanta" target="_blank">https://keycloak.mydomain.com/auth/realms/tenanta</a>).  This endpoint isn&#39;t secured and returns something similar to the following...</div><div><br></div></div></div></div><div><span style="color:rgb(0,0,0);font-family:monospace;font-size:medium">{</span><ul style="list-style-type:none;padding:0px;margin:0px 0px 0px 2em;color:rgb(0,0,0);font-family:monospace;font-size:medium"><li style="margin-left:15px"><div style="display:inline-block;padding:1px 2px;border-radius:2px"><span style="font-weight:bold">realm</span>: <span style="color:green">&quot;tenantA&quot;</span>,</div></li><li style="margin-left:15px"><div style="display:inline-block;padding:1px 2px;border-radius:2px"><span style="font-weight:bold">public_key</span>:<span style="color:green">&quot;MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA07H+1raA8G5lU9II9GwQ1r2yXzSeBpEC6Lz822iB+oZGi36KC6caVOyi1IVIWB/ZnxxoC8AHsn4ASYJnYUMNTjRvK9nwHCP825LD3nHFBHyQ0gUHBELRi6ZvmOu3TnyiIlnR2SCxwmND5ifgtDfKwldcdCTNWqJG5MkcOimhDEiZYLOrShH5pCcEkPE5JBj0GDGYs9AcUT8/OrJEvInVAfnMMxvzZfXhJQlXnq0HbkGPNL2LMq66bmfI7OTzWKpIIoa24DOcxvu5FEqnnfhEZ+RkhfrVVe876T7Jx9f128xOTAYgi98515+xeFGei1Qer1IJCtnE5vICKKVtDdJg1wIDAQAB&quot;</span>,</div></li><li style="margin-left:15px"><div style="display:inline-block;padding:1px 2px;border-radius:2px"><span style="font-weight:bold">token-service</span>: <span style="color:green">&quot;</span><a href="https://keycloak.cyberavenue.com.au/auth/realms/tenantA/protocol/openid-connect" target="_blank">https://keycloak.mydomain.com/auth/realms/tenantA/protocol/openid-connect</a><span style="color:green">&quot;</span>,</div></li><li style="margin-left:15px"><div style="display:inline-block;padding:1px 2px;border-radius:2px"><span style="font-weight:bold">account-service</span>: <span style="color:green">&quot;</span><a href="https://keycloak.cyberavenue.com.au/auth/realms/tenantA/account" target="_blank">https://keycloak.mydomain.com/auth/realms/tenantA/account</a><span style="color:green">&quot;</span>,</div></li><li style="margin-left:15px"><div style="display:inline-block;padding:1px 2px;border-radius:2px"><span style="font-weight:bold">admin-api</span>: <span style="color:green">&quot;</span><a href="https://keycloak.cyberavenue.com.au/auth/admin" target="_blank">https://keycloak.mydomain.com/auth/admin</a><span style="color:green">&quot;</span>,</div></li><li style="margin-left:15px"><div style="display:inline-block;padding:1px 2px;border-radius:2px"><span style="font-weight:bold">tokens-not-before</span>: <span style="color:blue">0</span></div></li></ul><span style="color:rgb(0,0,0);font-family:monospace;font-size:medium">}</span><br></div><div><span style="color:rgb(0,0,0);font-family:monospace;font-size:medium"><br></span></div><div>The <span class="">KeycloakConfigResolver</span> then uses the &quot;realm&quot; and &quot;public_key&quot; values from that response, overrides the values from the keycloak-template.json file to create the KeycloakDeployment (using KeycloakDeploymentBuilder).<br></div><div><br></div><div>If your client isn&#39;t public and the client-secret differs and isn&#39;t known in advance, then this solution wouldn&#39;t work.  In that case, another solution can be used which is slightly more complicated.  The idea is the <span class="">KeycloakConfigResolver</span> does the following...</div><div><br></div><div>1/ Get a token for the admin-cli client in the &quot;master&quot; realm.  This may require configuring a username and password that can be used used to obtain this token.</div><div>2/ Use the rest api to get a list of clients in the requested realm (ie. http get to <span style="font-size:12.8px">http://&lt;keycloak_url&gt;/</span>auth/admin/realms/{realm}/clients using a Bearer token obtained from step 1</div><div>3/ Iterate through the list and find the Client you&#39;re interested in (ie. client.getClientId().equals(&quot;my-client&quot;) ).  You need the client UID identifier from this.</div><div>4/ Use the rest api to get the keycloak deployment installation file by doing a GET to <span style="font-size:12.8px">http://&lt;keycloak_url&gt;</span>/auth/admin/realms/{realm}/clients/{client-uid}/installation/providers/keycloak-oidc-keycloak-json, using the Bearer token from step 1 and the client UID from step 3.  Then use KeycloakDeploymentBuilder on the response body returned from this service.</div><div><br></div><div><br></div><div><br></div><div>Regards,</div><div><br></div><div>Anthony</div><div><br></div></div>
<br><div class="gmail_quote"><div dir="ltr">On 04:43, Sat, 11/06/2016 Jesse Chahal &lt;<a href="mailto:jessec@stytch.com" target="_blank">jessec@stytch.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">The keycloak config resolver works well when all realms are known in<br>
advance. I was trying to imply in my diagram that all realms are not<br>
known in advance as realms are going to be created for new customers<br>
on demand. Doing a new production deployment whenever a SaaS product<br>
has a new customer added is not a feasible solution.<br>
<br>
On Wed, Jun 8, 2016 at 7:01 PM, Anthony Fryer &lt;<a href="mailto:anthony.fryer@gmail.com" target="_blank">anthony.fryer@gmail.com</a>&gt; wrote:<br>
&gt; Why do you say &quot;very hard to get App1 to support multiple realms (no adapter<br>
&gt; or keycloak support)&quot;?<br>
&gt;<br>
&gt; Keycloak does provide multi-tenancy support via the KeycloakConfigResolver.<br>
&gt; See <a href="https://github.com/keycloak/keycloak/tree/master/examples/multi-tenant" rel="noreferrer" target="_blank">https://github.com/keycloak/keycloak/tree/master/examples/multi-tenant</a>.<br>
&gt;<br>
&gt; The issue would be if your app can&#39;t use a keycloak adapter.<br>
&gt;<br>
&gt; On Thu, Jun 9, 2016 at 10:05 AM, Jesse Chahal &lt;<a href="mailto:jessec@stytch.com" target="_blank">jessec@stytch.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Hi,<br>
&gt;&gt;<br>
&gt;&gt; I&#39;m back again. I&#39;m trying to figure out how scale Identity Providers.<br>
&gt;&gt; We are planning on trying to integrate our App1 with salesforce. A<br>
&gt;&gt; user who logs into salesforce should be able to have a native feel of<br>
&gt;&gt; our App1 within it. Todo this we&#39;ll probably have to end up building<br>
&gt;&gt; salesforce native apps. For every salesforce organization/licensee we<br>
&gt;&gt; will have to register an Identity provider with keycloak to make sure<br>
&gt;&gt; they can correctly use App1. Some configuration options we came up<br>
&gt;&gt; with are listed below. Has anyone else solved a similar problem?<br>
&gt;&gt;<br>
&gt;&gt; OPTION 1<br>
&gt;&gt; ########################################################<br>
&gt;&gt; # Keycloak<br>
&gt;&gt;                               #<br>
&gt;&gt; # ---&gt; master realm<br>
&gt;&gt;                           #<br>
&gt;&gt; # ---&gt; realm 1<br>
&gt;&gt;                               #<br>
&gt;&gt; # --- ---&gt; app1_client (open ID)<br>
&gt;&gt;                      #<br>
&gt;&gt; # --- ---&gt; salesforce_org1_saml2.0_identity_provider<br>
&gt;&gt; #<br>
&gt;&gt; # --- ---&gt; salesforce_org2_saml2.0_identity_provider<br>
&gt;&gt; #<br>
&gt;&gt; #<br>
&gt;&gt;                                      #<br>
&gt;&gt; # Salesforce<br>
&gt;&gt;                               #<br>
&gt;&gt; # ---&gt; org1<br>
&gt;&gt;                                 #<br>
&gt;&gt; # ---- ----&gt; salesforce_appX (uses App1)<br>
&gt;&gt;               #<br>
&gt;&gt; # ---&gt; org 2<br>
&gt;&gt;                                 #<br>
&gt;&gt; # ---- ----&gt; salesforce_appX (uses App1)<br>
&gt;&gt;               #<br>
&gt;&gt; # ---- ----&gt; salesforce_appY (uses App1)<br>
&gt;&gt;               #<br>
&gt;&gt; # .....<br>
&gt;&gt;                                      #<br>
&gt;&gt; #<br>
&gt;&gt;                                      #<br>
&gt;&gt; # App 1<br>
&gt;&gt;                                  #<br>
&gt;&gt; # ---&gt; OpenID to realm1 (using adapter)<br>
&gt;&gt;               #<br>
&gt;&gt; ########################################################<br>
&gt;&gt; benefits<br>
&gt;&gt; - single login page<br>
&gt;&gt; - single realm<br>
&gt;&gt; cons<br>
&gt;&gt; - login page with infinite number of identity provider buttons present<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; OPTION 2<br>
&gt;&gt; ########################################################<br>
&gt;&gt; # Keycloak<br>
&gt;&gt;                               #<br>
&gt;&gt; # ---&gt; master realm<br>
&gt;&gt;                           #<br>
&gt;&gt; # ---&gt; realm 1<br>
&gt;&gt;                               #<br>
&gt;&gt; # --- ---&gt; app1_client (open ID)<br>
&gt;&gt;                      #<br>
&gt;&gt; # --- ---&gt; salesforce_org1_saml2.0_identity_provider<br>
&gt;&gt; #<br>
&gt;&gt; # ---&gt; realm 2<br>
&gt;&gt;                               #<br>
&gt;&gt; # --- ---&gt; app1_client (open ID)<br>
&gt;&gt;                      #<br>
&gt;&gt; # --- ---&gt; salesforce_org2_saml2.0_identity_provider<br>
&gt;&gt; #<br>
&gt;&gt; #<br>
&gt;&gt;                                      #<br>
&gt;&gt; # Salesforce<br>
&gt;&gt;                               #<br>
&gt;&gt; # ---&gt; org1<br>
&gt;&gt;                                 #<br>
&gt;&gt; # ---- ----&gt; salesforce_appX (uses App1)<br>
&gt;&gt;               #<br>
&gt;&gt; # ---&gt; org 2<br>
&gt;&gt;                                 #<br>
&gt;&gt; # ---- ----&gt; salesforce_appX (uses App1)<br>
&gt;&gt;               #<br>
&gt;&gt; # ---- ----&gt; salesforce_appY (uses App1)<br>
&gt;&gt;               #<br>
&gt;&gt; # .....<br>
&gt;&gt;                                      #<br>
&gt;&gt; #<br>
&gt;&gt;                                      #<br>
&gt;&gt; # App 1<br>
&gt;&gt;                                  #<br>
&gt;&gt; # ---&gt; OpenID to realm1, realm2, realm#.... (using adapter)<br>
&gt;&gt; #<br>
&gt;&gt; ########################################################<br>
&gt;&gt; benefits<br>
&gt;&gt; - single salesforce button per login page<br>
&gt;&gt; - users are more isolated in single realm<br>
&gt;&gt; cons<br>
&gt;&gt; - very hard to get App1 to support multiple realms (no adapter or<br>
&gt;&gt; keycloak support)<br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; keycloak-user mailing list<br>
&gt;&gt; <a href="mailto:keycloak-user@lists.jboss.org" target="_blank">keycloak-user@lists.jboss.org</a><br>
&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/keycloak-user" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-user</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; keycloak-user mailing list<br>
&gt; <a href="mailto:keycloak-user@lists.jboss.org" target="_blank">keycloak-user@lists.jboss.org</a><br>
&gt; <a href="https://lists.jboss.org/mailman/listinfo/keycloak-user" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-user</a><br>
</blockquote></div></div>