2424import java .util .concurrent .locks .Lock ;
2525import java .util .concurrent .locks .ReentrantLock ;
2626
27- public class AttestationTokenRetriever {
28- private static final Logger LOGGER = LoggerFactory .getLogger (AttestationTokenRetriever .class );
27+ public class AttestationResponseHandler {
28+ private static final Logger LOGGER = LoggerFactory .getLogger (AttestationResponseHandler .class );
2929
3030 private final IAttestationProvider attestationProvider ;
3131 private final String clientApiToken ;
@@ -47,27 +47,28 @@ public class AttestationTokenRetriever {
4747 private final AttestationTokenDecryptor attestationTokenDecryptor ;
4848 private final String appVersionHeader ;
4949 private final int attestCheckMilliseconds ;
50-
51- public AttestationTokenRetriever (Vertx vertx ,
52- String attestationEndpoint ,
53- String clientApiToken ,
54- ApplicationVersion appVersion ,
55- IAttestationProvider attestationProvider ,
56- Handler <Pair <Integer , String >> responseWatcher ,
57- Proxy proxy ) {
50+ private final AtomicReference <String > optOutUrl ;
51+
52+ public AttestationResponseHandler (Vertx vertx ,
53+ String attestationEndpoint ,
54+ String clientApiToken ,
55+ ApplicationVersion appVersion ,
56+ IAttestationProvider attestationProvider ,
57+ Handler <Pair <Integer , String >> responseWatcher ,
58+ Proxy proxy ) {
5859 this (vertx , attestationEndpoint , clientApiToken , appVersion , attestationProvider , responseWatcher , proxy , new InstantClock (), null , null , 60000 );
5960 }
60- public AttestationTokenRetriever (Vertx vertx ,
61- String attestationEndpoint ,
62- String clientApiToken ,
63- ApplicationVersion appVersion ,
64- IAttestationProvider attestationProvider ,
65- Handler <Pair <Integer , String >> responseWatcher ,
66- Proxy proxy ,
67- IClock clock ,
68- URLConnectionHttpClient httpClient ,
69- AttestationTokenDecryptor attestationTokenDecryptor ,
70- int attestCheckMilliseconds ) {
61+ public AttestationResponseHandler (Vertx vertx ,
62+ String attestationEndpoint ,
63+ String clientApiToken ,
64+ ApplicationVersion appVersion ,
65+ IAttestationProvider attestationProvider ,
66+ Handler <Pair <Integer , String >> responseWatcher ,
67+ Proxy proxy ,
68+ IClock clock ,
69+ URLConnectionHttpClient httpClient ,
70+ AttestationTokenDecryptor attestationTokenDecryptor ,
71+ int attestCheckMilliseconds ) {
7172 this .vertx = vertx ;
7273 this .attestationEndpoint = attestationEndpoint ;
7374 this .encodedAttestationEndpoint = this .encodeStringUnicodeAttestationEndpoint (attestationEndpoint );
@@ -77,6 +78,7 @@ public AttestationTokenRetriever(Vertx vertx,
7778 this .attestationToken = new AtomicReference <>(null );
7879 this .optOutJwt = new AtomicReference <>(null );
7980 this .coreJwt = new AtomicReference <>(null );
81+ this .optOutUrl = new AtomicReference <>(null );
8082 this .responseWatcher = responseWatcher ;
8183 this .clock = clock ;
8284 this .lock = new ReentrantLock ();
@@ -125,7 +127,7 @@ private void attestationExpirationCheck(long timerId) {
125127 }
126128
127129 attest ();
128- } catch (AttestationTokenRetrieverException e ) {
130+ } catch (AttestationResponseHandlerException e ) {
129131 notifyResponseWatcher (401 , e .getMessage ());
130132 LOGGER .info ("Re-attest failed: " , e );
131133 } catch (IOException e ){
@@ -144,9 +146,9 @@ private void scheduleAttestationExpirationCheck() {
144146 }
145147 }
146148
147- public void attest () throws IOException , AttestationTokenRetrieverException {
149+ public void attest () throws IOException , AttestationResponseHandlerException {
148150 if (!attestationProvider .isReady ()) {
149- throw new AttestationTokenRetrieverException ("attestation provider is not ready" );
151+ throw new AttestationResponseHandlerException ("attestation provider is not ready" );
150152 }
151153
152154 try {
@@ -177,26 +179,26 @@ public void attest() throws IOException, AttestationTokenRetrieverException {
177179
178180 if (statusCode < 200 || statusCode >= 300 ) {
179181 LOGGER .warn ("attestation failed with UID2 Core returning statusCode=" + statusCode );
180- throw new AttestationTokenRetrieverException (statusCode , "unexpected status code from uid core service" );
182+ throw new AttestationResponseHandlerException (statusCode , "unexpected status code from uid core service" );
181183 }
182184
183185 JsonObject responseJson = (JsonObject ) Json .decodeValue (responseBody );
184186 if (isFailed (responseJson )) {
185- throw new AttestationTokenRetrieverException (statusCode , "response did not return a successful status" );
187+ throw new AttestationResponseHandlerException (statusCode , "response did not return a successful status" );
186188 }
187189
188190 JsonObject innerBody = responseJson .getJsonObject ("body" );
189191 if (innerBody == null ) {
190- throw new AttestationTokenRetrieverException (statusCode , "response did not contain a body object" );
192+ throw new AttestationResponseHandlerException (statusCode , "response did not contain a body object" );
191193 }
192194
193195 String atoken = getAttestationToken (innerBody );
194196 if (atoken == null ) {
195- throw new AttestationTokenRetrieverException (statusCode , "response json does not contain body.attestation_token" );
197+ throw new AttestationResponseHandlerException (statusCode , "response json does not contain body.attestation_token" );
196198 }
197199 String expiresAt = getAttestationTokenExpiresAt (innerBody );
198200 if (expiresAt == null ) {
199- throw new AttestationTokenRetrieverException (statusCode , "response json does not contain body.expiresAt" );
201+ throw new AttestationResponseHandlerException (statusCode , "response json does not contain body.expiresAt" );
200202 }
201203
202204 atoken = new String (attestationTokenDecryptor .decrypt (Base64 .getDecoder ().decode (atoken ), keyPair .getPrivate ()), StandardCharsets .UTF_8 );
@@ -205,12 +207,13 @@ public void attest() throws IOException, AttestationTokenRetrieverException {
205207 setAttestationTokenExpiresAt (expiresAt );
206208 setOptoutJWTFromResponse (innerBody );
207209 setCoreJWTFromResponse (innerBody );
210+ setOptoutURLFromResponse (innerBody );
208211
209212 scheduleAttestationExpirationCheck ();
210213 } catch (IOException ioe ) {
211214 throw ioe ;
212215 } catch (Exception e ) {
213- throw new AttestationTokenRetrieverException (e );
216+ throw new AttestationResponseHandlerException (e );
214217 }
215218 }
216219
@@ -230,6 +233,10 @@ public String getCoreJWT() {
230233 return this .coreJwt .get ();
231234 }
232235
236+ public String getOptOutUrl () {
237+ return this .optOutUrl .get ();
238+ }
239+
233240 public String getAppVersionHeader () {
234241 return this .appVersionHeader ;
235242 }
@@ -266,6 +273,17 @@ private void setCoreJWTFromResponse(JsonObject responseBody) {
266273 }
267274 }
268275
276+ private void setOptoutURLFromResponse (JsonObject responseBody ) {
277+ String url = responseBody .getString ("optout_url" );
278+ if (url == null ) {
279+ LOGGER .info ("OptOut URL not received" );
280+ } else {
281+ LOGGER .info ("OptOut URL received" );
282+ LOGGER .debug ("OptOut URL to use: {}" , url );
283+ this .optOutUrl .set (url );
284+ }
285+ }
286+
269287 private static boolean isFailed (JsonObject responseJson ) {
270288 return responseJson .getString ("status" ) == null || !responseJson .getString ("status" ).equals ("success" );
271289 }
0 commit comments