77import io .vertx .core .Vertx ;
88import io .vertx .core .json .Json ;
99import io .vertx .core .json .JsonObject ;
10+ import lombok .Getter ;
1011import org .slf4j .Logger ;
1112import org .slf4j .LoggerFactory ;
1213import software .amazon .awssdk .utils .Pair ;
@@ -34,7 +35,7 @@ public class AttestationResponseHandler {
3435 private final AtomicReference <String > attestationToken ;
3536 private final AtomicReference <String > optOutJwt ;
3637 private final AtomicReference <String > coreJwt ;
37- private final Handler <Pair <Integer , String >> responseWatcher ;
38+ private final Handler <Pair <AttestationResponseCode , String >> responseWatcher ;
3839 private final String attestationEndpoint ;
3940 private final byte [] encodedAttestationEndpoint ;
4041 private final IClock clock ;
@@ -46,6 +47,7 @@ public class AttestationResponseHandler {
4647 private Instant attestationTokenExpiresAt = Instant .MAX ;
4748 private final Lock lock ;
4849 private final AttestationTokenDecryptor attestationTokenDecryptor ;
50+ @ Getter
4951 private final String appVersionHeader ;
5052 private final int attestCheckMilliseconds ;
5153 private final AtomicReference <String > optOutUrl ;
@@ -56,17 +58,18 @@ public AttestationResponseHandler(Vertx vertx,
5658 String operatorType ,
5759 ApplicationVersion appVersion ,
5860 IAttestationProvider attestationProvider ,
59- Handler <Pair <Integer , String >> responseWatcher ,
61+ Handler <Pair <AttestationResponseCode , String >> responseWatcher ,
6062 Proxy proxy ) {
6163 this (vertx , attestationEndpoint , clientApiToken , operatorType , appVersion , attestationProvider , responseWatcher , proxy , new InstantClock (), null , null , 60000 );
6264 }
65+
6366 public AttestationResponseHandler (Vertx vertx ,
6467 String attestationEndpoint ,
6568 String clientApiToken ,
6669 String operatorType ,
6770 ApplicationVersion appVersion ,
6871 IAttestationProvider attestationProvider ,
69- Handler <Pair <Integer , String >> responseWatcher ,
72+ Handler <Pair <AttestationResponseCode , String >> responseWatcher ,
7073 Proxy proxy ,
7174 IClock clock ,
7275 URLConnectionHttpClient httpClient ,
@@ -131,16 +134,7 @@ private void attestationExpirationCheck(long timerId) {
131134 }
132135
133136 attest ();
134- } catch (AttestationResponseHandlerException e ) {
135- if (e .isAttestationFailure ()) {
136- notifyResponseWatcher (401 , e .getMessage ());
137- LOGGER .info ("Re-attest failed with attestation failure: " , e );
138- } else {
139- notifyResponseWatcher (e .getStatusCode (), e .getMessage ());
140- LOGGER .info ("Re-attest failed with retryable failure: " , e );
141- }
142- } catch (IOException e ){
143- notifyResponseWatcher (500 , e .getMessage ());
137+ } catch (AttestationResponseHandlerException | IOException e ) {
144138 LOGGER .info ("Re-attest failed: " , e );
145139 } finally {
146140 this .isAttesting .set (false );
@@ -185,35 +179,32 @@ public void attest() throws IOException, AttestationResponseHandlerException {
185179
186180 int statusCode = response .statusCode ();
187181 String responseBody = response .body ();
188- notifyResponseWatcher (statusCode , responseBody );
189182
190- if (statusCode == 401 || statusCode == 403 ) {
191- LOGGER .warn ("attestation failed with UID2 Core returning statusCode={}" , statusCode );
192- throw new AttestationResponseHandlerException (statusCode , "Attestation Failure response from Core" );
193- }
183+ AttestationResponseCode responseCode = this .getAttestationResponseCodeFromHttpStatus (statusCode );
184+
185+ notifyResponseWatcher (responseCode , responseBody );
194186
195- if (statusCode < 200 || statusCode >= 300 ) {
196- LOGGER .warn ("attestation failed with UID2 Core returning statusCode={}" , statusCode );
197- throw new AttestationResponseHandlerException (statusCode , "unexpected status code from uid core service" );
187+ if (responseCode != AttestationResponseCode .Success ) {
188+ throw new AttestationResponseHandlerException (responseCode , "Non-success response from Core on attest" );
198189 }
199190
200191 JsonObject responseJson = (JsonObject ) Json .decodeValue (responseBody );
201192 if (isFailed (responseJson )) {
202- throw new AttestationResponseHandlerException (statusCode , "response did not return a successful status" );
193+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response did not return a successful status" );
203194 }
204195
205196 JsonObject innerBody = responseJson .getJsonObject ("body" );
206197 if (innerBody == null ) {
207- throw new AttestationResponseHandlerException (statusCode , "response did not contain a body object" );
198+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response did not contain a body object" );
208199 }
209200
210201 String atoken = getAttestationToken (innerBody );
211202 if (atoken == null ) {
212- throw new AttestationResponseHandlerException (statusCode , "response json does not contain body.attestation_token" );
203+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response json does not contain body.attestation_token" );
213204 }
214205 String expiresAt = getAttestationTokenExpiresAt (innerBody );
215206 if (expiresAt == null ) {
216- throw new AttestationResponseHandlerException (statusCode , "response json does not contain body.expiresAt" );
207+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response json does not contain body.expiresAt" );
217208 }
218209
219210 atoken = new String (attestationTokenDecryptor .decrypt (Base64 .getDecoder ().decode (atoken ), keyPair .getPrivate ()), StandardCharsets .UTF_8 );
@@ -225,8 +216,8 @@ public void attest() throws IOException, AttestationResponseHandlerException {
225216 setOptoutURLFromResponse (innerBody );
226217
227218 scheduleAttestationExpirationCheck ();
228- } catch (IOException ioe ) {
229- throw ioe ;
219+ } catch (AttestationResponseHandlerException | IOException e ) {
220+ throw e ;
230221 } catch (Exception e ) {
231222 throw new AttestationResponseHandlerException (e );
232223 }
@@ -252,10 +243,6 @@ public String getOptOutUrl() {
252243 return this .optOutUrl .get ();
253244 }
254245
255- public String getAppVersionHeader () {
256- return this .appVersionHeader ;
257- }
258-
259246 private void setAttestationTokenExpiresAt (String expiresAt ) {
260247 this .attestationTokenExpiresAt = Instant .parse (expiresAt );
261248 }
@@ -309,11 +296,15 @@ private static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
309296 return gen .generateKeyPair ();
310297 }
311298
312- private void notifyResponseWatcher (int statusCode , String responseBody ) {
299+ private void notifyResponseWatcher (AttestationResponseCode responseCode , String responseBody ) {
300+ if (responseCode != AttestationResponseCode .Success ) {
301+ LOGGER .warn ("Received a non-success response code on Attestation: ResponseCode: {}, Message: {}" , responseCode , responseBody );
302+ }
303+
313304 this .lock .lock ();
314305 try {
315306 if (this .responseWatcher != null )
316- this .responseWatcher .handle (Pair .of (statusCode , responseBody ));
307+ this .responseWatcher .handle (Pair .of (responseCode , responseBody ));
317308 } finally {
318309 lock .unlock ();
319310 }
@@ -328,4 +319,16 @@ private byte[] encodeStringUnicodeAttestationEndpoint(String data) {
328319 ByteBuffer buffer = StandardCharsets .UTF_8 .encode (data );
329320 return Arrays .copyOf (buffer .array (), buffer .limit ());
330321 }
322+
323+ private AttestationResponseCode getAttestationResponseCodeFromHttpStatus (int httpStatus ) {
324+ if (httpStatus == 401 || httpStatus == 403 ) {
325+ return AttestationResponseCode .AttestationFailure ;
326+ }
327+
328+ if (httpStatus == 200 ) {
329+ return AttestationResponseCode .Success ;
330+ }
331+
332+ return AttestationResponseCode .RetryableFailure ;
333+ }
331334}
0 commit comments