1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.client5.http.impl.auth;
28
29 import java.io.Serializable;
30 import java.security.Principal;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Locale;
34 import java.util.Map;
35
36 import org.apache.hc.client5.http.auth.AuthChallenge;
37 import org.apache.hc.client5.http.auth.AuthScheme;
38 import org.apache.hc.client5.http.auth.AuthScope;
39 import org.apache.hc.client5.http.auth.AuthStateCacheable;
40 import org.apache.hc.client5.http.auth.AuthenticationException;
41 import org.apache.hc.client5.http.auth.BearerToken;
42 import org.apache.hc.client5.http.auth.Credentials;
43 import org.apache.hc.client5.http.auth.CredentialsProvider;
44 import org.apache.hc.client5.http.auth.MalformedChallengeException;
45 import org.apache.hc.client5.http.auth.StandardAuthScheme;
46 import org.apache.hc.client5.http.impl.StateHolder;
47 import org.apache.hc.client5.http.protocol.HttpClientContext;
48 import org.apache.hc.core5.annotation.Internal;
49 import org.apache.hc.core5.http.HttpHost;
50 import org.apache.hc.core5.http.HttpRequest;
51 import org.apache.hc.core5.http.NameValuePair;
52 import org.apache.hc.core5.http.protocol.HttpContext;
53 import org.apache.hc.core5.util.Args;
54 import org.apache.hc.core5.util.Asserts;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58
59
60
61
62
63 @AuthStateCacheable
64 public class BearerScheme implements AuthScheme, StateHolder<BearerScheme.State>, Serializable {
65
66 private static final Logger LOG = LoggerFactory.getLogger(BearerScheme.class);
67
68 private final Map<String, String> paramMap;
69 private boolean complete;
70
71 private BearerToken bearerToken;
72
73 public BearerScheme() {
74 this.paramMap = new HashMap<>();
75 this.complete = false;
76 }
77
78 @Override
79 public String getName() {
80 return StandardAuthScheme.BEARER;
81 }
82
83 @Override
84 public boolean isConnectionBased() {
85 return false;
86 }
87
88 @Override
89 public String getRealm() {
90 return this.paramMap.get("realm");
91 }
92
93 @Override
94 public void processChallenge(
95 final AuthChallenge authChallenge,
96 final HttpContext context) throws MalformedChallengeException {
97 this.paramMap.clear();
98 final List<NameValuePair> params = authChallenge.getParams();
99 if (params != null) {
100 for (final NameValuePair param: params) {
101 this.paramMap.put(param.getName().toLowerCase(Locale.ROOT), param.getValue());
102 }
103 if (LOG.isDebugEnabled()) {
104 final String error = paramMap.get("error");
105 if (error != null) {
106 final StringBuilder buf = new StringBuilder();
107 buf.append(error);
108 final String desc = paramMap.get("error_description");
109 final String uri = paramMap.get("error_uri");
110 if (desc != null || uri != null) {
111 buf.append(" (");
112 buf.append(desc).append("; ").append(uri);
113 buf.append(")");
114 }
115 LOG.debug(buf.toString());
116 }
117 }
118 }
119 this.complete = true;
120 }
121
122 @Override
123 public boolean isChallengeComplete() {
124 return this.complete;
125 }
126
127 @Override
128 public boolean isResponseReady(
129 final HttpHost host,
130 final CredentialsProvider credentialsProvider,
131 final HttpContext context) throws AuthenticationException {
132
133 Args.notNull(host, "Auth host");
134 Args.notNull(credentialsProvider, "Credentials provider");
135
136 final AuthScope authScope = new AuthScope(host, getRealm(), getName());
137 final Credentials credentials = credentialsProvider.getCredentials(authScope, context);
138 if (credentials instanceof BearerToken) {
139 this.bearerToken = (BearerToken) credentials;
140 return true;
141 }
142
143 if (LOG.isDebugEnabled()) {
144 final HttpClientContext clientContext = HttpClientContext.cast(context);
145 final String exchangeId = clientContext.getExchangeId();
146 LOG.debug("{} No credentials found for auth scope [{}]", exchangeId, authScope);
147 }
148 this.bearerToken = null;
149 return false;
150 }
151
152 @Override
153 public Principal getPrincipal() {
154 return null;
155 }
156
157 @Override
158 public String generateAuthResponse(
159 final HttpHost host,
160 final HttpRequest request,
161 final HttpContext context) throws AuthenticationException {
162 Asserts.notNull(bearerToken, "Bearer token");
163 return StandardAuthScheme.BEARER + " " + bearerToken.getToken();
164 }
165
166 @Override
167 public State store() {
168 if (complete) {
169 return new State(new HashMap<>(paramMap), bearerToken);
170 } else {
171 return null;
172 }
173 }
174
175 @Override
176 public void restore(final State state) {
177 if (state != null) {
178 paramMap.clear();
179 paramMap.putAll(state.params);
180 bearerToken = state.bearerToken;
181 complete = true;
182 }
183 }
184
185 @Override
186 public String toString() {
187 return getName() + this.paramMap;
188 }
189
190 @Internal
191 public static class State {
192
193 final Map<String, String> params;
194 final BearerToken bearerToken;
195
196 State(final Map<String, String> params, final BearerToken bearerToken) {
197 this.params = params;
198 this.bearerToken = bearerToken;
199 }
200
201 @Override
202 public String toString() {
203 return "State{" +
204 "params=" + params +
205 ", bearerToken=" + bearerToken +
206 '}';
207 }
208
209 }
210
211 }