net.oauth.signatures.SignedOAuthTokenParser Maven / Gradle / Ivy
/**
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package net.oauth.signatures;
import java.security.SignatureException;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import net.oauth.jsontoken.Clock;
import net.oauth.jsontoken.JsonTokenParser;
import net.oauth.jsontoken.SystemClock;
import net.oauth.jsontoken.discovery.VerifierProviders;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicHeaderValueParser;
/**
* Parses signed OAuth tokens.
*/
public class SignedOAuthTokenParser {
private final VerifierProviders locators;
private final NonceChecker nonceChecker;
private final Clock clock;
/**
* Public constructor.
*
* @param locators an object that provides signature verifiers, based signature algorithm,
* as well as on the signer and key ids.
* @param nonceChecker An optional nonce checker. If not null, then the parser will
* call the nonce checker to make sure that the nonce has not been re-used.
*/
public SignedOAuthTokenParser(VerifierProviders locators, NonceChecker nonceChecker) {
this(locators, nonceChecker, new SystemClock());
}
/**
* Public constructor.
*
* @param locators an object that provides signature verifiers, based signature algorithm,
* as well as on the signer and key ids.
* @param nonceChecker An optional nonce checker. If not null, then the parser will
* call the nonce checker to make sure that the nonce has not been re-used.
* @param clock a clock that has implemented the
* {@link Clock#isCurrentTimeInInterval(org.joda.time.Instant, org.joda.time.Duration)} method
* with a suitable slack to account for clock skew when checking token validity.
*/
public SignedOAuthTokenParser(VerifierProviders locators, NonceChecker nonceChecker, Clock clock) {
this.locators = locators;
this.nonceChecker = nonceChecker;
this.clock = clock;
}
/**
* Extracts the signed OAuth token from the Authorization header and then verifies it.
* @param request the {@link HttpServletRequest} that contains the signed OAuth token in the
* Authorization header.
* @return the signed OAuth token.
* @throws SignatureException if the signature doesn't check out, or if authentication fails
* for other reason (missing Authorization header, etc.).
*/
public SignedOAuthToken parseToken(HttpServletRequest request) throws SignatureException {
// this guaranteed to return a string starting with "Token", or null
String header = getAuthHeader(request);
if (header == null) {
throw new SignatureException("missing Authorization header of type 'Token'");
}
String postFix = header.substring(0, SignedOAuthToken.AUTH_METHOD.length()); // read past "Token"
NameValuePair nvp = BasicHeaderValueParser.parseNameValuePair(postFix.trim(), null);
if (nvp == null) {
throw new SignatureException("missing signed_token in Authorization header: " + header);
}
if (!SignedOAuthToken.SIGNED_TOKEN_PARAM.equals(nvp.getName())) {
// Not logging the header in this case. maybe they just mis-spelled "token", but did send the
// actual OAuth token. We don't want to log that.
throw new SignatureException("missing signed_token in Authorization header");
}
String token = nvp.getValue().trim();
String method = request.getMethod();
StringBuffer uri = request.getRequestURL();
if (request.getQueryString() != null) {
uri.append("?");
uri.append(request.getQueryString());
}
return parseToken(token, method, uri.toString());
}
/**
* Parses the provided signed OAuth token, and then verifies it against the provided HTTP method
* and audience URI (in addition to checking the signature, and validity period).
* @param tokenString the signed OAuth token (in serialized form).
* @param method the HTTP method that was used when the token was exercised.
* @param uri the URI against which the token was exercised.
* @return the signed OAuth token (deserialized)
* @throws SignatureException if the signature (or anything else) doesn't check out.
*/
public SignedOAuthToken parseToken(String tokenString, String method, String uri) throws SignatureException {
JsonTokenParser parser = new JsonTokenParser(clock, locators, new SignedTokenAudienceChecker(uri));
SignedOAuthToken token = new SignedOAuthToken(parser.verifyAndDeserialize(tokenString));
if (!method.equalsIgnoreCase(token.getMethod())) {
throw new SignatureException("method does not equal in token (" + token.getMethod() + ")");
}
if (nonceChecker != null) {
nonceChecker.checkNonce(token.getNonce());
}
return token;
}
private String getAuthHeader(HttpServletRequest request) {
@SuppressWarnings("unchecked")
Enumeration authHeaders = request.getHeaders("Authorization");
if (authHeaders == null) {
return null;
}
while (authHeaders.hasMoreElements()) {
String header = (String) authHeaders.nextElement();
if (header.trim().startsWith(SignedOAuthToken.AUTH_METHOD)) {
return header.trim();
}
}
return null;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy