[oauth] Java client using HttpClient AuthScheme
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
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
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?
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?
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?
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?
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 -~--~~~~--~~--~--~---