| /* |
| * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| package org.glassfish.jersey.oauth1.signature; |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.UUID; |
| |
| import org.glassfish.jersey.uri.UriComponent; |
| |
| /** |
| * A data structure class that represents OAuth protocol parameters. |
| * |
| * @author Hubert A. Le Van Gong <hubert.levangong at Sun.COM> |
| * @author Paul C. Bryan <pbryan@sun.com> |
| */ |
| public class OAuth1Parameters extends HashMap<String, String> { |
| |
| /** Name of HTTP authorization header. */ |
| public static final String AUTHORIZATION_HEADER = "Authorization"; |
| |
| /** OAuth scheme in Authorization header. */ |
| public static final String SCHEME = "OAuth"; |
| |
| /** Name of parameter containing the protection realm. */ |
| public static final String REALM = "realm"; |
| |
| /** Name of parameter containing the consumer key. */ |
| public static final String CONSUMER_KEY = "oauth_consumer_key"; |
| |
| /** Name of parameter containing the access/request token. */ |
| public static final String TOKEN = "oauth_token"; |
| |
| /** Name of parameter containing the signature method. */ |
| public static final String SIGNATURE_METHOD = "oauth_signature_method"; |
| |
| /** Name of parameter containing the signature. */ |
| public static final String SIGNATURE = "oauth_signature"; |
| |
| /** Name of parameter containing the timestamp. */ |
| public static final String TIMESTAMP = "oauth_timestamp"; |
| |
| /** Name of parameter containing the nonce. */ |
| public static final String NONCE = "oauth_nonce"; |
| |
| /** Name of parameter containing the protocol version. */ |
| public static final String VERSION = "oauth_version"; |
| |
| /** Name of parameter containing the verifier code. */ |
| public static final String VERIFIER = "oauth_verifier"; |
| |
| /** Name of parameter containing the callback URL. */ |
| public static final String CALLBACK = "oauth_callback"; |
| |
| /** Name of parameter containing the token secret. |
| * This parameter is never used in requests. It is part of a response to the request token and access token requests. |
| */ |
| public static final String TOKEN_SECRET = "oauth_token_secret"; |
| |
| /** Name of parameter containing the token secret. |
| * This parameter is never used in requests. It is part of a response to the request token requests. |
| */ |
| public static final String CALLBACK_CONFIRMED = "oauth_callback_confirmed"; |
| |
| /** |
| * Default value of the callback URI that should be used during Authorization flow |
| * for Request Token request when the client is not capable of handling redirects (e.g. the client is |
| * a mobile application). |
| */ |
| public static final String NO_CALLBACK_URI_VALUE = "oob"; |
| |
| /* Authorization scheme and delimiter. */ |
| private static final String SCHEME_SPACE = SCHEME + ' '; |
| |
| /** |
| * Returns the protection realm for the request. |
| */ |
| public String getRealm() { |
| return get(REALM); |
| } |
| |
| /** |
| * Sets the protection realm for the request. |
| */ |
| public void setRealm(String realm) { |
| put(REALM, realm); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * protection realm. |
| * |
| * @param realm the protection realm for the request. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters realm(String realm) { |
| setRealm(realm); |
| return this; |
| } |
| |
| /** |
| * Returns the consumer key. |
| */ |
| public String getConsumerKey() { |
| return get(CONSUMER_KEY); |
| } |
| |
| /** |
| * Sets the consumer key. |
| */ |
| public void setConsumerKey(String consumerKey) { |
| put(CONSUMER_KEY, consumerKey); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * consumer key. |
| * |
| * @param consumerKey the consumer key. |
| */ |
| public OAuth1Parameters consumerKey(String consumerKey) { |
| setConsumerKey(consumerKey); |
| return this; |
| } |
| |
| /** |
| * Returns the request or access token. |
| */ |
| public String getToken() { |
| return get(TOKEN); |
| } |
| |
| @Override |
| public String put(String key, String value) { |
| return value == null ? remove(key) : super.put(key, value); |
| } |
| |
| /** |
| * Sets the request or access token. |
| */ |
| public void setToken(String token) { |
| if (token == null) { |
| remove(TOKEN); |
| } else { |
| put(TOKEN, token); |
| } |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * token. |
| * |
| * @param token the access or request token. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters token(String token) { |
| setToken(token); |
| return this; |
| } |
| |
| /** |
| * Returns the signature method used to sign the request. |
| */ |
| public String getSignatureMethod() { |
| return get(SIGNATURE_METHOD); |
| } |
| |
| /** |
| * Sets the signature method used to sign the request. |
| */ |
| public void setSignatureMethod(String signatureMethod) { |
| put(SIGNATURE_METHOD, signatureMethod); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * signature method. |
| * |
| * @param signatureMethod the signature method used to sign the request. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters signatureMethod(String signatureMethod) { |
| setSignatureMethod(signatureMethod); |
| return this; |
| } |
| |
| /** |
| * Returns the signature for the request. |
| */ |
| public String getSignature() { |
| return get(SIGNATURE); |
| } |
| |
| /** |
| * Sets the signature for the request. |
| */ |
| public void setSignature(String signature) { |
| put(SIGNATURE, signature); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * signature. |
| * |
| * @param signature the signature for the request. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters signature(String signature) { |
| setSignature(signature); |
| return this; |
| } |
| |
| /** |
| * Returns the timestamp, a value expected to be a positive integer, |
| * typically containing the number of seconds since January 1, 1970 |
| * 00:00:00 GMT (epoch). |
| */ |
| public String getTimestamp() { |
| return get(TIMESTAMP); |
| } |
| |
| /** |
| * Sets the timestamp. Its value is not validated, but should be a |
| * positive integer, typically containing the number of seconds since |
| * January 1, 1970 00:00:00 GMT (epoch). |
| */ |
| public void setTimestamp(String timestamp) { |
| put(TIMESTAMP, timestamp); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * timestamp. |
| * |
| * @param timestamp positive integer, typically number of seconds since epoch. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters timestamp(String timestamp) { |
| setTimestamp(timestamp); |
| return this; |
| } |
| |
| /** |
| * Sets the timestamp to the current time as number of seconds since epoch. |
| */ |
| public void setTimestamp() { |
| setTimestamp(Long.toString(System.currentTimeMillis() / 1000)); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * timestamp to the current time. |
| * |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters timestamp() { |
| setTimestamp(); |
| return this; |
| } |
| |
| /** |
| * Returns the nonce, a value that should be unique for a given |
| * timestamp. |
| */ |
| public String getNonce() { |
| return get(NONCE); |
| } |
| |
| /** |
| * Sets the nonce, a value that should be unique for a given timestamp. |
| */ |
| public void setNonce(String nonce) { |
| put(NONCE, nonce); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * nonce. |
| * |
| * @param nonce a value that should be unique for a given timestamp. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters nonce(String nonce) { |
| setNonce(nonce); |
| return this; |
| } |
| |
| /** |
| * Sets the nonce to contain a randomly-generated UUID. |
| */ |
| public void setNonce() { |
| setNonce(UUID.randomUUID().toString()); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * nonce to a randomly-generated UUID. |
| * |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters nonce() { |
| setNonce(); |
| return this; |
| } |
| |
| /** |
| * Returns the protocol version. |
| */ |
| public String getVersion() { |
| return get(VERSION); |
| } |
| |
| /** |
| * Sets the protocol version. |
| */ |
| public void setVersion(String version) { |
| put(VERSION, version); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * version. |
| * |
| * @param version the protocol version. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters version(String version) { |
| setVersion(version); |
| return this; |
| } |
| |
| /** |
| * Sets the protocol version to the default value of 1.0. |
| */ |
| public void setVersion() { |
| setVersion("1.0"); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * version to the default value of 1.0. |
| * |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters version() { |
| setVersion(); |
| return this; |
| } |
| |
| /** |
| * Returns the verifier code. |
| */ |
| public String getVerifier() { |
| return get(VERIFIER); |
| } |
| |
| /** |
| * Sets the verifier code. |
| */ |
| public void setVerifier(String verifier) { |
| put(VERIFIER, verifier); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * verifier code. |
| * |
| * @param verifier the verifier code. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters verifier(String verifier) { |
| setVerifier(verifier); |
| return this; |
| } |
| |
| /** |
| * Returns the callback URL. |
| */ |
| public String getCallback() { |
| return get(CALLBACK); |
| } |
| |
| /** |
| * Sets the callback URL. |
| */ |
| public void setCallback(String callback) { |
| put(CALLBACK, callback); |
| } |
| |
| /** |
| * Builder pattern method to return {@code OAuth1Parameters} after setting |
| * callback URL. |
| * |
| * @param callback the callback URL. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters callback(String callback) { |
| setCallback(callback); |
| return this; |
| } |
| |
| /** |
| * Removes (optional) quotation marks encapsulating parameter values in the |
| * Authorization header and returns the result. |
| */ |
| private static String dequote(String value) { |
| int length = value.length(); |
| return ((length >= 2 && value.charAt(0) == '"' && value.charAt(length - 1) == '"') |
| ? value.substring(1, length - 1) : value); |
| } |
| |
| /** |
| * Reads a request for OAuth parameters, and populates this object. |
| * |
| * @param request the request to read OAuth parameters from. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters readRequest(OAuth1Request request) { |
| |
| // read supported parameters from query string or request body (lowest preference) |
| for (String param : request.getParameterNames()) { |
| if (!param.startsWith("oauth_")) { |
| continue; |
| } |
| List<String> values = request.getParameterValues(param); |
| if (values == null) { |
| continue; |
| } |
| Iterator<String> i = values.iterator(); |
| if (!i.hasNext()) { |
| continue; |
| } |
| put(param, i.next()); |
| } |
| |
| // read all parameters from authorization header (highest preference) |
| List<String> headers = request.getHeaderValues(AUTHORIZATION_HEADER); |
| if (headers == null) { |
| return this; |
| } |
| |
| for (String header : headers) { |
| if (!header.regionMatches(true, 0, SCHEME_SPACE, 0, SCHEME_SPACE.length())) { |
| continue; |
| } |
| for (String param : header.substring(SCHEME_SPACE.length()).trim().split(",(?=(?:[^\"]*\"[^\"]*\")+$)")) { |
| String[] nv = param.split("=", 2); |
| if (nv.length != 2) { |
| continue; |
| } |
| put(UriComponent.decode(nv[0].trim(), UriComponent.Type.UNRESERVED), |
| UriComponent.decode(dequote(nv[1].trim()), UriComponent.Type.UNRESERVED)); |
| } |
| } |
| |
| return this; |
| } |
| |
| /** |
| * Writes the OAuth parameters to a request, as an Authorization header. |
| * |
| * @param request the request to write OAuth parameters to. |
| * @return this parameters object. |
| */ |
| public OAuth1Parameters writeRequest(OAuth1Request request) { |
| StringBuilder buf = new StringBuilder(SCHEME); |
| boolean comma = false; |
| for (String key : keySet()) { |
| String value = get(key); |
| if (value == null) { |
| continue; |
| } |
| buf.append(comma ? ", " : " ").append(UriComponent.encode(key, UriComponent.Type.UNRESERVED)); |
| buf.append("=\"").append(UriComponent.encode(value, UriComponent.Type.UNRESERVED)).append('"'); |
| comma = true; |
| } |
| request.addHeaderValue(AUTHORIZATION_HEADER, buf.toString()); |
| return this; |
| } |
| |
| @Override |
| public OAuth1Parameters clone() { |
| return (OAuth1Parameters) super.clone(); |
| } |
| } |
| |