|
7 | 7 |
|
8 | 8 | package org.elasticsearch.xpack.security.authc;
|
9 | 9 |
|
| 10 | +import org.apache.logging.log4j.LogManager; |
| 11 | +import org.apache.logging.log4j.Logger; |
10 | 12 | import org.elasticsearch.action.ActionListener;
|
| 13 | +import org.elasticsearch.xpack.core.common.IteratingActionListener; |
11 | 14 | import org.elasticsearch.xpack.core.security.authc.Authentication;
|
12 | 15 | import org.elasticsearch.xpack.core.security.authc.AuthenticationResult;
|
13 | 16 | import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
|
14 | 17 | import org.elasticsearch.xpack.core.security.authc.CustomAuthenticator;
|
15 | 18 |
|
16 | 19 | import java.util.Collections;
|
17 | 20 | 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; |
18 | 25 |
|
19 | 26 | public class PluggableAuthenticatorChain implements Authenticator {
|
20 | 27 |
|
| 28 | + private static final Logger logger = LogManager.getLogger(PluggableAuthenticatorChain.class); |
| 29 | + |
21 | 30 | private final List<CustomAuthenticator> customAuthenticators;
|
22 | 31 |
|
23 | 32 | public PluggableAuthenticatorChain(List<CustomAuthenticator> customAuthenticators) {
|
@@ -59,28 +68,47 @@ public void authenticate(Context context, ActionListener<AuthenticationResult<Au
|
59 | 68 | }
|
60 | 69 | AuthenticationToken token = context.getMostRecentAuthenticationToken();
|
61 | 70 | 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)); |
81 | 84 | }
|
| 85 | + return; |
82 | 86 | }
|
83 | 87 | listener.onResponse(AuthenticationResult.notHandled());
|
84 | 88 | }
|
85 | 89 |
|
| 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 | + |
86 | 114 | }
|
0 commit comments