From issues at jboss.org Thu Jun 25 04:33:54 2020 Content-Type: multipart/mixed; boundary="===============6068523465209391903==" MIME-Version: 1.0 From: Andrej Kolontai (Jira) To: jboss-jira at lists.jboss.org Subject: [jboss-jira] [JBoss JIRA] (WFLY-13619) Elytron: org.wildfly.security.auth.server.SecurityIdentity not Serializable Date: Thu, 25 Jun 2020 04:34:15 -0400 Message-ID: In-Reply-To: JIRA.12958803.1593073448000@Atlassian.JIRA --===============6068523465209391903== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable [ https://issues.redhat.com/browse/WFLY-13619?page=3Dcom.atlassian.jir= a.plugin.system.issuetabpanels:all-tabpanel ] Andrej Kolontai updated WFLY-13619: ----------------------------------- Steps to Reproduce: = The problem is reproducible with just one server by making the session stor= e persistent. My production setup is rather complex so I've created a tiny project just t= o show the effect: [https://github.com/andrejkolontai/jaspic-elytron-distri= buted-demo] =C2=A0 First, get a fresh wildfly distribution (version 20.0.0.Final) and unpack i= t. Start it with standalone.sh. Then, using jboss-cli.sh make the session store persistent: =C2=A0 {noformat} /subsystem=3Dinfinispan/cache-container=3Dweb/local-cache=3Dpassivation/sto= re=3Dfile:add(passivation=3Dfalse,purge=3Dfalse) { "outcome" =3D> "success", "response-headers" =3D> { "operation-requires-reload" =3D> true, "process-state" =3D> "reload-required" } }[standalone(a)localhost:9990 /] reload {noformat} Then create an elytron security domain and connect it to undertow: =C2=A0 {noformat} [standalone(a)localhost:9990 /] /subsystem=3Delytron/security-domain=3Delyt= ronjaspic:add {"outcome" =3D> "success"}[standalone(a)localhost:9990 /] /subsystem=3Dunde= rtow/application-security-domain=3Delytronjaspic:add(integrated-jaspi=3Dfal= se,security-domain=3Delytronjaspic) {"outcome" =3D> "success"} =C2=A0 {noformat} =C2=A0 The demo project has a servlet, a session scoped cdi bean (counts the reque= sts in a session) an a rather trivial authenticator which uses AutoApplySes= sion. =C2=A0 To build it, use the gradle wrapper: =C2=A0 {noformat} ./gradlew war{noformat} =C2=A0 The repository has three tags to see the difference between old security su= bsystem and elytron. First, the old security subsystem to ses how it's used to work: =C2=A0 {noformat} git checkout old-security = Previous HEAD position was 6dad6c3 Changed security domain to the elytron o= ne HEAD is now at 547cff7 First Commmit ./gradlew warBUILD SUCCESSFUL in 1s 2 actionable tasks: 1 executed, 1 up-to-date cp build/libs/jaspic.war ~/devel/wildfly-20.0.0.Final/standalone/deployment= s/{noformat} {{}} =C2=A0 =C2=A0Verify that the authentication mechanism kicks in: {noformat} curl -w '\n' -c cookies -b cookies localhost:8080/jaspic/hallo ErrorUnauthorized{no= format} call with authentication credentials: {noformat} curl -w '\n' -c cookies -b cookies -H "secret: shampoo" localhost:8080/jasp= ic/hallo Hallo Welt 0{noformat} verify that the authentication state is stored in the session (call without= secret): {noformat} curl -w '\n' -c cookies -b cookies localhost:8080/jaspic/hallo Hallo Welt 1{noformat} reload/restart wildfly verify the session has survived the reload: {noformat} curl -w '\n' -c cookies -b cookies localhost:8080/jaspic/hallo Hallo Welt 2{noformat} Now, switch to elytron by changing the security domain: {noformat} git checkout elytron-security{noformat} build & deploy like above Now do the same procedure but clear the cookies first: {noformat} rm cookies curl -w '\n' -c cookies -b cookies localhost:8080/jaspic/hallo ErrorUnauthorized curl -w '\n' -c cookies -b cookies -H "secret: shampoo" localhost:8080/jasp= ic/hallo Hallo Welt 0{noformat} At this point you should see wildfly throwing exceptions. My demo applicati= on seems to work. But my production application would stop working. And the= sessions are not actually persisted. One more effect in production: when a= server is restarted, it takes a very long time for it to come back again b= ecause the running server is struggling to serialize the session data which= is not possible while the restarting server is waiting for the cached sess= ion data to arrive. After a timeout, the affected applications would just g= o into .failed. A possible workaround is to make the application non-distributable: {noformat} git checkout non-distributable{noformat} build & deploy again like above. Repeat the test. Everything just works but= , of course, the sessions are not persisted and in production there would b= e no session failover. I=C2=A0 could stay with the old security subsystem (like "jaspitest"). But = I really like elytron better and words like "dummy" in a production configu= ration are kind of scary. That's not much of an issue. But I liked the feeling that I could just rede= ploy an application or restart a server during normal work hours instead of= waiting until midnight or so. What is also interesting: it only seems to affect jaspic/jsr375 enabled app= lications. We have one application using form authentication backed by an l= dap realm which doesen't seem to have this problem. was: The problem is reproducible with just one server by making the session stor= e persistent. My production setup is rather complex so I've created a tiny project just t= o show the effect: [https://github.com/andrejkolontai/jaspic-elytron-distri= buted-demo] =C2=A0 First, get a fresh wildfly distribution (version 20.0.0.Final) and unpack i= t. Start it with standalone.sh. Then, using jboss-cli.sh make the session store persistent: =C2=A0 {noformat} /subsystem=3Dinfinispan/cache-container=3Dweb/local-cache=3Dpassivation/sto= re=3Dfile:add(passivation=3Dfalse,purge=3Dfalse) { "outcome" =3D> "success", "response-headers" =3D> { "operation-requires-reload" =3D> true, "process-state" =3D> "reload-required" } }[standalone(a)localhost:9990 /] reload {noformat} {{}} =C2=A0 =C2=A0 Then create an elytron security domain and connect it to undertow: =C2=A0 {noformat} [standalone(a)localhost:9990 /] /subsystem=3Delytron/security-domain=3Delyt= ronjaspic:add {"outcome" =3D> "success"}[standalone(a)localhost:9990 /] /subsystem=3Dunde= rtow/application-security-domain=3Delytronjaspic:add(integrated-jaspi=3Dfal= se,security-domain=3Delytronjaspic) {"outcome" =3D> "success"} =C2=A0 {noformat} =C2=A0 The demo project has a servlet, a session scoped cdi bean (counts the reque= sts in a session) an a rather trivial authenticator which uses AutoApplySes= sion. =C2=A0 To build it, use the gradle wrapper: =C2=A0 {noformat} {noformat} {{./gradlew war}} =C2=A0 The repository has three tags to see the difference between old security su= bsystem and elytron. First, the old security subsystem to ses how it's used to work: =C2=A0 {noformat} git checkout old-security = Previous HEAD position was 6dad6c3 Changed security domain to the elytron o= ne HEAD is now at 547cff7 First Commmit ./gradlew warBUILD SUCCESSFUL in 1s 2 actionable tasks: 1 executed, 1 up-to-date cp build/libs/jaspic.war ~/devel/wildfly-20.0.0.Final/standalone/deployment= s/{noformat} {{}} =C2=A0 =C2=A0Verify that the authentication mechanism kicks in: {noformat} curl -w '\n' -c cookies -b cookies localhost:8080/jaspic/hallo ErrorUnauthorized{no= format} call with authentication credentials: {noformat} curl -w '\n' -c cookies -b cookies -H "secret: shampoo" localhost:8080/jasp= ic/hallo Hallo Welt 0{noformat} verify that the authentication state is stored in the session (call without= secret): {noformat} curl -w '\n' -c cookies -b cookies localhost:8080/jaspic/hallo Hallo Welt 1{noformat} reload/restart wildfly verify the session has survived the reload: {noformat} curl -w '\n' -c cookies -b cookies localhost:8080/jaspic/hallo Hallo Welt 2{noformat} Now, switch to elytron by changing the security domain: {noformat} git checkout elytron-security{noformat} build & deploy like above Now do the same procedure but clear the cookies first: {noformat} rm cookies curl -w '\n' -c cookies -b cookies localhost:8080/jaspic/hallo ErrorUnauthorized curl -w '\n' -c cookies -b cookies -H "secret: shampoo" localhost:8080/jasp= ic/hallo Hallo Welt 0{noformat} At this point you should see wildfly throwing exceptions. My demo applicati= on seems to work. But my production application would stop working. And the= sessions are not actually persisted. One more effect in production: when a= server is restarted, it takes a very long time for it to come back again b= ecause the running server is struggling to serialize the session data which= is not possible while the restarting server is waiting for the cached sess= ion data to arrive. After a timeout, the affected applications would just g= o into .failed. A possible workaround is to make the application non-distributable: {noformat} git checkout non-distributable{noformat} build & deploy again like above. Repeat the test. Everything just works but= , of course, the sessions are not persisted and in production there would b= e no session failover. I=C2=A0 could stay with the old security subsystem (like "jaspitest"). But = I really like elytron better and words like "dummy" in a production configu= ration are kind of scary. That's not much of an issue. But I liked the feeling that I could just rede= ploy an application or restart a server during normal work hours instead of= waiting until midnight or so. What is also interesting: it only seems to affect jaspic/jsr375 enabled app= lications. We have one application using form authentication backed by an l= dap realm which doesen't seem to have this problem. > Elytron: org.wildfly.security.auth.server.SecurityIdentity not Serializab= le > -------------------------------------------------------------------------= -- > > Key: WFLY-13619 > URL: https://issues.redhat.com/browse/WFLY-13619 > Project: WildFly > Issue Type: Bug > Components: Security > Affects Versions: 20.0.0.Final > Reporter: Andrej Kolontai > Assignee: Darran Lofthouse > Priority: Minor > > Since the old security subsystem has been deprecated for a while I decide= d to move my applications to elytron which worked just fine up to the point= where I tried to migrate an application that is: > * distributed > * uses Jaspic in form of a JSR375 HttpAuthenticationMechanism which has = {{@AutoApplySession }} > In the logs I see stacktraces like this: > {{09:37:22,045 WARN [org.infinispan.PERSISTENCE] (default task-1) ISPN000= 559: Cannot marshall 'class org.infinispan.marshall.protostream.impl.Marsha= llableUserObject': java.io.NotSerializableException: org.wildfly.security.a= uth.server.SecurityIdentity}} > {{ at org.jboss.marshalling.river(a)2.0.9.Final//org.jboss.marshalling.ri= ver.RiverMarshaller.doWriteObject(RiverMarshaller.java:272)}} > {{ at org.jboss.marshalling.river(a)2.0.9.Final//org.jboss.marshalling.ri= ver.RiverMarshaller.doWriteFields(RiverMarshaller.java:1141)}} > {{ at org.jboss.marshalling.river(a)2.0.9.Final//org.jboss.marshalling.ri= ver.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1099)}} > {{ at org.jboss.marshalling.river(a)2.0.9.Final//org.jboss.marshalling.ri= ver.RiverMarshaller.doWriteObject(RiverMarshaller.java:266)}} > {{ at org.jboss.marshalling(a)2.0.9.Final//org.jboss.marshalling.Abstract= ObjectOutput.writeObject(AbstractObjectOutput.java:58)}} > {{ at org.jboss.marshalling(a)2.0.9.Final//org.jboss.marshalling.Abstract= Marshaller.writeObject(AbstractMarshaller.java:111)}} > {{.....}} > {{Caused by: an exception which occurred:}} > {{ in field org.wildfly.elytron.web.undertow.server.servlet.ServletSecuri= tyContextImpl$IdentityContainer.securityIdentity}} > {{ in object org.wildfly.elytron.web.undertow.server.servlet.ServletSecur= ityContextImpl$IdentityContainer(a)7bf2af9a}} > {{ in object org.wildfly.elytron.web.undertow.server.servlet.ServletSecur= ityContextImpl$IdentityContainer(a)7bf2af9a}} > {{ in object java.util.concurrent.ConcurrentHashMap(a)d02a9ca2}} > {{ in object org.wildfly.clustering.marshalling.jboss.SimpleMarshalledVal= ue(a)d02a9ca2}} > =C2=A0 > Looks to me like it's trying to serialize the session to replicate it to = the other nodes in the cluster and fails because the user identity, which i= s part of the session because of AutoApplySession, is not serializable. I h= ave checked the source and it is really not serializable. > =C2=A0 > I had no problems with the old security subsystem (i.e. jaspitest). -- This message was sent by Atlassian Jira (v7.13.8#713008) --===============6068523465209391903==--