From b5a4218a0bfd91220a4cf38cdefa93ee1f4f5c26 Mon Sep 17 00:00:00 2001 From: Max Batischev Date: Fri, 14 Feb 2025 17:10:00 +0300 Subject: [PATCH 1/2] Make WebAuthnAuthenticationRequestToken Serializable Closes gh-16481 Signed-off-by: Max Batischev --- ...gSecurityCoreVersionSerializableTests.java | 29 ++++++++++++++ ....AuthenticatorAssertionResponse.serialized | Bin 0 -> 782 bytes ....api.CredentialPropertiesOutput.serialized | Bin 0 -> 306 bytes ...ticationExtensionsClientOutputs.serialized | Bin 0 -> 619 bytes ...ebauthn.api.PublicKeyCredential.serialized | Bin 0 -> 2078 bytes ...AuthnAuthenticationRequestToken.serialized | Bin 0 -> 3891 bytes ...lyingPartyAuthenticationRequest.serialized | Bin 0 -> 3196 bytes .../AuthenticationExtensionsClientOutput.java | 6 ++- ...AuthenticationExtensionsClientOutputs.java | 5 ++- .../api/AuthenticatorAssertionResponse.java | 7 +++- .../webauthn/api/AuthenticatorResponse.java | 6 ++- .../api/CredentialPropertiesOutput.java | 13 +++++- ...AuthenticationExtensionsClientOutputs.java | 6 ++- .../web/webauthn/api/PublicKeyCredential.java | 12 ++++-- .../WebAuthnAuthenticationRequestToken.java | 7 +++- .../RelyingPartyAuthenticationRequest.java | 10 ++++- .../TestAuthenticationAssertionResponses.java | 37 ++++++++++++++++++ .../webauthn/api/TestPublicKeyCredential.java | 13 +++++- 18 files changed, 134 insertions(+), 17 deletions(-) create mode 100644 config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse.serialized create mode 100644 config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.CredentialPropertiesOutput.serialized create mode 100644 config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientOutputs.serialized create mode 100644 config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.PublicKeyCredential.serialized create mode 100644 config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken.serialized create mode 100644 config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest.serialized create mode 100644 web/src/test/java/org/springframework/security/web/webauthn/api/TestAuthenticationAssertionResponses.java diff --git a/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java b/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java index cc53b8e159..7f4d78f41b 100644 --- a/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java +++ b/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java @@ -212,21 +212,30 @@ import org.springframework.security.web.savedrequest.SimpleSavedRequest; import org.springframework.security.web.server.firewall.ServerExchangeRejectedException; import org.springframework.security.web.session.HttpSessionCreatedEvent; import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs; +import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs; +import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse; import org.springframework.security.web.webauthn.api.AuthenticatorTransport; import org.springframework.security.web.webauthn.api.Bytes; import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput; +import org.springframework.security.web.webauthn.api.CredentialPropertiesOutput; import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInput; import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInputs; +import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientOutputs; import org.springframework.security.web.webauthn.api.ImmutablePublicKeyCredentialUserEntity; +import org.springframework.security.web.webauthn.api.PublicKeyCredential; import org.springframework.security.web.webauthn.api.PublicKeyCredentialDescriptor; import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions; import org.springframework.security.web.webauthn.api.PublicKeyCredentialType; import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity; +import org.springframework.security.web.webauthn.api.TestAuthenticationAssertionResponses; import org.springframework.security.web.webauthn.api.TestBytes; +import org.springframework.security.web.webauthn.api.TestPublicKeyCredential; import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialRequestOptions; import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialUserEntity; import org.springframework.security.web.webauthn.api.UserVerificationRequirement; import org.springframework.security.web.webauthn.authentication.WebAuthnAuthentication; +import org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken; +import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -629,6 +638,26 @@ class SpringSecurityCoreVersionSerializableTests { .allowCredentials(List.of(descriptor)) .build() ); + + CredentialPropertiesOutput credentialOutput = new CredentialPropertiesOutput(false); + AuthenticationExtensionsClientOutputs outputs = new ImmutableAuthenticationExtensionsClientOutputs(credentialOutput); + AuthenticatorAssertionResponse response = TestAuthenticationAssertionResponses.createAuthenticatorAssertionResponse() + .build(); + PublicKeyCredential credential = TestPublicKeyCredential.createPublicKeyCredential( + response, outputs) + .build(); + RelyingPartyAuthenticationRequest authRequest = new RelyingPartyAuthenticationRequest( + TestPublicKeyCredentialRequestOptions.create().build(), + credential + ); + WebAuthnAuthenticationRequestToken requestToken = new WebAuthnAuthenticationRequestToken(authRequest); + requestToken.setDetails(details); + generatorByClassName.put(CredentialPropertiesOutput.class, (o) -> credentialOutput); + generatorByClassName.put(ImmutableAuthenticationExtensionsClientOutputs.class, (o) -> outputs); + generatorByClassName.put(AuthenticatorAssertionResponse.class, (r) -> response); + generatorByClassName.put(RelyingPartyAuthenticationRequest.class, (r) -> authRequest); + generatorByClassName.put(PublicKeyCredential.class, (r) -> credential); + generatorByClassName.put(WebAuthnAuthenticationRequestToken.class, (r) -> requestToken); // @formatter:on } diff --git a/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse.serialized b/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse.serialized new file mode 100644 index 0000000000000000000000000000000000000000..64a8173e8e34a1ed9ebdb6e8e3783934a15943fb GIT binary patch literal 782 zcmZ4UmVvdnh`}enC|$3(peQphJ*_A)H?=&!C|j>MHMz7Xv!qh5JT(b~6H7}n^7Il5 zGW8sRtkk@c%;dz9{36HV;?$y&%>2Bd)Z&8tyy8@rrk>=qc{ivN*GK**6E{Jrw_AEA7~W_gRRpCTBq++2{ghQWEQf$E{P?Hg$#8Jj6MvU z#hK}Oi6x~)sZar~QlOhW67y1WAR-k-49*mI5$3alCo(rQy(&4+1hSMbIVTes2q0&8 z1^fGfZLTN)2BtA-Hi3P2sd1aV#<2zZK$D{xSd%~=E@5DbcB&{SEdtSNK8ycg;|O`c z#K2Hdz`(%JR;^T0S&*t^r34Epz4X))B^{;YjKrLr)Vy?%RE9xWdbxXGR=#tUW0gy2 zac)&WLAI_}n5S1zPS+{dho6+%^F`sue%T7<01?po!)8ua8%A~*^f98Ywybq@gB>l*$5 literal 0 HcmV?d00001 diff --git a/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.CredentialPropertiesOutput.serialized b/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.CredentialPropertiesOutput.serialized new file mode 100644 index 0000000000000000000000000000000000000000..78ddecc04253cac26a4cf70c69596d048012bfc7 GIT binary patch literal 306 zcmZ4UmVvdnh`}SjC|$3(peQphJ*_A)H?=&!C|j>MHMz7Xv!qh5JT(b~6H7}n^7Il5 zGWDE`Qd3g%N-`630*dkrQj1D5Q;YpeOA1O$E>CpN|LC__mWhGUhk-30ELOr0pQyUgOUMHMz7Xv!qh5JT(b~6H7}n^7Il5 zGW9%jb4yDSlX6lWfkLTyC7H>IC7Jnot`#MzdBs3Rv2#u)P}sk;q@c8eqx#L%V ziZd}V`Y^EPLj+401bng*%M$fVOEPoxeKLzntSbtDE|CHW>VX9H9E*w)D~naY6iC6% zB{uuccCcLnniI{ym{`If91SrdCowNw-#;lUH5p_`X%Rzcv=3<>BE}!qDnIl4_s#s> zz{J2%QNX~!zzB4%2Wj>=7p10v!YeT+peVl}wWuUBwHOjgmnXXCfArfd3l1bUNFbFk zM1lOFj}|fdu!zwIMhXanBSs$>G5Wa8SAj<{9 literal 0 HcmV?d00001 diff --git a/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.PublicKeyCredential.serialized b/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.PublicKeyCredential.serialized new file mode 100644 index 0000000000000000000000000000000000000000..6b2e6a8cc3fe42db44a292e90f1a2cb5b39ee344 GIT binary patch literal 2078 zcmb_dZA=_R7#^0dmPV8ki<)2xfl!iidj(1nOz^m#2i)<|gF8O1hR!W>$8yW=GBXQz zR8ec%(nvyWjo6rCt2OoqQ4_xcHC6kgHKt-(V6R&-i0^ zl6Q8V=Y5~|nRlmdfK-BkO~WAz(Xp(Cf*AIrAq|Hu1W5*#Y1A@=0{npn?Nu#Mmn|(u zK#?UEirO*iK`ND@@>AZ)lh-z9dIXT_23sUWW?@H!B9+LR>OsU%D51dXW<+8fk+?!6 zG7|onL?R;+ZH$uROOP^{J9xxy;x`*qHz=ug13~VgV6(dq4nk3ZYDjFQycV{Tis4W_ z+uWHTb8VC&j=TXQqH8Ka6gU!uSd+YlnFJ;bgG`}OoxwR1g!>24+Za%FL}v}$n^*(u z`}++F0}5J`lU(>SYKp&Dgh=GCE&&5f=k^iQS>VidW{QQZfrvv~Z zIshPv30IdG&#K{Du%;tSWkg~&{Ng#M_Dj>-xu!^IF_9?fO0dc6;}_gXWXH{gga=L(k!%Q#=+HD;bs?X=};JOM;Z-hawQ!VRy$PsOFL@T5q4c5AR z-KCw8PGv`5PkW`kwIR~za&|oGD+{RD)h0K#HlTVn?A&Fqs4Z1mXr*JPT;_s}tPf?0 z6=Gh`t53gIv+d$3(ezVlfZtdO1b?k*A+}E4%(<1eq3ws2e%q2pUia?Fni@HK=HkmO z@*klqrRDCKfu-)0*Pfgk>zL@6_kVP(C_Cf+0q^|u&&8EvbrYkLwsV_K4L-m0c=n6$ z7r)99{qM%qu#FII8FL_-(;(%*m=v6xs}ewp8)QMsD=@p015s=I`R>z=*cS8!7 zH#QPEq(W+7v>eDV7(pFWdz4rtf`L6TVb@%w)uHwAC-PeduG7y=Z)e7aJ5QsbwYkY; zW;2Md_Zs|tAG=zI_UH2{mtU2?GS4j`MDw@jOTAE0kQ(A!z1G3dkaJI;W*@c<@Ai`Z z;TAny(%`Fa@OVP1)m`rLwRSdnBuAITPHI>V$tpiasa_?DiY7s&S0l8l(pqWd&{!j+ zdHJg#R0w(^F016^_UgD$Vf_ntT^r3D>!sy6clQkL^N;`d#`G(PN-v$*dvoTQ+zBa{ zRRiJ-NzLho5y=^A1;!G5a|ZYv(#Y4LI`GBQv@4n%U6QL8us}UxbKGL56Pr-AlqK`ZqRD B1vvl! literal 0 HcmV?d00001 diff --git a/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken.serialized b/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken.serialized new file mode 100644 index 0000000000000000000000000000000000000000..5945cd459a5a5ff2116d3128645c62c2a4e9832c GIT binary patch literal 3891 zcmbtXeQZ-z6u;}bl?^vOrc5wHST=zO?HDlXwgkITyKWsD`(kXscx~^x$6nuiyYF^u zhfGlUii;?yNDLDc0x?95f_xc3{s7cDg+;=UuRp{X6oV241f%D^*R7)&uu7A@m%ew; z@0|NPzjN;CuB#|UA*fa&9-|@?Ui8!x&Wl?l(r8q$%SU(`Ft%VP`*J?oAR5^fiwv;0@Fre=oKS8$pZi``tLN;2Q3MHJ2-i@Yiq5Ff0 zZKBPcs6){;D50Mnc015e_FDp?c-S!-32 ziiY=d%hs^nPku05$j#_HwEXKuH^!=D3})9mww3VJ;W4B%504@hKi6*&>@`zB@pbDD7LuW1S?^5 zmQyBSU^`BMcR;+|&4Nkr%M`_GcC_C+h_UK{G4`s@7*e0{f$F*@0k< z0|fii_|2Oyk4!Anp%@1m~J@RWQNzr;snA60-S z9k1ozfno^PVs}$CBSKGk0g4&Y5D=RTRAY*)5km9}RwA%v6$T*nG#~?ke(Yy<7*~iFGR0Z6Dm7`YNAk zJ5+zAM3OOK?OqdF_v<$4_c@^%ruE+VX?^L?{Aro4j*O;_^al7aMIe^Rx0Yg;Hv^&fupNamA2_X_0M2Eyz@?scD3!?cI@3!{)Xpd z=5)t_rrUM;?JxASS8uF7UwdTzgrxYxomC1Oz&CKs!547~ z?-4obgL6Pz8SeuJ1)S&>v?p->=SN0tzd{PNsV`3OAHR5oeyf&zqSn4y7=`5}b5zez z`RqQ?$F5I9X{}nC%KBPrc4}YwcrZp)X>{UZXv!}&2cZrnWYH6Kasd!sU z<;E$6RrbQNGLM+ym|j#>K7US`%Ua_COBk*^yvWQbm9tGIL2_|IgQU=GbA~yCK@&+) zN`kBEIYGh8!lH_fo|hB$DBb>6!sRuI?G1E#@-TPv;@WjTez^a=Rhh>(Ex3N*rId}X z6gG5(8QC(dx^afO&TA7c{GC}h=~`o6@`j4ttxG#y>(`w-Irh(;Hw}wL-FWoQA8S{} zk6QS{#g(65L+LZ8cct$!9K5sEe`RaM(X(RlnK0OKTbxX$1%aR{rl{Jl=G6B(3oaU@Tq!HC!}~;9X6&k;sE$7 zd1!xkPZXz5N= z3{DApA_wP07}F{5#n8hkdQ>~1*l*KpA5n`FPVM2W(5f(jfn56wL{U+MVO549FrIjr zPGL0Cdi#^1lQcA;D`{4*Ox5|jbzk!C+#MYk)b^P$eES6U}X1QcD0=vhvstW#5 zplAg4b6#1%#=e?{@DkMRGvbZqn7q00GVG2 X_l!GZ7H4iV4^$g*GQstjz!3f){)3<2 literal 0 HcmV?d00001 diff --git a/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest.serialized b/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest.serialized new file mode 100644 index 0000000000000000000000000000000000000000..34f07eca8f47492278c841b45159bab6963056dc GIT binary patch literal 3196 zcmb_eZBSHI7(T2EE2tz=GFq52IO>e?p;3I!G_I#+>-30VE$uwl)^koiH0vSXP%J5*WY z1j_!nV9%awvl5*;5bFT5-8@HaumuScWR)yg;R#j0CQ9}1<$M%RwyO9Q3Xv2dQ=W93 zhk#j*X4nQzJQRGUD#AQXcVaON*y-kqC?yw$2x7=nF_I-pJtDvsCB!)8MeGd2P)I!q zNffRqO1KF~ucknn1J_08K)c_s5ZK70aXL~z-G|`gaM{4=Z||h&K#T(zM2&RyZ zgyT&PP9~ZrbD0y2Y|&`J7>49@^}`Mf?khOgB{ADpa9O3WjQSxfIz!a-Jh%Cim5WdHn$&oTZDbisfUdq!4I%nH zcq`?0+|=r;BmTC;bnLHLopi9{z`j#&RdRp$&Sqvi`dWt@^zS}9*j2l$cBuZujz!4{ zb6RVLj{LO5+*Q1*v&V9DT5sE{!_OqY@#&IxsG|QpFhy*UWfn55duT;PzopCV?HSC| z0lfnxLBcFh+l!VAt)K%K*v44v5%DTWV0a^5=6nJq3hffw$pnQ8D29TE*H(fUSfe9$ zTq2DXtIBJ4XyVeiLiYHi(^#;ROeUfM{PGx`uo zTbkx>f;^7|AKPlmX!8Y%RyT{*c1!!J8rk1oDYYysaoJ0pPM?tB$S!qNtu1%DZFO#X zQ^cH)6WBFEq&$;}7u}F=5@nKS&M;>%Xe`QdMfj8#@-o^Kq1BWrYw{zO7TRB*aji44 ztBGW%JmhKHP~ZK-dq>{hnt6Knx?6qEr|xp6QfolOrJ@X*ZoZ+R|K_4Ae`Yo;x!F>f zva|Y7`^J9vj_%86=lyozwqb*yTL9ktb^D76v)6z3{fnR71PgPs2Nr&8IC^(`@cQ2B zlb3|DixIH%_cr=p?sPJh|;9TgHNI`CT;pY|**%K1~C5 z{QYEK>X4{9G`0=$iW)C*L5Y9_NgYL&wV)7{SMk8|?wvO-oGGZgy|edc9f)&)nKTx} zz*x;w`It@zsnIAIiEA`6O3)0ijclient extension * output entry in {@link AuthenticationExtensionsClientOutputs}. @@ -24,7 +26,7 @@ package org.springframework.security.web.webauthn.api; * @see AuthenticationExtensionsClientOutputs#getOutputs() * @see CredentialPropertiesOutput */ -public interface AuthenticationExtensionsClientOutput { +public interface AuthenticationExtensionsClientOutput extends Serializable { /** * Gets the extension diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticationExtensionsClientOutputs.java b/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticationExtensionsClientOutputs.java index 54038e9588..8f1adccf05 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticationExtensionsClientOutputs.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticationExtensionsClientOutputs.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serializable; import java.util.List; /** @@ -31,7 +32,7 @@ import java.util.List; * @since 6.4 * @see PublicKeyCredential#getClientExtensionResults() */ -public interface AuthenticationExtensionsClientOutputs { +public interface AuthenticationExtensionsClientOutputs extends Serializable { /** * Gets all of the {@link AuthenticationExtensionsClientOutput}. diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorAssertionResponse.java b/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorAssertionResponse.java index 5d4609951f..045384128f 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorAssertionResponse.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorAssertionResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; + /** * The AuthenticatorAssertionResponse @@ -38,6 +40,9 @@ package org.springframework.security.web.webauthn.api; */ public final class AuthenticatorAssertionResponse extends AuthenticatorResponse { + @Serial + private static final long serialVersionUID = 324976481675434298L; + private final Bytes authenticatorData; private final Bytes signature; diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorResponse.java b/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorResponse.java index 29f34751cd..522f2d0874 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorResponse.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serializable; + /** * The AuthenticatorResponse @@ -26,7 +28,7 @@ package org.springframework.security.web.webauthn.api; * @author Rob Winch * @since 6.4 */ -public abstract class AuthenticatorResponse { +public abstract class AuthenticatorResponse implements Serializable { private final Bytes clientDataJSON; diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/CredentialPropertiesOutput.java b/web/src/main/java/org/springframework/security/web/webauthn/api/CredentialPropertiesOutput.java index 193fe6cbb4..45deb043b5 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/CredentialPropertiesOutput.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/CredentialPropertiesOutput.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; + /** * CredentialPropertiesOutput @@ -27,6 +30,9 @@ package org.springframework.security.web.webauthn.api; public class CredentialPropertiesOutput implements AuthenticationExtensionsClientOutput { + @Serial + private static final long serialVersionUID = -3201699313968303331L; + /** * The extension id. */ @@ -59,7 +65,10 @@ public class CredentialPropertiesOutput * @since 6.4 * @see #getOutput() */ - public static final class ExtensionOutput { + public static final class ExtensionOutput implements Serializable { + + @Serial + private static final long serialVersionUID = 4557406414847424019L; private final boolean rk; diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientOutputs.java b/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientOutputs.java index b1b74d48bf..2e35bf4cfe 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientOutputs.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientOutputs.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; import java.util.Arrays; import java.util.List; @@ -26,6 +27,9 @@ import java.util.List; */ public class ImmutableAuthenticationExtensionsClientOutputs implements AuthenticationExtensionsClientOutputs { + @Serial + private static final long serialVersionUID = -4656390173585180393L; + private final List> outputs; public ImmutableAuthenticationExtensionsClientOutputs(List> outputs) { diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredential.java b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredential.java index ac04b22f0f..541801b819 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredential.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredential.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; + /** * PublicKeyCredential * contains the attributes that are returned to the caller when a new credential is @@ -24,7 +27,10 @@ package org.springframework.security.web.webauthn.api; * @author Rob Winch * @since 6.4 */ -public final class PublicKeyCredential { +public final class PublicKeyCredential implements Serializable { + + @Serial + private static final long serialVersionUID = -1864035469276082606L; private final String id; @@ -34,7 +40,7 @@ public final class PublicKeyCredential { private final R response; - private final AuthenticatorAttachment authenticatorAttachment; + private final transient AuthenticatorAttachment authenticatorAttachment; private final AuthenticationExtensionsClientOutputs clientExtensionResults; diff --git a/web/src/main/java/org/springframework/security/web/webauthn/authentication/WebAuthnAuthenticationRequestToken.java b/web/src/main/java/org/springframework/security/web/webauthn/authentication/WebAuthnAuthenticationRequestToken.java index a885ed7549..7b851b74c2 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/authentication/WebAuthnAuthenticationRequestToken.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/authentication/WebAuthnAuthenticationRequestToken.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.springframework.security.web.webauthn.authentication; +import java.io.Serial; + import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest; @@ -30,6 +32,9 @@ import org.springframework.util.Assert; */ public class WebAuthnAuthenticationRequestToken extends AbstractAuthenticationToken { + @Serial + private static final long serialVersionUID = -1682693433877522403L; + private final RelyingPartyAuthenticationRequest webAuthnRequest; /** diff --git a/web/src/main/java/org/springframework/security/web/webauthn/management/RelyingPartyAuthenticationRequest.java b/web/src/main/java/org/springframework/security/web/webauthn/management/RelyingPartyAuthenticationRequest.java index 1dd1a66c84..62565d7f5c 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/management/RelyingPartyAuthenticationRequest.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/management/RelyingPartyAuthenticationRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ package org.springframework.security.web.webauthn.management; +import java.io.Serial; +import java.io.Serializable; + import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse; import org.springframework.security.web.webauthn.api.PublicKeyCredential; import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions; @@ -29,7 +32,10 @@ import org.springframework.util.Assert; * @since 6.4 * @see WebAuthnRelyingPartyOperations#authenticate(RelyingPartyAuthenticationRequest) */ -public class RelyingPartyAuthenticationRequest { +public class RelyingPartyAuthenticationRequest implements Serializable { + + @Serial + private static final long serialVersionUID = -928083091875202086L; private final PublicKeyCredentialRequestOptions requestOptions; diff --git a/web/src/test/java/org/springframework/security/web/webauthn/api/TestAuthenticationAssertionResponses.java b/web/src/test/java/org/springframework/security/web/webauthn/api/TestAuthenticationAssertionResponses.java new file mode 100644 index 0000000000..a81b0d06ab --- /dev/null +++ b/web/src/test/java/org/springframework/security/web/webauthn/api/TestAuthenticationAssertionResponses.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.web.webauthn.api; + +/** + * @author Max Batischev + */ +public final class TestAuthenticationAssertionResponses { + + public static AuthenticatorAssertionResponse.AuthenticatorAssertionResponseBuilder createAuthenticatorAssertionResponse() { + return AuthenticatorAssertionResponse.builder() + .authenticatorData(Bytes.fromBase64("SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MdAAAAAA")) + .clientDataJSON(Bytes.fromBase64( + "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiaDB2Z3dHUWpvQ3pBekRVc216UHBrLUpWSUpSUmduMEw0S1ZTWU5SY0VaYyIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIsImNyb3NzT3JpZ2luIjpmYWxzZX0")) + .signature(Bytes.fromBase64( + "MEUCIAdfzPAn3voyXynwa0IXk1S0envMY5KP3NEe9aj4B2BuAiEAm_KJhQoWXdvfhbzwACU3NM4ltQe7_Il46qFUwtpuTdg")) + .userHandle(Bytes.fromBase64("oWJtkJ6vJ_m5b84LB4_K7QKTCTEwLIjCh4tFMCGHO4w")); + } + + private TestAuthenticationAssertionResponses() { + } + +} diff --git a/web/src/test/java/org/springframework/security/web/webauthn/api/TestPublicKeyCredential.java b/web/src/test/java/org/springframework/security/web/webauthn/api/TestPublicKeyCredential.java index f2f919b3da..5ae19ac23c 100644 --- a/web/src/test/java/org/springframework/security/web/webauthn/api/TestPublicKeyCredential.java +++ b/web/src/test/java/org/springframework/security/web/webauthn/api/TestPublicKeyCredential.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,6 +38,17 @@ public final class TestPublicKeyCredential { .clientExtensionResults(clientExtensionResults); } + public static PublicKeyCredential.PublicKeyCredentialBuilder createPublicKeyCredential( + R response, AuthenticationExtensionsClientOutputs outputs) { + return PublicKeyCredential.builder() + .id("AX6nVVERrH6opMafUGn3Z9EyNEy6cftfBKV_2YxYl1jdW8CSJxMKGXFV3bnrKTiMSJeInkG7C6B2lPt8E5i3KaM") + .rawId(Bytes + .fromBase64("AX6nVVERrH6opMafUGn3Z9EyNEy6cftfBKV_2YxYl1jdW8CSJxMKGXFV3bnrKTiMSJeInkG7C6B2lPt8E5i3KaM")) + .response(response) + .type(PublicKeyCredentialType.PUBLIC_KEY) + .clientExtensionResults(outputs); + } + private TestPublicKeyCredential() { } From 946812691e5b9c6820060b2bfef95ecb69462c38 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Fri, 14 Feb 2025 12:59:59 -0700 Subject: [PATCH 2/2] Make AuthenticatorAttestation Serializable Issue gh-16481 --- ...gSecurityCoreVersionSerializableTests.java | 10 +++++++++- ...thn.api.AuthenticatorAttachment.serialized | Bin 0 -> 130 bytes ...ebauthn.api.PublicKeyCredential.serialized | Bin 2078 -> 2272 bytes ...AuthnAuthenticationRequestToken.serialized | Bin 3891 -> 3974 bytes ...lyingPartyAuthenticationRequest.serialized | Bin 3196 -> 3279 bytes .../webauthn/api/AuthenticatorAttachment.java | 14 +++++++++++++- .../web/webauthn/api/PublicKeyCredential.java | 2 +- 7 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.AuthenticatorAttachment.serialized diff --git a/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java b/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java index 7f4d78f41b..2982d2a005 100644 --- a/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java +++ b/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java @@ -46,6 +46,7 @@ import jakarta.servlet.http.Cookie; import org.apereo.cas.client.validation.AssertionImpl; import org.instancio.Instancio; import org.instancio.InstancioApi; +import org.instancio.InstancioOfClassApi; import org.instancio.Select; import org.instancio.generator.Generator; import org.junit.jupiter.api.Disabled; @@ -55,6 +56,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.ResolvableType; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpSession; @@ -214,6 +216,7 @@ import org.springframework.security.web.session.HttpSessionCreatedEvent; import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs; import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs; import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse; +import org.springframework.security.web.webauthn.api.AuthenticatorAttachment; import org.springframework.security.web.webauthn.api.AuthenticatorTransport; import org.springframework.security.web.webauthn.api.Bytes; import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput; @@ -658,6 +661,7 @@ class SpringSecurityCoreVersionSerializableTests { generatorByClassName.put(RelyingPartyAuthenticationRequest.class, (r) -> authRequest); generatorByClassName.put(PublicKeyCredential.class, (r) -> credential); generatorByClassName.put(WebAuthnAuthenticationRequestToken.class, (r) -> requestToken); + generatorByClassName.put(AuthenticatorAttachment.class, (r) -> AuthenticatorAttachment.PLATFORM); // @formatter:on } @@ -768,7 +772,11 @@ class SpringSecurityCoreVersionSerializableTests { } private static InstancioApi instancioWithDefaults(Class clazz) { - InstancioApi instancio = Instancio.of(clazz); + InstancioOfClassApi instancio = Instancio.of(clazz); + ResolvableType[] generics = ResolvableType.forClass(clazz).getGenerics(); + for (ResolvableType type : generics) { + instancio.withTypeParameters(type.resolve()); + } if (generatorByClassName.containsKey(clazz)) { instancio.supply(Select.all(clazz), generatorByClassName.get(clazz)); } diff --git a/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.AuthenticatorAttachment.serialized b/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.AuthenticatorAttachment.serialized new file mode 100644 index 0000000000000000000000000000000000000000..449d5b9a9814420db1f69c3f4be1de49b487a2a1 GIT binary patch literal 130 zcmWlSy$!-J6b2tikq{+=I2{dD3c7Sm@WpZ*ga7pWoWM>rjKl!!KvJA^SKa$ZO<}qw zwyI=y(T}OSJ!DKA{-WA27XSbN literal 0 HcmV?d00001 diff --git a/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.PublicKeyCredential.serialized b/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.api.PublicKeyCredential.serialized index 6b2e6a8cc3fe42db44a292e90f1a2cb5b39ee344..2edec67206b88d76f897e14a1ff2853be5f9881a 100644 GIT binary patch delta 287 zcmbOy@IY`vupFBYgLqtF$<^$RjZ?B?lrh z`95npKTAbHF-U`CDTtJr9LminpcvUoLG`yY?&P>lsEGaEYg$i($7N-_@B<7{$Ktw8v7@UDdSx)}Irp3=(QBVw0Ct3<3B_?aK ycgZ6QFfcGMGlyFv3r#-2uE!2j|CK!e&i3JG5n!q)C}H3#C{4=AOxDd#tposm%Q$-g diff --git a/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken.serialized b/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken.serialized index 5945cd459a5a5ff2116d3128645c62c2a4e9832c..b7eda5a62d70b7c0ae5a54b7a07ddea7caa4be07 100644 GIT binary patch delta 205 zcmdli*CxLqn?;(P+_M>f%Ke`N5^f4wKd84uG*Yw{S}_GD>Wo&!fo*7dy|J G!UzEE%s!|9 delta 186 zcmZpZ-z>Kwn}v~e^97bf#?3}-=b3HAeHa82OG`3R^GY(46HD@oToOwX3mNJdfD)X= zndy0nC8b5FPyw#e;?yFK#JrRoh{$9+u5^C!ih^R0yhbUA)SkSBt4khPfPsO5nK|4V kS!l91w;nr8eFJv@jJ^3fw-h6z_~uVMnv8HUCB76!08@-KSpWb4 diff --git a/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest.serialized b/config/src/test/resources/serialized/6.4.x/org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest.serialized index 34f07eca8f47492278c841b45159bab6963056dc..ea313db10713c1763ccc703c91568a83e54f1a59 100644 GIT binary patch delta 261 zcmew(ab9vmA)_3d4}*AOX-P(EUP)$hVo83HV@XM3az-wYU&7!%@x1=zy^P$v$imi} zix>+TSqqAb7-A*|vgu9sSu|hsg$V1i;xVI9eFlC+l*y z2=M|fOU_8l$w|#ihZ=pDGao2v%(WA){4>{VM&8N&-1qp|D+)>&I17qW(^89yQd0nn C2v8&d delta 263 zcmX>v`A1?yAtNK}=4*_Fj4Z`P3^9`vc=RUE;Z~n)&&0lY1#>O4BfAfSU}9-WMrvM3 zW^!UlevwOJNn#;G9RpB;vp6$7FR`SwC>1KeRa%@{Q`C}MC18|lr$J$XL6 z7C(DMK`}_JWGRT0nS6u2OCDK(fq{XUIoujqXmUP>9y?6^5{>{k`!`1mBirN#&K4ma zpi`1F5_57=^U@&}PZs0K2THba?Sw0LAuthenticatorAttachment. @@ -23,7 +27,10 @@ package org.springframework.security.web.webauthn.api; * @author Rob Winch * @since 6.4 */ -public final class AuthenticatorAttachment { +public final class AuthenticatorAttachment implements Serializable { + + @Serial + private static final long serialVersionUID = 8446133215195918090L; /** * Indicates implemen private final R response; - private final transient AuthenticatorAttachment authenticatorAttachment; + private final AuthenticatorAttachment authenticatorAttachment; private final AuthenticationExtensionsClientOutputs clientExtensionResults;