26
26
27
27
import com .fasterxml .jackson .annotation .JsonCreator ;
28
28
import com .fasterxml .jackson .annotation .JsonProperty ;
29
+ import com .yubico .internal .util .ExceptionUtil ;
29
30
import com .yubico .webauthn .data .AuthenticatorAssertionExtensionOutputs ;
30
31
import com .yubico .webauthn .data .AuthenticatorData ;
31
32
import com .yubico .webauthn .data .ByteArray ;
@@ -46,24 +47,16 @@ public class AssertionResult {
46
47
private final boolean success ;
47
48
48
49
/**
49
- * The <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#credential-id">credential
50
- * ID</a> of the credential used for the assertion.
51
- *
52
- * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#credential-id">Credential
53
- * ID</a>
54
- * @see PublicKeyCredentialRequestOptions#getAllowCredentials()
55
- */
56
- @ NonNull private final ByteArray credentialId ;
57
-
58
- /**
59
- * The <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#user-handle">user handle</a>
60
- * of the authenticated user.
50
+ * The {@link RegisteredCredential} that was returned by {@link
51
+ * CredentialRepository#lookup(ByteArray, ByteArray)} and whose public key was used to
52
+ * successfully verify the assertion signature.
61
53
*
62
- * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#user-handle">User Handle</a>
63
- * @see UserIdentity#getId()
64
- * @see #getUsername()
54
+ * <p>NOTE: The {@link RegisteredCredential#getSignatureCount() signature count} in this object
55
+ * will reflect the signature counter state <i>before</i> the assertion operation, not the new
56
+ * counter value. When updating your database state, use the signature counter from {@link
57
+ * #getSignatureCount()} instead.
65
58
*/
66
- @ NonNull private final ByteArray userHandle ;
59
+ private final RegisteredCredential credential ;
67
60
68
61
/**
69
62
* The username of the authenticated user.
@@ -107,22 +100,54 @@ public class AssertionResult {
107
100
108
101
private final AuthenticatorAssertionExtensionOutputs authenticatorExtensionOutputs ;
109
102
103
+ private AssertionResult (
104
+ boolean success ,
105
+ @ NonNull @ JsonProperty ("credential" ) RegisteredCredential credential ,
106
+ @ NonNull String username ,
107
+ long signatureCount ,
108
+ boolean signatureCounterValid ,
109
+ ClientAssertionExtensionOutputs clientExtensionOutputs ,
110
+ AuthenticatorAssertionExtensionOutputs authenticatorExtensionOutputs ) {
111
+ this (
112
+ success ,
113
+ credential ,
114
+ username ,
115
+ null ,
116
+ null ,
117
+ signatureCount ,
118
+ signatureCounterValid ,
119
+ clientExtensionOutputs ,
120
+ authenticatorExtensionOutputs );
121
+ }
122
+
110
123
@ JsonCreator
111
124
private AssertionResult (
112
125
@ JsonProperty ("success" ) boolean success ,
113
- @ NonNull @ JsonProperty ("credentialId" ) ByteArray credentialId ,
114
- @ NonNull @ JsonProperty ("userHandle" ) ByteArray userHandle ,
126
+ @ NonNull @ JsonProperty ("credential" ) RegisteredCredential credential ,
115
127
@ NonNull @ JsonProperty ("username" ) String username ,
128
+ @ JsonProperty ("credentialId" ) ByteArray credentialId , // TODO: Delete in next major release
129
+ @ JsonProperty ("userHandle" ) ByteArray userHandle , // TODO: Delete in next major release
116
130
@ JsonProperty ("signatureCount" ) long signatureCount ,
117
131
@ JsonProperty ("signatureCounterValid" ) boolean signatureCounterValid ,
118
132
@ JsonProperty ("clientExtensionOutputs" )
119
133
ClientAssertionExtensionOutputs clientExtensionOutputs ,
120
134
@ JsonProperty ("authenticatorExtensionOutputs" )
121
135
AuthenticatorAssertionExtensionOutputs authenticatorExtensionOutputs ) {
122
136
this .success = success ;
123
- this .credentialId = credentialId ;
124
- this .userHandle = userHandle ;
137
+ this .credential = credential ;
125
138
this .username = username ;
139
+
140
+ if (credentialId != null ) {
141
+ ExceptionUtil .assure (
142
+ credential .getCredentialId ().equals (credentialId ),
143
+ "Legacy credentialId is present and does not equal credential.credentialId" );
144
+ }
145
+ if (userHandle != null ) {
146
+ ExceptionUtil .assure (
147
+ credential .getUserHandle ().equals (userHandle ),
148
+ "Legacy userHandle is present and does not equal credential.userHandle" );
149
+ }
150
+
126
151
this .signatureCount = signatureCount ;
127
152
this .signatureCounterValid = signatureCounterValid ;
128
153
this .clientExtensionOutputs =
@@ -132,6 +157,36 @@ private AssertionResult(
132
157
this .authenticatorExtensionOutputs = authenticatorExtensionOutputs ;
133
158
}
134
159
160
+ /**
161
+ * The <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#credential-id">credential
162
+ * ID</a> of the credential used for the assertion.
163
+ *
164
+ * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#credential-id">Credential
165
+ * ID</a>
166
+ * @see PublicKeyCredentialRequestOptions#getAllowCredentials()
167
+ * @deprecated Use {@link #getCredential()}.{@link RegisteredCredential#getCredentialId()
168
+ * getCredentialId()} instead.
169
+ */
170
+ @ Deprecated
171
+ public ByteArray getCredentialId () {
172
+ return credential .getCredentialId ();
173
+ }
174
+
175
+ /**
176
+ * The <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#user-handle">user handle</a>
177
+ * of the authenticated user.
178
+ *
179
+ * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#user-handle">User Handle</a>
180
+ * @see UserIdentity#getId()
181
+ * @see #getUsername()
182
+ * @deprecated Use {@link #getCredential()}.{@link RegisteredCredential#getUserHandle()} ()
183
+ * getUserHandle()} instead.
184
+ */
185
+ @ Deprecated
186
+ public ByteArray getUserHandle () {
187
+ return credential .getUserHandle ();
188
+ }
189
+
135
190
/**
136
191
* The <a
137
192
* href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#client-extension-output">client
@@ -180,49 +235,42 @@ public Step2 success(boolean success) {
180
235
}
181
236
182
237
public class Step2 {
183
- public Step3 credentialId ( ByteArray credentialId ) {
184
- builder .credentialId ( credentialId );
238
+ public Step3 credential ( RegisteredCredential credential ) {
239
+ builder .credential ( credential );
185
240
return new Step3 ();
186
241
}
187
242
}
188
243
189
244
public class Step3 {
190
- public Step4 userHandle ( ByteArray userHandle ) {
191
- builder .userHandle ( userHandle );
245
+ public Step4 username ( String username ) {
246
+ builder .username ( username );
192
247
return new Step4 ();
193
248
}
194
249
}
195
250
196
251
public class Step4 {
197
- public Step5 username ( String username ) {
198
- builder .username ( username );
252
+ public Step5 signatureCount ( long signatureCount ) {
253
+ builder .signatureCount ( signatureCount );
199
254
return new Step5 ();
200
255
}
201
256
}
202
257
203
258
public class Step5 {
204
- public Step6 signatureCount ( long signatureCount ) {
205
- builder .signatureCount ( signatureCount );
259
+ public Step6 signatureCounterValid ( boolean signatureCounterValid ) {
260
+ builder .signatureCounterValid ( signatureCounterValid );
206
261
return new Step6 ();
207
262
}
208
263
}
209
264
210
265
public class Step6 {
211
- public Step7 signatureCounterValid (boolean signatureCounterValid ) {
212
- builder .signatureCounterValid (signatureCounterValid );
213
- return new Step7 ();
214
- }
215
- }
216
-
217
- public class Step7 {
218
- public Step8 clientExtensionOutputs (
266
+ public Step7 clientExtensionOutputs (
219
267
ClientAssertionExtensionOutputs clientExtensionOutputs ) {
220
268
builder .clientExtensionOutputs (clientExtensionOutputs );
221
- return new Step8 ();
269
+ return new Step7 ();
222
270
}
223
271
}
224
272
225
- public class Step8 {
273
+ public class Step7 {
226
274
public AssertionResultBuilder assertionExtensionOutputs (
227
275
AuthenticatorAssertionExtensionOutputs authenticatorExtensionOutputs ) {
228
276
return builder .authenticatorExtensionOutputs (authenticatorExtensionOutputs );
0 commit comments