AuthenticatorAssertionResponse.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.data;
26
27
import com.fasterxml.jackson.annotation.JsonCreator;
28
import com.fasterxml.jackson.annotation.JsonProperty;
29
import com.yubico.webauthn.data.exception.Base64UrlException;
30
import java.io.IOException;
31
import java.util.Optional;
32
import lombok.Builder;
33
import lombok.Getter;
34
import lombok.NonNull;
35
import lombok.Value;
36
37
/**
38
 * Represents an authenticator's response to a client’s request for generation of a new
39
 * authentication assertion given the WebAuthn Relying Party's {@linkplain
40
 * PublicKeyCredentialRequestOptions#getChallenge()} challenge} and OPTIONAL {@linkplain
41
 * PublicKeyCredentialRequestOptions#getAllowCredentials()} list of credentials} it is aware of.
42
 * This response contains a cryptographic {@linkplain #signature} proving possession of the
43
 * credential private key, and optionally evidence of user consent to a specific transaction.
44
 *
45
 * @see <a
46
 *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#authenticatorassertionresponse">§5.2.2.
47
 *     Web Authentication Assertion (interface AuthenticatorAssertionResponse) </a>
48
 */
49
@Value
50
public class AuthenticatorAssertionResponse implements AuthenticatorResponse {
51
52
  @NonNull
53
  @Getter(onMethod = @__({@Override}))
54
  private final ByteArray authenticatorData;
55
56
  @NonNull
57
  @Getter(onMethod = @__({@Override}))
58
  private final ByteArray clientDataJSON;
59
60
  /**
61
   * The raw signature returned from the authenticator. See <a
62
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-op-get-assertion">§6.3.3 The
63
   * authenticatorGetAssertion Operation</a>.
64
   */
65
  @NonNull private final ByteArray signature;
66
67
  /**
68
   * The user handle returned from the authenticator, or empty if the authenticator did not return a
69
   * user handle. See <a
70
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-op-get-assertion">§6.3.3 The
71
   * authenticatorGetAssertion Operation</a>.
72
   */
73
  private final ByteArray userHandle;
74
75
  // This overrides the default getter in AuthenticatorResponse which re-parses the authenticator
76
  // data on every invocation. This "optimization" has no measurable impact on performance, but it
77
  // seems rude to obviously waste cycles for nothing.
78
  private final transient AuthenticatorData parsedAuthenticatorData;
79
80
  @NonNull
81
  @Getter(onMethod = @__({@Override}))
82
  private final transient CollectedClientData clientData;
83
84
  @JsonCreator
85
  @Builder(toBuilder = true)
86
  private AuthenticatorAssertionResponse(
87 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("authenticatorData") final ByteArray authenticatorData,
88 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("clientDataJSON") final ByteArray clientDataJSON,
89 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("signature") final ByteArray signature,
90
      @JsonProperty("userHandle") final ByteArray userHandle)
91
      throws IOException, Base64UrlException {
92
    this.authenticatorData = authenticatorData;
93
    this.parsedAuthenticatorData = new AuthenticatorData(authenticatorData);
94
    this.clientDataJSON = clientDataJSON;
95
    this.signature = signature;
96
    this.userHandle = userHandle;
97
    this.clientData = new CollectedClientData(this.clientDataJSON);
98
  }
99
100
  /**
101
   * The user handle returned from the authenticator, or empty if the authenticator did not return a
102
   * user handle. See <a
103
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-op-get-assertion">§6.3.3 The
104
   * authenticatorGetAssertion Operation</a>.
105
   */
106
  public Optional<ByteArray> getUserHandle() {
107 1 1. getUserHandle : replaced return value with Optional.empty for com/yubico/webauthn/data/AuthenticatorAssertionResponse::getUserHandle → KILLED
    return Optional.ofNullable(userHandle);
108
  }
109
110
  public static AuthenticatorAssertionResponseBuilder.MandatoryStages builder() {
111 1 1. builder : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse::builder → KILLED
    return new AuthenticatorAssertionResponseBuilder.MandatoryStages();
112
  }
113
114
  public static class AuthenticatorAssertionResponseBuilder {
115
    private ByteArray userHandle = null;
116
117
    public static class MandatoryStages {
118
      private final AuthenticatorAssertionResponseBuilder builder =
119
          new AuthenticatorAssertionResponseBuilder();
120
121
      /**
122
       * {@link AuthenticatorAssertionResponseBuilder#authenticatorData(ByteArray)
123
       * authenticatorData} is a required parameter.
124
       *
125
       * @see AuthenticatorAssertionResponseBuilder#authenticatorData(ByteArray)
126
       */
127
      public Step2 authenticatorData(ByteArray authenticatorData) {
128
        builder.authenticatorData(authenticatorData);
129 1 1. authenticatorData : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse$AuthenticatorAssertionResponseBuilder$MandatoryStages::authenticatorData → KILLED
        return new Step2();
130
      }
131
132
      public class Step2 {
133
        /**
134
         * {@link AuthenticatorAssertionResponseBuilder#clientDataJSON(ByteArray) clientDataJSON} is
135
         * a required parameter.
136
         *
137
         * @see AuthenticatorAssertionResponseBuilder#clientDataJSON(ByteArray)
138
         */
139
        public Step3 clientDataJSON(ByteArray clientDataJSON) {
140
          builder.clientDataJSON(clientDataJSON);
141 1 1. clientDataJSON : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse$AuthenticatorAssertionResponseBuilder$MandatoryStages$Step2::clientDataJSON → KILLED
          return new Step3();
142
        }
143
      }
144
145
      public class Step3 {
146
        /**
147
         * {@link AuthenticatorAssertionResponseBuilder#signature(ByteArray) signature} is a
148
         * required parameter.
149
         *
150
         * @see AuthenticatorAssertionResponseBuilder#signature(ByteArray)
151
         */
152
        public AuthenticatorAssertionResponseBuilder signature(ByteArray signature) {
153 1 1. signature : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse$AuthenticatorAssertionResponseBuilder$MandatoryStages$Step3::signature → KILLED
          return builder.signature(signature);
154
        }
155
      }
156
    }
157
158
    /**
159
     * The user handle returned from the authenticator, or empty if the authenticator did not return
160
     * a user handle. See <a
161
     * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-op-get-assertion">§6.3.3 The
162
     * authenticatorGetAssertion Operation</a>.
163
     */
164
    public AuthenticatorAssertionResponseBuilder userHandle(
165 1 1. userHandle : negated conditional → KILLED
        @NonNull Optional<ByteArray> userHandle) {
166 1 1. userHandle : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse$AuthenticatorAssertionResponseBuilder::userHandle → KILLED
      return this.userHandle(userHandle.orElse(null));
167
    }
168
169
    /**
170
     * The user handle returned from the authenticator, or empty if the authenticator did not return
171
     * a user handle. See <a
172
     * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-op-get-assertion">§6.3.3 The
173
     * authenticatorGetAssertion Operation</a>.
174
     */
175
    public AuthenticatorAssertionResponseBuilder userHandle(ByteArray userHandle) {
176
      this.userHandle = userHandle;
177 1 1. userHandle : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse$AuthenticatorAssertionResponseBuilder::userHandle → KILLED
      return this;
178
    }
179
  }
180
}

Mutations

87

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

88

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

89

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

107

1.1
Location : getUserHandle
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/AuthenticatorAssertionResponse::getUserHandle → KILLED

111

1.1
Location : builder
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse::builder → KILLED

129

1.1
Location : authenticatorData
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse$AuthenticatorAssertionResponseBuilder$MandatoryStages::authenticatorData → KILLED

141

1.1
Location : clientDataJSON
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse$AuthenticatorAssertionResponseBuilder$MandatoryStages$Step2::clientDataJSON → KILLED

153

1.1
Location : signature
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse$AuthenticatorAssertionResponseBuilder$MandatoryStages$Step3::signature → KILLED

165

1.1
Location : userHandle
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

166

1.1
Location : userHandle
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse$AuthenticatorAssertionResponseBuilder::userHandle → KILLED

177

1.1
Location : userHandle
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAssertionResponse$AuthenticatorAssertionResponseBuilder::userHandle → KILLED

Active mutators

Tests examined


Report generated by PIT 1.15.0