users@jersey.java.net

Re: [Jersey] oAuth HMAC_SHA1 implementation bug

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Fri, 28 Aug 2009 11:27:47 +0200

On Aug 27, 2009, at 9:48 PM, DirkM wrote:

>
>
> Paul Sandoz wrote:
>>
>> You should be able to use a container request filter or a resource
>>
>
> I'm very impressed with the way every time I think of a new use-case
> Jersey
> has a well thought-out way to handle it. I think it would be helpful
> to add
> a link from the wiki page about OAuth to the container filter package
> description you cited above.
>

Anyone with an account can edit the wiki. Would you like to do so?


>
> Here's the class I wrote for simple OAuth authentication.
>

Thanks for sharing.


> Notes:
> 1. AuthenticationFailedException is a class I wrote. I have an
> ExceptionMapper to turn it into an HTTP 401. I need to do it this way
> because of how our architecture is set up, but anyone copying this
> code
> could simply throw a WebApplicationException.
>
> 2. Checking for the existence of each parameter is not really
> necessary, I
> just did it to be able to give a nicer error message to the user.
>
> 3. In order to get this to work with Guice, I couldn't use an <init-
> param>
> in the web.xml (as for some reason it doesn't get picked up).
> Instead I did
> this:
> HashMap<String, String> params = new HashMap<String,
> String>();
>
> params.put("com.sun.jersey.spi.container.ContainerRequestFilters",
> "com.olx.iphone.auth.AuthenticationFilter");
> serve("/*").with(GuiceContainer.class, params);
>

Yes, the way Guice web-app integration works is the initialization
parameters for a servlet/filter need to be added programatically. The
web.xml is really just a bootstrap.


> 4. Please don't use my password to break into my bank account
>

I promise :-)

Paul.


>
> public class AuthenticationFilter implements ContainerRequestFilter {
> private final static int TIMESTAMP_EXPIRY_SECONDS = 60;
>
>
> @Override
> public ContainerRequest filter(ContainerRequest containerRequest) {
> // Read the OAuth parameters from the request
> OAuthServerRequest request = new
> OAuthServerRequest(containerRequest);
> OAuthParameters params = new OAuthParameters();
> params.readRequest(request);
>
> // Check the required OAuth parameters have been provided
> checkForParameter(OAuthParameters.SIGNATURE_METHOD,
> params.getSignatureMethod());
> checkForParameter(OAuthParameters.SIGNATURE,
> params.getSignature());
> checkForParameter(OAuthParameters.TOKEN, params.getToken());
> checkForParameter(OAuthParameters.NONCE, params.getNonce());
> checkForParameter(OAuthParameters.TIMESTAMP,
> params.getTimestamp());
> checkForParameter(OAuthParameters.VERSION,
> params.getVersion());
>
> // Set the token secret, against which we will verify the
> request
> OAuthSecrets secrets = new OAuthSecrets();
> String tokenSecret = "tokensecret";
> secrets.setTokenSecret(tokenSecret);
>
> // Check that the timestamp has not expired
> String timestampStr = params.getTimestamp();
> try {
> long timestampSeconds = Long.valueOf(timestampStr);
> long timestampMillis = timestampSeconds * 1000;
> long currentTimeMillis = System.currentTimeMillis();
> long currentTimeSeconds = currentTimeMillis / 1000;
> if(timestampSeconds > currentTimeSeconds) {
> String msg = "Timestamp is in the future!\n" +
> "Timestamp " + timestampStr + " (" + (new
> Date(timestampMillis)) + ") " +
> "is later than the current time (" + (new
> Date(currentTimeMillis)) + ")";
> throwException(msg);
> }
> if(timestampSeconds < currentTimeSeconds -
> TIMESTAMP_EXPIRY_SECONDS) {
> String msg = "Timestamp expired\n" +
> "Timestamp " + timestampStr + " (" + (new
> Date(timestampMillis)) + ") " +
> "is more than " +
> TIMESTAMP_EXPIRY_SECONDS + "
> " +
> "seconds before the current time (" + (new
> Date(currentTimeMillis)) + ")";
> throwException(msg);
> }
> } catch (NumberFormatException e) {
> throwException("Could not parse oAuth timestamp '" +
> timestampStr + "'");
> }
>
> // Verify the signature
> try {
> if(!OAuthSignature.verify(request, params, secrets)) {
> throwException("Signature failed verification");
> }
> } catch (OAuthSignatureException e) {
> throw new AuthenticationFailedException(e);
> }
>
> return containerRequest;
> }
>
> private void checkForParameter(String paramName, String
> paramValue) {
> if(paramValue == null || paramValue.isEmpty()) {
> throwException("Missing or empty parameter '" + paramName +
> "'");
> }
> }
>
> private void throwException(String msg) {
> String exceptionMsg = "OAuth authentication failure: " + msg;
> throw new AuthenticationFailedException(exceptionMsg);
> }
> }
>
> --
> View this message in context: http://n2.nabble.com/oAuth-HMAC-SHA1-implementation-bug-tp3506009p3529549.html
> Sent from the Jersey mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>