SAML はマルチテナンシーを提供します。つまり、単一のターゲットアプリケーション (WAR) を複数の Keycloak レルムで保護できます。レルムは、同じ Keycloak インスタンスまたは異なるインスタンスに配置できます。
これを行うには、アプリケーションに複数の keycloak-saml.xml
アダプター構成ファイルが必要です。
異なるアダプター構成ファイルを持つ WAR の複数のインスタンスを異なるコンテキストパスにデプロイできますが、これは不便な場合があり、コンテキストパス以外の何かに基づいてレルムを選択したい場合もあります。
Keycloak を使用すると、カスタム構成リゾルバーを持つことができるため、リクエストごとに使用するアダプター構成を選択できます。SAML では、構成はログイン処理でのみ重要です。ユーザーがログインすると、セッションが認証され、返された keycloak-saml.xml
が異なっていても問題ありません。そのため、同じセッションに対して同じ構成を返すのが正しい方法です。
これを実現するには、org.keycloak.adapters.saml.SamlConfigResolver
の実装を作成します。次の例では、Host
ヘッダーを使用して適切な構成を見つけてロードし、アプリケーションの Java クラスパスから関連する要素をロードします。
package example;
import java.io.InputStream;
import org.keycloak.adapters.saml.SamlConfigResolver;
import org.keycloak.adapters.saml.SamlDeployment;
import org.keycloak.adapters.saml.config.parsers.DeploymentBuilder;
import org.keycloak.adapters.saml.config.parsers.ResourceLoader;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.saml.common.exceptions.ParsingException;
public class SamlMultiTenantResolver implements SamlConfigResolver {
@Override
public SamlDeployment resolve(HttpFacade.Request request) {
String host = request.getHeader("Host");
String realm = null;
if (host.contains("tenant1")) {
realm = "tenant1";
} else if (host.contains("tenant2")) {
realm = "tenant2";
} else {
throw new IllegalStateException("Not able to guess the keycloak-saml.xml to load");
}
InputStream is = getClass().getResourceAsStream("/" + realm + "-keycloak-saml.xml");
if (is == null) {
throw new IllegalStateException("Not able to find the file /" + realm + "-keycloak-saml.xml");
}
ResourceLoader loader = new ResourceLoader() {
@Override
public InputStream getResourceAsStream(String path) {
return getClass().getResourceAsStream(path);
}
};
try {
return new DeploymentBuilder().build(is, loader);
} catch (ParsingException e) {
throw new IllegalStateException("Cannot load SAML deployment", e);
}
}
}
web.xml
の keycloak.config.resolver
コンテキストパラメーターを使用して、使用する SamlConfigResolver
実装も構成する必要があります。
<web-app>
...
<context-param>
<param-name>keycloak.config.resolver</param-name>
<param-value>example.SamlMultiTenantResolver</param-value>
</context-param>
</web-app>