View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
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.protocol.HttpClientContext;
47  import org.apache.hc.core5.http.HttpHost;
48  import org.apache.hc.core5.http.HttpRequest;
49  import org.apache.hc.core5.http.NameValuePair;
50  import org.apache.hc.core5.http.protocol.HttpContext;
51  import org.apache.hc.core5.util.Args;
52  import org.apache.hc.core5.util.Asserts;
53  import org.slf4j.Logger;
54  import org.slf4j.LoggerFactory;
55  
56  /**
57   * Bearer authentication scheme.
58   *
59   * @since 5.3
60   */
61  @AuthStateCacheable
62  public class BearerScheme implements AuthScheme, Serializable {
63  
64      private static final Logger LOG = LoggerFactory.getLogger(BearerScheme.class);
65  
66      private final Map<String, String> paramMap;
67      private boolean complete;
68  
69      private BearerToken bearerToken;
70  
71      public BearerScheme() {
72          this.paramMap = new HashMap<>();
73          this.complete = false;
74      }
75  
76      @Override
77      public String getName() {
78          return StandardAuthScheme.BEARER;
79      }
80  
81      @Override
82      public boolean isConnectionBased() {
83          return false;
84      }
85  
86      @Override
87      public String getRealm() {
88          return this.paramMap.get("realm");
89      }
90  
91      @Override
92      public void processChallenge(
93              final AuthChallenge authChallenge,
94              final HttpContext context) throws MalformedChallengeException {
95          this.paramMap.clear();
96          final List<NameValuePair> params = authChallenge.getParams();
97          if (params != null) {
98              for (final NameValuePair param: params) {
99                  this.paramMap.put(param.getName().toLowerCase(Locale.ROOT), param.getValue());
100             }
101             if (LOG.isDebugEnabled()) {
102                 final String error = paramMap.get("error");
103                 if (error != null) {
104                     final StringBuilder buf = new StringBuilder();
105                     buf.append(error);
106                     final String desc = paramMap.get("error_description");
107                     final String uri = paramMap.get("error_uri");
108                     if (desc != null || uri != null) {
109                         buf.append(" (");
110                         buf.append(desc).append("; ").append(uri);
111                         buf.append(")");
112                     }
113                     LOG.debug(buf.toString());
114                 }
115             }
116         }
117         this.complete = true;
118     }
119 
120     @Override
121     public boolean isChallengeComplete() {
122         return this.complete;
123     }
124 
125     @Override
126     public boolean isResponseReady(
127             final HttpHost host,
128             final CredentialsProvider credentialsProvider,
129             final HttpContext context) throws AuthenticationException {
130 
131         Args.notNull(host, "Auth host");
132         Args.notNull(credentialsProvider, "Credentials provider");
133 
134         final AuthScope authScope = new AuthScope(host, getRealm(), getName());
135         final Credentials credentials = credentialsProvider.getCredentials(authScope, context);
136         if (credentials instanceof BearerToken) {
137             this.bearerToken = (BearerToken) credentials;
138             return true;
139         }
140 
141         if (LOG.isDebugEnabled()) {
142             final HttpClientContext clientContext = HttpClientContext.adapt(context);
143             final String exchangeId = clientContext.getExchangeId();
144             LOG.debug("{} No credentials found for auth scope [{}]", exchangeId, authScope);
145         }
146         this.bearerToken = null;
147         return false;
148     }
149 
150     @Override
151     public Principal getPrincipal() {
152         return null;
153     }
154 
155     @Override
156     public String generateAuthResponse(
157             final HttpHost host,
158             final HttpRequest request,
159             final HttpContext context) throws AuthenticationException {
160         Asserts.notNull(bearerToken, "Bearer token");
161         return StandardAuthScheme.BEARER + " " + bearerToken.getToken();
162     }
163 
164     @Override
165     public String toString() {
166         return getName() + this.paramMap;
167     }
168 
169 }