Skip to content

Commit 236e305

Browse files
committed
Allow caller to determine auth callback methods.
1 parent 4e5af4c commit 236e305

7 files changed

Lines changed: 95 additions & 7 deletions

File tree

cwbi-auth-http-client/src/main/java/hec/army/usace/hec/cwbi/auth/http/client/AuthCodePkceTokenRequestBuilder.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public void handle(HttpExchange exchange) throws IOException {
8282

8383
code.set(parameters.get("code").get(0));
8484
state.set(parameters.get("state").get(0));
85+
exchange.sendResponseHeaders(201, 0);
8586
System.out.println("Got code");
8687
server.stop(0);
8788
future.complete(null);
@@ -99,11 +100,8 @@ public void handle(HttpExchange exchange) throws IOException {
99100
String urlStr= String.format("%s?%s", getAuthUrl().getApiRoot(), authParameters.encode());
100101
// start server to listen
101102
server.start();
102-
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Action.BROWSE)) {
103-
Desktop.getDesktop().browse(URI.create(urlStr));
104-
} else {
105-
System.out.println(String.format("Paste the following into a browser to continue login: %s", urlStr));
106-
}
103+
this.authCallBack.accept(URI.create(urlStr));
104+
107105

108106
future.join();
109107
System.out.println("Next steps.");

cwbi-auth-http-client/src/main/java/hec/army/usace/hec/cwbi/auth/http/client/CwbiAuthTokenProviderBase.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.io.IOException;
2727
import java.util.Objects;
28+
2829
import mil.army.usace.hec.cwms.http.client.ApiConnectionInfo;
2930
import mil.army.usace.hec.cwms.http.client.auth.OAuth2Token;
3031
import mil.army.usace.hec.cwms.http.client.auth.OAuth2TokenProvider;

cwbi-auth-http-client/src/main/java/hec/army/usace/hec/cwbi/auth/http/client/OidcAuthTokenProvider.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package hec.army.usace.hec.cwbi.auth.http.client;
22

33
import java.io.IOException;
4+
import java.net.URI;
45
import java.util.Objects;
56
import java.util.concurrent.CompletionException;
7+
import java.util.function.Consumer;
68

79
import mil.army.usace.hec.cwms.http.client.ApiConnectionInfo;
810
import mil.army.usace.hec.cwms.http.client.ApiConnectionInfoBuilder;
@@ -23,6 +25,9 @@ public final class OidcAuthTokenProvider implements OAuth2TokenProvider {
2325
private final ApiConnectionInfo tokenUrl;
2426
private final ApiConnectionInfo authUrl;
2527
private OAuth2Token token = null;
28+
// Default to open browser or print to console for usage, but allow overriding for testing and
29+
// other usages.
30+
private Consumer<URI> authCallback = TokenRequestBuilder.BROWSER_OR_CONSOLE_AUTH_CALLBACK;
2631

2732
public OidcAuthTokenProvider(String clientId, String wellKnownUrl) {
2833
this.clientId = Objects.requireNonNull(clientId, "Missing required client id.");
@@ -55,6 +60,16 @@ public void clear() {
5560
}
5661
}
5762

63+
@Override
64+
public Consumer<URI> getAuthCallback() {
65+
return authCallback;
66+
}
67+
68+
@Override
69+
public void setAuthCallback(Consumer<URI> authCallback) {
70+
this.authCallback = authCallback;
71+
}
72+
5873
@Override
5974
public OAuth2Token getToken() throws IOException {
6075
synchronized(this) {
@@ -89,6 +104,7 @@ public OAuth2Token newToken() throws IOException {
89104
token = new AuthCodePkceTokenRequestBuilder()
90105
.withAuthUrl(authUrl)
91106
.withTokenUrl(tokenUrl)
107+
.withAuthCallback(authCallback)
92108
.buildRequest()
93109
.withClientId(clientId)
94110
.fetchToken();

cwbi-auth-http-client/src/main/java/hec/army/usace/hec/cwbi/auth/http/client/TokenRequestBuilder.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,35 @@
2323
*/
2424
package hec.army.usace.hec.cwbi.auth.http.client;
2525

26+
import java.awt.Desktop;
27+
import java.awt.Desktop.Action;
2628
import java.io.IOException;
29+
import java.net.URI;
2730
import java.util.Objects;
31+
import java.util.function.Consumer;
32+
2833
import mil.army.usace.hec.cwms.http.client.ApiConnectionInfo;
2934
import mil.army.usace.hec.cwms.http.client.auth.OAuth2Token;
3035

3136
abstract class TokenRequestBuilder<T> implements TokenRequestFluentBuilder<TokenRequestBuilder<T>> {
37+
public static final Consumer<URI> BROWSER_OR_CONSOLE_AUTH_CALLBACK = u -> {
38+
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Action.BROWSE)) {
39+
try {
40+
Desktop.getDesktop().browse(u);
41+
} catch (IOException ex) {
42+
throw new RuntimeException("Unable to open browser", ex);
43+
}
44+
} else {
45+
System.out.println(String.format("Paste the following into a browser to continue login: %s", u.toString()));
46+
}
47+
};
3248

3349
static final String MEDIA_TYPE = "application/x-www-form-urlencoded";
3450
private ApiConnectionInfo url;
3551
private ApiConnectionInfo authUrl;
3652
private ApiConnectionInfo tokenUrl;
3753
private String clientId;
54+
protected Consumer<URI> authCallBack = (u) -> {}; // by default do nothing.
3855

3956
abstract OAuth2Token retrieveToken() throws IOException;
4057

@@ -64,6 +81,12 @@ ApiConnectionInfo getTokenUrl() {
6481
return tokenUrl;
6582
}
6683

84+
@Override
85+
public TokenRequestBuilder<T> withAuthCallback(Consumer<URI> authCallback) {
86+
this.authCallBack = authCallback;
87+
return this;
88+
}
89+
6790
String getClientId() {
6891
return clientId;
6992
}

cwbi-auth-http-client/src/main/java/hec/army/usace/hec/cwbi/auth/http/client/TokenRequestFluentBuilder.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
*/
2424
package hec.army.usace.hec.cwbi.auth.http.client;
2525

26+
import java.net.URI;
27+
import java.util.function.Consumer;
28+
2629
import mil.army.usace.hec.cwms.http.client.ApiConnectionInfo;
2730

2831
public interface TokenRequestFluentBuilder<T> {
@@ -57,4 +60,12 @@ public interface TokenRequestFluentBuilder<T> {
5760
* @return
5861
*/
5962
TokenRequestFluentBuilder<T> withTokenUrl(ApiConnectionInfo url);
63+
64+
/**
65+
* For methods where an external step is required to finish authentication
66+
* pass in desired operation
67+
* @param authCallback
68+
* @return
69+
*/
70+
TokenRequestFluentBuilder<T> withAuthCallback(Consumer<URI> authCallback);
6071
}

cwbi-auth-http-client/src/test/java/hec/army/usace/hec/cwbi/auth/http/client/TestOidcTokenProvider.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import static org.junit.jupiter.api.Assertions.assertEquals;
3131
import static org.junit.jupiter.api.Assertions.assertNotNull;
3232

33+
import java.awt.Desktop;
34+
import java.awt.Desktop.Action;
3335
import java.io.File;
3436
import java.io.IOException;
3537
import java.net.InetAddress;
@@ -39,11 +41,17 @@
3941
import java.nio.file.Path;
4042
import java.util.concurrent.ExecutorService;
4143
import java.util.concurrent.Executors;
44+
import java.util.concurrent.Future;
45+
import java.util.concurrent.TimeUnit;
46+
4247
import javax.net.ssl.SSLSocketFactory;
4348
import mil.army.usace.hec.cwms.http.client.MockHttpServer;
4449
import mil.army.usace.hec.cwms.http.client.ApiConnectionInfo;
4550
import mil.army.usace.hec.cwms.http.client.ApiConnectionInfoBuilder;
51+
import mil.army.usace.hec.cwms.http.client.HttpRequestBuilderImpl;
52+
import mil.army.usace.hec.cwms.http.client.HttpRequestResponse;
4653
import mil.army.usace.hec.cwms.http.client.auth.OAuth2Token;
54+
import mil.army.usace.hec.cwms.http.client.request.HttpRequestExecutor;
4755
import mil.army.usace.hec.cwms.http.client.request.QueryParameters;
4856
import okhttp3.HttpUrl;
4957
import okhttp3.mockwebserver.Dispatcher;
@@ -107,7 +115,7 @@ protected String getResource(String resource) throws IOException {
107115
}
108116

109117
@Test
110-
void testBuildTokenProvider() throws IOException {
118+
void testBuildTokenProvider() throws Exception {
111119
mockAuthServer.getMockServer().setDispatcher(new Dispatcher() {
112120

113121
@Override
@@ -141,7 +149,24 @@ else if (path.endsWith("/token")) {
141149

142150
String wellKnown = "http://localhost:"+mockAuthServer.getPort()+"/auth/realms/cwbi/.well-known/openid-configuration";
143151
OidcAuthTokenProvider tokenProvider = new OidcAuthTokenProvider("test", wellKnown);
144-
OAuth2Token token = tokenProvider.getToken();
152+
tokenProvider.setAuthCallback(u -> {
153+
try {
154+
HttpRequestExecutor executor =
155+
new HttpRequestBuilderImpl(new ApiConnectionInfoBuilder(u.toString()).build())
156+
.get()
157+
.withMediaType("text/plain");
158+
159+
try (HttpRequestResponse response = executor.execute()) {
160+
// redirect should be automatically followed. If changes
161+
// made that fail this section either enable redirect or handle it.
162+
}
163+
164+
} catch (IOException ex) {
165+
fail("Unable to perform client side of authorization procedure.", ex);
166+
}
167+
168+
});
169+
final OAuth2Token token = tokenProvider.getToken();
145170
assertNotNull(token);
146171
}
147172
}

cwms-http-client/src/main/java/mil/army/usace/hec/cwms/http/client/auth/OAuth2TokenProvider.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
package mil.army.usace.hec.cwms.http.client.auth;
2626

2727
import java.io.IOException;
28+
import java.net.URI;
29+
import java.util.function.Consumer;
2830

2931
/**
3032
*
@@ -41,4 +43,16 @@ public interface OAuth2TokenProvider {
4143

4244
OAuth2Token newToken() throws IOException;
4345

46+
/**
47+
* Return auth callback that will be used for this provider.
48+
* By default do nothing.
49+
* @return
50+
*/
51+
default Consumer<URI> getAuthCallback() {
52+
return u -> {};
53+
}
54+
55+
default void setAuthCallback(Consumer<URI> authCallback) {
56+
/** default do nothing... for now */
57+
}
4458
}

0 commit comments

Comments
 (0)