[oauth] Java client using HttpClient AuthScheme

2009-03-22 Thread Paul Austin

The current OAuth client uses a custom wrapper around the HttpClient.
What I'd like to propose is to use the standard HttpClient but
implement an AuthScheme which would automatically sign the request in
the same way that basic and digest authentication works.

Code #1 is an example of the AuthScheme with a direct authentication.
To do the delegated authentication a subclass of Credentials could be
defined which would store the access token and secret.

Code #2 shows an example of registering the the AuthScheme and using a
consumerKey and consumerSecret for authentication.

Code #1

import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthMessage;
import net.oauth.OAuthServiceProvider;

import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.RequestLine;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.Credentials;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.auth.RFC2617Scheme;
import org.apache.http.impl.client.RequestWrapper;
import org.apache.http.message.BasicHeader;

public class OAuthScheme extends RFC2617Scheme {

  public Header authenticate(Credentials credentials, HttpRequest
request)
throws AuthenticationException {
try {
  RequestLine requestLine = request.getRequestLine();
  String uri;
  String method;
  if (request instanceof RequestWrapper) {
HttpUriRequest uriRequest = (HttpUriRequest)((RequestWrapper)
request).getOriginal();
uri = uriRequest.getURI().toString();
method = uriRequest.getMethod();
  } else if (request instanceof HttpUriRequest) {
HttpUriRequest uriRequest = (HttpUriRequest)request;
uri = uriRequest.getURI().toString();
method = uriRequest.getMethod();
  } else {
uri = requestLine.getUri();
method = requestLine.getMethod();
  }

  List parameters = URLEncodedUtils.parse(new URI
(uri), null);
  Map parameterMap = new HashMap
();
  for (NameValuePair parameter : parameters) {
parameterMap.put(parameter.getName(), parameter.getValue());
  }

  String url = uri;
  int queryIndex = url.indexOf('?');
  if (queryIndex != -1) {
url = url.substring(0, queryIndex);
  }
  Set> parameterEntries =
parameterMap.entrySet();
  OAuthMessage message = new OAuthMessage(method, url,
parameterEntries);
  String consumerKey = credentials.getUserPrincipal().getName();
  String consumerSecret = credentials.getPassword();
  OAuthAccessor accessor = new OAuthAccessor(new OAuthConsumer("",
consumerKey, consumerSecret, new OAuthServiceProvider("", "",
"")));
  message.addRequiredParameters(accessor);
  String realm = getParameter("realm");
  String authorization = message.getAuthorizationHeader(realm);
  return new BasicHeader("Authorization", authorization);
} catch (Throwable t) {
  t.printStackTrace();
  throw new AuthenticationException("Unable to create OAuth
header", t);
}
  }

  public String getSchemeName() {
return "oauth";
  }

  public boolean isComplete() {
return false;
  }

  public boolean isConnectionBased() {
return false;
  }

}


--
Code #2
  HttpContext context = new BasicHttpContext();
 context.setAttribute(ClientContext.AUTH_SCHEME_PREF, Arrays.asList
("oauth"));

DefaultHttpClient httpclient = new DefaultHttpClient();

httpclient.getAuthSchemes().register("oauth", new
OAuthSchemeFactory());

httpclient.getCredentialsProvider().setCredentials(
  new AuthScope("localhost", 8080),
  new UsernamePasswordCredentials
("ec1e0b2b-0f3e-401d-844d-0a649eca19d0",
"559a4162-8167-4eca-9010-603ad707ecbf"));

HttpGet users = new HttpGet("http://localhost:8080/bcgov-bpf/ws/
users/");

HttpResponse response = httpclient.execute(users, context);
HttpEntity entity = response.getEntity();

IOUtils.copy(entity.getContent(), System.out);

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"OAuth" group.
To post to this group, send email to oauth@googlegroups.com
To unsubscribe from this group, send email to oauth+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/oauth?hl=en
-~--~~~~--~~--~--~---



[oauth] Re: Java client using HttpClient AuthScheme

2009-03-22 Thread John Panzer

I'd suggest also implementing processChallenge() to deal with 
WWW-Authenticate: challenges from a server and making it available to 
clients in a reasonable way.

I don't understand the use of UsernamePasswordCredentials in 
setCredentials example though :).

Paul Austin wrote:
> The current OAuth client uses a custom wrapper around the HttpClient.
> What I'd like to propose is to use the standard HttpClient but
> implement an AuthScheme which would automatically sign the request in
> the same way that basic and digest authentication works.
>
> Code #1 is an example of the AuthScheme with a direct authentication.
> To do the delegated authentication a subclass of Credentials could be
> defined which would store the access token and secret.
>
> Code #2 shows an example of registering the the AuthScheme and using a
> consumerKey and consumerSecret for authentication.
>
> Code #1
>
> import java.net.URI;
> import java.util.HashMap;
> import java.util.List;
> import java.util.Map;
> import java.util.Set;
> import java.util.Map.Entry;
>
> import net.oauth.OAuthAccessor;
> import net.oauth.OAuthConsumer;
> import net.oauth.OAuthMessage;
> import net.oauth.OAuthServiceProvider;
>
> import org.apache.http.Header;
> import org.apache.http.HttpRequest;
> import org.apache.http.NameValuePair;
> import org.apache.http.RequestLine;
> import org.apache.http.auth.AuthenticationException;
> import org.apache.http.auth.Credentials;
> import org.apache.http.client.methods.HttpUriRequest;
> import org.apache.http.client.utils.URLEncodedUtils;
> import org.apache.http.impl.auth.RFC2617Scheme;
> import org.apache.http.impl.client.RequestWrapper;
> import org.apache.http.message.BasicHeader;
>
> public class OAuthScheme extends RFC2617Scheme {
>
>   public Header authenticate(Credentials credentials, HttpRequest
> request)
> throws AuthenticationException {
> try {
>   RequestLine requestLine = request.getRequestLine();
>   String uri;
>   String method;
>   if (request instanceof RequestWrapper) {
> HttpUriRequest uriRequest = (HttpUriRequest)((RequestWrapper)
> request).getOriginal();
> uri = uriRequest.getURI().toString();
> method = uriRequest.getMethod();
>   } else if (request instanceof HttpUriRequest) {
> HttpUriRequest uriRequest = (HttpUriRequest)request;
> uri = uriRequest.getURI().toString();
> method = uriRequest.getMethod();
>   } else {
> uri = requestLine.getUri();
> method = requestLine.getMethod();
>   }
>
>   List parameters = URLEncodedUtils.parse(new URI
> (uri), null);
>   Map parameterMap = new HashMap
> ();
>   for (NameValuePair parameter : parameters) {
> parameterMap.put(parameter.getName(), parameter.getValue());
>   }
>
>   String url = uri;
>   int queryIndex = url.indexOf('?');
>   if (queryIndex != -1) {
> url = url.substring(0, queryIndex);
>   }
>   Set> parameterEntries =
> parameterMap.entrySet();
>   OAuthMessage message = new OAuthMessage(method, url,
> parameterEntries);
>   String consumerKey = credentials.getUserPrincipal().getName();
>   String consumerSecret = credentials.getPassword();
>   OAuthAccessor accessor = new OAuthAccessor(new OAuthConsumer("",
> consumerKey, consumerSecret, new OAuthServiceProvider("", "",
> "")));
>   message.addRequiredParameters(accessor);
>   String realm = getParameter("realm");
>   String authorization = message.getAuthorizationHeader(realm);
>   return new BasicHeader("Authorization", authorization);
> } catch (Throwable t) {
>   t.printStackTrace();
>   throw new AuthenticationException("Unable to create OAuth
> header", t);
> }
>   }
>
>   public String getSchemeName() {
> return "oauth";
>   }
>
>   public boolean isComplete() {
> return false;
>   }
>
>   public boolean isConnectionBased() {
> return false;
>   }
>
> }
>
>
> --
> Code #2
>   HttpContext context = new BasicHttpContext();
>  context.setAttribute(ClientContext.AUTH_SCHEME_PREF, Arrays.asList
> ("oauth"));
>
> DefaultHttpClient httpclient = new DefaultHttpClient();
>
> httpclient.getAuthSchemes().register("oauth", new
> OAuthSchemeFactory());
>
> httpclient.getCredentialsProvider().setCredentials(
>   new AuthScope("localhost", 8080),
>   new UsernamePasswordCredentials
> ("ec1e0b2b-0f3e-401d-844d-0a649eca19d0",
> "559a4162-8167-4eca-9010-603ad707ecbf"));
>
> HttpGet users = new HttpGet("http://localhost:8080/bcgov-bpf/ws/
> users/");
>
> HttpResponse response = httpclient.execute(users, context);
> HttpEntity entity = response.getEntity();
>
> IOUtils.copy(entity.getContent(), System.out);
>
> >
>   


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"OAuth" group.
To post to this group, send email to oauth@googlegroups.com
To u

[oauth] Re: Java client using HttpClient AuthScheme

2009-03-22 Thread Paul Austin

I have submitted a feature enhancement request to Apache HttpClient to
see if we can get it into the core

http://issues.apache.org/jira/browse/HTTPCLIENT-836

In there I have added a new type of Credential called OAuthCredential
which can have a consumer secret/key and access token/key.

In the example I was using a direct authentication which only requests
a consumerKey (username) and consumerSecret (password). I could have
extended this example to work with digest, basic or oauth
authentication when the server returns multiple www-authenticate
headers so that's why I used UsernamePasswordAuthentication in this
case.

If you changed the example with the new class it would have use
OAuthCredentials(consumerKey, consumerSecret) or OAuthCredentials
(consumerKey, consumerSecret, accessToken, tokenSecret).

I'm not sure if processChallenge needs to do anything special, because
the WWW-Authenticate header for OAuth just returns the realm, it's not
like Digest where the server returns the nonce, qop, and auth.

Paul

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"OAuth" group.
To post to this group, send email to oauth@googlegroups.com
To unsubscribe from this group, send email to oauth+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/oauth?hl=en
-~--~~~~--~~--~--~---



[oauth] load testing an oAuth provider?

2009-03-22 Thread Perryn Fowler

Has anyone performed load testing on an oAuth provider? If so, what did you use?

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"OAuth" group.
To post to this group, send email to oauth@googlegroups.com
To unsubscribe from this group, send email to oauth+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/oauth?hl=en
-~--~~~~--~~--~--~---



[oauth] Security through obscurity?

2009-03-22 Thread Nial

I've been working on some JS that works as an OS X dashboard widget.
The widget connects to a third-party service which requires OAuth
authorization.

In regards to the Consumer Key/Secret, as far as I understand it,
these two pieces of information (particularly the Secret) are
sensitive and thus should not be shared with anyone. Obviously, the
problem here is that both variables are easily accessible if the user
is to snoop around in the widget's JS files. I'm aware that this is
regularly discussed amongst the OAuth community (and have done some
searches) but wanted to get your opinions.

On the one hand, it's still more secure than Basic HTTP
authentication, whereby the users credentials are sent, unencoded,
with each and every server request. Similarly, I appreciate that the
Secret key could also be found amongst desktop apps with a bit more
poking and prodding. But on the other, it opens my application to the
possibility of spoofing, whereby a malicious user could use my details
to send nasty requests to the third-party service.

This opens the question of whether or not to store my consumer key/
secret within the widgets JS files or request them from a third-party
server as and when the widget is initialized. If I were to do the
former (as I am currently), I'd have to put out a new version of my
widget if my old consumer key/secret were compromised. Which I suppose
begs the question: how often do such things occur?

Any suggestions?

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"OAuth" group.
To post to this group, send email to oauth@googlegroups.com
To unsubscribe from this group, send email to oauth+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/oauth?hl=en
-~--~~~~--~~--~--~---



[oauth] Re: Security through obscurity?

2009-03-22 Thread Chris Messina
On Sun, Mar 22, 2009 at 3:37 PM, Nial  wrote:

>
> I've been working on some JS that works as an OS X dashboard widget.
> The widget connects to a third-party service which requires OAuth
> authorization.
>
> In regards to the Consumer Key/Secret, as far as I understand it,
> these two pieces of information (particularly the Secret) are
> sensitive and thus should not be shared with anyone. Obviously, the
> problem here is that both variables are easily accessible if the user
> is to snoop around in the widget's JS files. I'm aware that this is
> regularly discussed amongst the OAuth community (and have done some
> searches) but wanted to get your opinions.
>
> On the one hand, it's still more secure than Basic HTTP
> authentication, whereby the users credentials are sent, unencoded,
> with each and every server request. Similarly, I appreciate that the
> Secret key could also be found amongst desktop apps with a bit more
> poking and prodding. But on the other, it opens my application to the
> possibility of spoofing, whereby a malicious user could use my details
> to send nasty requests to the third-party service.
>
> This opens the question of whether or not to store my consumer key/
> secret within the widgets JS files or request them from a third-party
> server as and when the widget is initialized. If I were to do the
> former (as I am currently), I'd have to put out a new version of my
> widget if my old consumer key/secret were compromised. Which I suppose
> begs the question: how often do such things occur?
>

I have no idea how often this needs to happen. I would imagine far less
often than people playing it up to happen — or worry about it happening —
but it's an unsolvable risk if your code is going to be in the clear, so
it's a risk that is generally accepted given the alternatives.

That said, you could simply watch for nefarious behavior with your consumer
key and if you find that it's being used nefarious, just invalidate it but
provide a mechanism to politely exchange the old consumer key for a new one,
like the way AT&T updates the iPhone:

http://www.flickr.com/photos/factoryjoe/3290923828/
http://www.flickr.com/photos/factoryjoe/3290106337

This won't exactly solve your problem, but at least gives you some recourse
to force people to update to a new version and perhaps reauthenticate. It
won't prevent abuse indefinitely, but it might stem it.
The alternative is to put a unique consumer key in each Dashboard Widget
download, which is costly from a server side management perspective and
doesn't necessarily get you better security — only better visibility into
how certain consumers are being used. Depending on your app, it might be
worth it. For most, it's probably not worth it.

Perhaps other people have more telling experiences/numbers?

Chris

-- 
Chris Messina
Citizen-Participant &
 Open Web Advocate

factoryjoe.com // diso-project.org // vidoop.com
This email is:   [ ] bloggable[X] ask first   [ ] private

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"OAuth" group.
To post to this group, send email to oauth@googlegroups.com
To unsubscribe from this group, send email to oauth+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/oauth?hl=en
-~--~~~~--~~--~--~---



[oauth] Re: Security through obscurity?

2009-03-22 Thread Allen Tom

So how does this 3rd party server authenticate your widget? What's to 
stop someone from reverse engineering the protocol and requesting your 
CK/Secret?

We believe that it is impossible to safeguard any secrets embedded in 
downloadable client applications. Someone with a debugger and some 
patience will be able to extract the secrets very quickly. Likewise, any 
secret protocol between a downloadable client and a server can also be 
easily reverse engineered. Therefore, it's impossible to securely 
identify a client application, and a downloadable client application's 
consumer key (even when signed with its consumer secret) is about as 
meaningful as your browser's HTTP User-Agent string.

Unlike downloadable client applications, server based apps are able to 
safeguard their consumer secret, so it is possible to authenticate 
server based applications.

Allen



Nial wrote:
> This opens the question of whether or not to store my consumer key/
> secret within the widgets JS files or request them from a third-party
> server as and when the widget is initialized. If I were to do the
> former (as I am currently), I'd have to put out a new version of my
> widget if my old consumer key/secret were compromised. Which I suppose
> begs the question: how often do such things occur?
>
>   


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"OAuth" group.
To post to this group, send email to oauth@googlegroups.com
To unsubscribe from this group, send email to oauth+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/oauth?hl=en
-~--~~~~--~~--~--~---