Skip to content

Commit 02a519a

Browse files
ankit--sethielasticsearchmachineslobodanadamovic
authored
Custom authenticator followup + tests (#134241)
* initial commit - tests pending potentially * [CI] Auto commit changes from spotless * fix syntax * correct javadoc * fix style issue * fix tests * [PoC] Pluggable authenticator chain * [CI] Auto commit changes from spotless * spotless + remove unused method * fix javadoc line lenght * refactor with code review feedback and new validation for cloud-saml-kibana * [CI] Auto commit changes from spotless * code review stuff * [CI] Auto commit changes from spotless * followups from previous PR - 1. Using IteratingActionListener instead of a for-loop in the main flow of PluggableAuthenticatorChain 2. Adding unit test coverage for PluggableAuthenticatorChain * [CI] Auto commit changes from spotless * revert bad change * [CI] Auto commit changes from spotless * fix imports * fix import * don't need this any more * code review changes + update pointer * fix test * Update x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/PluggableAuthenticatorChain.java Co-authored-by: Slobodan Adamović <[email protected]> * code review stuff --------- Co-authored-by: elasticsearchmachine <[email protected]> Co-authored-by: Slobodan Adamovic <[email protected]> Co-authored-by: Slobodan Adamović <[email protected]>
1 parent af1739b commit 02a519a

File tree

2 files changed

+391
-19
lines changed

2 files changed

+391
-19
lines changed

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/PluggableAuthenticatorChain.java

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,26 @@
77

88
package org.elasticsearch.xpack.security.authc;
99

10+
import org.apache.logging.log4j.LogManager;
11+
import org.apache.logging.log4j.Logger;
1012
import org.elasticsearch.action.ActionListener;
13+
import org.elasticsearch.xpack.core.common.IteratingActionListener;
1114
import org.elasticsearch.xpack.core.security.authc.Authentication;
1215
import org.elasticsearch.xpack.core.security.authc.AuthenticationResult;
1316
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
1417
import org.elasticsearch.xpack.core.security.authc.CustomAuthenticator;
1518

1619
import java.util.Collections;
1720
import java.util.List;
21+
import java.util.function.BiConsumer;
22+
import java.util.function.Function;
23+
24+
import static org.elasticsearch.common.Strings.format;
1825

1926
public class PluggableAuthenticatorChain implements Authenticator {
2027

28+
private static final Logger logger = LogManager.getLogger(PluggableAuthenticatorChain.class);
29+
2130
private final List<CustomAuthenticator> customAuthenticators;
2231

2332
public PluggableAuthenticatorChain(List<CustomAuthenticator> customAuthenticators) {
@@ -59,28 +68,47 @@ public void authenticate(Context context, ActionListener<AuthenticationResult<Au
5968
}
6069
AuthenticationToken token = context.getMostRecentAuthenticationToken();
6170
if (token != null) {
62-
// TODO switch to IteratingActionListener
63-
for (CustomAuthenticator customAuthenticator : customAuthenticators) {
64-
if (customAuthenticator.supports(token)) {
65-
customAuthenticator.authenticate(token, ActionListener.wrap(response -> {
66-
if (response.isAuthenticated()) {
67-
listener.onResponse(response);
68-
} else if (response.getStatus() == AuthenticationResult.Status.TERMINATE) {
69-
final Exception ex = response.getException();
70-
if (ex == null) {
71-
listener.onFailure(context.getRequest().authenticationFailed(token));
72-
} else {
73-
listener.onFailure(context.getRequest().exceptionProcessingRequest(ex, token));
74-
}
75-
} else if (response.getStatus() == AuthenticationResult.Status.CONTINUE) {
76-
listener.onResponse(AuthenticationResult.notHandled());
77-
}
78-
}, ex -> listener.onFailure(context.getRequest().exceptionProcessingRequest(ex, token))));
79-
return;
80-
}
71+
var iteratingListener = new IteratingActionListener<>(
72+
listener,
73+
getAuthConsumer(context),
74+
customAuthenticators,
75+
context.getThreadContext(),
76+
Function.identity(),
77+
result -> result.getStatus() == AuthenticationResult.Status.CONTINUE
78+
);
79+
try {
80+
iteratingListener.run();
81+
} catch (Exception e) {
82+
logger.debug(() -> format("Authentication of token [%s] failed", token.getClass().getName()), e);
83+
listener.onFailure(context.getRequest().exceptionProcessingRequest(e, token));
8184
}
85+
return;
8286
}
8387
listener.onResponse(AuthenticationResult.notHandled());
8488
}
8589

90+
private BiConsumer<CustomAuthenticator, ActionListener<AuthenticationResult<Authentication>>> getAuthConsumer(Context context) {
91+
AuthenticationToken token = context.getMostRecentAuthenticationToken();
92+
return (authenticator, iteratingListener) -> {
93+
if (authenticator.supports(token)) {
94+
authenticator.authenticate(token, ActionListener.wrap(response -> {
95+
if (response.isAuthenticated()) {
96+
iteratingListener.onResponse(response);
97+
} else if (response.getStatus() == AuthenticationResult.Status.TERMINATE) {
98+
final Exception ex = response.getException();
99+
if (ex == null) {
100+
iteratingListener.onFailure(context.getRequest().authenticationFailed(token));
101+
} else {
102+
iteratingListener.onFailure(context.getRequest().exceptionProcessingRequest(ex, token));
103+
}
104+
} else if (response.getStatus() == AuthenticationResult.Status.CONTINUE) {
105+
iteratingListener.onResponse(AuthenticationResult.notHandled());
106+
}
107+
}, ex -> iteratingListener.onFailure(context.getRequest().exceptionProcessingRequest(ex, token))));
108+
} else {
109+
iteratingListener.onResponse(AuthenticationResult.notHandled()); // try the next custom authenticator
110+
}
111+
};
112+
}
113+
86114
}

0 commit comments

Comments
 (0)