20.0.0: TypeError: user.getAttribute exception thrown from code in custom provider
See original GitHub issueArea
adapter/javascript
Describe the bug
Since upgrading from 19.0.3 to 20.0.0 our small custom provider stopped working throwing an exception:
Nov 03 10:48:53 hnkeycloak kc.sh[302]: 2022-11-03 10:48:53,577 ERROR [org.keycloak.protocol.saml.mappers.ScriptBasedMapper] (executor-thread-91) Error during execution of ProtocolMapper script: org.keycloak.scripting.ScriptExecutionException: Could not execute script 'attribute-mapper-script_ldap_id_nextcloud' problem was: TypeError: user.getAttribute is not a function in <eval> at line number 2
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.scripting.AbstractEvaluatableScriptAdapter.evalUnchecked(AbstractEvaluatableScriptAdapter.java:64)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.scripting.AbstractEvaluatableScriptAdapter.eval(AbstractEvaluatableScriptAdapter.java:30)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.protocol.saml.mappers.ScriptBasedMapper.transformAttributeStatement(ScriptBasedMapper.java:132)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.protocol.saml.SamlProtocol.populateAttributeStatements(SamlProtocol.java:572)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.protocol.saml.SamlProtocol.authenticated(SamlProtocol.java:493)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.services.managers.AuthenticationManager.redirectAfterSuccessfulFlow(AuthenticationManager.java:973)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.services.managers.AuthenticationManager.redirectAfterSuccessfulFlow(AuthenticationManager.java:921)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.services.managers.AuthenticationManager.finishedRequiredActions(AuthenticationManager.java:1073)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.authentication.AuthenticationProcessor.authenticationComplete(AuthenticationProcessor.java:1118)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:985)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:311)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:282)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:274)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:339)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.internal.reflect.GeneratedMethodAccessor333.invoke(Unknown Source)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at java.base/java.lang.reflect.Method.invoke(Method.java:566)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:82)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:42)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:84)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:71)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:430)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:408)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$0(QuarkusRequestFilter.java:82)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:564)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at java.base/java.lang.Thread.run(Thread.java:829)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: Caused by: javax.script.ScriptException: TypeError: user.getAttribute is not a function in <eval> at line number 2
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:477)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:433)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine$3.eval(NashornScriptEngine.java:521)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at java.scripting/javax.script.CompiledScript.eval(CompiledScript.java:89)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.scripting.CompiledEvaluatableScriptAdapter.eval(CompiledEvaluatableScriptAdapter.java:39)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at org.keycloak.scripting.AbstractEvaluatableScriptAdapter.evalUnchecked(AbstractEvaluatableScriptAdapter.java:61)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: ... 58 more
Nov 03 10:48:53 hnkeycloak kc.sh[302]: Caused by: <eval>:2 TypeError: user.getAttribute is not a function
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:213)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:185)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:172)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.Undefined.lookup(Undefined.java:100)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.linker.NashornLinker.getGuardedInvocation(NashornLinker.java:106)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.linker.NashornLinker.getGuardedInvocation(NashornLinker.java:96)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.dynalink/jdk.dynalink.linker.support.CompositeTypeBasedGuardingDynamicLinker.getGuardedInvocation(CompositeTypeBasedGuardingDynamicLinker.java:161)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.dynalink/jdk.dynalink.linker.support.CompositeGuardingDynamicLinker.getGuardedInvocation(CompositeGuardingDynamicLinker.java:109)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.dynalink/jdk.dynalink.LinkerServicesImpl.lambda$getGuardedInvocation$0(LinkerServicesImpl.java:137)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.dynalink/jdk.dynalink.LinkerServicesImpl.getWithLookupInternal(LinkerServicesImpl.java:168)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.dynalink/jdk.dynalink.LinkerServicesImpl.getGuardedInvocation(LinkerServicesImpl.java:135)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.dynalink/jdk.dynalink.DynamicLinker.relink(DynamicLinker.java:242)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn.scripts/jdk.nashorn.internal.scripts.Script$Recompilation$14$\^eval\_$cu1$restOf/0x0000000840f3c840.:program(<eval>:2)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:655)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:527)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:428)
Nov 03 10:48:53 hnkeycloak kc.sh[302]: ... 62 more
Version
20.0.0
Expected behavior
See no errors / have to code working like in the previous version 19.0.3.
Actual behavior
ERROR [org.keycloak.protocol.saml.mappers.ScriptBasedMapper] (executor-thread-91) Error during execution of ProtocolMapper script: org.keycloak.scripting.ScriptExecutionException: Could not execute script ‘attribute-mapper-script_ldap_id_nextcloud’ problem was: TypeError: user.getAttribute is not a function in <eval> at line number 2
How to Reproduce?
The actual code of our small custom provider (I’d be happy to not have to use that workaround at all - details outlined further below in the “Anything else?” section):
uppercase-ldap-id-nextcloud/META-INF/keycloak-scripts.json
{
"saml-mappers": [
{
"name": "Javascript - Uppercase LDAP_ID",
"fileName": "uppercase-ldap-id-nextcloud.js",
"description": "Converts LDAP_ID to uppercase for Nextcloud."
}
]
}
uppercase-ldap-id-nextcloud/uppercase-ldap-id-nextcloud.js
var value = Java.type("java.lang.String");
var ldap_id_nextcloud = new value(user.getAttribute("LDAP_ID")[0]);
ldap_id_nextcloud.toUpperCase();
Example: Users -> User details
showing the LDAP UUID in lowercase on a Keycloak user entry that the custom provider picks up and then offers it uppercase as ldap_id_nextcloud for Nextcloud in my configuration:
I couldn’t find anything releated in the release/upgrade notes in regards to any changes/breakage here and/or guidance what I might have to change.
Anything else?
We previously handled this in Keycloak itself but in the latest versions >= 19.0.2 had to transfer our small javascript to the custom provider because the feature to add javascript in the Keycloak Administration Console was removed.
Generally this is a real pain and always has been as Keycloak provides the information in lowercase only but the Nextcloud saml plugin is case-sensitive and the nextcloud ldap plugin just dumps the uppercase values from e.g. Active Directory into Nextcloud causing the user IDs to never match, there are more issues reported than you can count and I’m still looking for a native way to get things going without having to fiddle with custom javascript/provider.
For reference about the issue this small code tries to solve between Keycloak<->Nextcloud: https://github.com/nextcloud/user_saml/issues/406 https://github.com/nextcloud/user_saml/issues/622 https://github.com/nextcloud/user_saml/issues/563
If you could give any hints if there’s a genuine way to do this without the need of any custom providers & workarounds I and probably many others from the various bugreports over at the Nextcloud user_saml plugin would be really glad.
Issue Analytics
- State:
- Created a year ago
- Comments:7
Top GitHub Comments
Hi Timo,
Thanks for your reply. I was able to resolve the issue like that. I got confused about the instructions on https://github.com/keycloak/keycloak-documentation/blob/main/server_development/topics/providers.adoc#deploy-the-script-engine-on-java-15-and-later about the pom.xml file, but that doesn’t seem necessary in my use-case.
Regards, Rik
On Fri, Dec 2, 2022 at 5:49 PM Timo Gurr @.***> wrote:
–
Rik
Glad you got it working! (I actually got confused by exact the same, see my comment above in this regard: https://github.com/keycloak/keycloak/issues/15312#issuecomment-1303171957)