source: josm/trunk/src/oauth/signpost/AbstractOAuthConsumer.java@ 8176

Last change on this file since 8176 was 6849, checked in by stoecker, 10 years ago

see #9710 - update oauth library code

File size: 9.1 KB
Line 
1/* Copyright (c) 2009 Matthias Kaeppler
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15package oauth.signpost;
16
17import java.io.IOException;
18import java.io.InputStream;
19import java.util.Random;
20
21import oauth.signpost.basic.UrlStringRequestAdapter;
22import oauth.signpost.exception.OAuthCommunicationException;
23import oauth.signpost.exception.OAuthExpectationFailedException;
24import oauth.signpost.exception.OAuthMessageSignerException;
25import oauth.signpost.http.HttpParameters;
26import oauth.signpost.http.HttpRequest;
27import oauth.signpost.signature.AuthorizationHeaderSigningStrategy;
28import oauth.signpost.signature.HmacSha1MessageSigner;
29import oauth.signpost.signature.OAuthMessageSigner;
30import oauth.signpost.signature.QueryStringSigningStrategy;
31import oauth.signpost.signature.SigningStrategy;
32
33/**
34 * ABC for consumer implementations. If you're developing a custom consumer you
35 * will probably inherit from this class to save you a lot of work.
36 *
37 * @author Matthias Kaeppler
38 */
39public abstract class AbstractOAuthConsumer implements OAuthConsumer {
40
41 private static final long serialVersionUID = 1L;
42
43 private String consumerKey, consumerSecret;
44
45 private String token;
46
47 private OAuthMessageSigner messageSigner;
48
49 private SigningStrategy signingStrategy;
50
51 // these are params that may be passed to the consumer directly (i.e.
52 // without going through the request object)
53 private HttpParameters additionalParameters;
54
55 // these are the params which will be passed to the message signer
56 private HttpParameters requestParameters;
57
58 private boolean sendEmptyTokens;
59
60 final private Random random = new Random(System.nanoTime());
61
62 public AbstractOAuthConsumer(String consumerKey, String consumerSecret) {
63 this.consumerKey = consumerKey;
64 this.consumerSecret = consumerSecret;
65 setMessageSigner(new HmacSha1MessageSigner());
66 setSigningStrategy(new AuthorizationHeaderSigningStrategy());
67 }
68
69 public void setMessageSigner(OAuthMessageSigner messageSigner) {
70 this.messageSigner = messageSigner;
71 messageSigner.setConsumerSecret(consumerSecret);
72 }
73
74 public void setSigningStrategy(SigningStrategy signingStrategy) {
75 this.signingStrategy = signingStrategy;
76 }
77
78 public void setAdditionalParameters(HttpParameters additionalParameters) {
79 this.additionalParameters = additionalParameters;
80 }
81
82 public synchronized HttpRequest sign(HttpRequest request) throws OAuthMessageSignerException,
83 OAuthExpectationFailedException, OAuthCommunicationException {
84 if (consumerKey == null) {
85 throw new OAuthExpectationFailedException("consumer key not set");
86 }
87 if (consumerSecret == null) {
88 throw new OAuthExpectationFailedException("consumer secret not set");
89 }
90
91 requestParameters = new HttpParameters();
92 try {
93 if (additionalParameters != null) {
94 requestParameters.putAll(additionalParameters, false);
95 }
96 collectHeaderParameters(request, requestParameters);
97 collectQueryParameters(request, requestParameters);
98 collectBodyParameters(request, requestParameters);
99
100 // add any OAuth params that haven't already been set
101 completeOAuthParameters(requestParameters);
102
103 requestParameters.remove(OAuth.OAUTH_SIGNATURE);
104
105 } catch (IOException e) {
106 throw new OAuthCommunicationException(e);
107 }
108
109 String signature = messageSigner.sign(request, requestParameters);
110 OAuth.debugOut("signature", signature);
111
112 signingStrategy.writeSignature(signature, request, requestParameters);
113 OAuth.debugOut("Request URL", request.getRequestUrl());
114
115 return request;
116 }
117
118 public synchronized HttpRequest sign(Object request) throws OAuthMessageSignerException,
119 OAuthExpectationFailedException, OAuthCommunicationException {
120 return sign(wrap(request));
121 }
122
123 public synchronized String sign(String url) throws OAuthMessageSignerException,
124 OAuthExpectationFailedException, OAuthCommunicationException {
125 HttpRequest request = new UrlStringRequestAdapter(url);
126
127 // switch to URL signing
128 SigningStrategy oldStrategy = this.signingStrategy;
129 this.signingStrategy = new QueryStringSigningStrategy();
130
131 sign(request);
132
133 // revert to old strategy
134 this.signingStrategy = oldStrategy;
135
136 return request.getRequestUrl();
137 }
138
139 /**
140 * Adapts the given request object to a Signpost {@link HttpRequest}. How
141 * this is done depends on the consumer implementation.
142 *
143 * @param request
144 * the native HTTP request instance
145 * @return the adapted request
146 */
147 protected abstract HttpRequest wrap(Object request);
148
149 public void setTokenWithSecret(String token, String tokenSecret) {
150 this.token = token;
151 messageSigner.setTokenSecret(tokenSecret);
152 }
153
154 public String getToken() {
155 return token;
156 }
157
158 public String getTokenSecret() {
159 return messageSigner.getTokenSecret();
160 }
161
162 public String getConsumerKey() {
163 return this.consumerKey;
164 }
165
166 public String getConsumerSecret() {
167 return this.consumerSecret;
168 }
169
170 /**
171 * <p>
172 * Helper method that adds any OAuth parameters to the given request
173 * parameters which are missing from the current request but required for
174 * signing. A good example is the oauth_nonce parameter, which is typically
175 * not provided by the client in advance.
176 * </p>
177 * <p>
178 * It's probably not a very good idea to override this method. If you want
179 * to generate different nonces or timestamps, override
180 * {@link #generateNonce()} or {@link #generateTimestamp()} instead.
181 * </p>
182 *
183 * @param out
184 * the request parameter which should be completed
185 */
186 protected void completeOAuthParameters(HttpParameters out) {
187 if (!out.containsKey(OAuth.OAUTH_CONSUMER_KEY)) {
188 out.put(OAuth.OAUTH_CONSUMER_KEY, consumerKey, true);
189 }
190 if (!out.containsKey(OAuth.OAUTH_SIGNATURE_METHOD)) {
191 out.put(OAuth.OAUTH_SIGNATURE_METHOD, messageSigner.getSignatureMethod(), true);
192 }
193 if (!out.containsKey(OAuth.OAUTH_TIMESTAMP)) {
194 out.put(OAuth.OAUTH_TIMESTAMP, generateTimestamp(), true);
195 }
196 if (!out.containsKey(OAuth.OAUTH_NONCE)) {
197 out.put(OAuth.OAUTH_NONCE, generateNonce(), true);
198 }
199 if (!out.containsKey(OAuth.OAUTH_VERSION)) {
200 out.put(OAuth.OAUTH_VERSION, OAuth.VERSION_1_0, true);
201 }
202 if (!out.containsKey(OAuth.OAUTH_TOKEN)) {
203 if (token != null && !token.equals("") || sendEmptyTokens) {
204 out.put(OAuth.OAUTH_TOKEN, token, true);
205 }
206 }
207 }
208
209 public HttpParameters getRequestParameters() {
210 return requestParameters;
211 }
212
213 public void setSendEmptyTokens(boolean enable) {
214 this.sendEmptyTokens = enable;
215 }
216
217 /**
218 * Collects OAuth Authorization header parameters as per OAuth Core 1.0 spec
219 * section 9.1.1
220 */
221 protected void collectHeaderParameters(HttpRequest request, HttpParameters out) {
222 HttpParameters headerParams = OAuth.oauthHeaderToParamsMap(request.getHeader(OAuth.HTTP_AUTHORIZATION_HEADER));
223 out.putAll(headerParams, false);
224 }
225
226 /**
227 * Collects x-www-form-urlencoded body parameters as per OAuth Core 1.0 spec
228 * section 9.1.1
229 */
230 protected void collectBodyParameters(HttpRequest request, HttpParameters out)
231 throws IOException {
232
233 // collect x-www-form-urlencoded body params
234 String contentType = request.getContentType();
235 if (contentType != null && contentType.startsWith(OAuth.FORM_ENCODED)) {
236 InputStream payload = request.getMessagePayload();
237 out.putAll(OAuth.decodeForm(payload), true);
238 }
239 }
240
241 /**
242 * Collects HTTP GET query string parameters as per OAuth Core 1.0 spec
243 * section 9.1.1
244 */
245 protected void collectQueryParameters(HttpRequest request, HttpParameters out) {
246
247 String url = request.getRequestUrl();
248 int q = url.indexOf('?');
249 if (q >= 0) {
250 // Combine the URL query string with the other parameters:
251 out.putAll(OAuth.decodeForm(url.substring(q + 1)), true);
252 }
253 }
254
255 protected String generateTimestamp() {
256 return Long.toString(System.currentTimeMillis() / 1000L);
257 }
258
259 protected String generateNonce() {
260 return Long.toString(random.nextLong());
261 }
262}
Note: See TracBrowser for help on using the repository browser.