Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OAuth authentication/permissions. #8

Closed
tomchristie opened this issue May 13, 2011 · 30 comments
Closed

Add OAuth authentication/permissions. #8

tomchristie opened this issue May 13, 2011 · 30 comments

Comments

@tomchristie
Copy link
Member

The plan would be to use David Larlet's OAuth plus, and keep it as an external dependency for anyone requiring OAuth support.

See: https://bitbucket.org/david/django-oauth-plus/overview

At least as a first pass this oughta be pretty easy - most of the OAuth stuff is just down to oauth-plus to deal with and you only need to tie in the very last leg.

You'll want to start off looking at examples/provider in oauth-plus. You'll see the 'outh_providers.urls' views listed in there. Those don't need to tie in at all to begin with. They'll just need to be unprotected un-api'ed views that just work exactly as they do already.
(At some point it'd be really great to tie them in with the auto-documenting API - that'd really really improve the ease of use I think.)

So the part you do need to tie in is CheckOAuth. With oauth-plus you'd normally apply that check to a view as a simple decorator, and it'd ensure that:

  1. The request is signed with a valid OAuth token
  2. The OAuth tokens 'name' matches the view name (I think that'd right.)

We'll prob want pretty much the same thing eg.

  1. A .scope attribute gets put on any Resource you want to protect with OAuth.
  2. The OAuthAuthenticator gets added to the Resource's authenticators.
  3. The OAuthAuthenticator.authenticate(request) method uses CheckOAuth (or some equivalent) to ensure the token is valid and the token's name matches the Resource's 'scope', or raises an HttpException (PERMISSION DENIED).

I think it's that simple. (?)

@mammique
Copy link
Contributor

mammique commented Feb 1, 2012

Why not using OAuth2app? : http://hiidef.github.com/oauth2app/

It should be much simpler, as it implements OAuth 2.0, which is less tricky than OAuth 1.0 provided by django-oauth-plus. I did this my own way for my API, which was done from scratch, I'm learning django-rest-framework to migrate to it now, I'll try to figure out how feasible this is.

@flashingpumpkin
Copy link
Contributor

@mammique
Copy link
Contributor

Interesting! I don't really understand why there are two module levels: provider and oauth2, are you anticipating provider.oauth3? However, it seems pretty neat! Have you ever experience its integration in DRF?

@tomchristie
Copy link
Member Author

May I suggest https://github.com/caffeinehit/django-oauth2-provider ? ;)

Yes please.

Things to note:

  1. There's no reason OAuth support needs to go into core as such. - Could be an external library that provides an OAuthAuthentication class and OAuthScopePermission class.
  2. There's a bunch of OAuth tests in there at the moment that David Larlet worked on. Plugging them never quite got finished off. Any work that does get done on this should take that into account (possibly removing them if appropriate). I think there's also something in the test settings file.
  3. My comment at the top of this issue isn't quite right - the authenticator shouldn't do any permissions checking. That should be up to a permission class.

Also this is more a future thing, but worth bearing in mind:

  1. It's occurred to me that the current system whereby authenticators return a single 'auth' context (which is usually the user) doesn't quite work - they should probably return a two-tuple of (user, auth). user is the User instance that's been authenticated, and auth is any additional authentication information (eg. scope, expiry or other tokening information) Session authentication, and basic authentication would just return (user, None), OAuth and other API tokening schemes would return (user, auth).
  2. In the same way that .DATA is moving to the request.DATA instead of view.DATA (See Views are using a subclass or HttpRequest #141), we should also have request.user and request.auth. The authenticators should move to the request in the same way that the parsers have.

/cc @sebpiq

@mammique
Copy link
Contributor

OK, correct me if I'm wrong, but I think that David's stuff is OAuth 1.0 related. I'm not sure that 1.0 worth the challenge nowadays regarding its tedious design and that 2.0 is ramping up… Indeed, authenticators will probably need (user, auth), I was thinking about that as well. Thanks for the warnings about the next evolution of DRF :-) I keep browsing around the code until I find where to start hacking from :-)

Camille.

@tomchristie
Copy link
Member Author

OK, correct me if I'm wrong, but I think that David's stuff is OAuth 1.0 related.

As far as I know, yup. It was last summer, and I don't think the OAuth 2.0 was very finalized.

I'm not sure that 1.0 worth the challenge nowadays regarding its tedious design and that 2.0 is ramping up…

Yup. Makes sense to me. Thought I'd better just point out that there are vestiges of 1.0 stuff in there that might need ripping out if we get an OAuth 2.0 implementation.

@reinout
Copy link
Contributor

reinout commented Sep 18, 2012

I've been looking at oauth for two days now and I'd personally say that it is just fine to use 1.0. 1.0 works fine and is pretty clear, 2.0 seems to be quite enterprisy and hard to implement right. So if there's a proper 1.0 library...

As a data point: dropbox is using oauth 1.0.

@tomchristie
Copy link
Member Author

Yup I'd somewhat come to the same conclusion.

The confusingly named python-oauth2 library (It actually implements 1.0) seems very well used.

There's an example service that uses it here:
https://github.com/honza/oauth-service

And a plugin to Kenneth Reitz'a requests that gives you an oauth client here, which'd be useful for testing:
https://github.com/maraujop/requests-oauth

@tomchristie
Copy link
Member Author

@flashingpumpkin's django-oauth2-provider looks like the best option to me.

He's given me a sketch of an auth class: https://gist.github.com/877c9ffb14568031609c
Would need updating slightly for 2.0, plus some docs. (Although leave the bulk of documentation to the django-oauth2-provider project - I don't really want to get into maintaining anything beyond a stub plugin.

Anyone up for taking this on?

@flashingpumpkin
Copy link
Contributor

I've got no time currently. :/

@tomchristie
Copy link
Member Author

@flashingpumpkin shame. D'ya think it'd be worth me pulling together an Authentication class for django-oauth2-provider? How likely is it to get a little bit of "getting started" style docs love sometime? I don't think it needs much, but at the moment I'd be a bit lost around things like say, why client_type is relevant, and what effect, if any it actually has. I think my only other quibble is that I think the bitwise scopes are a bit awkward - it'd be nice to just have a proper Scope table with name and description. I guess it's possible I could put a little bit of time into django-oauth2-provider if it looks like it's going to remain well maintained.

@flashingpumpkin
Copy link
Contributor

@tomchristie When I get some time spare I'm definitely up for it. We're using it quite heavily in our projects. Re bitwise scopes: It's easy to swap them out for a table with name and description, but again, time. :(

@tomchristie
Copy link
Member Author

When I get some time spare I'm definitely up for it.

@flashingpumpkin - That's good enough for me. If I get around to it I might tick off the Authentication class myself.
I don't really care about that side of things too much myself, since it's a pretty small stub. It's mostly about being confident that the provider library used is something that's going to get a bit of support & maintenance now and again.

but again, time. :(

Yup. As ever. Feeling pretty lucky that I've managed to get some real quality on-the-clock hours for REST framework 2, would have been a pretty impossible slog otherwise.

@michaelmior
Copy link
Contributor

Curious if anyone has made any progress on this. Wondering if there's any way I can lend a hand. If people are happy with the approach of django-oauth2-provider as an approach but no one has the time to implement right now, I can give that a go.

@tomchristie
Copy link
Member Author

@michaelmior - Nope it's still kicking around. As you can see there's not loads needed in terms of implementation, so I think a big chunk of the work needed is simply around adequate documentation and testing. Also I don't know if there's any python oauth2 client at the moment, but it'd def be helpful if we could provide examples to implementers of how to access with eg. a python client.

I'm also not really sure if it'd make sense to implement this as a third party package, or include it directly in core.

@michaelmior
Copy link
Contributor

I haven't tried it, but there is python-oauth2 which seems promising. Personally I'd like to see this end up in the core since OAuth is becoming pretty standard as an auth method for any API.

My experience with OAuth in Python has strictly been on the server side (currently using Piston, which uses about the same OAuth code as django-oauth-plus).

@tomchristie
Copy link
Member Author

Note that python-oauth2 is actually (somewhat confusingly) support for
oauth1.
It's the underlying library that django-oauth-plus uses.

On 7 January 2013 16:43, Michael Mior notifications@github.com wrote:

I haven't tried it, but there is python-oauth2https://github.com/simplegeo/python-oauth2which seems promising. Personally I'd like to see this end up in the core
since OAuth is becoming pretty standard as an auth method for any API.

My experience with OAuth in Python has strictly been on the server side
(currently using Piston, which uses about the same OAuth code as
django-oauth-plus).


Reply to this email directly or view it on GitHubhttps://github.com//issues/8#issuecomment-11959115.

@matthewlmcclure
Copy link

I believe oauthlib implements OAuth 2 client behavior. Server support
was still in the works as of a few weeks ago.

@tomchristie
Copy link
Member Author

Assuming you mean this oauthlib: https://github.com/idan/oauthlib

There isn't a well-documented, maintained Django binding for that yet.

This is the closest I've seen, https://github.com/craigbruce/django-oauth

Have toyed with the idea of putting together a Django binding for oauthlib,
which might be doable, but only if we could get some community support
behind the effort.

On 7 January 2013 17:23, matthewlmcclure notifications@github.com wrote:

I believe oauthlib implements OAuth 2 client behavior. Server support
was still in the works as of a few weeks ago.


Reply to this email directly or view it on GitHubhttps://github.com//issues/8#issuecomment-11961019.

@matthewlmcclure
Copy link

Yes, that's the oauthlib I meant.

@michaelmior
Copy link
Contributor

I took a look at https://github.com/craigbruce/django-oauth. The project seems pretty far from complete, but perhaps a good starting point. However, I'm inclined to say that your initial suggestion of OAuth plus seems like the best option so far.

I'm a little biased since as mentioned, I'm using almost the same code in one of my current projects via Piston. I've found it to be quite stable.

@dulacp
Copy link
Contributor

dulacp commented Feb 21, 2013

Hi everyone,

I've read the whole issue and I'm willing to give a hand on adding the OAuth and OAuth2 support.

If I correctly understand the work @tomchristie is suggesting, the goal is to provide just an Authentication class that returns a tuple (user, token) just like the TokenAuthentication.authentication is working but for that to work with any OAuth2 backend we want, we need to let the developer implement the method that validate the token and retrieve the user from the token submitted, usually called authenticate_credentials, right ?

This way, we can build a perfectly decoupled OAuth2 authentication support.
And guide the user in the documentation on how to use it of course.

I will add a pull request to translate those clumsy words into a full of sense code :)

@tomchristie
Copy link
Member Author

I've read the whole issue and I'm willing to give a hand on adding the OAuth and OAuth2 support.

@dulaccc - That'd be great!

but for that to work with any OAuth2 backend we want, we need to let the developer implement the method

Actually, not quite. At this point we don't really need to provide any extra layers of abstraction, we just need a concrete implementation of OAuth (using django-oauth-plus) and/or OAuth2 (using django-oauth2-provider).

Having good documentation for them is also really important. At the moment it's often quite hard to know where to start with OAuth, so we need to make sure we provide a really simple, easy guide.

@swistakm
Copy link
Contributor

I think this could be done the same way it's done in django-tastypie. Their OAuthAuthentication class verifies only OAuth signature and checks if provided access token is valid. Obtaining of request token and access token still should be left outside rest framework (oauth dance). This will leave for devs choice of suitable oauth flow (three-legged, two-legged, xAuth etc.)

I don't see the point in making developer to implement his own validation methods for tokens and signatures. Maybe I'm wrong because I know know only OAuth 1.0a specification and perhaps 2.0 is more flexible (and needs such approach).

I recommend looking at tastypie code as a reference and starting point but AFAIK this solution is quite incomplete (e.g. it lacks validation of nonces).

@tomchristie
Copy link
Member Author

@swistakm Agreed on all counts, they use django-oauth-plus and seems good to me.

Any more info about eg validation of nonces? Doesn't mention anything about that in the django-oauth-plus docs.

@swistakm
Copy link
Contributor

@tomchristie there is already everything needed in django-oauth-plus (including nonces). I was only mentioning tastypie implementation which lacks this feature (what makes it vulnerable to reply attacks).

I have even working OAuth code for django-rest-framework but I hadn't time to clean it and add to lib. I hope I will find time this week to make pull request.

BTW oauth-plus wasn't very developed over last year but I already contacted its author and I will take lead of this project (because it still needs some fixes IMO)

@dulacp
Copy link
Contributor

dulacp commented Feb 24, 2013

@tomchristie I agree, if we choose a specific backend (like django-oauth2-provider for OAuth2) then we can implement the validation method ourself.

Having good documentation for them is also really important. At the moment it's often quite hard to know where to start with OAuth, so we need to make sure we provide a really simple, easy guide.

Can't agree more. The issue is that django-oauth2-provider doesn't have a decent documentation currently. I've been through all the source code and the good news is that it is really well commented and brilliantly executed, so I think it's just a matter of time before they'd generate a complete documentation. I'll fill an issue on their project to ask them to update the online doc.

I need to implement an OAuth2 Authentication class for a current project of mine. The OAuth2 dance is working right now using the django-oauth2-provider backend.
So I'll make a little PR with it and some documentation, and @swistakm you can handle the OAuth1 part :)

@dbrgn
Copy link
Contributor

dbrgn commented Feb 25, 2013

By the way, there's also the rauth library which apparently supports OAuth1.0/a, 2.0 and Ofly. Its only requirement is requests.

It's on readthedocs and well tested. But I've never used it yet and don't know exactly how well it covers everything we need.

@michaelmior
Copy link
Contributor

@dbrgn It looks like rauth is for client-side only?

@dbrgn
Copy link
Contributor

dbrgn commented Feb 25, 2013

@michaelmior D'oh, I'm sorry, you're right :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants