AssertionResultV2.java

1
// Copyright (c) 2018, Yubico AB
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are met:
6
//
7
// 1. Redistributions of source code must retain the above copyright notice, this
8
//    list of conditions and the following disclaimer.
9
//
10
// 2. Redistributions in binary form must reproduce the above copyright notice,
11
//    this list of conditions and the following disclaimer in the documentation
12
//    and/or other materials provided with the distribution.
13
//
14
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25
package com.yubico.webauthn;
26
27
import com.fasterxml.jackson.annotation.JsonCreator;
28
import com.fasterxml.jackson.annotation.JsonIgnore;
29
import com.fasterxml.jackson.annotation.JsonProperty;
30
import com.yubico.webauthn.data.AuthenticatorAssertionExtensionOutputs;
31
import com.yubico.webauthn.data.AuthenticatorAssertionResponse;
32
import com.yubico.webauthn.data.AuthenticatorAttachment;
33
import com.yubico.webauthn.data.AuthenticatorData;
34
import com.yubico.webauthn.data.AuthenticatorDataFlags;
35
import com.yubico.webauthn.data.AuthenticatorResponse;
36
import com.yubico.webauthn.data.ByteArray;
37
import com.yubico.webauthn.data.ClientAssertionExtensionOutputs;
38
import com.yubico.webauthn.data.Extensions;
39
import com.yubico.webauthn.data.PublicKeyCredential;
40
import java.util.Optional;
41
import lombok.AccessLevel;
42
import lombok.Getter;
43
import lombok.NonNull;
44
import lombok.Value;
45
46
/**
47
 * The result of a call to {@link RelyingPartyV2#finishAssertion(FinishAssertionOptions)}.
48
 *
49
 * @deprecated EXPERIMENTAL: This is an experimental feature. It is likely to change or be deleted
50
 *     before reaching a mature release.
51
 */
52
@Deprecated
53
@Value
54
public class AssertionResultV2<C extends CredentialRecord> {
55
56
  /** <code>true</code> if the assertion was verified successfully. */
57
  private final boolean success;
58
59
  @JsonProperty
60
  @Getter(AccessLevel.NONE)
61
  private final PublicKeyCredential<AuthenticatorAssertionResponse, ClientAssertionExtensionOutputs>
62
      credentialResponse;
63
64
  /**
65
   * The {@link CredentialRecord} that was returned by {@link
66
   * CredentialRepositoryV2#lookup(ByteArray, ByteArray)} and whose public key was used to
67
   * successfully verify the assertion signature.
68
   *
69
   * <p>NOTE: The {@link CredentialRecord#getSignatureCount() signature count}, {@link
70
   * CredentialRecord#isBackupEligible() backup eligibility} and {@link
71
   * CredentialRecord#isBackedUp() backup state} properties in this object will reflect the state
72
   * <i>before</i> the assertion operation, not the new state. When updating your database state,
73
   * use the signature counter and backup state from {@link #getSignatureCount()}, {@link
74
   * #isBackupEligible()} and {@link #isBackedUp()} instead.
75
   *
76
   * @deprecated EXPERIMENTAL: This is an experimental feature. It is likely to change or be deleted
77
   *     before reaching a mature release.
78
   */
79
  @Deprecated private final C credential;
80
81
  /**
82
   * <code>true</code> if and only if at least one of the following is true:
83
   *
84
   * <ul>
85
   *   <li>The {@link AuthenticatorData#getSignatureCounter() signature counter value} in the
86
   *       assertion was strictly greater than {@link CredentialRecord#getSignatureCount() the
87
   *       stored one}.
88
   *   <li>The {@link AuthenticatorData#getSignatureCounter() signature counter value} in the
89
   *       assertion and {@link CredentialRecord#getSignatureCount() the stored one} were both zero.
90
   * </ul>
91
   *
92
   * @see <a
93
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-authenticator-data">§6.1.
94
   *     Authenticator Data</a>
95
   * @see AuthenticatorData#getSignatureCounter()
96
   * @see CredentialRecord#getSignatureCount()
97
   * @see RelyingParty.RelyingPartyBuilder#validateSignatureCounter(boolean)
98
   */
99
  private final boolean signatureCounterValid;
100
101
  @JsonCreator
102
  AssertionResultV2(
103
      @JsonProperty("success") boolean success,
104 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("credentialResponse")
105
          PublicKeyCredential<AuthenticatorAssertionResponse, ClientAssertionExtensionOutputs>
106
              credentialResponse,
107 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("credential") C credential,
108
      @JsonProperty("signatureCounterValid") boolean signatureCounterValid) {
109
    this.success = success;
110
    this.credentialResponse = credentialResponse;
111
    this.credential = credential;
112
    this.signatureCounterValid = signatureCounterValid;
113
  }
114
115
  /**
116
   * Check whether the <a href="https://www.w3.org/TR/webauthn/#user-verification">user
117
   * verification</a> as performed during the authentication ceremony.
118
   *
119
   * <p>This flag is also available via <code>
120
   * {@link PublicKeyCredential}.{@link PublicKeyCredential#getResponse() getResponse()}.{@link AuthenticatorResponse#getParsedAuthenticatorData() getParsedAuthenticatorData()}.{@link AuthenticatorData#getFlags() getFlags()}.{@link AuthenticatorDataFlags#UV UV}
121
   * </code>.
122
   *
123
   * @return <code>true</code> if and only if the authenticator claims to have performed user
124
   *     verification during the authentication ceremony.
125
   * @see <a href="https://www.w3.org/TR/webauthn/#user-verification">User Verification</a>
126
   * @see <a href="https://w3c.github.io/webauthn/#authdata-flags-uv">UV flag in §6.1. Authenticator
127
   *     Data</a>
128
   */
129
  @JsonIgnore
130
  public boolean isUserVerified() {
131 2 1. isUserVerified : replaced boolean return with false for com/yubico/webauthn/AssertionResultV2::isUserVerified → KILLED
2. isUserVerified : replaced boolean return with true for com/yubico/webauthn/AssertionResultV2::isUserVerified → KILLED
    return credentialResponse.getResponse().getParsedAuthenticatorData().getFlags().UV;
132
  }
133
134
  /**
135
   * Check whether the asserted credential is <a
136
   * href="https://w3c.github.io/webauthn/#backup-eligible">backup eligible</a>, using the <a
137
   * href="https://w3c.github.io/webauthn/#authdata-flags-be">BE flag</a> in the authenticator data.
138
   *
139
   * <p>You SHOULD store this value in your representation of the corresponding {@link
140
   * CredentialRecord} if no value is stored yet. {@link CredentialRepository} implementations
141
   * SHOULD set this value when reconstructing that {@link CredentialRecord}.
142
   *
143
   * @return <code>true</code> if and only if the created credential is backup eligible. NOTE that
144
   *     this is only a hint and not a guarantee, unless backed by a trusted authenticator
145
   *     attestation.
146
   * @see <a href="https://w3c.github.io/webauthn/#backup-eligible">Backup Eligible in §4.
147
   *     Terminology</a>
148
   * @see <a href="https://w3c.github.io/webauthn/#authdata-flags-be">BE flag in §6.1. Authenticator
149
   *     Data</a>
150
   * @deprecated EXPERIMENTAL: This feature is from a not yet mature standard; it could change as
151
   *     the standard matures.
152
   */
153
  @Deprecated
154
  @JsonIgnore
155
  public boolean isBackupEligible() {
156 2 1. isBackupEligible : replaced boolean return with false for com/yubico/webauthn/AssertionResultV2::isBackupEligible → KILLED
2. isBackupEligible : replaced boolean return with true for com/yubico/webauthn/AssertionResultV2::isBackupEligible → KILLED
    return credentialResponse.getResponse().getParsedAuthenticatorData().getFlags().BE;
157
  }
158
159
  /**
160
   * Get the current <a href="https://w3c.github.io/webauthn/#backup-state">backup state</a> of the
161
   * asserted credential, using the <a href="https://w3c.github.io/webauthn/#authdata-flags-bs">BS
162
   * flag</a> in the authenticator data.
163
   *
164
   * <p>You SHOULD update this value in your representation of a {@link CredentialRecord}. {@link
165
   * CredentialRepository} implementations SHOULD set this value when reconstructing that {@link
166
   * CredentialRecord}.
167
   *
168
   * @return <code>true</code> if and only if the created credential is believed to currently be
169
   *     backed up. NOTE that this is only a hint and not a guarantee, unless backed by a trusted
170
   *     authenticator attestation.
171
   * @see <a href="https://w3c.github.io/webauthn/#backup-state">Backup State in §4. Terminology</a>
172
   * @see <a href="https://w3c.github.io/webauthn/#authdata-flags-bs">BS flag in §6.1. Authenticator
173
   *     Data</a>
174
   * @deprecated EXPERIMENTAL: This feature is from a not yet mature standard; it could change as
175
   *     the standard matures.
176
   */
177
  @Deprecated
178
  @JsonIgnore
179
  public boolean isBackedUp() {
180 2 1. isBackedUp : replaced boolean return with false for com/yubico/webauthn/AssertionResultV2::isBackedUp → KILLED
2. isBackedUp : replaced boolean return with true for com/yubico/webauthn/AssertionResultV2::isBackedUp → KILLED
    return credentialResponse.getResponse().getParsedAuthenticatorData().getFlags().BS;
181
  }
182
183
  /**
184
   * The <a href="https://w3c.github.io/webauthn/#authenticator-attachment-modality">authenticator
185
   * attachment modality</a> in effect at the time the asserted credential was used.
186
   *
187
   * @see PublicKeyCredential#getAuthenticatorAttachment()
188
   * @deprecated EXPERIMENTAL: This feature is from a not yet mature standard; it could change as
189
   *     the standard matures.
190
   */
191
  @Deprecated
192
  @JsonIgnore
193
  public Optional<AuthenticatorAttachment> getAuthenticatorAttachment() {
194 1 1. getAuthenticatorAttachment : replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::getAuthenticatorAttachment → KILLED
    return credentialResponse.getAuthenticatorAttachment();
195
  }
196
197
  /**
198
   * The new <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#signcount">signature
199
   * count</a> of the credential used for the assertion.
200
   *
201
   * <p>You should update this value in your database.
202
   *
203
   * @see AuthenticatorData#getSignatureCounter()
204
   */
205
  @JsonIgnore
206
  public long getSignatureCount() {
207 1 1. getSignatureCount : replaced long return with 0 for com/yubico/webauthn/AssertionResultV2::getSignatureCount → KILLED
    return credentialResponse.getResponse().getParsedAuthenticatorData().getSignatureCounter();
208
  }
209
210
  /**
211
   * The <a
212
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#client-extension-output">client
213
   * extension outputs</a>, if any.
214
   *
215
   * <p>This is present if and only if at least one extension output is present in the return value.
216
   *
217
   * @see <a
218
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-client-extension-processing">§9.4.
219
   *     Client Extension Processing</a>
220
   * @see ClientAssertionExtensionOutputs
221
   * @see #getAuthenticatorExtensionOutputs() ()
222
   */
223
  @JsonIgnore
224
  public Optional<ClientAssertionExtensionOutputs> getClientExtensionOutputs() {
225 1 1. getClientExtensionOutputs : replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::getClientExtensionOutputs → KILLED
    return Optional.of(credentialResponse.getClientExtensionResults())
226 2 1. lambda$getClientExtensionOutputs$0 : replaced boolean return with true for com/yubico/webauthn/AssertionResultV2::lambda$getClientExtensionOutputs$0 → SURVIVED
2. lambda$getClientExtensionOutputs$0 : negated conditional → KILLED
        .filter(ceo -> !ceo.getExtensionIds().isEmpty());
227
  }
228
229
  /**
230
   * The <a
231
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#authenticator-extension-output">authenticator
232
   * extension outputs</a>, if any.
233
   *
234
   * <p>This is present if and only if at least one extension output is present in the return value.
235
   *
236
   * @see <a
237
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-authenticator-extension-processing">§9.5.
238
   *     Authenticator Extension Processing</a>
239
   * @see AuthenticatorAssertionExtensionOutputs
240
   * @see #getClientExtensionOutputs()
241
   */
242
  @JsonIgnore
243
  public Optional<AuthenticatorAssertionExtensionOutputs> getAuthenticatorExtensionOutputs() {
244 1 1. getAuthenticatorExtensionOutputs : replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::getAuthenticatorExtensionOutputs → KILLED
    return AuthenticatorAssertionExtensionOutputs.fromAuthenticatorData(
245
        credentialResponse.getResponse().getParsedAuthenticatorData());
246
  }
247
248
  /**
249
   * Retrieve a suitable nickname for this credential, if one is available. This MAY differ from
250
   * {@link RegistrationResult#getAuthenticatorDisplayName() the value returned during
251
   * registration}, if any. In that case the application may want to offer the user to update the
252
   * previously stored value, if any.
253
   *
254
   * <p>This returns the <code>authenticatorDisplayName</code> output from the <a
255
   * href="https://w3c.github.io/webauthn/#sctn-authenticator-credential-properties-extension">
256
   * <code>credProps</code></a> extension.
257
   *
258
   * @return A user-chosen or vendor-default display name for the credential, if available.
259
   *     Otherwise empty.
260
   * @see <a
261
   *     href="https://w3c.github.io/webauthn/#dom-credentialpropertiesoutput-authenticatordisplayname">
262
   *     <code>authenticatorDisplayName</code> in §10.1.3. Credential Properties Extension
263
   *     (credProps)</a>
264
   * @see RegistrationResult#getAuthenticatorDisplayName()
265
   * @see Extensions.CredentialProperties.CredentialPropertiesOutput#getAuthenticatorDisplayName()
266
   * @deprecated EXPERIMENTAL: This feature is from a not yet mature standard; it could change as
267
   *     the standard matures.
268
   */
269
  @JsonIgnore
270
  @Deprecated
271
  public Optional<String> getAuthenticatorDisplayName() {
272 1 1. getAuthenticatorDisplayName : replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::getAuthenticatorDisplayName → KILLED
    return getClientExtensionOutputs()
273 1 1. lambda$getAuthenticatorDisplayName$1 : replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::lambda$getAuthenticatorDisplayName$1 → KILLED
        .flatMap(outputs -> outputs.getCredProps())
274 1 1. lambda$getAuthenticatorDisplayName$2 : replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::lambda$getAuthenticatorDisplayName$2 → KILLED
        .flatMap(credProps -> credProps.getAuthenticatorDisplayName());
275
  }
276
}

Mutations

104

1.1
Location : <init>
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

107

1.1
Location : <init>
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

131

1.1
Location : isUserVerified
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced boolean return with false for com/yubico/webauthn/AssertionResultV2::isUserVerified → KILLED

2.2
Location : isUserVerified
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced boolean return with true for com/yubico/webauthn/AssertionResultV2::isUserVerified → KILLED

156

1.1
Location : isBackupEligible
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced boolean return with false for com/yubico/webauthn/AssertionResultV2::isBackupEligible → KILLED

2.2
Location : isBackupEligible
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced boolean return with true for com/yubico/webauthn/AssertionResultV2::isBackupEligible → KILLED

180

1.1
Location : isBackedUp
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced boolean return with false for com/yubico/webauthn/AssertionResultV2::isBackedUp → KILLED

2.2
Location : isBackedUp
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced boolean return with true for com/yubico/webauthn/AssertionResultV2::isBackedUp → KILLED

194

1.1
Location : getAuthenticatorAttachment
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::getAuthenticatorAttachment → KILLED

207

1.1
Location : getSignatureCount
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced long return with 0 for com/yubico/webauthn/AssertionResultV2::getSignatureCount → KILLED

225

1.1
Location : getClientExtensionOutputs
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::getClientExtensionOutputs → KILLED

226

1.1
Location : lambda$getClientExtensionOutputs$0
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
negated conditional → KILLED

2.2
Location : lambda$getClientExtensionOutputs$0
Killed by : none
replaced boolean return with true for com/yubico/webauthn/AssertionResultV2::lambda$getClientExtensionOutputs$0 → SURVIVED

244

1.1
Location : getAuthenticatorExtensionOutputs
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::getAuthenticatorExtensionOutputs → KILLED

272

1.1
Location : getAuthenticatorDisplayName
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::getAuthenticatorDisplayName → KILLED

273

1.1
Location : lambda$getAuthenticatorDisplayName$1
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::lambda$getAuthenticatorDisplayName$1 → KILLED

274

1.1
Location : lambda$getAuthenticatorDisplayName$2
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with Optional.empty for com/yubico/webauthn/AssertionResultV2::lambda$getAuthenticatorDisplayName$2 → KILLED

Active mutators

Tests examined


Report generated by PIT 1.15.0