CAS 5.3.9 and Azure OIDC Delegation - ClassCastException in pac4j

446 views
Skip to first unread message

Paul Bransford

unread,
Mar 26, 2019, 4:10:21 PM3/26/19
to CAS Community
Hello folks,

Does anyone have a working CAS 5.x deployment delegating authentication via OpenID Connect? I'd love to pick your brain.

I am working on a CAS 5.3.9 deployment, testing CAS delegation to Azure AD via OpenID Connect. I think I am close, but I'm running into a problem.

When I try to access '/cas/clientredirect?client_name=REDACTED' via the link on the `/cas/login' page, I receive a 500 error with a stacktrace as follows below. There is no STDOUT/STDERR emitted when this occurs, and I have tweaked my log levels so that I would expect to see *something*. I'll share those later.

What worries me, is if I start nosing around in IDEA, the IDE also throws a hint that this is an invalid cast. (I used './gradlew idea' in a clone of the cas repository, and opened the generated idea project in IntelliJ IDEA Ultimate).

Here's the stack trace:
org.pac4j.core.exception.TechnicalException: java.lang.ClassCastException: java.util.Collections$SingletonList cannot be cast to java.lang.String
	at org.pac4j.oidc.redirect.OidcRedirectActionBuilder.buildAuthenticationRequestUrl(OidcRedirectActionBuilder.java:113)
	at org.pac4j.oidc.redirect.OidcRedirectActionBuilder.redirect(OidcRedirectActionBuilder.java:78)
	at org.pac4j.core.client.IndirectClient.getRedirectAction(IndirectClient.java:109)
	at org.apereo.cas.web.DelegatedClientNavigationController.redirectToProvider(DelegatedClientNavigationController.java:83)
	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.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:849)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:760)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:867)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1623)
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:214)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.apereo.cas.web.support.AuthenticationCredentialsThreadLocalBinderClearingFilter.doFilter(AuthenticationCredentialsThreadLocalBinderClearingFilter.java:30)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.apereo.cas.security.RequestParameterPolicyEnforcementFilter.doFilter(RequestParameterPolicyEnforcementFilter.java:261)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.apereo.cas.security.ResponseHeadersEnforcementFilter.doFilter(ResponseHeadersEnforcementFilter.java:240)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.apereo.cas.security.AddResponseHeadersFilter.doFilter(AddResponseHeadersFilter.java:94)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:111)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.apereo.cas.logging.web.ThreadContextMDCServletFilter.doFilter(ThreadContextMDCServletFilter.java:91)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:103)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:130)
	at org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:66)
	at org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:105)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:123)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.apereo.inspektr.common.web.ClientInfoThreadLocalFilter.doFilter(ClientInfoThreadLocalFilter.java:66)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:540)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1588)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1345)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1557)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1247)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:220)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.Server.handle(Server.java:502)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
	at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:305)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:132)
	at org.eclipse.jetty.http2.HTTP2Connection.produce(HTTP2Connection.java:171)
	at org.eclipse.jetty.http2.HTTP2Connection.onFillable(HTTP2Connection.java:126)
	at org.eclipse.jetty.http2.HTTP2Connection$FillableCallback.succeeded(HTTP2Connection.java:338)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:411)
	at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:305)
	at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:159)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassCastException: java.util.Collections$SingletonList cannot be cast to java.lang.String
	at com.nimbusds.oauth2.sdk.AuthorizationRequest.parse(AuthorizationRequest.java:972)
	at com.nimbusds.openid.connect.sdk.AuthenticationRequest.parse(AuthenticationRequest.java:1374)
	at com.nimbusds.openid.connect.sdk.AuthenticationRequest.parse(AuthenticationRequest.java:1340)
	at org.pac4j.oidc.redirect.OidcRedirectActionBuilder.buildAuthenticationRequestUrl(OidcRedirectActionBuilder.java:110)
	... 103 more

Here's the code from pac4j in question:
    protected String buildAuthenticationRequestUrl(final Map<String, String> params) {
       
// Build authentication request query string
       
final String queryString;
       
try {
            queryString
= AuthenticationRequest.parse(params.entrySet().stream().collect(
                   
Collectors.toMap(Map.Entry::getKey, e -> Collections.singletonList(e.getValue())))).toQueryString();
       
} catch (Exception e) {
           
throw new TechnicalException(e);
       
}
       
return configuration.getProviderMetadata().getAuthorizationEndpointURI().toString() + "?" + queryString;
   
}


IDEA whines about two things, here. I've underlined them both. The first is "Non-static method cannot be referenced from a static context" and the second "Bad return type in lambda expression: List<String> cannot be converted to U." Interestingly this second issue is exactly what lives at the top of the stacktrace... Is this a bug? In case it's not, and I've just done something wrong or silly...

Now, for some build/environment stuff. I'm stuffing cas.war into a docker container with jetty (tweaked to work around a bug). I'm building a standalone WAR without tomcat etc. Note that I have my own pom.xml based on cas-overlay. This deployment is working fine for several other CAS deployments that I haven't yet pulled forward from CAS 5.2.x, which use JDBC authentication to an Oracle instance instead.

Here's what the relevant (I think) section of my cas.properties looks like, with appropriate fields redacted. The log4j2.xml is unmodified except for changing the on-disk output paths.
logging.level.org.apereo.cas=INFO
logging
.level.org.springframework=FATAL
logging
.level.org.apereo.inspektr.audit=INFO
logging
.level.org.apereo.cas.support.pac4j=DEBUG
logging
.level.org.pac4j=DEBUG
logging
.config=file:/etc/cas/config/log4j2.xml

cas
.authn.pac4j.cookie.crypto.encryption.key=REDACTED
cas
.authn.pac4j.cookie.crypto.signing.key=REDACTED
cas
.authn.pac4j.name=DelegatePAC4J
cas
.authn.pac4j.oidc[0].autoRedirect=false
cas
.authn.pac4j.oidc[0].azureTenantId=REDACTED.onmicrosoft.com
cas
.authn.pac4j.oidc[0].clientName=REDACTED
cas
.authn.pac4j.oidc[0].discoveryUri=https://login.microsoftonline.com/REDACTED.onmicrosoft.com/v2.0/.well-known/openid-configuration
cas
.authn.pac4j.oidc[0].id=REDACTED
cas
.authn.pac4j.oidc[0].logoutUrl=https://login.microsoftonline.com/REDACTED.onmicrosoft.com}/oauth2/v2.0/logout
cas
.authn.pac4j.oidc[0].maxClockSkew=600
cas
.authn.pac4j.oidc[0].preferredJwsAlgorithm=RS256
cas
.authn.pac4j.oidc[0].principalAttributeId=oid
cas
.authn.pac4j.oidc[0].responseMode=form_post
cas
.authn.pac4j.oidc[0].responseType=code
cas
.authn.pac4j.oidc[0].scope=openid profile
cas
.authn.pac4j.oidc[0].secret=REDACTED
cas
.authn.pac4j.oidc[0].type=AZURE
cas
.authn.pac4j.oidc[0].useNonce=true
cas
.authn.pac4j.oidc[0].usePathBasedCallbackUrl=true
cas
.authn.policy.req.enabled=true
cas
.authn.policy.req.handlerName=DelegatePAC4J
cas
.authn.policy.req.tryAll=false


I have also tried the non-v2.0 URLs but saw no difference.

I see the Pac4jAuthenticationEventExecutionPlanConfiguration emit the following log entry while CAS is initializing, the contents look OK to me (newlines added for clarity)
DEBUG [org.apereo.cas.support.pac4j.config.support.authentication.Pac4jAuthenticationEventExecutionPlanConfiguration] - <
  The following clients are built: [
    [
      #AzureAdClient# |
      name: REDACTED |
      callbackUrl: null |
      callbackUrlResolver: org.pac4j.core.http.callback.PathParameterCallbackUrlResolver@74bfba13 |
      ajaxRequestResolver: null |
      redirectActionBuilder: null |
      credentialsExtractor: null |
      authenticator: null |
      profileCreator: org.pac4j.core.profile.creator.AuthenticatorProfileCreator@52907b1e |
      logoutActionBuilder: org.pac4j.core.logout.NoLogoutActionBuilder@1865ede |
      authorizationGenerators: [] |
      configuration: #AzureAdOidcConfiguration# |
      clientId: REDACTED |
      secret: [protected] |
      discoveryURI: https://login.microsoftonline.com/REDACTED.onmicrosoft.com/.well-known/openid-configuration |
      scope: openid profile |
      customParams: {} |
      clientAuthenticationMethod: null |
      useNonce: true |
      preferredJwsAlgorithm: RS256 |
      maxAge: null |
      maxClockSkew: 600 |
      connectTimeout: 500 |
      readTimeout: 5000 |
      resourceRetriever: null |
      responseType: code |
      responseMode: form_post |
      logoutUrl: https://login.microsoftonline.com/REDACTED.onmicrosoft.com/oauth2/v2.0/logout |
      withState: false |
      stateGenerator: org.pac4j.core.state.StaticOrRandomStateGenerator@68b2c3aa |
      |
    ]
  ]
>

I wouldn't be surprised in the least to find i'm doing something stupid, here. The docs just throw parameter names at you, with no explanation or type information - and I had to refer to the source code many times.

For giggles, my pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd ">
 
<modelVersion>4.0.0</modelVersion>
 
<groupId>edu.usf.epi</groupId>
 
<artifactId>cas-overlay</artifactId>
 
<packaging>war</packaging>
 
<version>1.0</version>
 
<properties>
   
<cas.version>5.3.9</cas.version>
   
<springboot.version>1.5.18.RELEASE</springboot.version>
   
<maven.compiler.source>1.8</maven.compiler.source>
   
<maven.compiler.target>1.8</maven.compiler.target>
   
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
   
<mainClassName>org.springframework.boot.loader.WarLauncher</mainClassName>
   
<isExecutable>false</isExecutable>
   
<manifestFileToUse>${project.build.directory}/war/work/org.apereo.cas/cas-server-webapp/META-INF/MANIFEST.MF</manifestFileToUse>
 
</properties>
 
<profiles>
   
<profile>
     
<activation>
       
<activeByDefault>true</activeByDefault>
     
</activation>
     
<id>default</id>
     
<dependencies>
       
<dependency>
         
<groupId>org.apereo.cas</groupId>
         
<artifactId>cas-server-webapp</artifactId>
         
<version>${cas.version}</version>
         
<type>war</type>
         
<scope>runtime</scope>
       
</dependency>
       
<dependency>
         
<groupId>org.apereo.cas</groupId>
         
<artifactId>cas-server-support-pac4j-webflow</artifactId>
         
<version>${cas.version}</version>
       
</dependency>
       
<dependency>
         
<groupId>org.apereo.cas</groupId>
         
<artifactId>cas-server-support-json-service-registry</artifactId>
         
<version>${cas.version}</version>
       
</dependency>
       
<dependency>
         
<groupId>org.apereo.cas</groupId>
         
<artifactId>cas-server-support-redis-ticket-registry</artifactId>
         
<version>${cas.version}</version>
       
</dependency>
       
<dependency>
         
<!-- see also Dockerfile and go.sh -->
         
<groupId>com.oracle.jdbc</groupId>
         
<artifactId>ojdbc8</artifactId>
         
<version>12.2.0.1</version>
       
</dependency>
     
</dependencies>
   
</profile>
 
</profiles>
 
<repositories>
   
<repository>
     
<id>sonatype-releases</id>
     
<url>http://oss.sonatype.org/content/repositories/releases/</url>
     
<snapshots>
       
<enabled>false</enabled>
     
</snapshots>
     
<releases>
       
<enabled>true</enabled>
     
</releases>
   
</repository>
   
<repository>
     
<id>sonatype-snapshots</id>
     
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
     
<snapshots>
       
<enabled>true</enabled>
     
</snapshots>
     
<releases>
       
<enabled>false</enabled>
     
</releases>
   
</repository>
   
<repository>
     
<id>shibboleth-releases</id>
     
<url>https://build.shibboleth.net/nexus/content/repositories/releases</url>
   
</repository>
 
</repositories>
 
<build>
   
<plugins> <!-- keep versions in sync with ../cas-redirect/pom.xml for efficiency -->
     
<plugin>
       
<groupId>org.springframework.boot</groupId>
       
<artifactId>spring-boot-maven-plugin</artifactId>
       
<version>${springboot.version}</version>
       
<configuration>
         
<mainClass>${mainClassName}</mainClass>
         
<addResources>true</addResources>
         
<executable>${isExecutable}</executable>
         
<layout>WAR</layout>
         
<excludeDevtools>true</excludeDevtools>
       
</configuration>
       
<executions>
         
<execution>
           
<goals>
             
<goal>repackage</goal>
           
</goals>
         
</execution>
       
</executions>
     
</plugin>
     
<plugin>
       
<groupId>org.apache.maven.plugins</groupId>
       
<artifactId>maven-war-plugin</artifactId>
       
<version>2.6</version>
       
<configuration>
         
<warName>cas</warName>
         
<failOnMissingWebXml>false</failOnMissingWebXml>
         
<recompressZippedFiles>false</recompressZippedFiles>
         
<archive>
           
<compress>false</compress>
           
<manifestFile>${manifestFileToUse}</manifestFile>
         
</archive>
         
<overlays>
           
<overlay>
             
<groupId>org.apereo.cas</groupId>
             
<artifactId>cas-server-webapp</artifactId>
           
</overlay>
         
</overlays>
         
<!-- because excludeDevtools is broken in spring-boot-maven-plugin, we use the nuclear option. -->
         
<!-- also tomcat leaks in and 'mvn dependency:tree' doesn't show why... -->
         
<packagingExcludes>
            WEB-INF/lib/spring-boot-devtools-*.jar,
            WEB-INF/lib/spring-boot-starter-tomcat-*.jar,
            WEB-INF/lib/tomcat-*.jar
         
</packagingExcludes>
       
</configuration>
     
</plugin>
     
<plugin>
       
<groupId>org.apache.maven.plugins</groupId>
       
<artifactId>maven-compiler-plugin</artifactId>
       
<version>3.3</version>
     
</plugin>
   
</plugins>
   
<finalName>cas</finalName>
 
</build>
</project>


Paul Bransford

unread,
Mar 26, 2019, 4:12:13 PM3/26/19
to CAS Community
Eh. The underlinesin the pac4j code got eaten by the syntax hilighter. First one was "Map.Entry::getKey" and the other "Collections.singletonList(e.getValue())"

Drew Liscomb

unread,
Mar 27, 2019, 11:09:45 AM3/27/19
to cas-...@apereo.org
Hi Paul,
I ran across something like this in my recent 5.1->5.3 upgrade.
I'll have to go see what changed.
Code that used to return a String now returns a List<String>, so I had to do `list.first()` or some such

-Drew

On Tue, Mar 26, 2019 at 4:12 PM Paul Bransford <dra...@gmail.com> wrote:
Eh. The underlinesin the pac4j code got eaten by the syntax hilighter. First one was "Map.Entry::getKey" and the other "Collections.singletonList(e.getValue())"

--
- Website: https://apereo.github.io/cas
- Gitter Chatroom: https://gitter.im/apereo/cas
- List Guidelines: https://goo.gl/1VRrw7
- Contributions: https://goo.gl/mh7qDG
---
You received this message because you are subscribed to the Google Groups "CAS Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cas-user+u...@apereo.org.
To view this discussion on the web visit https://groups.google.com/a/apereo.org/d/msgid/cas-user/6a8f9508-9f05-4504-8ab8-e6b93da89179%40apereo.org.

Drew Liscomb

unread,
Mar 27, 2019, 11:13:37 AM3/27/19
to cas-...@apereo.org
Ah, the issue was with attributes passed into a custom AbstractRegisteredServiceAttributeReleasePolicy.
We used to see a single value for 'uid', but now we see 2, and so the new code became:
List<String> stringList = (List<String>) attributes.get("uid");
String userUUID = stringList.get(0);

Drew Liscomb

unread,
Mar 27, 2019, 11:15:49 AM3/27/19
to cas-...@apereo.org
But that doesn't look like your problem.

Paul Bransford

unread,
Mar 27, 2019, 12:21:02 PM3/27/19
to CAS Community
I *think* my issue is related to this change on the pac4j-oidc side. (maven is bundling in pac4j-oidc-3.6.1.jar)

I'm trying to work out what the most recent version of this library is prior to that commit.

It doesn't look like CAS depends on a particular version of it. build.gradle for support/cas-server-support-pac4j* all say either 'implementation libraries.pac4j' or 'api libraries.pac4j' - though I'm nowhere near as familiar with gradle as maven (and even that's a shaky familiarity).

I'll follow up if I manage to fix this issue this route or not.

Paul Bransford

unread,
Mar 27, 2019, 12:29:31 PM3/27/19
to CAS Community
pac4jVersion=3.6.1

Paul Bransford

unread,
Mar 27, 2019, 12:54:03 PM3/27/19
to CAS Community
I've also gone and asked on the pac4j-user mailing list. This commit has been around since 2018, so I can't be the only one who's run into this - assuming it's in fact not something I'm causing with a misconfiguration.

Paul Bransford

unread,
Mar 27, 2019, 2:12:59 PM3/27/19
to CAS Community
OK! Forcing pac4j 3.4.0 and then fixing my client name so it has no spaces (pac4j 3.4.0 throws an error about that - i did make sure and this doesn't matter regarding the error I see with 3.6.1) and CAS is now sending me along to Azure.

Granted, now I'm having problems azure-side but that's a whole different subject.

leleuj

unread,
Mar 28, 2019, 3:40:00 AM3/28/19
to CAS Community
Hi,

This change was tested and works in pac4j applications. The issue in CAS is that there are conflicts regarding the Nimbus versions libraries.

Add this to make it work:

<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>6.0.2</version>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>oauth2-oidc-sdk</artifactId>
<version>6.5</version>
</dependency>

Thanks.
Best regards,
Jérôme

Paul Bransford

unread,
Mar 28, 2019, 4:31:38 PM3/28/19
to CAS Community
Thank you, this does the trick!

There's some other concern around how to appropriately accomplish this in my reply on the other group. I meant to put that all here instead of over there, but what's sent is sent so I'll leave it be. If anyone else finds this thread and needs to see that context, check out that other thread here: https://groups.google.com/d/msg/pac4j-users/RlZ98-KhaXY/gytfPjojBQAJ

Thank you once again!

Misagh Moayyed

unread,
Mar 29, 2019, 2:25:28 PM3/29/19
to CAS Community
You may want to try your luck with the next SNAPSHOT, 5.3.10-SNAPSHOT, and sidestep dependency changes.
Reply all
Reply to author
Forward
0 new messages