appdotnet / api-spec

App.net API Documentation is on the web at https://developers.app.net. Source for these docs is in the new-docs branch here. Please use the issue tracker and submit pull requests! Help us build the real-time social service where users and developers come first, not advertisers.
https://developers.app.net
952 stars 99 forks source link

Non-web-based client auth flow (app-specific passwords?) #45

Open geofft opened 12 years ago

geofft commented 12 years ago

First off, I want to confirm one thing: the auth spec appears to imply that an app that only uses the client-side flow never needs to use the client_secret at all (as does the OAuth i-d). Is this correct?

Anyway, the client-side flow requires directing the user to a URL on App.net, having them log in, and getting back a token via an HTTP redirect. I'm guessing the imagined use case is an HTML5 app, an iOS app, etc., where there's a convenient web browser available, and where there's an obvious URL to receive the token callback on a redirect (the actual URL of the HTML5 app, a custom protocol scheme registered with iOS, etc.).

This is pretty awkward for a command-line client, since there may be no web browser, and even if there is a web browser, there may be no way to receive the redirect back in the app. I'm curious if you've considered this use case, and have a recommendation. (I specifically want to add support to Barnowl, which is a multi-protocol client that you can basically treat like your favorite command-line IRC client for the purposes of this discussion.)

One option would be to allow an explicit way for an API client to pass a username and password. I can see why this would be distasteful, but note that disallowing it is only mild obfuscation -- it's pretty possible for me to scrape your login page and write code to take a username and password, hit the login page, programatically authorize my app, and return back to it.

Another option would be to generate an app-specific password on the web interface (think Google's fallback for using protocols like IMAP or XMPP when you have 2-factor authentication). This would be simple enough for the user to do, and simple enough to support on the application end. For bonus elegance points, the app-specific password should just be an access token, although a password usable with e.g. SSL-protected Basic auth would be fine too.

I also note that the spec does not specify when an access token will expire, or whether they expire at all. For a long-running command-line client on a remote machine in a screen session, we'll preferably want the access token to be usable indefinitely, and if not we'll want an explicit expiration time so we can alert the user enough in advance to re-do the auth flow while they're connected (preferably a day or so in advance, so tokens should last at least several days if requested). Can this be clarified?

One advantage of the app-specific password approach is it makes it abundantly clear how long that password is valid, namely, as long as that app-specific password is still listed on the user's profile, and it also makes it obvious how to revoke access for a client.

A related use case that's worth considering is robot accounts (commit notifications, etc.), where some code legitimately has a password of its own, and ideally a human doesn't need to visit a website even if the bot needs to be restarted.

digitalquery commented 12 years ago

I'm interested in understanding how to do this as well. Trying to move my twitter @testcricket bot across - it's a command line app that posts as a single user

janole commented 12 years ago

I'm looking for the same, because the web based OAuth flow doesn't work well on the platform I'm working on at the moment.

We need some username/password or username/app-password authentication to get access tokens.

There are similar authentication APIs available for Twitter and Facebook.

What would be really cool is if users were getting an eMail once a username/password client requested authorization.

That eMail would include the details of the app as well as the authorization granted - much like the info you're shown on the regular web form for granting OAuth access.

Maybe that eMail could even include a link for further action ("Revoke", "Manage", whatever.)

digitalquery commented 12 years ago

@voidfiles advised that this wasn't implemented yet

https://alpha.app.net/voidfiles/post/98902

geofft commented 12 years ago

@digitalquery , I think we're looking for different things. For your use case -- a bot that authenticates as itself -- the client password flow is fine, so you're only waiting for it to be enabled, For my use case and @janole's, we're building a non-web app that authenticates as a user. If we had the ability to show a web UI, the user token client-side flow would work, but we don't have that ability in a command line app.

Put differently, your app has the credentials it needs built-in, and ours need a Ui to request them from the user. Currently the only such UI is a web interface. This ticket is about how we can build a non-web UI for that purpose.

jdscolam commented 12 years ago

+1 on this, as I'm in the exact same boat, and it has been a real stumbling block for me lately. I had thought about a clearing house, where you could set your redirectUri to the clearing house with some way to distinguish your request and app name, then your app could contact the clearing house and see if the user token is available. I can't think of another way to do it right now, but this is a HUGE stumbling block for me right now as I am trying to write an API wrapper.

mattflaschen commented 12 years ago

I wanted to note that I am considering using the client-side flow (Implicit Grant Flow) for an installed app (really a plugin) as well. In my case, I should be able to deal with the web page with some finagling, but I'll follow any developments (libraries or API changes).

I also wanted to point people to https://dev.twitter.com/docs/auth/pin-based-authorization , what Twitter calls "PIN-based authorization", for comparison. I think this is similar in effect to an "app-specific password".

I would strongly recommend that we not allow direct user/password auth (despite the fact thatless scrupulous apps can bypass OAuth). It's not secure and does not allow revocation. Users are gradually learning from various OAuth apps (FB, Google, Twitter, etc.) not to expect this.

Adding pin-based auth is a better idea.

fwanicka commented 12 years ago

Yeah, this is major shortcoming at the moment. I planned on starting a WPF app tonight, but his threw a monkey wrench into my plan. I have a workaround in mind that I'm going to try, but it's going to be very clunky, and a lot of extra work. There definitely needs an easy way for non-browser apps to authenticate.

jdscolam commented 12 years ago

@fwanicka Ping me when you can either via e-mail or on app.net. I'm interested in coordinating with you on that work around.

fwanicka commented 12 years ago

Ok, I got it working. Here's what I did.

I set up a SignalR server (Node.js guys could use socket.io), and connected to it with my WPF app. The SignalR server sends the unique ConnectionId back down to the WPF app upon connection. I then launch a web browser with the authorization URL for my app, and the ConnectionId appended as the state parameter. The ConnectionId/state parameter is passed back to my redirect URL by app.net. After completing the auth process, I use the ConnectionId to broadcast the user auth code, user id and user name down to the WPF app.

In a worst case scenario, you could display the authorization URL to the user, and they could paste it into a browser. Everything from there would work the same. It's certainly not ideal, but it works.

JoshBlake commented 12 years ago

@fwanicka Did you consider or attempt embedding the WebBrowser control and then parsing the token from the URL once it changes?

fwanicka commented 12 years ago

@JoshBlake Briefly. The WPF app is just to get my feet wet with the API. I plan on creating a Win 8 (whatever they are calling Metro now) app soon, so I needed a solution that would potentially work for that as well. My assumption is that there is no way to embed the WebBrowser control in a Win8 app, but I haven't actually researched it.

And I've been wanting to try SignalR for some time now. I wanted to see if this would work for the guys creating console apps that have no other way to do it.

fwanicka commented 12 years ago

@JoshBlake After a brief search, it is apparently pretty easy to embed browser functionality in a Metro app (WebView control), so that's probably a better solution for that project.

jdscolam commented 12 years ago

@JoshBlake Just wanted to let you (and everyone else) know that @fwanicka and I now have an authentication clearing house (SignalR Hub) at http://rapptorapp.net, and Rapptor now has an authentication implementation. Just provide your credentials, give it a callback, and go. Should work on JS SignalR as well.

berg commented 11 years ago

We have the Password flow for authentication now:

https://github.com/appdotnet/api-spec/blob/master/password_auth.md

But I'm leaving this issue open to consider app-specific passwords (I really like this idea).

jdscolam commented 11 years ago

@berg I'd like to ping you guys about getting a demo/dummy app.net app that can be used to demonstrate these authentications for integration testing. Though this might work better if we have an actual sandbox to use. Anyway, thanks for all the work on this one!