@@ -29,18 +29,21 @@ import com.fasterxml.jackson.core.`type`.TypeReference
29
29
import com .fasterxml .jackson .databind .DeserializationFeature
30
30
import com .fasterxml .jackson .databind .ObjectMapper
31
31
import com .fasterxml .jackson .databind .SerializationFeature
32
+ import com .fasterxml .jackson .databind .exc .ValueInstantiationException
33
+ import com .fasterxml .jackson .databind .node .ObjectNode
34
+ import com .fasterxml .jackson .databind .node .TextNode
32
35
import com .fasterxml .jackson .datatype .jdk8 .Jdk8Module
33
36
import com .yubico .webauthn .AssertionRequest
34
37
import com .yubico .webauthn .AssertionResult
35
38
import com .yubico .webauthn .Generators ._
39
+ import com .yubico .webauthn .RegisteredCredential
36
40
import com .yubico .webauthn .RegistrationResult
37
41
import com .yubico .webauthn .attestation .Attestation
38
42
import com .yubico .webauthn .attestation .Generators ._
39
43
import com .yubico .webauthn .attestation .Transport
40
44
import com .yubico .webauthn .data .Generators ._
41
45
import com .yubico .webauthn .extension .appid .AppId
42
46
import com .yubico .webauthn .extension .appid .Generators ._
43
- import com .yubico .webauthn .RegisteredCredential
44
47
import org .junit .runner .RunWith
45
48
import org .scalacheck .Arbitrary
46
49
import org .scalatest .FunSpec
@@ -161,6 +164,106 @@ class JsonIoSpec extends FunSpec with Matchers with ScalaCheckDrivenPropertyChec
161
164
}
162
165
test(new TypeReference [PublicKeyCredential [AuthenticatorAssertionResponse , ClientAssertionExtensionOutputs ]](){})
163
166
}
167
+
168
+ it(" allows rawId to be present without id." ) {
169
+ def test [P <: PublicKeyCredential [_, _]](tpe : TypeReference [P ])(implicit a : Arbitrary [P ]): Unit = {
170
+ forAll { value : P =>
171
+ val encoded : String = json.writeValueAsString(value)
172
+ val decoded = json.readTree(encoded)
173
+ decoded.asInstanceOf [ObjectNode ]
174
+ .set[ObjectNode ](" rawId" , new TextNode (value.getId.getBase64Url))
175
+ .remove(" id" )
176
+ val reencoded = json.writeValueAsString(decoded)
177
+ val restored : P = json.readValue(reencoded, tpe)
178
+
179
+ restored.getId should equal (value.getId)
180
+ restored should equal (value)
181
+ }
182
+ }
183
+ test(new TypeReference [PublicKeyCredential [AuthenticatorAssertionResponse , ClientAssertionExtensionOutputs ]](){})
184
+ test(new TypeReference [PublicKeyCredential [AuthenticatorAttestationResponse , ClientRegistrationExtensionOutputs ]](){})
185
+ }
186
+
187
+ it(" allows id to be present without rawId." ) {
188
+ def test [P <: PublicKeyCredential [_, _]](tpe : TypeReference [P ])(implicit a : Arbitrary [P ]): Unit = {
189
+ forAll { value : P =>
190
+ val encoded : String = json.writeValueAsString(value)
191
+ val decoded = json.readTree(encoded)
192
+ decoded.asInstanceOf [ObjectNode ]
193
+ .set[ObjectNode ](" id" , new TextNode (value.getId.getBase64Url))
194
+ .remove(" rawId" )
195
+ val reencoded = json.writeValueAsString(decoded)
196
+ val restored : P = json.readValue(reencoded, tpe)
197
+
198
+ restored should equal (value)
199
+ }
200
+ }
201
+ test(new TypeReference [PublicKeyCredential [AuthenticatorAssertionResponse , ClientAssertionExtensionOutputs ]](){})
202
+ test(new TypeReference [PublicKeyCredential [AuthenticatorAttestationResponse , ClientRegistrationExtensionOutputs ]](){})
203
+ }
204
+
205
+ it(" allows both id and rawId to be present if equal." ) {
206
+ def test [P <: PublicKeyCredential [_, _]](tpe : TypeReference [P ])(implicit a : Arbitrary [P ]): Unit = {
207
+ forAll { value : P =>
208
+ val encoded : String = json.writeValueAsString(value)
209
+ val decoded = json.readTree(encoded)
210
+ decoded.asInstanceOf [ObjectNode ].set(" id" , new TextNode (value.getId.getBase64Url))
211
+ decoded.asInstanceOf [ObjectNode ].set(" rawId" , new TextNode (value.getId.getBase64Url))
212
+ val reencoded = json.writeValueAsString(decoded)
213
+ val restored : P = json.readValue(reencoded, tpe)
214
+
215
+ restored should equal (value)
216
+ }
217
+ }
218
+ test(new TypeReference [PublicKeyCredential [AuthenticatorAssertionResponse , ClientAssertionExtensionOutputs ]](){})
219
+ test(new TypeReference [PublicKeyCredential [AuthenticatorAttestationResponse , ClientRegistrationExtensionOutputs ]](){})
220
+ }
221
+
222
+ it(" does not allow both id and rawId to be absent." ) {
223
+ def test [P <: PublicKeyCredential [_, _]](tpe : TypeReference [P ])(implicit a : Arbitrary [P ]): Unit = {
224
+ forAll { value : P =>
225
+ val encoded : String = json.writeValueAsString(value)
226
+ val decoded = json.readTree(encoded).asInstanceOf [ObjectNode ]
227
+ decoded.remove(" id" )
228
+ decoded.remove(" rawId" )
229
+ val reencoded = json.writeValueAsString(decoded)
230
+
231
+ an [ValueInstantiationException ] should be thrownBy {
232
+ json.readValue(reencoded, tpe)
233
+ }
234
+ }
235
+ }
236
+
237
+ test(new TypeReference [PublicKeyCredential [AuthenticatorAssertionResponse , ClientAssertionExtensionOutputs ]](){})
238
+ test(new TypeReference [PublicKeyCredential [AuthenticatorAttestationResponse , ClientRegistrationExtensionOutputs ]](){})
239
+ }
240
+
241
+ it(" does not allow both id and rawId to be present and not equal." ) {
242
+ def test [P <: PublicKeyCredential [_, _]](tpe : TypeReference [P ])(implicit a : Arbitrary [P ]): Unit = {
243
+ forAll { value : P =>
244
+ val modId = new ByteArray (
245
+ if (value.getId.getBytes.isEmpty)
246
+ Array (0 )
247
+ else
248
+ value.getId.getBytes.updated(0 , (value.getId.getBytes()(0 ) + 1 % 127 ).byteValue)
249
+ )
250
+
251
+ val encoded : String = json.writeValueAsString(value)
252
+ val decoded = json.readTree(encoded)
253
+ decoded.asInstanceOf [ObjectNode ]
254
+ .set[ObjectNode ](" id" , new TextNode (value.getId.getBase64Url))
255
+ .set[ObjectNode ](" rawId" , new TextNode (modId.getBase64Url))
256
+ val reencoded = json.writeValueAsString(decoded)
257
+
258
+ an [ValueInstantiationException ] should be thrownBy {
259
+ json.readValue(reencoded, tpe)
260
+ }
261
+ }
262
+ }
263
+
264
+ test(new TypeReference [PublicKeyCredential [AuthenticatorAssertionResponse , ClientAssertionExtensionOutputs ]](){})
265
+ test(new TypeReference [PublicKeyCredential [AuthenticatorAttestationResponse , ClientRegistrationExtensionOutputs ]](){})
266
+ }
164
267
}
165
268
166
269
}
0 commit comments