kandi background
Explore Kits

keycloak | Open Source Identity and Access Management | Identity Management library

 by   keycloak Java Version: nightly License: Apache-2.0

 by   keycloak Java Version: nightly License: Apache-2.0

Download this library from

kandi X-RAY | keycloak Summary

keycloak is a Java library typically used in Security, Identity Management applications. keycloak has build file available, it has a Permissive License and it has high support. However keycloak has 1314 bugs and it has 71 vulnerabilities. You can install using 'npm i keycloak-js' or download it from GitHub, npm.
Keycloak is an Open Source Identity and Access Management solution for modern Applications and Services. This repository contains the source code for the Keycloak Server, Java adapters and the JavaScript adapter.
Support
Support
Quality
Quality
Security
Security
License
License
Reuse
Reuse

kandi-support Support

  • keycloak has a highly active ecosystem.
  • It has 12056 star(s) with 4406 fork(s). There are 346 watchers for this library.
  • There were 3 major release(s) in the last 6 months.
  • There are 649 open issues and 742 have been closed. On average issues are closed in 35 days. There are 196 open pull requests and 0 closed requests.
  • It has a negative sentiment in the developer community.
  • The latest version of keycloak is nightly
keycloak Support
Best in #Identity Management
Average in #Identity Management
keycloak Support
Best in #Identity Management
Average in #Identity Management

quality kandi Quality

  • keycloak has 1314 bugs (38 blocker, 11 critical, 775 major, 490 minor) and 18891 code smells.
keycloak Quality
Best in #Identity Management
Average in #Identity Management
keycloak Quality
Best in #Identity Management
Average in #Identity Management

securitySecurity

  • keycloak has 16 vulnerability issues reported (1 critical, 9 high, 6 medium, 0 low).
  • keycloak code analysis shows 55 unresolved vulnerabilities (34 blocker, 12 critical, 9 major, 0 minor).
  • There are 177 security hotspots that need review.
keycloak Security
Best in #Identity Management
Average in #Identity Management
keycloak Security
Best in #Identity Management
Average in #Identity Management

license License

  • keycloak is licensed under the Apache-2.0 License. This license is Permissive.
  • Permissive licenses have the least restrictions, and you can use them in most projects.
keycloak License
Best in #Identity Management
Average in #Identity Management
keycloak License
Best in #Identity Management
Average in #Identity Management

buildReuse

  • keycloak releases are available to install and integrate.
  • Deployable package is available in npm.
  • Build file is available. You can build the component from source.
  • Installation instructions, examples and code snippets are available.
  • keycloak saves you 1267880 person hours of effort in developing the same functionality from scratch.
  • It has 563706 lines of code, 45885 functions and 6982 files.
  • It has medium code complexity. Code complexity directly impacts maintainability of the code.
keycloak Reuse
Best in #Identity Management
Average in #Identity Management
keycloak Reuse
Best in #Identity Management
Average in #Identity Management
Top functions reviewed by kandi - BETA

kandi has reviewed keycloak and discovered the below as its top functions. This is intended to give you an instant insight into keycloak implemented functionality, and help decide if they suit your requirements.

  • Associates the first broker login flow with the given realm .
  • Initialize the topology
  • Given an IPv6 address and an IPv6 address return the canonical form of it .
  • Updates the realm .
  • Create a client object from an OIDC client .
  • Creates a wrapper for the policy store .
  • Verify OCSP response certificate .
  • Handle an action token .
  • Read a message .
  • Handle login response .

keycloak Key Features

Open Source Identity and Access Management For Modern Applications and Services

Getting started

copy iconCopydownload iconDownload
bin/standalone.[sh|bat] 

How to access the original case sensitive username input in custom user storage provider of keycloak?

copy iconCopydownload iconDownload
<spi name="userCache">
    <provider name="default" enabled="true"/>
</spi>
<spi name="userCache">
    <provider name="default" enabled="false"/>
</spi>
FROM jboss/keycloak:latest
USER root
COPY disable-usercache.cli /opt/jboss/startup-scripts/disable-usercache.cli
USER 1000
embed-server --server-config=standalone-ha.xml --std-out=echo
batch

/subsystem=keycloak-server/spi=userCache/provider=default/:write-attribute(name=enabled,value=false)

run-batch
stop-embedded-server
-----------------------
<spi name="userCache">
    <provider name="default" enabled="true"/>
</spi>
<spi name="userCache">
    <provider name="default" enabled="false"/>
</spi>
FROM jboss/keycloak:latest
USER root
COPY disable-usercache.cli /opt/jboss/startup-scripts/disable-usercache.cli
USER 1000
embed-server --server-config=standalone-ha.xml --std-out=echo
batch

/subsystem=keycloak-server/spi=userCache/provider=default/:write-attribute(name=enabled,value=false)

run-batch
stop-embedded-server
-----------------------
<spi name="userCache">
    <provider name="default" enabled="true"/>
</spi>
<spi name="userCache">
    <provider name="default" enabled="false"/>
</spi>
FROM jboss/keycloak:latest
USER root
COPY disable-usercache.cli /opt/jboss/startup-scripts/disable-usercache.cli
USER 1000
embed-server --server-config=standalone-ha.xml --std-out=echo
batch

/subsystem=keycloak-server/spi=userCache/provider=default/:write-attribute(name=enabled,value=false)

run-batch
stop-embedded-server
-----------------------
<spi name="userCache">
    <provider name="default" enabled="true"/>
</spi>
<spi name="userCache">
    <provider name="default" enabled="false"/>
</spi>
FROM jboss/keycloak:latest
USER root
COPY disable-usercache.cli /opt/jboss/startup-scripts/disable-usercache.cli
USER 1000
embed-server --server-config=standalone-ha.xml --std-out=echo
batch

/subsystem=keycloak-server/spi=userCache/provider=default/:write-attribute(name=enabled,value=false)

run-batch
stop-embedded-server

Quarkus GraphQL Client with Keycloak

copy iconCopydownload iconDownload
DynamicGraphQLClientBuilder.newBuilder()
   .header("KEY", "VALUE") // obtain the correct value from Keycloak and pass it here
.... 
-----------------------
@Singleton
public class Client {

    public IClient client;

    public Client(JsonWebToken accessToken) {
        client = TypesafeGraphQLClientBuilder.newBuilder()
                .header("Authorization", "Bearer " + accessToken.getRawToken())
                .build(IClient.class);
    }
}

Using Keycloak adapter with Wildfly 26 does not provide &quot;KEYCLOAK&quot; as mechanism

copy iconCopydownload iconDownload
{
  "realm": "myrealm",
  "client-id": "my-client-app",
  "auth-server-url": "${keycloak.url}/auth",
  "provider-url": "${keycloak.url}/auth/realms/myrealm",
  "bearer-only": true,
  "enable-cors": true,
  "ssl-required": "none"
}
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <!-- other configuration -->

    <login-config>
        <auth-method>OIDC</auth-method>
    </login-config>

</web-app>
-----------------------
{
  "realm": "myrealm",
  "client-id": "my-client-app",
  "auth-server-url": "${keycloak.url}/auth",
  "provider-url": "${keycloak.url}/auth/realms/myrealm",
  "bearer-only": true,
  "enable-cors": true,
  "ssl-required": "none"
}
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <!-- other configuration -->

    <login-config>
        <auth-method>OIDC</auth-method>
    </login-config>

</web-app>
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}
-----------------------
/subsystem=elytron/token-realm=xyz2ap112-token-realm/:add(\
    principal-claim=preferred_username,\
    oauth2-introspection={\
        client-id=xyz2ap112-web-api,\
        client-secret=${env.keycloak_client_secret},\
        introspection-url=${env.keycloak_introspection_url}\
    }\
)
/subsystem=elytron/simple-role-decoder=xyz2ap112-realm-access-roles/:add(\
    attribute=realm_access_roles\
)
/subsystem=elytron/security-domain=xyz2ap112-token-security-domain/:add(\
    realms=[{realm="xyz2ap112-token-realm",role-decoder="xyz2ap112-realm-access-roles"}],\
    default-realm=xyz2ap112-token-realm,\
    permission-mapper=default-permission-mapper\
)
/subsystem=elytron/http-authentication-factory=xyz2ap112-web-api-authentication-factory/:add(\
    security-domain=xyz2ap112-token-security-domain,\
    mechanism-configurations=[{\
        mechanism-name=BEARER_TOKEN,\
        mechanism-realm-configurations=[realm-name=xyz2ap112-token-realm]\
    }],\
    http-server-mechanism-factory=global\
)
/subsystem=ejb3/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    security-domain=xyz2ap112-token-security-domain\
)
/subsystem=undertow/application-security-domain=xyz2ap112-web-api-security-domain/:add(\
    http-authentication-factory=xyz2ap112-web-api-authentication-factory,\
    override-deployment-config=true\
)
<jboss-web>
    <context-root>/xyz2ap112-web-api</context-root>
    <resource-ref>
        <res-ref-name>jdbc/xyz2ap112</res-ref-name> <!-- Logical name only. -->
        <jndi-name>java:/jdbc/xyz2ap112</jndi-name> <!-- Real JNDI name. -->
    </resource-ref>
    <security-domain>xyz2ap112-web-api-security-domain</security-domain>
</jboss-web>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>xyz2ap112-web-api-security-domain</realm-name>
</login-config>
{
    "client-id": "xyz2ap112-web",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "public-client": true,
    "ssl-required": "external"
}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1098)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:883)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
    at org.xyz.jax.rs.client.base.AbstractFacadeServiceClient.find(AbstractFacadeServiceClient.java:28)
    at xyz2.BarrioFacadeClient.find(BarrioFacadeClient.java:40)
    at xyz2.BarrioFacadeClient.main(BarrioFacadeClient.java:24)
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
    ...
                    <h1 id="kc-page-title">
                        Sign in to your account
                    </h1>
    ...
</html>
{
    "client-id": "xyz2ap112-web-api",
    "confidential-port": 8543,
    "principal-attribute": "preferred_username",
    "provider-url": "http://localhost:8180/auth/realms/jrcam",
    "ssl-required": "external",
    "bearer-only": true,
    "verify-token-audience": true,
    "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk3PD30r3SQBqnO15g/Jc5z3NFnt9HLA6QlQt2QLtxvGhLcerTD2rVWCst/4NSQev9dBscFnwxXyAoZAqTm7w0oPzlhw1Xbqt1dpKdNjMtbJxmpqzCRLTjmNatPmoAGx+9TWOPKw1qfEwZOy9xOqnCbBeT5eGCAXci+wvt8mpNX9lpAguFxgpFtyVc0at35Lw3BdZ13+6Ljxu6Z+mam1tQ9mwey0ubfhV3NK0eN8jruKWrCyGw6DRbmvKFTwQa5akDbMWt3H/HaSLMXBOrBKq9He6azVL3dkbdd40drgHtI8G+ANC1NhOPzjPtuifo9U2wHD6o8S03o35mm4xjJNcqQIDAQAB",
    "credentials": {
        "secret": "8c98045a-4640-46e7-9f68-74a289e43b7e"
    }
}

React navigate after login with keycloak

copy iconCopydownload iconDownload
const Auth = (props) => {

     props.navigation...
  }
...
<Auth navigation={navigation} />
...
-----------------------
const Auth = (props) => {

     props.navigation...
  }
...
<Auth navigation={navigation} />
...

Deploying a Keycloak HA cluster to kubernetes | Pods are not discovering each other

copy iconCopydownload iconDownload
export TARGET_NAMESPACE=default

# convenient method to create a service account 
kubectl create serviceaccount keycloak-kubeping-service-account -n $TARGET_NAMESPACE

# No convenient method to create Role and RoleBindings
# Needed to explicitly define them.
cat <<EOF | kubectl apply -f -
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: keycloak-kubeping-pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]

---

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: keycloak-kubeping-api-access
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: keycloak-kubeping-pod-reader
subjects:
- kind: ServiceAccount
  name: keycloak-kubeping-service-account
  namespace: $TARGET_NAMESPACE

EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: keycloak
spec:
  template:
    spec:
      serviceAccount: keycloak-kubeping-service-account
      serviceAccountName: keycloak-kubeping-service-account
      containers:
      - name: keycloak
        image: jboss/keycloak
        env:
#          ...
            - name: JGROUPS_DISCOVERY_PROTOCOL
              value: kubernetes.KUBE_PING
            - name: JGROUPS_DISCOVERY_PROPERTIES
              value: dump_requests=true
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
#          ...
-----------------------
export TARGET_NAMESPACE=default

# convenient method to create a service account 
kubectl create serviceaccount keycloak-kubeping-service-account -n $TARGET_NAMESPACE

# No convenient method to create Role and RoleBindings
# Needed to explicitly define them.
cat <<EOF | kubectl apply -f -
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: keycloak-kubeping-pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]

---

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: keycloak-kubeping-api-access
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: keycloak-kubeping-pod-reader
subjects:
- kind: ServiceAccount
  name: keycloak-kubeping-service-account
  namespace: $TARGET_NAMESPACE

EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: keycloak
spec:
  template:
    spec:
      serviceAccount: keycloak-kubeping-service-account
      serviceAccountName: keycloak-kubeping-service-account
      containers:
      - name: keycloak
        image: jboss/keycloak
        env:
#          ...
            - name: JGROUPS_DISCOVERY_PROTOCOL
              value: kubernetes.KUBE_PING
            - name: JGROUPS_DISCOVERY_PROPERTIES
              value: dump_requests=true
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
#          ...

Keycloak token verification fails when the backend is running in a Docker container

copy iconCopydownload iconDownload
{
  "issuer":"https://keycloak-container-name/auth/realms/<your-realm>",
  ...
}
{
  "issuer":"http://localhost:8080/auth/realms/<your-realm>",
  ...
}
{
  "issuer":"http://localhost:8080/auth/realms/<your-realm>",
  ...
}
-----------------------
{
  "issuer":"https://keycloak-container-name/auth/realms/<your-realm>",
  ...
}
{
  "issuer":"http://localhost:8080/auth/realms/<your-realm>",
  ...
}
{
  "issuer":"http://localhost:8080/auth/realms/<your-realm>",
  ...
}
-----------------------
{
  "issuer":"https://keycloak-container-name/auth/realms/<your-realm>",
  ...
}
{
  "issuer":"http://localhost:8080/auth/realms/<your-realm>",
  ...
}
{
  "issuer":"http://localhost:8080/auth/realms/<your-realm>",
  ...
}

OAUTH2 user service with Custom Authentication Providers

copy iconCopydownload iconDownload
@Controller
public class Tenant1HomeController {

    @GetMapping("/tenant1/home")
    public String home() {
        return "tenant1Home";
    }

}
@Controller
public class Tenant2HomeController {

    @GetMapping("/tenant2/home")
    public String home() {
        return "tenant2Home";
    }

}
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .antMatchers("/manage/**").permitAll()
                .antMatchers("/api/auth-info").permitAll()
                .antMatchers("/api/**").authenticated()
                .antMatchers("/management/health").permitAll()
                .antMatchers("/management/info").permitAll()
                .antMatchers("/management/prometheus").permitAll()
                .antMatchers("/management/**").hasAuthority("ADMIN")
                .antMatchers("/tenant1/**").authenticated()
                .and()
                .oauth2Login()
                .and()
                .cors()
                .disable();
    }
}
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new AntPathRequestMatcher("/tenant2/**"))
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
                .and()
                .httpBasic();
        http.cors().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}password")
                .roles("BASIC_USER");
    }
}
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: myclient
            client-secret: c6dce03e-ea13-4b76-8aab-c876f5c2c1d9
        provider:
          keycloak:
            issuer-uri: http://localhost:8180/auth/realms/myrealm
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
            ...
            .and()
            .oauth2Login()
            .and()
            ...
            
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(XXX)
-----------------------
@Controller
public class Tenant1HomeController {

    @GetMapping("/tenant1/home")
    public String home() {
        return "tenant1Home";
    }

}
@Controller
public class Tenant2HomeController {

    @GetMapping("/tenant2/home")
    public String home() {
        return "tenant2Home";
    }

}
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .antMatchers("/manage/**").permitAll()
                .antMatchers("/api/auth-info").permitAll()
                .antMatchers("/api/**").authenticated()
                .antMatchers("/management/health").permitAll()
                .antMatchers("/management/info").permitAll()
                .antMatchers("/management/prometheus").permitAll()
                .antMatchers("/management/**").hasAuthority("ADMIN")
                .antMatchers("/tenant1/**").authenticated()
                .and()
                .oauth2Login()
                .and()
                .cors()
                .disable();
    }
}
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new AntPathRequestMatcher("/tenant2/**"))
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
                .and()
                .httpBasic();
        http.cors().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}password")
                .roles("BASIC_USER");
    }
}
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: myclient
            client-secret: c6dce03e-ea13-4b76-8aab-c876f5c2c1d9
        provider:
          keycloak:
            issuer-uri: http://localhost:8180/auth/realms/myrealm
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
            ...
            .and()
            .oauth2Login()
            .and()
            ...
            
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(XXX)
-----------------------
@Controller
public class Tenant1HomeController {

    @GetMapping("/tenant1/home")
    public String home() {
        return "tenant1Home";
    }

}
@Controller
public class Tenant2HomeController {

    @GetMapping("/tenant2/home")
    public String home() {
        return "tenant2Home";
    }

}
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .antMatchers("/manage/**").permitAll()
                .antMatchers("/api/auth-info").permitAll()
                .antMatchers("/api/**").authenticated()
                .antMatchers("/management/health").permitAll()
                .antMatchers("/management/info").permitAll()
                .antMatchers("/management/prometheus").permitAll()
                .antMatchers("/management/**").hasAuthority("ADMIN")
                .antMatchers("/tenant1/**").authenticated()
                .and()
                .oauth2Login()
                .and()
                .cors()
                .disable();
    }
}
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new AntPathRequestMatcher("/tenant2/**"))
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
                .and()
                .httpBasic();
        http.cors().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}password")
                .roles("BASIC_USER");
    }
}
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: myclient
            client-secret: c6dce03e-ea13-4b76-8aab-c876f5c2c1d9
        provider:
          keycloak:
            issuer-uri: http://localhost:8180/auth/realms/myrealm
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
            ...
            .and()
            .oauth2Login()
            .and()
            ...
            
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(XXX)
-----------------------
@Controller
public class Tenant1HomeController {

    @GetMapping("/tenant1/home")
    public String home() {
        return "tenant1Home";
    }

}
@Controller
public class Tenant2HomeController {

    @GetMapping("/tenant2/home")
    public String home() {
        return "tenant2Home";
    }

}
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .antMatchers("/manage/**").permitAll()
                .antMatchers("/api/auth-info").permitAll()
                .antMatchers("/api/**").authenticated()
                .antMatchers("/management/health").permitAll()
                .antMatchers("/management/info").permitAll()
                .antMatchers("/management/prometheus").permitAll()
                .antMatchers("/management/**").hasAuthority("ADMIN")
                .antMatchers("/tenant1/**").authenticated()
                .and()
                .oauth2Login()
                .and()
                .cors()
                .disable();
    }
}
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new AntPathRequestMatcher("/tenant2/**"))
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
                .and()
                .httpBasic();
        http.cors().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}password")
                .roles("BASIC_USER");
    }
}
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: myclient
            client-secret: c6dce03e-ea13-4b76-8aab-c876f5c2c1d9
        provider:
          keycloak:
            issuer-uri: http://localhost:8180/auth/realms/myrealm
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
            ...
            .and()
            .oauth2Login()
            .and()
            ...
            
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(XXX)
-----------------------
@Controller
public class Tenant1HomeController {

    @GetMapping("/tenant1/home")
    public String home() {
        return "tenant1Home";
    }

}
@Controller
public class Tenant2HomeController {

    @GetMapping("/tenant2/home")
    public String home() {
        return "tenant2Home";
    }

}
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .antMatchers("/manage/**").permitAll()
                .antMatchers("/api/auth-info").permitAll()
                .antMatchers("/api/**").authenticated()
                .antMatchers("/management/health").permitAll()
                .antMatchers("/management/info").permitAll()
                .antMatchers("/management/prometheus").permitAll()
                .antMatchers("/management/**").hasAuthority("ADMIN")
                .antMatchers("/tenant1/**").authenticated()
                .and()
                .oauth2Login()
                .and()
                .cors()
                .disable();
    }
}
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new AntPathRequestMatcher("/tenant2/**"))
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
                .and()
                .httpBasic();
        http.cors().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}password")
                .roles("BASIC_USER");
    }
}
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: myclient
            client-secret: c6dce03e-ea13-4b76-8aab-c876f5c2c1d9
        provider:
          keycloak:
            issuer-uri: http://localhost:8180/auth/realms/myrealm
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
            ...
            .and()
            .oauth2Login()
            .and()
            ...
            
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(XXX)
-----------------------
@Controller
public class Tenant1HomeController {

    @GetMapping("/tenant1/home")
    public String home() {
        return "tenant1Home";
    }

}
@Controller
public class Tenant2HomeController {

    @GetMapping("/tenant2/home")
    public String home() {
        return "tenant2Home";
    }

}
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .antMatchers("/manage/**").permitAll()
                .antMatchers("/api/auth-info").permitAll()
                .antMatchers("/api/**").authenticated()
                .antMatchers("/management/health").permitAll()
                .antMatchers("/management/info").permitAll()
                .antMatchers("/management/prometheus").permitAll()
                .antMatchers("/management/**").hasAuthority("ADMIN")
                .antMatchers("/tenant1/**").authenticated()
                .and()
                .oauth2Login()
                .and()
                .cors()
                .disable();
    }
}
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new AntPathRequestMatcher("/tenant2/**"))
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
                .and()
                .httpBasic();
        http.cors().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}password")
                .roles("BASIC_USER");
    }
}
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: myclient
            client-secret: c6dce03e-ea13-4b76-8aab-c876f5c2c1d9
        provider:
          keycloak:
            issuer-uri: http://localhost:8180/auth/realms/myrealm
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
            ...
            .and()
            .oauth2Login()
            .and()
            ...
            
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(XXX)
-----------------------
@Controller
public class Tenant1HomeController {

    @GetMapping("/tenant1/home")
    public String home() {
        return "tenant1Home";
    }

}
@Controller
public class Tenant2HomeController {

    @GetMapping("/tenant2/home")
    public String home() {
        return "tenant2Home";
    }

}
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .antMatchers("/manage/**").permitAll()
                .antMatchers("/api/auth-info").permitAll()
                .antMatchers("/api/**").authenticated()
                .antMatchers("/management/health").permitAll()
                .antMatchers("/management/info").permitAll()
                .antMatchers("/management/prometheus").permitAll()
                .antMatchers("/management/**").hasAuthority("ADMIN")
                .antMatchers("/tenant1/**").authenticated()
                .and()
                .oauth2Login()
                .and()
                .cors()
                .disable();
    }
}
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new AntPathRequestMatcher("/tenant2/**"))
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
                .and()
                .httpBasic();
        http.cors().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}password")
                .roles("BASIC_USER");
    }
}
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: myclient
            client-secret: c6dce03e-ea13-4b76-8aab-c876f5c2c1d9
        provider:
          keycloak:
            issuer-uri: http://localhost:8180/auth/realms/myrealm
@Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
            ...
            .and()
            .oauth2Login()
            .and()
            ...
            
@Order(90)
@Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(XXX)

How to save the keycloak data when running inside docker container?

copy iconCopydownload iconDownload
mkdir -m 777 ./keycloak_data
docker run -v ./keycloak_data:/opt/jboss/keycloak/standalone/data/ -p 8080:8080  -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:15.0.2
docker run -v ./keycloak_data:/opt/jboss/keycloak/standalone/data/ -p 8080:8080 quay.io/keycloak/keycloak:15.0.2
-----------------------
mkdir -m 777 ./keycloak_data
docker run -v ./keycloak_data:/opt/jboss/keycloak/standalone/data/ -p 8080:8080  -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:15.0.2
docker run -v ./keycloak_data:/opt/jboss/keycloak/standalone/data/ -p 8080:8080 quay.io/keycloak/keycloak:15.0.2
-----------------------
mkdir -m 777 ./keycloak_data
docker run -v ./keycloak_data:/opt/jboss/keycloak/standalone/data/ -p 8080:8080  -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:15.0.2
docker run -v ./keycloak_data:/opt/jboss/keycloak/standalone/data/ -p 8080:8080 quay.io/keycloak/keycloak:15.0.2

Spring Boot Keycloak Multi Tenant Configuration

copy iconCopydownload iconDownload
public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {

    @Override
    public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
        if (request.getPath().startsWith("alternative")) { // or some other criteria 
            InputStream is = getClass().getResourceAsStream("/tenant1-keycloak.json");
            return KeycloakDeploymentBuilder.build(is); //TODO: cache result
        } else {
            InputStream is = getClass().getResourceAsStream("/default-keycloak.json");
            return KeycloakDeploymentBuilder.build(is); //TODO: cache result
        }
    }    
}
@Configuration
@EnableWebSecurity
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Bean
    public KeycloakConfigResolver keycloakConfigResolver() {
        return new PathBasedKeycloakConfigResolver();
    }

    [...]
}
-----------------------
public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {

    @Override
    public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
        if (request.getPath().startsWith("alternative")) { // or some other criteria 
            InputStream is = getClass().getResourceAsStream("/tenant1-keycloak.json");
            return KeycloakDeploymentBuilder.build(is); //TODO: cache result
        } else {
            InputStream is = getClass().getResourceAsStream("/default-keycloak.json");
            return KeycloakDeploymentBuilder.build(is); //TODO: cache result
        }
    }    
}
@Configuration
@EnableWebSecurity
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Bean
    public KeycloakConfigResolver keycloakConfigResolver() {
        return new PathBasedKeycloakConfigResolver();
    }

    [...]
}

Add custom validation in Update User Profile in Keycloak

copy iconCopydownload iconDownload
    public List<FormMessage> getCustomAttributeError(String organization) {
        List<FormMessage> errors = new ArrayList<>();

        // You can add more conditions & parameters to be validated
        if(Validation.isBlank(organization)){
            errors.add(new FormMessage("organization", "missingOrganizationMessage"));
        }

        return errors;
    }
    if(getCustomAttributeError(profile.getAttributes().getFirstValue("organization")).size() > 0){
        throw new ValidationException();                
    }
    List<FormMessage> extraErrors = getCustomAttributeErrors(profile.getAttributes().getFirstValue("organization"));
    for(FormMessage error : extraErrors) {
        errors.add(error);
    }
-----------------------
    public List<FormMessage> getCustomAttributeError(String organization) {
        List<FormMessage> errors = new ArrayList<>();

        // You can add more conditions & parameters to be validated
        if(Validation.isBlank(organization)){
            errors.add(new FormMessage("organization", "missingOrganizationMessage"));
        }

        return errors;
    }
    if(getCustomAttributeError(profile.getAttributes().getFirstValue("organization")).size() > 0){
        throw new ValidationException();                
    }
    List<FormMessage> extraErrors = getCustomAttributeErrors(profile.getAttributes().getFirstValue("organization"));
    for(FormMessage error : extraErrors) {
        errors.add(error);
    }
-----------------------
    public List<FormMessage> getCustomAttributeError(String organization) {
        List<FormMessage> errors = new ArrayList<>();

        // You can add more conditions & parameters to be validated
        if(Validation.isBlank(organization)){
            errors.add(new FormMessage("organization", "missingOrganizationMessage"));
        }

        return errors;
    }
    if(getCustomAttributeError(profile.getAttributes().getFirstValue("organization")).size() > 0){
        throw new ValidationException();                
    }
    List<FormMessage> extraErrors = getCustomAttributeErrors(profile.getAttributes().getFirstValue("organization"));
    for(FormMessage error : extraErrors) {
        errors.add(error);
    }

Community Discussions

Trending Discussions on keycloak
  • Confidential Rest-Api w/ Permissions - Always 403s - What Am I Doing Wrong?
  • How to access the original case sensitive username input in custom user storage provider of keycloak?
  • Keycloak 17: Unsatisfied dependency for type org.keycloak.models.KeycloakSession and qualifiers [@Default]
  • Quarkus GraphQL Client with Keycloak
  • Using Keycloak adapter with Wildfly 26 does not provide &quot;KEYCLOAK&quot; as mechanism
  • React navigate after login with keycloak
  • Secure WebApp in Wildfly 25 using OpenID Connect (OIDC) without installing a Keycloak client adapter
  • How to modify existing claims in JWT from Keycloak for OIDC flow?
  • Deploying a Keycloak HA cluster to kubernetes | Pods are not discovering each other
  • keycloak + Kong API Gateway
Trending Discussions on keycloak

QUESTION

Confidential Rest-Api w/ Permissions - Always 403s - What Am I Doing Wrong?

Asked 2022-Apr-11 at 18:17

I've tried for many hours now and seem to have hit a wall. Any advice/help would be appreciated.

Goal: I want to authorize the express rest-api (ex client-id: "my-rest-api") routes (example resource: "WeatherForecast") across various HTTP methods mapped to client scopes (examples: "create"/"read"/"update"/"delete"). I want to control those permissions through policies (For example - "Read - WeatherForecast - Permission" will be granted if policy "Admin Group Only" (user belongs to admin group) is satisfied.

Rest-api will not log users in (will be done from front end talking directly to keycloak and then they will use that token to talk with rest-api).

Environment:

What Happens: I can login from keycloak login page through postman and get an access token. However when I hit any endpoint that uses keycloak.protect() or keycloak.enforce() (with or without specifying resource permissions) I can't get through. In the following code the delete endpoint returns back 200 + the HTML of the keycloak login page in postman and the Get returns back 403 + "Access Denied".

Current State of Realm

  • Test User (who I login with in Postman) has group "Admin".
  • Client "my-rest-api" with access-type: Confidential with Authorization enabled.
  • Authorization set up:
    • Policy Enforcement Mode: Enforcing, Decision Strategy: Unanimous
    • "WeatherForecast" resource with uri "/api/WeatherForecast" and create/read/update/delete client scopes applied.
    • "Only Admins Policy" for anyone in group admin. Logic positive.
    • Permission for each of the client scopes for "WeatherForecast" resource with "Only Admins Policy" selected, Decision Strategy: "Affirmative".

Current State of Nodejs Code:

import express from 'express';
import bodyParser from 'body-parser';
import session from "express-session";
import KeycloakConnect from 'keycloak-connect';

const app = express();

app.use(bodyParser.json());

const memoryStore = new session.MemoryStore();
app.use(session({
    secret: 'some secret',
    resave: false,
    saveUninitialized: true,
    store: memoryStore
  }));

const kcConfig: any = { 
    clientId: 'my-rest-api',
    bearerOnly: true,
    serverUrl: 'http://localhost:8080/auth',
    realm: 'my-realm',
};
const keycloak = new KeycloakConnect({ store: memoryStore }, kcConfig);

app.use(keycloak.middleware({
    logout: '/logout',
    admin: '/',
}));

app.get('/api/WeatherForecast', keycloak.enforcer(['WeatherForecast:read'],{  resource_server_id: "my-rest-api"}), function (req, res) {
   res.json("GET worked")
  });

app.delete('/api/WeatherForecast', keycloak.protect(), function (req, res) {
     res.json("DELETE worked")
});

app.listen(8081, () => {
    console.log(`server running on port 8081`);
  });
  

A Few Other Things Tried:

  • I tried calling RPT endpoint with curl using token gotten from postman and got the RPT token perfectly fine, saw permissions as expected.
  • I tried calling keycloak.checkPermissions({permissions: [{id: "WeatherForecast", scopes: ["read"]}]}, req).then(grant => res.json(grant.access_token)); from inside an unsecured endpoint and got "Connection refused 127.0.0.1:8080".
  • I tried just disabling Policy Enforcement Mode just to see, still got Access Denied/403.
  • I tried using keycloak.json config instead of object method above - same exact results either way.
  • I tried openid-client (from another tutorial) and also got connected refused issues.
  • I've tried using docker host ip, host.docker.internal, the container name, etc. to no avail (even though I don't think it is an issue as I obviously can hit the auth service and get the first access token).

I really want to use Keycloak and I feel like my team is so close to being able to do so but need some assistance getting past this part. Thank you!

------------------- END ORIGINAL QUESTION ------------------------

EDIT/UPDATE #1: Alright so a couple more hours sank into this. Decided to read through every line of keycloak-connect library that it hits and debug as it goes. Found it fails inside keycloak-connect/middleware/auth-utils/grant-manager.js on the last line of checkPermissions. No error is displayed or catch block to debug on - chasing the rabbit hole down further I was able to find it occurs in the fetch method that uses http with options:

'{"protocol":"http:","slashes":true,"auth":null,"host":"localhost:8080","port":"8080","hostname":"localhost","hash":null,"search":null,"query":null,"pathname":"/auth/realms/my-realm/protocol/openid-connect/token","path":"/auth/realms/my-realm/protocol/openid-connect/token","href":"http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/token","headers":{"Content-Type":"application/x-www-form-urlencoded","X-Client":"keycloak-nodejs-connect","Authorization":"Basic YW(etc...)Z2dP","Content-Length":1498},"method":"POST"}'

It does not appear to get into the callback of that fetch/http wrapper. I added NODE_DEBUG=http to my start up command and was able to find that swallowed error, which appears I am back to the starting line:

HTTP 31: SOCKET ERROR: connect ECONNREFUSED 127.0.0.1:8080 Error: connect ECONNREFUSED 127.0.0.1:8080

    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1157:16)

    at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17)

I then saw something that I thought may be related due to my docker network set up (Keycloak and Spring Boot web app in dockerized environment) and tried change host name dns so I could use something other then local host but it didn't work either (even added to redirect uri, etc.).

UPDATE #2: Alright so I got the keycloak.protect() (pure authentication) endpoint working now. I found through reading through the keycloak-connect lib code more options and it seems that adding "realmPublicKey" to the keycloak config object when instantiating keycloak-connect fixed that one. Still no luck yet on the authorization keycloak.enforce side.

const kcConfig: any = { 
    clientId: 'my-rest-api',
    bearerOnly: true,
    serverUrl: 'http://localhost:8080/auth',
    realm: 'my-realm',
    realmPublicKey : "MIIBIjANBgk (...etc) uQIDAQAB",
};

ANSWER

Answered 2022-Apr-11 at 18:17

So my team finally figured it out - the resolution was a two part process:

  1. Followed the instructions on similar issue stackoverflow question answers such as : https://stackoverflow.com/a/51878212/5117487 Rough steps incase that link is ever broken somehow:
  • Add hosts entry for 127.0.0.1 keycloak (if 'keycloak' is the name of your docker container for keycloak, I changed my docker-compose to specify container name to make it a little more fool-proof)
  • Change keycloak-connect config authServerUrl setting to be: 'http://keycloak:8080/auth/' instead of 'http://localhost:8080/auth/'
  1. Postman OAuth 2.0 token request Auth URL and Access Token URL changed to use the now updated hosts entry:
  • "http://localhost:8080/auth/realms/abra/protocol/openid-connect/auth" -> "http://keycloak:8080/auth/realms/abra/protocol/openid-connect/auth"
  • "http://localhost:8080/auth/realms/abra/protocol/openid-connect/token" -> "http://keycloak:8080/auth/realms/abra/protocol/openid-connect/token"

Source https://stackoverflow.com/questions/71802757

Community Discussions, Code Snippets contain sources that include Stack Exchange Network

Vulnerabilities

No vulnerabilities reported

Install keycloak

To run Keycloak download the distribution from our website. Unzip and run:.

Support

DocumentationUser Mailing List - Mailing list for help and general questions about Keycloak

DOWNLOAD this Library from

Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases

Save this library and start creating your kit

Explore Related Topics

Share this Page

share link
Consider Popular Identity Management Libraries
Compare Identity Management Libraries with Highest Support
Compare Identity Management Libraries with Permissive License
Compare Identity Management Libraries with Highest Reuse
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases

Save this library and start creating your kit

  • © 2022 Open Weaver Inc.