3

It may be a duplicate question but there hasn't been an answer yet. The libraries oauth-dot-net and DotNetOpenAuth are both frighteningly convoluted, a theme that seems to run through OAuth, and while OAuth with Verification in .NET is instructive and much easier to understand, it says

Use a WebBrowser control, and open the authorize web page within the desktop app. When the user clicks "Allow", grab the response text from that WebBrowser control, extract the PIN automatically, then get the access tokens. You send 5 or 6 HTTP requests but the user needs to see only a single Allow/Deny dialog. Simple.

This is OAuth without a browser? No, it isn't. It works, provided you use a web browser to invoke the URL and run the response, which is an all-singing all-dancing miracle of browser based automation in HTML, meta refresh, noscript tags and javascript. But I do not wish to do this.

Microsoft, this is aimed at you! I need to do pure REST, not mostly REST except when it's javascript.

I wish to retrieve a request token, as described by the OAuth RFC. A request token, not a software authentication robot. A REQUEST TOKEN.

When I use WebClient to directly execute this GET

GET /oauth20_authorize.srf?client_id=00000000400A9B87&scope=wl.signin%20wl.basic&response_type=code&redirect_uri=http%3a%2f%2fwhitehouse.podzone.net%2f HTTP/1.1

I get back an unspeakable mess of machine generated javascript. For the love of Pete, I want a goddamn request_token, not a javascript love-in. So, how the blazes do I get a request token from live.com?

I'm currently wading throught the obfuscated and compressed libraries referenced by the sent HTML, but it's heavy going. If anyone has already done this I would be very grateful for assistance. Or even guidance on how to hijack and trace the script on this page, which would probably speed things up a fair bit.

If you're examining the GET, the redirect URI http://whitehouse.podzone.net/ maps through to the webserver on my home desktop machine, which is usually an HttpListener in the application being debugged, or sometimes IIS. That's how I process the redirect (usually just drop it, but it's nice to know things got that far).


I have a short term hack lifted from some work I did based on someone else's work around Skydrive. It avoids the problem by exploiting the fact that the Skydrive application is pre-approved for every Live account. However, this is a hack. I'd like to use OAuth properly, it just doesn't seem like that's going to be practical.


Despite a really gutsy attempt to help from Darin, which turned up some stuff I wish I'd seen on day one, I'm left with this quote from his link http://msdn.microsoft.com/en-us/library/live/hh826529.aspx (my emphasis)

To implement the client-side authentication flow, desktop apps must use a web browser control. Most development languages include such a control. In this example, our app uses the System.Windows.Forms.WebBrowser class. After sign in is complete, all subsequent Live Connect API calls can be accomplished by using the System.Net.WebRequest class. Use the web browser control to start the sign-in, passing a URL similar to this one.

They only want me to use their robot for sign-in because relinquishing control of the exchange makes it harder to skip presenting a user intervention opportunity. There is no inherent reason I can't implement the sign-in procedure myself. Anything their javascript can post I can post with WebClient. I can do the same encryption. On an ethical level the user would hardly be presenting their username and password if they didn't want my software to do its thing.

I've marked up Darin's answer because he's tried very hard to assist and presented some excellent stuff, but I guess I'll be sticking with my little hack which is disappointing.

Community
  • 1
  • 1
Peter Wone
  • 17,965
  • 12
  • 82
  • 134
  • I don't quite understand your question. You do not wish to use a WebBrowser at all? – Darin Dimitrov Feb 24 '13 at 09:40
  • 1
    That's correct, Darin. I am not writing a web app, I am not writing a desktop app and I am not writing a handler for a web server. I *am* writing server software and I would like to outource the whole user identity management problem. The OAuth RFC actually describes my scenario *before* it discusses the web, it's called an Active client, as distinct from the sort that has to be hosted in a browser which is called a Passive client. Sorry if my tone is somewhat aggressive, Darin, it's just that this has been going in circles for weeks, and Google is even less helpful than Microsoft. – Peter Wone Feb 24 '13 at 10:02
  • 1
    The OAuth specification defines a profile which allows to retrieve an access token from the end user username and password. But this assumes that you already posses those credentials which isn't your case. In addition to that service providers (such as Live, Google and Facebook) explicitly do not support this OAuth profile and will not let you do that. You need a webBrowser if you want to authenticate with `live.com`. That's the only secure way to do that. If your client application cannot use WebBrowsers you will have to ask the user perform the authorization step manually (to be continued) – Darin Dimitrov Feb 24 '13 at 10:12
  • 2
    ... So you will ask the user to use a webbrowser to log in to live.com and retrieve the access token manually. Then he could paste this access token to your application so that you could perform authenticated requests. Also you do not need to have a web server if you use the `implicit grant flow` which I suggested in my answer. You could subscribe to the callback url inside the WebBrowser (using the `Navigating` event) and then capture the `access_token` parameter and hide the browser. It could be a dummy callback url which you registered with live.com but you don't need any HTTP listener. – Darin Dimitrov Feb 24 '13 at 10:14
  • hi. i have the same issue. can you share your hack? thanks – Yisroel M. Olewski Nov 08 '13 at 08:44
  • @DarinDimitrov: I had a similar issue with a different API secured by OAuth, and found that I had to use the `Navigated` event instead of `Navigating`. I never got a `Navigating` event for the callback URL, only `Navigated`. I don't know if it matters that I had IE 10 installed. – John Saunders Jan 06 '14 at 06:00

1 Answers1

4

You could use the implicit grant flow with rich client applications (grant_type=token). The idea is to have a WebBrowser control which initiates the authentication flow by redirecting to the live.com authorization server and providing a callback url. If the user authorizes your application the live.com will redirect back to the callback url and pass the access token in the url:

http://contoso.com/Callback.htm#access_token=ACCESS_TOKEN

You could then retrieve the access_token fragment of the url from the WebBrowser and use it to perform authenticated requests. You do not need to parse the returned content inside your WebBrowser. What you need to do is to retrieve the access token from the url.

There's also the authorization grant code flow (grant_type=code) which is more suitable for web based applications.

You might take a look at the following article for a complete sample using a desktop application.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • I just spent the afternoon experimenting with implicit grant flow. I appreciate that you're trying to help but the whole run-it-in-a-browser thing fails because the service runs as a single user identity so cookies are not private to the caller's identity, they are shared. – Peter Wone Feb 24 '13 at 10:21
  • Sorry I didn't understand the problem with the cookies. Could you elaborate? – Darin Dimitrov Feb 24 '13 at 10:22
  • You might check out the following article for a complete step by step example on how you could integrate live id connect with mobile and desktop applications: http://msdn.microsoft.com/en-us/library/live/hh826529.aspx – Darin Dimitrov Feb 24 '13 at 10:57
  • +1 for quality of info even though it's not the answer I'm looking for – Peter Wone Feb 24 '13 at 12:10
  • 1
    @PeterWone, the reason why identity providers do not allow you to send direct HTTP requests is because you are not supposed to write an application where you would harvest the username and password. This is for security reasons. The only secure way to authenticate is to use the sign-in form offered by the identity provider. You realize that if this was possible people could write malicious applications for stealing usernames and passwords. – Darin Dimitrov Feb 24 '13 at 12:49
  • That's like saying "if we all agree not to have guns the world will be a safer place", all it achieves is peace of mind for the unscrupulous people who lied and kept their weapons. People *can still* write malicious code if there's enough motivation. It's just harder work. This is just security theatre like the nonsense you get at airports. – Peter Wone Feb 24 '13 at 23:23
  • @PeterWone, I am by far not a security expert and would not like to involve in such discussions. What I can say is that IMHO there are security experts working for those companies (MSFT, GOOGLE, FB, ...) which I think know their job and I am sure that there is a good reason for them taking the decision to disable the password delegation profile. – Darin Dimitrov Feb 25 '13 at 06:59
  • Leaving aside my concern that security theatre gives Joe Public a false sense of security, please understand that my requirements are heavily shaped by the fact that Silverlight uses the old SiteServer architecture which has extensibility points but they expect you to implement ValidateUser(name, password). I have already found a way to trick live.com into directly validating a username/password pair but I wanted to do things "properly". Since that doesn't seem possible without an incredible amount of work, I'm going to totally change my approach to all this, with a new question. – Peter Wone Feb 26 '13 at 02:27
  • I'm going to exploit the fact that a Silverlight app always lives in a web page, so I can do things the way you've suggested such that at the point where the SL app is launched, the dance is over, consent has been interactively give and the app is handed a token. I hope you will contribute to that question because I really like your work. – Peter Wone Feb 26 '13 at 02:31
  • If you have a Silverlight application, why not authenticate first through the web page hosting this application and then simply passing the access token to the SL app? – Darin Dimitrov Feb 26 '13 at 06:49