backport accessTokenProvider fix (#8726)
This commit is contained in:
parent
46fac99de5
commit
74951717bc
|
|
@ -44,6 +44,7 @@ public class HubConnection {
|
||||||
private List<OnClosedCallback> onClosedCallbackList;
|
private List<OnClosedCallback> onClosedCallbackList;
|
||||||
private final boolean skipNegotiate;
|
private final boolean skipNegotiate;
|
||||||
private Single<String> accessTokenProvider;
|
private Single<String> accessTokenProvider;
|
||||||
|
private Single<String> redirectAccessTokenProvider;
|
||||||
private final Map<String, String> headers = new HashMap<>();
|
private final Map<String, String> headers = new HashMap<>();
|
||||||
private ConnectionState connectionState = null;
|
private ConnectionState connectionState = null;
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
|
|
@ -240,11 +241,11 @@ public class HubConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (negotiateResponse.getAccessToken() != null) {
|
if (negotiateResponse.getAccessToken() != null) {
|
||||||
this.accessTokenProvider = Single.just(negotiateResponse.getAccessToken());
|
this.redirectAccessTokenProvider = Single.just(negotiateResponse.getAccessToken());
|
||||||
String token = "";
|
String token = "";
|
||||||
// We know the Single is non blocking in this case
|
// We know the Single is non blocking in this case
|
||||||
// It's fine to call blockingGet() on it.
|
// It's fine to call blockingGet() on it.
|
||||||
token = this.accessTokenProvider.blockingGet();
|
token = this.redirectAccessTokenProvider.blockingGet();
|
||||||
this.headers.put("Authorization", "Bearer " + token);
|
this.headers.put("Authorization", "Bearer " + token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -433,6 +434,8 @@ public class HubConnection {
|
||||||
logger.info("HubConnection stopped.");
|
logger.info("HubConnection stopped.");
|
||||||
hubConnectionState = HubConnectionState.DISCONNECTED;
|
hubConnectionState = HubConnectionState.DISCONNECTED;
|
||||||
handshakeResponseSubject.onComplete();
|
handshakeResponseSubject.onComplete();
|
||||||
|
redirectAccessTokenProvider = null;
|
||||||
|
this.headers.remove("Authorization");
|
||||||
} finally {
|
} finally {
|
||||||
hubConnectionStateLock.unlock();
|
hubConnectionStateLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1213,4 +1213,86 @@ class HubConnectionTest {
|
||||||
() -> hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait());
|
() -> hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait());
|
||||||
assertEquals("Unexpected status code returned from negotiate: 500 Internal server error.", exception.getMessage());
|
assertEquals("Unexpected status code returned from negotiate: 500 Internal server error.", exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void accessTokenProviderReferenceIsKeptAfterNegotiateRedirect() {
|
||||||
|
AtomicReference<String> token = new AtomicReference<>();
|
||||||
|
AtomicReference<String> beforeRedirectToken = new AtomicReference<>();
|
||||||
|
|
||||||
|
TestHttpClient client = new TestHttpClient()
|
||||||
|
.on("POST", "http://example.com/negotiate", (req) -> {
|
||||||
|
beforeRedirectToken.set(req.getHeaders().get("Authorization"));
|
||||||
|
return Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"newToken\"}"));
|
||||||
|
})
|
||||||
|
.on("POST", "http://testexample.com/negotiate", (req) -> {
|
||||||
|
token.set(req.getHeaders().get("Authorization"));
|
||||||
|
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
|
||||||
|
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"));
|
||||||
|
});
|
||||||
|
|
||||||
|
MockTransport transport = new MockTransport(true);
|
||||||
|
HubConnection hubConnection = HubConnectionBuilder
|
||||||
|
.create("http://example.com")
|
||||||
|
.withTransport(transport)
|
||||||
|
.withHttpClient(client)
|
||||||
|
.withAccessTokenProvider(Single.just("User Registered Token"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait();
|
||||||
|
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
|
||||||
|
hubConnection.stop().timeout(1, TimeUnit.SECONDS).blockingAwait();
|
||||||
|
assertEquals("Bearer User Registered Token", beforeRedirectToken.get());
|
||||||
|
assertEquals("Bearer newToken", token.get());
|
||||||
|
|
||||||
|
// Clear the tokens to see if they get reset to the proper values
|
||||||
|
beforeRedirectToken.set("");
|
||||||
|
token.set("");
|
||||||
|
|
||||||
|
// Restart the connection to make sure that the orignal accessTokenProvider that we registered is still registered before the redirect.
|
||||||
|
hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait();
|
||||||
|
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
|
||||||
|
hubConnection.stop();
|
||||||
|
assertEquals("Bearer User Registered Token", beforeRedirectToken.get());
|
||||||
|
assertEquals("Bearer newToken", token.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void authorizationHeaderFromNegotiateGetsClearedAfterStopping() {
|
||||||
|
AtomicReference<String> token = new AtomicReference<>();
|
||||||
|
AtomicReference<String> beforeRedirectToken = new AtomicReference<>();
|
||||||
|
|
||||||
|
TestHttpClient client = new TestHttpClient()
|
||||||
|
.on("POST", "http://example.com/negotiate", (req) -> {
|
||||||
|
beforeRedirectToken.set(req.getHeaders().get("Authorization"));
|
||||||
|
return Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"newToken\"}"));
|
||||||
|
})
|
||||||
|
.on("POST", "http://testexample.com/negotiate", (req) -> {
|
||||||
|
token.set(req.getHeaders().get("Authorization"));
|
||||||
|
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
|
||||||
|
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"));
|
||||||
|
});
|
||||||
|
|
||||||
|
MockTransport transport = new MockTransport(true);
|
||||||
|
HubConnection hubConnection = HubConnectionBuilder
|
||||||
|
.create("http://example.com")
|
||||||
|
.withTransport(transport)
|
||||||
|
.withHttpClient(client)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait();
|
||||||
|
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
|
||||||
|
hubConnection.stop().timeout(1, TimeUnit.SECONDS).blockingAwait();
|
||||||
|
assertEquals("Bearer newToken", token.get());
|
||||||
|
|
||||||
|
// Clear the tokens to see if they get reset to the proper values
|
||||||
|
beforeRedirectToken.set("");
|
||||||
|
token.set("");
|
||||||
|
|
||||||
|
// Restart the connection to make sure that the orignal accessTokenProvider that we registered is still registered before the redirect.
|
||||||
|
hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait();
|
||||||
|
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
|
||||||
|
hubConnection.stop();
|
||||||
|
assertNull(beforeRedirectToken.get());
|
||||||
|
assertEquals("Bearer newToken", token.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue