Proposal: HttpClient SPI improvements
by Dmitry Telegin
Hi,
We are considering the following improvements to the HttpClient SPI:
- ability to return a JAX-RS client instance in addition to Apache HttpClient. The former will use the latter as an engine;
- multiple clients with config param overrides (pooling/TTLs/timeouts/etc.)
Just wanted to know if the Keycloak team would be interested in having this in upstream.
The main purpose is to simplify development of the providers that consume multiple external REST services. Background: our in-house providers are currently using ad-hoc ResteasyClient, and there are concerns about thread safety and code duplication, so we're looking into migrating to the built-in HttpClient wrapped into JAX-RS client.
Regards,
Dmitry
5 years, 3 months
Unable to connect to an external datasource for a protocol mapper
by Thomas
I'm a little inexperienced when it comes to Java EE. So let me apoligize
because I'm guessing this will be a small setup mistake. I've setup
databases for applications but I'm having a really tough time with
connecting to for a Keycloak module. The database exists separate from
Keycloak's user db and a LDAP/AD because other services for our application
need to access the claims database through rabbitmq and rest services.
I'm able to setup a datasource in Wildfly and verify it can connect to the
database. So I know the connection info is good. The module successfully
deploys to Keycloak. When the Protocol Mapper is ran, I only try checking
the nullity of the EntityManager that should be injected as well as one
that gets created from the PU by hand. The injected em is null and the one
created on a spot throws an exception about being unable to find the
persistence.xml file.
What are some good troubleshooting techniques for developing in Keycloak?
Is it more appropriate to turn up the hibernate logger in Keycloak or
Wildfly?
Could someone take a look at an exmple give me some advice?
A code example is at https://github.com/tlann/tokenEnhancer.git
The deployment log and exception are as follows
Thanks,
Thomas
17:06:51,406 INFO [org.jboss.as.server.deployment] (MSC service thread
1-4) WFLYSRV0027: Starting deployment of
"token-enhancer-ear-1.0.0-SNAPSHOT.ear" (runtime-name:
"token-enhancer-ear-1.0.0-SNAPSHOT.ear")
17:06:51,493 INFO [org.jboss.as.server.deployment] (MSC service thread
1-2) WFLYSRV0207: Starting subdeployment (runtime-name:
"com.example.security-token-enhancer-module-1.0.0-SNAPSHOT.jar")
17:06:51,497 INFO [org.jboss.as.jpa] (MSC service thread 1-4) WFLYJPA0002:
Read persistence.xml for UserPU
17:06:51,514 INFO [org.jboss.as.jpa] (MSC service thread 1-4) WFLYJPA0002:
Read persistence.xml for UserPU
17:06:51,539 WARN [org.jboss.as.dependency.private] (MSC service thread
1-1) WFLYSRV0018: Deployment
"deployment.token-enhancer-ear-1.0.0-SNAPSHOT.ear.com.example.security-token-enhancer-module-1.0.0-SNAPSHOT.jar"
is using a private module ("org.keycloak.keycloak-services") which may be
changed or removed in future versions without notice.
17:06:51,553 WARN [org.jboss.as.dependency.private] (MSC service thread
1-4) WFLYSRV0018: Deployment
"deployment.token-enhancer-ear-1.0.0-SNAPSHOT.ear" is using a private
module ("org.keycloak.keycloak-services") which may be changed or removed
in future versions without notice.
17:06:51,555 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 81)
WFLYJPA0010: Starting Persistence Unit (phase 1 of 2) Service
'token-enhancer-ear-1.0.0-SNAPSHOT.ear/com.example.security-token-enhancer-module-1.0.0-SNAPSHOT.jar#UserPU'
17:06:51,555 INFO [org.hibernate.jpa.internal.util.LogHelper]
(ServerService Thread Pool -- 81) HHH000204: Processing PersistenceUnitInfo
[
name: UserPU
...]
17:06:51,575 INFO [org.jboss.weld.deployer] (MSC service thread 1-3)
WFLYWELD0003: Processing weld deployment
token-enhancer-ear-1.0.0-SNAPSHOT.ear
17:06:51,599 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 82)
WFLYJPA0010: Starting Persistence Unit (phase 1 of 2) Service
'token-enhancer-ear-1.0.0-SNAPSHOT.ear#UserPU'
17:06:51,599 INFO [org.hibernate.jpa.internal.util.LogHelper]
(ServerService Thread Pool -- 82) HHH000204: Processing PersistenceUnitInfo
[
name: UserPU
...]
17:06:51,643 INFO
[org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor]
(MSC service thread 1-3) Deploying Keycloak provider:
com.example.security-token-enhancer-module-1.0.0-SNAPSHOT.jar
17:06:51,678 WARN [org.keycloak.services] (MSC service thread 1-3)
KC-SERVICES0047: oidc-token-enhancer-mapper
(business.KeycloakTokenEnhancer) is implementing the internal SPI
protocol-mapper. This SPI is internal and may change without notice
17:06:51,701 INFO [org.jboss.weld.deployer] (MSC service thread 1-3)
WFLYWELD0003: Processing weld deployment
com.example.security-token-enhancer-module-1.0.0-SNAPSHOT.jar
17:06:51,779 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 81)
WFLYJPA0010: Starting Persistence Unit (phase 2 of 2) Service
'token-enhancer-ear-1.0.0-SNAPSHOT.ear/com.example.security-token-enhancer-module-1.0.0-SNAPSHOT.jar#UserPU'
17:06:51,780 INFO [org.hibernate.dialect.Dialect] (ServerService Thread
Pool -- 81) HHH000400: Using dialect:
org.hibernate.dialect.PostgreSQL95Dialect
17:06:51,797 INFO
[org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl]
(ServerService Thread Pool -- 81) HHH000424: Disabling contextual LOB
creation as createClob() method threw error :
java.lang.reflect.InvocationTargetException
17:06:51,797 INFO [org.hibernate.type.BasicTypeRegistry] (ServerService
Thread Pool -- 81) HHH000270: Type registration [java.util.UUID] overrides
previous : org.hibernate.type.UUIDBinaryType@3e14892a
17:06:51,801 INFO [org.hibernate.envers.boot.internal.EnversServiceImpl]
(ServerService Thread Pool -- 81) Envers integration enabled? : true
17:06:51,820 WARN
[org.infinispan.hibernate.cache.v53.InfinispanRegionFactory]
(ServerService Thread Pool -- 81) HHH025030: Transactional caches are not
supported. The configuration option will be ignored; please unset.
17:06:51,820 WARN
[org.infinispan.hibernate.cache.v53.InfinispanRegionFactory]
(ServerService Thread Pool -- 81) HHH025030: Transactional caches are not
supported. The configuration option will be ignored; please unset.
17:06:51,821 WARN
[org.infinispan.hibernate.cache.v53.InfinispanRegionFactory]
(ServerService Thread Pool -- 81) HHH025030: Transactional caches are not
supported. The configuration option will be ignored; please unset.
17:06:51,821 WARN
[org.infinispan.hibernate.cache.v53.InfinispanRegionFactory]
(ServerService Thread Pool -- 81) HHH025030: Transactional caches are not
supported. The configuration option will be ignored; please unset.
17:06:51,854 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 82)
WFLYJPA0010: Starting Persistence Unit (phase 2 of 2) Service
'token-enhancer-ear-1.0.0-SNAPSHOT.ear#UserPU'
17:06:51,855 INFO [org.hibernate.dialect.Dialect] (ServerService Thread
Pool -- 82) HHH000400: Using dialect:
org.hibernate.dialect.PostgreSQL95Dialect
17:06:51,868 INFO
[org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl]
(ServerService Thread Pool -- 82) HHH000424: Disabling contextual LOB
creation as createClob() method threw error :
java.lang.reflect.InvocationTargetException
17:06:51,869 INFO [org.hibernate.type.BasicTypeRegistry] (ServerService
Thread Pool -- 82) HHH000270: Type registration [java.util.UUID] overrides
previous : org.hibernate.type.UUIDBinaryType@3e14892a
17:06:51,873 INFO [org.hibernate.envers.boot.internal.EnversServiceImpl]
(ServerService Thread Pool -- 82) Envers integration enabled? : true
17:06:51,882 WARN
[org.infinispan.hibernate.cache.v53.InfinispanRegionFactory]
(ServerService Thread Pool -- 82) HHH025030: Transactional caches are not
supported. The configuration option will be ignored; please unset.
17:06:51,882 WARN
[org.infinispan.hibernate.cache.v53.InfinispanRegionFactory]
(ServerService Thread Pool -- 82) HHH025030: Transactional caches are not
supported. The configuration option will be ignored; please unset.
17:06:51,882 WARN
[org.infinispan.hibernate.cache.v53.InfinispanRegionFactory]
(ServerService Thread Pool -- 82) HHH025030: Transactional caches are not
supported. The configuration option will be ignored; please unset.
17:06:51,883 WARN
[org.infinispan.hibernate.cache.v53.InfinispanRegionFactory]
(ServerService Thread Pool -- 82) HHH025030: Transactional caches are not
supported. The configuration option will be ignored; please unset.
17:06:51,982 INFO [io.smallrye.metrics] (MSC service thread 1-1)
MicroProfile: Metrics activated
17:06:52,273 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2)
WFLYSRV0010: Deployed "token-enhancer-ear-1.0.0-SNAPSHOT.ear" (runtime-name
: "token-enhancer-ear-1.0.0-SNAPSHOT.ear")
17:07:15,373 INFO [stdout] (default task-16)
++++++++++++++++++++++++++++++++
17:07:15,380 INFO [stdout] (default task-16) entityManager is null
17:07:15,381 INFO [org.hibernate.jpa.boot.internal.PersistenceXmlParser]
(default task-16) HHH000318: Could not find any META-INF/persistence.xml
file in the classpath
17:07:15,381 INFO [org.hibernate.jpa.boot.internal.PersistenceXmlParser]
(default task-16) HHH000318: Could not find any META-INF/persistence.xml
file in the classpath
17:07:15,381 INFO [org.hibernate.jpa.boot.internal.PersistenceXmlParser]
(default task-16) HHH000318: Could not find any META-INF/persistence.xml
file in the classpath
17:07:15,381 INFO [org.hibernate.jpa.boot.internal.PersistenceXmlParser]
(default task-16) HHH000318: Could not find any META-INF/persistence.xml
file in the classpath
17:07:15,381 INFO [org.hibernate.jpa.boot.internal.PersistenceXmlParser]
(default task-16) HHH000318: Could not find any META-INF/persistence.xml
file in the classpath
17:07:15,381 ERROR [org.keycloak.services.error.KeycloakErrorHandler]
(default task-16) Uncaught server error:
javax.persistence.PersistenceException: No Persistence provider for
EntityManager named UserPU
at
javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
at
javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at
business.KeycloakTokenEnhancer.transformAccessToken(KeycloakTokenEnhancer.java:43)
at
org.keycloak.protocol.oidc.TokenManager.transformAccessToken(TokenManager.java:553)
at
org.keycloak.protocol.oidc.TokenManager.createClientAccessToken(TokenManager.java:411)
at
org.keycloak.protocol.oidc.TokenManager$AccessTokenResponseBuilder.generateAccessToken(TokenManager.java:712)
at
org.keycloak.services.resources.admin.ClientScopeEvaluateResource.generateToken(ClientScopeEvaluateResource.java:206)
at
org.keycloak.services.resources.admin.ClientScopeEvaluateResource.generateExampleAccessToken(ClientScopeEvaluateResource.java:178)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at
org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:138)
at
org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:517)
at
org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:406)
at
org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:370)
at
org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:355)
at
org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:372)
at
org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:344)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:137)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:106)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:132)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:106)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:132)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:106)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:132)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:106)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:132)
at
org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:100)
at
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:440)
at
org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229)
at
org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135)
at
org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:355)
at
org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138)
at
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215)
at
org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227)
at
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
at
io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at
org.keycloak.services.filters.KeycloakSessionServletFilter.doFilter(KeycloakSessionServletFilter.java:90)
at
io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at
io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at
io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at
io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at
io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at
org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
at
io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at
io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at
io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at
io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at
io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at
io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at
io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at
io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at
io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at
io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at
io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at
org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at
org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at
org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at
org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at
org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at
io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at
io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at
io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
at
io.undertow.server.Connectors.executeRootHandler(Connectors.java:364)
at
io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at
org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at
org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
at
org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at
org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
at java.lang.Thread.run(Thread.java:748)
5 years, 3 months
Feedback on PRs
by Stian Thorgersen
First of all thanks to everyone that has sent a PR to Keycloak. Without the
communities participation Keycloak wouldn't be the same!
At the moment we are struggling a bit with keeping up with reviewing PRs so
please bear with us. We are discussing in the team how we can improve on
the current situation. Suggestions are obviously welcome.
We would also love it if people from the community would also participate
in reviewing PRs. We highly value your input.
5 years, 3 months
[KEYCLOAK-6876] advancedMsg in all template
by cedric@couralet.eu
Hello,
I wanted to edit the login page to add the client name (as in Log In to <client.name>), and I also want to have the possibility to localize that client name (as for the account application).
It seems it would be possible if the advancedMsg function was available in all template/page (it is only in two at the moment).
Is there a reason to not put advancedMsg in all page ? (performance or other...)
Would you be open to a PR to that effect ?
Regards,
Cédric Couralet
5 years, 3 months
WebAuthn testing
by Marek Posolda
We have community PR for adding initial webauthn support [1]. The PR is
great work for the start IMO (anyone welcome to review PR :)
But among other things, it touches one of the challenges for webauthn
support, which is automated testing. So far, the PR introduces testing
webauthn with the Chrome WebDriver and the Chrome testing API [2] . The
Chrome Testing API allows chrome browser to "simulate" the webauthn
authenticator without having the real webauthn authenticator device
available.
IMO it is fine to use the Chrome Testing API for the parts, which are
more focus on the Keycloak integration itself rather than on the details
of WebAuthn configurations. From one point of view, it may be sufficient
to test just with Chrome Testing API as Keycloak is just WebAuthn
Relying party and it doesn't need to care which underlying WebAuthn
authenticator was used - that's more the responsibilty of the platform
and web browser, which sends HTTP requests to Keycloak. However I afraid
that there may be some cases where this is not sufficient and we may
need some more proper interoperability testing. Especially for testing
the details of webauthn specification. For example if Keycloak sends the
WebAuthn registration request with "userVerification: required", we may
need to ensure that authentication will fail if userVerification flag is
not provided by the authenticator etc.
So what are possible options?
(a) Use just testing with chrome testing API and rely on the underlying
webauthn library (webauthn4j) to hide the webauthn specification
interoperability testing. This may be the easy option, but not sure
whether sufficient?
(b) Look at WebDriver Authenticator Extension and check if/when it is
possible to use it. Details here [2] (also see the open PR linked from
there). I am not sure when this will be available for us to be able to
consume it, so not sure if this is an option...
(c) Look at FIDO Alliance certification conformance [3] and investigate
if it provides some automated tests, which can be somehow
used/forked/duplicated to our testsuite
(d) Check how webauthn4j library (and eventually some other libraries)
are doing automated tests and inspire from them if possible.
(e) Test manually with some defined set of webauthn authenticators on
some defined set of platforms/browsers. Then investigate which HTTP
requests were sent to Keycloak from the browser for various
configuration options and use those manual tests to create some
"client", which will just use Apache HTTP Client under the covers to
directly send HTTP requests to Keycloak. In other words, just simulate
the browser+OS+Authenticator. This is not ideal, however possibly useful
as a fallback option?
(f) any better option?
[1] https://github.com/keycloak/keycloak/pull/6248/files
[2]
https://chromium.googlesource.com/chromium/src/+/a82bdb76536b5fce18573422...
[3] https://github.com/w3c/webauthn/issues/1236
[4]
https://fidoalliance.org/certification/functional-certification/conformance/
Marek
5 years, 3 months
Support case sensitive usernames
by Marek Posolda
At this moment, Keycloak internally saves all usernames in the DB in
lowercase. This means that if Keycloak DB contains user "john" and user
fills the login form with uppercase like "John", Keycloak is still able
to find the user because it lowercase the username from the login form
to "john" and then query DB for lookup of username "john" . At the same
time, DB queries have good performance as they are not needed to be case
sensitive.
Also when we import users from the 3rd party user storage like ldap, we
first convert them to lowercase. Unfortunately this causes issues for
some users, as they have LDAP users in uppercase like "JOHN" and
usernames in keycloak tokens are returned in lowercase like "john",
which causes issues in some applications.
I see 2 possibilities to address this issue:
1) Have a switch at the realm level to support case-sensitive usernames
2) Address this issue at LDAP level and add special attribute to users
imported from LDAP
More details:
The solution (1) has some more flexibility and is not LDAP specific,
however it may either have non-trivial performance penalty due the
case-sensitive DB searches or it may mean possibility of duplicated
usernames different just by cases like "john", "John" and "JOHN".
I can imagine that switch at realm level will have 3 options similar to
this:
* (a) Don't support case insensitive usernames (default value and
current behaviour). So usernames are lowercased before saving to
Keycloak DB and before DB searches.
* (b) Support case sensitive usernames with case-sensitive duplicated
users. If this option is chosen, it will be possible to have for
example 3 separate Keycloak users like "mposolda", "Mposolda" and
"MPOSOLDA". This will mean that users will need to fill exactly
their case-sensitive username on the login form
* (c) Support case sensitive usernames without case-sensitive
duplicated users. If this option is chosen, you will have
case-sensitive user saved in the DB, however it won't be allowed to
have duplicated usernames different just by cases. So you won't be
able to have "mposolda", "Mposolda" and "MPOSOLDA". The third option
has price-to-pay as DB searches will need to be case-sensitive and
hence may have quite bad performance as mentioned for example in
this blog:
https://alvinalexander.com/sql/sql-select-case-insensitive-query-queries-...
. I am not even convinced whether to ever support this option, I
rather vote for no. Performance may be better once we move away from
RDBMS to Keycloak.next storage, but not sure.
2) Address this issue at LDAP level and add special attribute to users
imported from LDAP. That will allow that LDAP user "MPOSOLDA" can be
mapped to Keycloak user "mposolda". At the Keycloak level, the user
"mposolda" will have the attribute like LDAP_USERNAME with the value
"MPOSOLDA" . In this case, people may need to create protocol mapper,
which will map the LDAP_USERNAME attribute to their token. Protocol
mapper can be added to client scope, which can be added to all required
clients. Not sure if this is workaround or not
So far, I vote for (1) and maybe just add the (a) and (b) options. WDYT?
Marek
5 years, 3 months
Putting a value into a custom Protocol mapper
by Chris Smith
I'm trying to have a custom protocol mapper provide a serialized Kerberos ticket as a claim
I have updated the KerberosUsernamePasswordAuthenticator so that it gets the ticket
public Subject authenticateSubject(String username, String password) throws LoginException {
String principal = getKerberosPrincipal(username);
logger.debug("Validating password of principal: " + principal);
loginContext = new LoginContext("does-not-matter", null,
createJaasCallbackHandler(principal, password),
createJaasConfiguration());
loginContext.login();
serializedKerberosTicket = serializeTicket();
logger.debug("Principal " + principal + " authenticated succesfully");
return loginContext.getSubject();
}
private String serializeTicket() {
KerberosTicket kerberosTicket = loginContext.getSubject()
.getPrivateCredentials(KerberosTicket.class)
.stream().findFirst().get();
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)){
oos.writeObject(kerberosTicket);
return Base64.getEncoder().encodeToString(bos.toByteArray());
} catch (IOException e) {
logger.error("Kerberos ticket serialization failed", e);
return null;
}
}
I reviewed the SPNEGOAuthenticator and traced it's execution to see how it adds the Kerberos ticket and I do not see that as a workable approach as it is so different from the Kerberos User/Password authenticator.
Where can my custom KerberosUsernamePasswordAuthenticator put the serialized ticket so that my custom protocol mapper will get it and add it as a claim on my Access token?
I have looked and googled with no luck.
5 years, 3 months
Do I need a different ODIC protocol mapper?
by Chris Smith
I'm capturing a Kerberos Ticket on a successful Kerberos User/Password authentication. The ticket is then serialized and then saved as a user session note with KerberosConstants.GSS_DELEGATION_CREDENTIAL as the key... because... well... That is what the SPNEGO authentication does. The claim is then converted to a GSSCredential by the existing client adapter (Tomcat in my case)
So even though both are named as a GSSCredential claim, they are really Kerberos Tickets.
Ok, so what. The User/Password ticket is not created by "Delegation", unlike the SPNEGO ticket. Would you guys consider that to be accepted as a PR, it should have a different name and a new protocol mapper is required?
5 years, 3 months
Re: [keycloak-dev] passing SAML extensions and context to custom authenticators
by Caranzo Gideon
Hi Hynek,
Thank you for your response. Yes, I agree with you. It would be good to have this mechanism in those areas as well.
I already have a PR ready for just the SAML login portion. Is it fine with you if I submit this first so that we can use it as early as possible? We can create a separate ticket to implement similar mechanism for other SAML messages and broker endpoint which can be done in near future.
Thanks,
Gideon
-----Original Message-----
From: keycloak-dev-bounces(a)lists.jboss.org [mailto:keycloak-dev-bounces@lists.jboss.org] On Behalf Of Hynek Mlnarik
Sent: Thursday, January 24, 2019 1:58 AM
To: Gideon Caranzo <gideonray(a)gmail.com>
Cc: keycloak-dev <keycloak-dev(a)lists.jboss.org>
Subject: Re: [keycloak-dev] passing SAML extensions and context to custom authenticators
Hi Gideon,
thanks for the idea. Something like that would be a useful enhancement. The implementation would need to cover also the broker endpoint, other SAML message types (extensions are part of message types other than AuthnRequest as well), and count on several implementations of the hypothetical SamlAuthenticationPreprocessor. Could you please file an "Enhancement" JIRA?
--Hynek
On Wed, Jan 16, 2019 at 5:49 PM Gideon Caranzo <gideonray(a)gmail.com> wrote:
> Hi All,
>
> I'd like to propose a feature that allows custom authenticators to
> handle SAML extensions, authentication context and other request attributes.
>
> Right now in OIDC, all request claims are passed to custom
> authenticators which allows for customized behavior depending on the claims.
> However, this is not the case for SAML. Only attributes that are
> explicitly set (e.g. NameID) in the auth session are passed to custom authenticators.
>
> Information like SAML extension and authentication context are not
> available which limits the ability to define custom behaviors. In the
> past, we ran into similar limitation and we had to update keycloak
> core to add support for NameID attribute.
>
> To solve this, we can have an optional hook that pre-process SAML
> login request right before authentication. The hook can then extract
> the needed attributes and set it accordingly for custom authenticators to process.
>
> The pre-processing will be done in
> *SamlService.BindingProtocol.loginRequest()*:
>
> *public* *class* SamlService *extends* AuthorizationEndpointBase {
>
> *. . .*
>
> *public* *abstract* *class* BindingProtocol {
>
> . . .
>
> *protected* Response loginRequest(String relayState,
> AuthnRequestType requestAbstractType, ClientModel client) {
>
> . . .
>
> SamlAuthenticationPreprocessor preProcessor = session
> .getProvider(SamlAuthenticationPreprocessor.*class*);
>
> *if* (preProcessor != *null*) {
>
> preProcessor.process(requestAbstractType, authSession);
>
> }
>
>
>
> *return* newBrowserAuthentication(authSession,
> requestAbstractType.isIsPassive(), redirectToAuthentication);
>
> }
>
>
> Let me know what you think. Thanks.
>
> Best regards,
> Gideon
> _______________________________________________
> keycloak-dev mailing list
> keycloak-dev(a)lists.jboss.org
> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flis
> ts.jboss.org%2Fmailman%2Flistinfo%2Fkeycloak-dev&data=02%7C01%7Cgi
> deon.caranzo%40gemalto.com%7C6f947d88676b4f788b2108d681d1d529%7C37d0a9
> db7c464096bfe31add5b495d6d%7C0%7C0%7C636839135555784466&sdata=Yhpx
> 28KFJWJGa1kv1ROWWqJd3nt60YvAb0YmeKUU5Mg%3D&reserved=0
>
_______________________________________________
keycloak-dev mailing list
keycloak-dev(a)lists.jboss.org
https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists....
________________________________
This message and any attachments are intended solely for the addressees and may contain confidential information. Any unauthorized use or disclosure, either whole or partial, is prohibited.
E-mails are susceptible to alteration. Our company shall not be liable for the message if altered, changed or falsified. If you are not the intended recipient of this message, please delete it and notify the sender.
Although all reasonable efforts have been made to keep this transmission free from viruses, the sender will not be liable for damages caused by a transmitted virus.
5 years, 3 months