david-django-oauth-plus-91f6df5e8a28/.hg_archival.txt0000644000000000000000000000017112251631323020547 0ustar 00000000000000repo: 3dcd2afa78919ee5301de49778a6b1f653a48464 node: 91f6df5e8a281b7dcf17144b8cad40d46bd8e18a branch: default tag: 2.2.3 david-django-oauth-plus-91f6df5e8a28/.hgignore0000644000000000000000000000025512251631323017267 0ustar 00000000000000syntax:glob .tox *.elc *.pyc *~ *.orig *.log *.swp *.tmp *.DS_Store testdb.sqlite dist/* django_oauth.egg-info/* setuptools_hg-0.1-py2.5.egg junitxml .idea *.egg *.egg-infodavid-django-oauth-plus-91f6df5e8a28/.hgtags0000644000000000000000000000072312251631323016742 0ustar 00000000000000eec5864034862511559260be1715636fe132d4ec v1.0 7cb2d808b6122ae9c599c89739cbf8b0e7d55829 1.1 bd803476aa4f4b84afbb8877a3d204c9cd8ae2fb 2.1.0 d32d2e99d5d6e562b5fecb74fdf5e833de246e01 2.1.2 2688039dded882340ad83709acedc7eb0bdfab34 2.1.3 0c547f5bb4c84bebc74d9b53082e62fb93d94e48 2.2.0 1e293883e3f9c54686ca66391450e2e65af20e4c 2.2.1 1e293883e3f9c54686ca66391450e2e65af20e4c 2.2.1 0000000000000000000000000000000000000000 2.2.1 80af819c1f67b0e353cab8f6a545759d2e4ae991 2.2.2 david-django-oauth-plus-91f6df5e8a28/AUTHORS0000644000000000000000000000041312251631323016530 0ustar 00000000000000David Larlet Dan Wilson Jay Graves Ariel Nunez Jesper Noerh Toby White Thomas Johansson MichaƂ Jaworski Andy Mroczkowski Atle Frenvik Sveen Andrei Kopats Alex Irpan Changhwan Song david-django-oauth-plus-91f6df5e8a28/LICENSE0000644000000000000000000000277012251631323016475 0ustar 00000000000000Copyright (c) 2008, see AUTHORS All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Django-OAuth nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. david-django-oauth-plus-91f6df5e8a28/oauth_provider/__init__.py0000644000000000000000000000012012251631323022616 0ustar 00000000000000VERSION = (2, 2, 3) # PEP 386 __version__ = ".".join([str(x) for x in VERSION])david-django-oauth-plus-91f6df5e8a28/oauth_provider/admin.py0000644000000000000000000000062412251631323022160 0ustar 00000000000000from django.contrib import admin from models import Scope, Consumer, Token class ScopeAdmin(admin.ModelAdmin): pass class ConsumerAdmin(admin.ModelAdmin): raw_id_fields = ['user'] class TokenAdmin(admin.ModelAdmin): raw_id_fields = ['user', 'consumer', 'scope'] admin.site.register(Scope, ScopeAdmin) admin.site.register(Consumer, ConsumerAdmin) admin.site.register(Token, TokenAdmin)david-django-oauth-plus-91f6df5e8a28/oauth_provider/backends.py0000644000000000000000000000271312251631323022643 0ustar 00000000000000# -*- coding: utf-8 -*- import django.core.validators from compat import get_user_model User = get_user_model() class XAuthAuthenticationBackend(object): """Custom Authentication Backend. Supports both username and email as identification """ supports_anonymous_user = False def authenticate(self, x_auth_username=None, x_auth_password=None, x_auth_mode=None): """Authenticates a user through the combination email/username with password. Returns signed ``User`` instance x_auth_username -- a string containing the username or e-mail of the user that is trying to authenticate. x_auth_password -- string containing the password for the user. """ if x_auth_mode != 'client_auth': return None try: django.core.validators.validate_email(x_auth_username) try: user = User.objects.get(email__iexact=x_auth_username) except User.DoesNotExist: return None except django.core.validators.ValidationError: try: user = User.objects.get(username__iexact=x_auth_username) except User.DoesNotExist: return None if user.check_password(x_auth_password): return user def get_user(self, user_id): try: return User.objects.get(pk=user_id) except User.DoesNotExist: return Nonedavid-django-oauth-plus-91f6df5e8a28/oauth_provider/compat.py0000644000000000000000000000331212251631323022350 0ustar 00000000000000# -*- coding: utf-8 -*- import django # location of patterns, url, include changes in 1.4 onwards try: from django.conf.urls import patterns, url, include except ImportError: from django.conf.urls.defaults import patterns, url, include # in Django>=1.5 CustomUser models can be specified if django.VERSION >= (1, 5): from django.contrib.auth import get_user_model from django.conf import settings AUTH_USER_MODEL = settings.AUTH_USER_MODEL else: from django.contrib.auth.models import User get_user_model = lambda: User AUTH_USER_MODEL = "auth.User" try: from django.utils.crypto import get_random_string except ImportError: import random # fallback for older versions of django (<=1.3). You shouldn't use them get_random_string = lambda length: ''.join([random.choice('abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(length)]) try: from django.utils.timezone import now except ImportError: import datetime try: # this is fallback for old versions of django import pytz from functools import partial now = partial(datetime.datetime.now, tz=pytz.UTC) except ImportError: # if there is no pytz and this is old version of django, probably # no one cares for timezones now = datetime.datetime.now if django.VERSION >= (1, 4): from django.http import HttpResponse class UnsafeRedirect(HttpResponse): def __init__(self, url, *args, **kwargs): super(UnsafeRedirect, self).__init__(*args, status=302, **kwargs) self["Location"] = url else: from django.http import HttpResponseRedirect as UnsafeRedirectdavid-django-oauth-plus-91f6df5e8a28/oauth_provider/consts.py0000644000000000000000000000151312251631323022377 0ustar 00000000000000from django.utils.translation import ugettext_lazy as _ from django.conf import settings KEY_SIZE = getattr(settings, 'OAUTH_PROVIDER_KEY_SIZE', 32) SECRET_SIZE = getattr(settings, 'OAUTH_PROVIDER_SECRET_SIZE', 16) VERIFIER_SIZE = getattr(settings, 'OAUTH_PROVIDER_VERIFIER_SIZE', 10) CONSUMER_KEY_SIZE = getattr(settings, 'OAUTH_PROVIDER_CONSUMER_KEY_SIZE', 256) MAX_URL_LENGTH = 2083 # http://www.boutell.com/newfaq/misc/urllength.html PENDING = 1 ACCEPTED = 2 CANCELED = 3 REJECTED = 4 CONSUMER_STATES = ( (PENDING, _('Pending')), (ACCEPTED, _('Accepted')), (CANCELED, _('Canceled')), (REJECTED, _('Rejected')), ) PARAMETERS_NAMES = ('consumer_key', 'token', 'signature', 'signature_method', 'timestamp', 'nonce') OAUTH_PARAMETERS_NAMES = ['oauth_'+s for s in PARAMETERS_NAMES] OUT_OF_BAND = 'oob' david-django-oauth-plus-91f6df5e8a28/oauth_provider/decorators.py0000644000000000000000000000505612251631323023241 0ustar 00000000000000import oauth2 as oauth try: from functools import update_wrapper except ImportError: from django.utils.functional import update_wrapper # Python 2.3, 2.4 fallback. from django.utils.translation import ugettext as _ from responses import INVALID_PARAMS_RESPONSE, INVALID_CONSUMER_RESPONSE, COULD_NOT_VERIFY_OAUTH_REQUEST_RESPONSE, INVALID_SCOPE_RESPONSE from utils import initialize_server_request, send_oauth_error, get_oauth_request, verify_oauth_request from consts import OAUTH_PARAMETERS_NAMES from store import store, InvalidTokenError, InvalidConsumerError from functools import wraps class CheckOauth(object): """ Decorator that checks that the OAuth parameters passes the given test, raising an OAuth error otherwise. If the test is passed, the view function is invoked. We use a class here so that we can define __get__. This way, when a CheckOAuth object is used as a method decorator, the view function is properly bound to its instance. """ def __init__(self, scope_name=None): self.scope_name = scope_name def __new__(cls, arg=None): if not callable(arg): return super(CheckOauth, cls).__new__(cls) else: obj = super(CheckOauth, cls).__new__(cls) obj.__init__() return obj(arg) def __call__(self, view_func): @wraps(view_func) def wrapped_view(request, *args, **kwargs): oauth_request = get_oauth_request(request) if oauth_request is None: return INVALID_PARAMS_RESPONSE try: consumer = store.get_consumer(request, oauth_request, oauth_request['oauth_consumer_key']) except InvalidConsumerError: return INVALID_CONSUMER_RESPONSE try: token = store.get_access_token(request, oauth_request, consumer, oauth_request.get_parameter('oauth_token')) except InvalidTokenError: return send_oauth_error(oauth.Error(_('Invalid access token: %s') % oauth_request.get_parameter('oauth_token'))) if not verify_oauth_request(request, oauth_request, consumer, token): return COULD_NOT_VERIFY_OAUTH_REQUEST_RESPONSE if self.scope_name and (not token.scope or token.scope.name != self.scope_name): return INVALID_SCOPE_RESPONSE if token.user: request.user = token.user return view_func(request, *args, **kwargs) return wrapped_view oauth_required = CheckOauth david-django-oauth-plus-91f6df5e8a28/oauth_provider/forms.py0000644000000000000000000000027612251631323022221 0ustar 00000000000000from django import forms class AuthorizeRequestTokenForm(forms.Form): oauth_token = forms.CharField(widget=forms.HiddenInput) authorize_access = forms.BooleanField(required=False) david-django-oauth-plus-91f6df5e8a28/oauth_provider/managers.py0000644000000000000000000000144212251631323022664 0ustar 00000000000000from django.db import models class TokenManager(models.Manager): def create_token(self, consumer, token_type, timestamp, scope, user=None, callback=None, callback_confirmed=False): """Shortcut to create a token with random key/secret.""" token, created = self.get_or_create(consumer=consumer, token_type=token_type, timestamp=timestamp, scope=scope, user=user, callback=callback, callback_confirmed=callback_confirmed) if created: token.generate_random_codes() return token david-django-oauth-plus-91f6df5e8a28/oauth_provider/migrations/0001_initial.py0000644000000000000000000002354312251631323025342 0ustar 00000000000000# encoding: utf-8 import datetime from south.db import db from south.v2 import SchemaMigration from oauth_provider.compat import AUTH_USER_MODEL from django.db import models class Migration(SchemaMigration): def forwards(self, orm): # Adding model 'Nonce' db.create_table('oauth_provider_nonce', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('token_key', self.gf('django.db.models.fields.CharField')(max_length=32)), ('consumer_key', self.gf('django.db.models.fields.CharField')(max_length=256)), ('key', self.gf('django.db.models.fields.CharField')(max_length=255)), )) db.send_create_signal('oauth_provider', ['Nonce']) # Adding model 'Resource' db.create_table('oauth_provider_resource', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('name', self.gf('django.db.models.fields.CharField')(max_length=255)), ('url', self.gf('django.db.models.fields.TextField')(max_length=2083)), ('is_readonly', self.gf('django.db.models.fields.BooleanField')(default=True)), )) db.send_create_signal('oauth_provider', ['Resource']) # Adding model 'Consumer' db.create_table('oauth_provider_consumer', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('name', self.gf('django.db.models.fields.CharField')(max_length=255)), ('description', self.gf('django.db.models.fields.TextField')()), ('key', self.gf('django.db.models.fields.CharField')(max_length=256)), ('secret', self.gf('django.db.models.fields.CharField')(max_length=16, blank=True)), ('status', self.gf('django.db.models.fields.SmallIntegerField')(default=1)), ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm[AUTH_USER_MODEL], null=True, blank=True)), )) db.send_create_signal('oauth_provider', ['Consumer']) # Adding model 'Token' db.create_table('oauth_provider_token', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('key', self.gf('django.db.models.fields.CharField')(max_length=32, null=True, blank=True)), ('secret', self.gf('django.db.models.fields.CharField')(max_length=16, null=True, blank=True)), ('token_type', self.gf('django.db.models.fields.SmallIntegerField')()), ('timestamp', self.gf('django.db.models.fields.IntegerField')(default=1327884735L)), ('is_approved', self.gf('django.db.models.fields.BooleanField')(default=False)), ('user', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='tokens', null=True, to=orm[AUTH_USER_MODEL])), ('consumer', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['oauth_provider.Consumer'])), ('resource', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['oauth_provider.Resource'])), ('verifier', self.gf('django.db.models.fields.CharField')(max_length=10)), ('callback', self.gf('django.db.models.fields.CharField')(max_length=2083, null=True, blank=True)), ('callback_confirmed', self.gf('django.db.models.fields.BooleanField')(default=False)), )) db.send_create_signal('oauth_provider', ['Token']) def backwards(self, orm): # Deleting model 'Nonce' db.delete_table('oauth_provider_nonce') # Deleting model 'Resource' db.delete_table('oauth_provider_resource') # Deleting model 'Consumer' db.delete_table('oauth_provider_consumer') # Deleting model 'Token' db.delete_table('oauth_provider_token') models = { 'auth.group': { 'Meta': {'object_name': 'Group'}, 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) }, 'auth.permission': { 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, AUTH_USER_MODEL: { 'Meta': {'object_name': AUTH_USER_MODEL.split('.')[-1]}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, 'contenttypes.contenttype': { 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, 'oauth_provider.consumer': { 'Meta': {'object_name': 'Consumer'}, 'description': ('django.db.models.fields.TextField', [], {}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '256'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'secret': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % AUTH_USER_MODEL, 'null': 'True', 'blank': 'True'}) }, 'oauth_provider.nonce': { 'Meta': {'object_name': 'Nonce'}, 'consumer_key': ('django.db.models.fields.CharField', [], {'max_length': '256'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'token_key': ('django.db.models.fields.CharField', [], {'max_length': '32'}) }, 'oauth_provider.resource': { 'Meta': {'object_name': 'Resource'}, 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_readonly': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'url': ('django.db.models.fields.TextField', [], {'max_length': '2083'}) }, 'oauth_provider.token': { 'Meta': {'object_name': 'Token'}, 'callback': ('django.db.models.fields.CharField', [], {'max_length': '2083', 'null': 'True', 'blank': 'True'}), 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oauth_provider.Consumer']"}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), 'resource': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oauth_provider.Resource']"}), 'secret': ('django.db.models.fields.CharField', [], {'max_length': '16', 'null': 'True', 'blank': 'True'}), 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1327884735L'}), 'token_type': ('django.db.models.fields.SmallIntegerField', [], {}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': "orm['%s']" % AUTH_USER_MODEL}), 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'}) } } complete_apps = ['oauth_provider'] ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000david-django-oauth-plus-91f6df5e8a28/oauth_provider/migrations/0002_auto__add_field_consumer_xauth_allowed.pydavid-django-oauth-plus-91f6df5e8a28/oauth_provider/migrations/0002_auto__add_field_consumer_xauth_a0000644000000000000000000001537312251631323031773 0ustar 00000000000000# encoding: utf-8 import datetime from south.db import db from south.v2 import SchemaMigration from django.db import models from oauth_provider.consts import SECRET_SIZE class Migration(SchemaMigration): def forwards(self, orm): # Adding field 'Consumer.xauth_allowed' db.add_column('oauth_provider_consumer', 'xauth_allowed', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) def backwards(self, orm): # Deleting field 'Consumer.xauth_allowed' db.delete_column('oauth_provider_consumer', 'xauth_allowed') models = { 'auth.group': { 'Meta': {'object_name': 'Group'}, 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) }, 'auth.permission': { 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, 'auth.user': { 'Meta': {'object_name': 'User'}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, 'contenttypes.contenttype': { 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, 'oauth_provider.consumer': { 'Meta': {'object_name': 'Consumer'}, 'description': ('django.db.models.fields.TextField', [], {}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '256'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'secret': ('django.db.models.fields.CharField', [], {'max_length': str(SECRET_SIZE), 'blank': 'True'}), 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), 'xauth_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) }, 'oauth_provider.nonce': { 'Meta': {'object_name': 'Nonce'}, 'consumer_key': ('django.db.models.fields.CharField', [], {'max_length': '256'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'token_key': ('django.db.models.fields.CharField', [], {'max_length': '32'}) }, 'oauth_provider.resource': { 'Meta': {'object_name': 'Resource'}, 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_readonly': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'url': ('django.db.models.fields.TextField', [], {'max_length': '2083'}) }, 'oauth_provider.token': { 'Meta': {'object_name': 'Token'}, 'callback': ('django.db.models.fields.CharField', [], {'max_length': '2083', 'null': 'True', 'blank': 'True'}), 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oauth_provider.Consumer']"}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), 'resource': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oauth_provider.Resource']"}), 'secret': ('django.db.models.fields.CharField', [], {'max_length': str(SECRET_SIZE), 'null': 'True', 'blank': 'True'}), 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1327884847L'}), 'token_type': ('django.db.models.fields.SmallIntegerField', [], {}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': "orm['auth.User']"}), 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'}) } } complete_apps = ['oauth_provider'] ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000david-django-oauth-plus-91f6df5e8a28/oauth_provider/migrations/0003_auto__add_field_nonce_timestamp.pydavid-django-oauth-plus-91f6df5e8a28/oauth_provider/migrations/0003_auto__add_field_nonce_timestamp.0000644000000000000000000001574312251631323031674 0ustar 00000000000000# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration from django.db import models from oauth_provider.compat import AUTH_USER_MODEL class Migration(SchemaMigration): def forwards(self, orm): # Adding field 'Nonce.timestamp' db.add_column(u'oauth_provider_nonce', 'timestamp', self.gf('django.db.models.fields.PositiveIntegerField')(default=1375699511, db_index=True), keep_default=False) def backwards(self, orm): # Deleting field 'Nonce.timestamp' db.delete_column(u'oauth_provider_nonce', 'timestamp') models = { u'auth.group': { 'Meta': {'object_name': 'Group'}, u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) }, u'auth.permission': { 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, u'%s' % AUTH_USER_MODEL: { 'Meta': {'object_name': AUTH_USER_MODEL.split('.')[-1]}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, u'contenttypes.contenttype': { 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, u'oauth_provider.consumer': { 'Meta': {'object_name': 'Consumer'}, 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '256'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'secret': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['%s']" % AUTH_USER_MODEL, 'null': 'True', 'blank': 'True'}), 'xauth_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) }, u'oauth_provider.nonce': { 'Meta': {'object_name': 'Nonce'}, 'consumer_key': ('django.db.models.fields.CharField', [], {'max_length': '256'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'timestamp': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), 'token_key': ('django.db.models.fields.CharField', [], {'max_length': '32'}) }, u'oauth_provider.resource': { 'Meta': {'object_name': 'Resource'}, u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_readonly': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'url': ('django.db.models.fields.TextField', [], {'max_length': '2083'}) }, u'oauth_provider.token': { 'Meta': {'object_name': 'Token'}, 'callback': ('django.db.models.fields.CharField', [], {'max_length': '2083', 'null': 'True', 'blank': 'True'}), 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['oauth_provider.Consumer']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), 'resource': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['oauth_provider.Resource']"}), 'secret': ('django.db.models.fields.CharField', [], {'max_length': '16', 'null': 'True', 'blank': 'True'}), 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1375699483L'}), 'token_type': ('django.db.models.fields.SmallIntegerField', [], {}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['%s']" % AUTH_USER_MODEL}), 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'}) } } complete_apps = ['oauth_provider']david-django-oauth-plus-91f6df5e8a28/oauth_provider/migrations/0004_resource_to_scope.py0000644000000000000000000001604012251631323027430 0ustar 00000000000000# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration from django.db import models from oauth_provider.compat import AUTH_USER_MODEL class Migration(SchemaMigration): def forwards(self, orm): db.rename_table(u'oauth_provider_resource', u'oauth_provider_scope') db.rename_column(u'oauth_provider_token', u'resource_id', u'scope_id') db.send_create_signal(u'oauth_provider', [u'Scope']) def backwards(self, orm): db.rename_table(u'oauth_provider_scope', u'oauth_provider_resource') db.rename_column(u'oauth_provider_token', u'scope_id', u'resource_id') db.send_create_signal(u'oauth_provider', [u'Resource']) models = { u'auth.group': { 'Meta': {'object_name': 'Group'}, u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) }, u'auth.permission': { 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, u'%s' % AUTH_USER_MODEL: { 'Meta': {'object_name': AUTH_USER_MODEL.split('.')[-1]}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, u'contenttypes.contenttype': { 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, u'oauth_provider.consumer': { 'Meta': {'object_name': 'Consumer'}, 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '256'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'secret': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['%s']" % AUTH_USER_MODEL, 'null': 'True', 'blank': 'True'}), 'xauth_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) }, u'oauth_provider.nonce': { 'Meta': {'object_name': 'Nonce'}, 'consumer_key': ('django.db.models.fields.CharField', [], {'max_length': '256'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'timestamp': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), 'token_key': ('django.db.models.fields.CharField', [], {'max_length': '32'}) }, u'oauth_provider.scope': { 'Meta': {'object_name': 'Scope'}, u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_readonly': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'url': ('django.db.models.fields.TextField', [], {'max_length': '2083'}) }, u'oauth_provider.token': { 'Meta': {'object_name': 'Token'}, 'callback': ('django.db.models.fields.CharField', [], {'max_length': '2083', 'null': 'True', 'blank': 'True'}), 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['oauth_provider.Consumer']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['oauth_provider.Scope']"}), 'secret': ('django.db.models.fields.CharField', [], {'max_length': '16', 'null': 'True', 'blank': 'True'}), 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1382371788L'}), 'token_type': ('django.db.models.fields.SmallIntegerField', [], {}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['%s']" % AUTH_USER_MODEL}), 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'}) }, } complete_apps = ['oauth_provider']david-django-oauth-plus-91f6df5e8a28/oauth_provider/migrations/0005_auto__chg_field_token_scope.py0000644000000000000000000001603112251631323031373 0ustar 00000000000000# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration from django.db import models from oauth_provider.compat import AUTH_USER_MODEL class Migration(SchemaMigration): def forwards(self, orm): # Changing field 'Token.scope' db.alter_column(u'oauth_provider_token', 'scope_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['oauth_provider.Scope'], null=True)) def backwards(self, orm): # Changing field 'Token.scope' db.alter_column(u'oauth_provider_token', 'scope_id', self.gf('django.db.models.fields.related.ForeignKey')(default=0, to=orm['oauth_provider.Scope'])) models = { u'auth.group': { 'Meta': {'object_name': 'Group'}, u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) }, u'auth.permission': { 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, u'%s' % AUTH_USER_MODEL: { 'Meta': {'object_name': AUTH_USER_MODEL.split('.')[-1]}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, u'contenttypes.contenttype': { 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, u'oauth_provider.consumer': { 'Meta': {'object_name': 'Consumer'}, 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '256'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'secret': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['%s']" % AUTH_USER_MODEL, 'null': 'True', 'blank': 'True'}), 'xauth_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) }, u'oauth_provider.nonce': { 'Meta': {'object_name': 'Nonce'}, 'consumer_key': ('django.db.models.fields.CharField', [], {'max_length': '256'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'timestamp': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), 'token_key': ('django.db.models.fields.CharField', [], {'max_length': '32'}) }, u'oauth_provider.scope': { 'Meta': {'object_name': 'Scope'}, u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_readonly': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'url': ('django.db.models.fields.TextField', [], {'max_length': '2083'}) }, u'oauth_provider.token': { 'Meta': {'object_name': 'Token'}, 'callback': ('django.db.models.fields.CharField', [], {'max_length': '2083', 'null': 'True', 'blank': 'True'}), 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['oauth_provider.Consumer']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['oauth_provider.Scope']", 'null': 'True', 'blank': 'True'}), 'secret': ('django.db.models.fields.CharField', [], {'max_length': '16', 'null': 'True', 'blank': 'True'}), 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1382376977L'}), 'token_type': ('django.db.models.fields.SmallIntegerField', [], {}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to':u"orm['%s']" % AUTH_USER_MODEL}), 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'}) }, } complete_apps = ['oauth_provider']david-django-oauth-plus-91f6df5e8a28/oauth_provider/migrations/__init__.py0000644000000000000000000000000012251631323024767 0ustar 00000000000000david-django-oauth-plus-91f6df5e8a28/oauth_provider/models.py0000644000000000000000000001271412251631323022356 0ustar 00000000000000import uuid import urllib import urlparse from time import time import warnings import oauth2 as oauth from django.db import models from oauth_provider.compat import AUTH_USER_MODEL, get_random_string from oauth_provider.managers import TokenManager from oauth_provider.consts import KEY_SIZE, SECRET_SIZE, CONSUMER_KEY_SIZE, CONSUMER_STATES,\ PENDING, VERIFIER_SIZE, MAX_URL_LENGTH, OUT_OF_BAND from oauth_provider.utils import check_valid_callback class Nonce(models.Model): token_key = models.CharField(max_length=KEY_SIZE) consumer_key = models.CharField(max_length=CONSUMER_KEY_SIZE) key = models.CharField(max_length=255) timestamp = models.PositiveIntegerField(db_index=True) def __unicode__(self): return u"Nonce %s for %s" % (self.key, self.consumer_key) class Scope(models.Model): name = models.CharField(max_length=255) url = models.TextField(max_length=MAX_URL_LENGTH) is_readonly = models.BooleanField(default=True) def __unicode__(self): return u"Resource %s with url %s" % (self.name, self.url) class Resource(Scope): def __init__(self, *args, **kwargs): warnings.warn("oauth_provider.Resource model is deprecated, use oauth_provider.Scope instead", DeprecationWarning) super(Resource, self).__init__(*args, **kwargs) class Meta: proxy = True class Consumer(models.Model): name = models.CharField(max_length=255) description = models.TextField(blank=True) key = models.CharField(max_length=CONSUMER_KEY_SIZE) secret = models.CharField(max_length=SECRET_SIZE, blank=True) status = models.SmallIntegerField(choices=CONSUMER_STATES, default=PENDING) user = models.ForeignKey(AUTH_USER_MODEL, null=True, blank=True) xauth_allowed = models.BooleanField("Allow xAuth", default = False) def __unicode__(self): return u"Consumer %s with key %s" % (self.name, self.key) def generate_random_codes(self): """ Used to generate random key/secret pairings. Use this after you've added the other data in place of save(). """ self.key = uuid.uuid4().hex self.secret = get_random_string(length=SECRET_SIZE) self.save() class Token(models.Model): REQUEST = 1 ACCESS = 2 TOKEN_TYPES = ((REQUEST, u'Request'), (ACCESS, u'Access')) key = models.CharField(max_length=KEY_SIZE, null=True, blank=True) secret = models.CharField(max_length=SECRET_SIZE, null=True, blank=True) token_type = models.SmallIntegerField(choices=TOKEN_TYPES) timestamp = models.IntegerField(default=long(time())) is_approved = models.BooleanField(default=False) user = models.ForeignKey(AUTH_USER_MODEL, null=True, blank=True, related_name='tokens') consumer = models.ForeignKey(Consumer) scope = models.ForeignKey(Scope, null=True, blank=True) @property def resource(self): return self.scope @resource.setter def resource(self, value): self.scope = value ## OAuth 1.0a stuff verifier = models.CharField(max_length=VERIFIER_SIZE) callback = models.CharField(max_length=MAX_URL_LENGTH, null=True, blank=True) callback_confirmed = models.BooleanField(default=False) objects = TokenManager() def __unicode__(self): return u"%s Token %s for %s" % (self.get_token_type_display(), self.key, self.consumer) def to_string(self, only_key=False): token_dict = { 'oauth_token': self.key, 'oauth_token_secret': self.secret, 'oauth_callback_confirmed': self.callback_confirmed and 'true' or 'error' } if self.verifier: token_dict['oauth_verifier'] = self.verifier if only_key: del token_dict['oauth_token_secret'] del token_dict['oauth_callback_confirmed'] return urllib.urlencode(token_dict) def generate_random_codes(self): """ Used to generate random key/secret pairings. Use this after you've added the other data in place of save(). """ self.key = uuid.uuid4().hex self.secret = get_random_string(length=SECRET_SIZE) self.save() def get_callback_url(self, args=None): """ OAuth 1.0a, append the oauth_verifier. """ if self.callback and self.verifier: parts = urlparse.urlparse(self.callback) scheme, netloc, path, params, query, fragment = parts[:6] if query: query = '%s&oauth_verifier=%s' % (query, self.verifier) else: query = 'oauth_verifier=%s' % self.verifier # workaround for non-http scheme urlparse problem in py2.6 (issue #2) if "?" in path: query = "%s&%s" % (path.split("?")[-1], query) path = "?".join(path[:-1]) if args is not None: query += "&%s" % urllib.urlencode(args) return urlparse.urlunparse((scheme, netloc, path, params, query, fragment)) args = args is not None and "?%s" % urllib.urlencode(args) or "" return self.callback and self.callback + args def set_callback(self, callback): if callback != OUT_OF_BAND: # out of band, says "we can't do this!" if check_valid_callback(callback): self.callback = callback self.callback_confirmed = True self.save() else: raise oauth.Error('Invalid callback URL.') david-django-oauth-plus-91f6df5e8a28/oauth_provider/responses.py0000644000000000000000000000107712251631323023114 0ustar 00000000000000# -*- coding: utf-8 -*- from django.utils.translation import ugettext as _ from django.http import HttpResponseBadRequest import oauth2 as oauth from oauth_provider.utils import send_oauth_error INVALID_PARAMS_RESPONSE = send_oauth_error(oauth.Error(_('Invalid request parameters.'))) INVALID_CONSUMER_RESPONSE = HttpResponseBadRequest('Invalid Consumer.') INVALID_SCOPE_RESPONSE = send_oauth_error(oauth.Error(_('You are not allowed to access this resource.'))) COULD_NOT_VERIFY_OAUTH_REQUEST_RESPONSE = send_oauth_error(oauth.Error(_('Could not verify OAuth request.')))david-django-oauth-plus-91f6df5e8a28/oauth_provider/runtests/__init__.py0000644000000000000000000000000012251631323024502 0ustar 00000000000000david-django-oauth-plus-91f6df5e8a28/oauth_provider/runtests/manage.py0000755000000000000000000000122012251631323024203 0ustar 00000000000000#!/usr/bin/env python # put django-oauth in PYTHONPATH import sys, os sys.path = [os.path.join(os.getcwd(), '../../')] + sys.path from django.core.management import execute_manager try: import settings # Assumed to be in the same directory. except ImportError: import sys sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) sys.exit(1) if __name__ == "__main__": execute_manager(settings) david-django-oauth-plus-91f6df5e8a28/oauth_provider/runtests/runtests.py0000755000000000000000000000221712251631323024651 0ustar 00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # https://github.com/swistakm/django-rest-framework/blob/master/rest_framework/runtests/runtests.py import os import sys # fix sys path so we don't need to setup PYTHONPATH sys.path.append(os.path.join(os.path.dirname(__file__), "../..")) os.environ['DJANGO_SETTINGS_MODULE'] = 'oauth_provider.runtests.settings' from django.conf import settings from django.test.utils import get_runner from south.management.commands import patch_for_test_db_setup def usage(): return """ Usage: python runtests.py [UnitTestClass].[method] You can pass the Class name of the `UnitTestClass` you want to test. Append a method name if you only want to test a specific method of that class. """ def main(): TestRunner = get_runner(settings) test_runner = TestRunner(verbosity=2) if len(sys.argv) == 2: test_case = '.' + sys.argv[1] elif len(sys.argv) == 1: test_case = '' else: print(usage()) sys.exit(1) patch_for_test_db_setup() failures = test_runner.run_tests(['tests' + test_case]) sys.exit(failures) if __name__ == '__main__': main() david-django-oauth-plus-91f6df5e8a28/oauth_provider/runtests/settings.py0000644000000000000000000000405712251631323024623 0ustar 00000000000000import os ROOT_PATH = os.path.dirname(__file__) TEMPLATE_DEBUG = DEBUG = True MANAGERS = ADMINS = () DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 'NAME': 'testdb.sqlite', # Or path to database file if using sqlite3. 'USER': '', # Not used with sqlite3. 'PASSWORD': '', # Not used with sqlite3. 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 'PORT': '', # Set to empty string for default. Not used with sqlite3. } } TIME_ZONE = 'America/Chicago' LANGUAGE_CODE = 'en-us' SITE_ID = 1 USE_I18N = True MEDIA_ROOT = '' MEDIA_URL = '' ADMIN_MEDIA_PREFIX = '/media/' SECRET_KEY = '2+@4vnr#v8e273^+a)g$8%dre^dwcn#d&n#8+l6jk7r#$p&3zk' TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', ) AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', 'oauth_provider.backends.XAuthAuthenticationBackend', ) MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', ) ROOT_URLCONF = 'urls' TEMPLATE_DIRS = (os.path.join(ROOT_PATH, 'templates'),) INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'south', 'oauth_provider', 'oauth_provider.tests' ) OAUTH_UNSAFE_REDIRECTS = True OAUTH_NONCE_VALID_PERIOD = 120 import django if django.VERSION >= (1, 5): # custom user model for tests issue #22 INSTALLED_APPS += ('test_app',) AUTH_USER_MODEL = 'test_app.TestUser' try: import xmlrunner except ImportError: pass else: TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner' TEST_OUTPUT_VERBOSE = True TEST_OUTPUT_DESCRIPTIONS = True TEST_OUTPUT_DIR = 'junitxml'david-django-oauth-plus-91f6df5e8a28/oauth_provider/runtests/test_app/__init__.py0000644000000000000000000000002712251631323026332 0ustar 00000000000000# -*- coding: utf-8 -*-david-django-oauth-plus-91f6df5e8a28/oauth_provider/runtests/test_app/models.py0000644000000000000000000000016412251631323026060 0ustar 00000000000000# -*- coding: utf-8 -*- from django.contrib.auth.models import AbstractUser class TestUser(AbstractUser): pass david-django-oauth-plus-91f6df5e8a28/oauth_provider/runtests/urls.py0000644000000000000000000000131412251631323023741 0ustar 00000000000000from django.http import HttpResponse from oauth_provider.compat import url, patterns, include from oauth_provider.decorators import oauth_required from oauth_provider.views import protected_resource_example @oauth_required("some") def resource_some_scope_view(request): return HttpResponse() @oauth_required def resource_None_scope_view(request): return HttpResponse() urlpatterns = patterns('', url(r'^oauth/', include('oauth_provider.urls')), url(r'^oauth/photo/$', protected_resource_example, name='oauth_example'), url(r'^oauth/some/$', resource_some_scope_view, name='oauth_resource_some_scope'), url(r'^oauth/none/$', resource_None_scope_view, name='oauth_resource_None_scope'), ) david-django-oauth-plus-91f6df5e8a28/oauth_provider/store/__init__.py0000644000000000000000000001423012251631323023761 0ustar 00000000000000from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.utils import importlib class Error(Exception): """Base class for Store exceptions.""" class InvalidConsumerError(Error): """Invalid consumer.""" class InvalidTokenError(Error): """Invalid token.""" class Store(object): """ The Store class is the backbone of piston's OAuth implementation. It is used by the views and the authentication backend to get consumers and tokens, and to create tokens. The following terms are used in the documentation of the API: Consumer: A class defining at minimum `key` and `secret` attributes. Both of these attributes must be either str or unicode. Token: A class defining at minimum `key` and `secret` attributes. Both of these attributes must be either str or unicode. User: A `django.contrib.auth.models.User` instance. Any API that takes a consumer or token will be passed a Consumer or Token instance it itself returned at an earlier stage from one of the methods that take a key and return a Consumer or Token. This means if your store implementation uses tokens that keep a reference to its Consumer on the Token itself, `get_consumer_for_request_token` can simply return `request_token.consumer`. """ def get_consumer(self, request, oauth_request, consumer_key): """ Return the Consumer for `consumer_key` or raise `InvalidConsumerError`. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `consumer_key`: The consumer key. """ raise NotImplementedError def get_consumer_for_request_token(self, request, oauth_request, request_token): """ Return the Consumer associated with the `request_token` Token. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `request_token`: The request token to get the consumer for. """ raise NotImplementedError def get_consumer_for_access_token(self, request, oauth_request, access_token): """ Return the Consumer associated with the `access_token` Token. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `access_token`: The access Token to get the consumer for. """ raise NotImplementedError def create_request_token(self, request, oauth_request, consumer, callback): """ Generate and return a Token. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `consumer`: The Consumer that made the request. """ raise NotImplementedError def get_request_token(self, request, oauth_request, request_token_key): """ Return the Token for `request_token_key` or raise `InvalidTokenError`. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `consumer`: The Consumer that made the request. `request_token_key`: The request token key. """ raise NotImplementedError def authorize_request_token(self, request, oauth_request, request_token): """ Authorize the `request_token` Token and return it. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `request_token`: The request token to authorize. """ raise NotImplementedError def create_access_token(self, request, oauth_request, consumer, request_token): """ Generate and return a Token. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `consumer`: The Consumer that made the request. `request_token`: The Token used to make the request. """ raise NotImplementedError def get_access_token(self, request, oauth_request, consumer, access_token_key): """ Return the Token for `access_token_key` or raise `InvalidTokenError`. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `consumer`: The Consumer that made the request. `access_token_key`: The token key used to make the request. """ raise NotImplementedError def get_user_for_access_token(self, request, oauth_request, access_token): """ Return the associated User for `access_token`. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `consumer`: The Consumer that made the request. `access_token`: The Token used to make the request. """ raise NotImplementedError def get_user_for_consumer(self, request, oauth_request, consumer): """ Return the associated User for `consumer`. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `consumer`: The Consumer that made the request. """ raise NotImplementedError def check_nonce(self, request, oauth_request, nonce, timestamp): """ Return `True` if the nonce has not yet been used, `False` otherwise. `request`: The Django request object. `oauth_request`: The `oauth2.Request` object. `nonce`: The nonce to check. `timestamp`: nonce timestamp. """ raise NotImplementedError def get_store(path='oauth_provider.store.db.ModelStore'): """ Load the oauth store. Should not be called directly unless testing. """ path = getattr(settings, 'OAUTH_STORE', path) try: module, attr = path.rsplit('.', 1) store_class = getattr(importlib.import_module(module), attr) except ValueError: raise ImproperlyConfigured('Invalid oauth store string: "%s"' % path) except ImportError, e: raise ImproperlyConfigured('Error loading oauth store module "%s": "%s"' % (module, e)) except AttributeError: raise ImproperlyConfigured('Module "%s" does not define an oauth store named "%s"' % (module, attr)) return store_class() store = get_store() david-django-oauth-plus-91f6df5e8a28/oauth_provider/store/db.py0000644000000000000000000000711512251631323022613 0ustar 00000000000000import oauth2 as oauth from django.conf import settings from oauth_provider.compat import now from oauth_provider.store import InvalidConsumerError, InvalidTokenError, Store from oauth_provider.models import Nonce, Token, Consumer, Scope, VERIFIER_SIZE NONCE_VALID_PERIOD = getattr(settings, "OAUTH_NONCE_VALID_PERIOD", None) class ModelStore(Store): """ Store implementation using the Django models defined in `piston.models`. """ def get_consumer(self, request, oauth_request, consumer_key): try: return Consumer.objects.get(key=consumer_key) except Consumer.DoesNotExist: raise InvalidConsumerError() def get_consumer_for_request_token(self, request, oauth_request, request_token): return request_token.consumer def get_consumer_for_access_token(self, request, oauth_request, access_token): return access_token.consumer def create_request_token(self, request, oauth_request, consumer, callback): try: scope = Scope.objects.get(name=oauth_request.get_parameter('scope')) except oauth.Error: # oauth.Error means that scope wasn't specified scope = None except Scope.DoesNotExist: # Scope.DoesNotExist means that specified scope doesn't exist in db raise oauth.Error('Scope does not exist.') token = Token.objects.create_token( token_type=Token.REQUEST, consumer=Consumer.objects.get(key=oauth_request['oauth_consumer_key']), timestamp=oauth_request['oauth_timestamp'], scope=scope, ) token.set_callback(callback) token.save() return token def get_request_token(self, request, oauth_request, request_token_key): try: return Token.objects.get(key=request_token_key, token_type=Token.REQUEST) except Token.DoesNotExist: raise InvalidTokenError() def authorize_request_token(self, request, oauth_request, request_token): request_token.is_approved = True request_token.user = request.user request_token.verifier = oauth.generate_verifier(VERIFIER_SIZE) request_token.save() return request_token def create_access_token(self, request, oauth_request, consumer, request_token): scope = request_token.scope access_token = Token.objects.create_token( token_type=Token.ACCESS, timestamp=oauth_request['oauth_timestamp'], consumer=Consumer.objects.get(key=consumer.key), user=request_token.user, scope=scope, ) request_token.delete() return access_token def get_access_token(self, request, oauth_request, consumer, access_token_key): try: return Token.objects.get(key=access_token_key, token_type=Token.ACCESS) except Token.DoesNotExist: raise InvalidTokenError() def get_user_for_access_token(self, request, oauth_request, access_token): return access_token.user def get_user_for_consumer(self, request, oauth_request, consumer): return consumer.user def check_nonce(self, request, oauth_request, nonce, timestamp=0): timestamp = int(timestamp) if NONCE_VALID_PERIOD and int(now().strftime("%s")) - timestamp > NONCE_VALID_PERIOD: return False nonce, created = Nonce.objects.get_or_create( consumer_key=oauth_request['oauth_consumer_key'], token_key=oauth_request.get('oauth_token', ''), key=nonce, timestamp=timestamp, ) return created david-django-oauth-plus-91f6df5e8a28/oauth_provider/tests/__init__.py0000644000000000000000000000002712251631323023766 0ustar 00000000000000# -*- coding: utf-8 -*-david-django-oauth-plus-91f6df5e8a28/oauth_provider/tests/auth.py0000644000000000000000000001476012251631323023201 0ustar 00000000000000# -*- coding: utf-8 -*- import time import urllib import re from urlparse import parse_qs, urlparse from django.test import TestCase, Client import oauth2 from oauth_provider.models import Scope, Consumer, Token from oauth_provider.compat import get_user_model User = get_user_model() METHOD_AUTHORIZATION_HEADER = 0 METHOD_POST_REQUEST_BODY = 1 METHOD_URL_QUERY = 2 class BaseOAuthTestCase(TestCase): def setUp(self): self.username = 'jane' self.password = 'toto' self.email = 'jane@example.com' self.jane = User.objects.create_user(self.username, self.email, self.password) self.scope = Scope.objects.create(name='photos', url='/oauth/photo/') self.CONSUMER_KEY = 'dpf43f3p2l4k3l03' self.CONSUMER_SECRET = 'kd94hf93k423kf44' consumer = self.consumer = Consumer(key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET, name='printer.example.com', user=self.jane) consumer.save() self.callback_token = self.callback = 'http://printer.example.com/request_token_ready' self.callback_confirmed = True self.c = Client() def _request_token(self, method=METHOD_URL_QUERY, **parameters_overriden): # The Consumer sends the following HTTP POST request to the # Service Provider: parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_signature_method': 'PLAINTEXT', 'oauth_signature': '%s&' % self.CONSUMER_SECRET, 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': 'requestnonce', 'oauth_version': '1.0', 'oauth_callback': self.callback, # 'scope': self.scope.name, # custom argument to specify Protected Resource } parameters.update(parameters_overriden) if method==METHOD_AUTHORIZATION_HEADER: header = self._get_http_authorization_header(parameters) response = self.c.get("/oauth/request_token/", HTTP_AUTHORIZATION=header) elif method==METHOD_URL_QUERY: response = self.c.get("/oauth/request_token/", parameters) elif method==METHOD_POST_REQUEST_BODY: body = urllib.urlencode(parameters) response = self.c.post("/oauth/request_token/", body, content_type="application/x-www-form-urlencoded") else: raise NotImplementedError if response.status_code != 200: print response self.assertEqual(response.status_code, 200) self.assert_( re.match(r'oauth_token_secret=[^&]+&oauth_token=[^&]+&oauth_callback_confirmed=true', response.content )) token = self.request_token = list(Token.objects.all())[-1] self.assert_(token.key in response.content) self.assert_(token.secret in response.content) self.assert_(not self.request_token.is_approved) return response def _authorize_and_access_token_using_form(self, method=METHOD_URL_QUERY): self.c.login(username=self.username, password=self.password) parameters = self.authorization_parameters = {'oauth_token': self.request_token.key} response = self.c.get("/oauth/authorize/", parameters) self.assertEqual(response.status_code, 200) # fill form (authorize us) parameters['authorize_access'] = 1 response = self.c.post("/oauth/authorize/", parameters) self.assertEqual(response.status_code, 302) # finally access authorized access_token oauth_verifier = parse_qs(urlparse(response['Location']).query)['oauth_verifier'][0] # logout to ensure that will not authorize with session self.c.logout() self._access_token(oauth_verifier=oauth_verifier, oauth_token=self.request_token.key) def _access_token(self, method=METHOD_URL_QUERY, **parameters_overriden): if hasattr(self, 'request_token'): oauth_signature = "%s&%s" % (self.CONSUMER_SECRET, self.request_token.secret) else: oauth_signature = "%s&" % (self.CONSUMER_SECRET) parameters = { 'oauth_signature_method': 'PLAINTEXT', 'oauth_signature': oauth_signature, 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': "12981230918711", 'oauth_version': '1.0', 'scope': self.scope.name, # custom argument to specify Protected Resource } parameters.update(parameters_overriden) if method==METHOD_AUTHORIZATION_HEADER: header = self._get_http_authorization_header(parameters) response = self.c.get("/oauth/access_token/", HTTP_AUTHORIZATION=header) elif method==METHOD_URL_QUERY: response = self.c.get("/oauth/access_token/", parameters) elif method==METHOD_POST_REQUEST_BODY: body = urllib.urlencode(parameters) response = self.c.post("/oauth/access_token/", body, content_type="application/x-www-form-urlencoded") else: raise NotImplementedError self.assertEqual(response.status_code, 200) response_params = parse_qs(response.content) self.ACCESS_TOKEN_KEY = response_params['oauth_token'][0] self.ACCESS_TOKEN_SECRET = response_params['oauth_token_secret'][0] def _get_http_authorization_header(self, parameters): HEADERS = oauth2.Request("GET", parameters=parameters).to_header() authorization_header = HEADERS["Authorization"] # patch header with scope authorization_header += ", scope=%s" % self.scope.name return authorization_header class TestOAuthDifferentAuthorizationMethods(BaseOAuthTestCase): def test_request_token_with_authorization_header(self): self._request_token(METHOD_AUTHORIZATION_HEADER) def test_request_token_with_url_query(self): self._request_token(METHOD_URL_QUERY) def test_request_token_with_post_request_body(self): self._request_token(METHOD_POST_REQUEST_BODY) def test_access_token_with_authorization_header(self): self._request_token(METHOD_AUTHORIZATION_HEADER) self._authorize_and_access_token_using_form(METHOD_AUTHORIZATION_HEADER) def test_access_token_with_url_query(self): self._request_token(METHOD_URL_QUERY) self._authorize_and_access_token_using_form(METHOD_URL_QUERY) def test_access_token_with_post_request_body(self): self._request_token(METHOD_POST_REQUEST_BODY) self._authorize_and_access_token_using_form(METHOD_POST_REQUEST_BODY)david-django-oauth-plus-91f6df5e8a28/oauth_provider/tests/compat.py0000644000000000000000000000074112251631323023515 0ustar 00000000000000# -*- coding: utf-8 -*- from django.test import TestCase class Issue45ErrorLoadingOauthStoreModule(TestCase): def test_store_import(self): from oauth_provider.store import store self.assertIsNotNone(store) def test_import_user_from_compat(self): from oauth_provider.compat import get_user_model from oauth_provider.compat import AUTH_USER_MODEL self.assertIsNotNone(get_user_model()) self.assertIsNotNone(AUTH_USER_MODEL)david-django-oauth-plus-91f6df5e8a28/oauth_provider/tests/decorators.py0000644000000000000000000001047112251631323024400 0ustar 00000000000000## -*- coding: utf-8 -*- from pprint import pprint import time import urllib from oauth_provider.models import Scope from oauth_provider.tests.auth import BaseOAuthTestCase, METHOD_POST_REQUEST_BODY, METHOD_AUTHORIZATION_HEADER, METHOD_URL_QUERY class OAuthTestOauthRequiredDecorator(BaseOAuthTestCase): def setUp(self): # create Scope 'all' for all requests without scope specified super(OAuthTestOauthRequiredDecorator, self).setUp() def _oauth_signed_get(self, url, method=METHOD_URL_QUERY): parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_signature_method': "PLAINTEXT", 'oauth_version': "1.0", 'oauth_token': self.ACCESS_TOKEN_KEY, 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': str(int(time.time()))+"nonce", 'oauth_signature': "%s&%s" % (self.CONSUMER_SECRET, self.ACCESS_TOKEN_SECRET), "additional_data": "whoop", # some additional data } if method==METHOD_AUTHORIZATION_HEADER: header = self._get_http_authorization_header(parameters) response = self.c.get(url, HTTP_AUTHORIZATION=header) elif method==METHOD_URL_QUERY: response = self.c.get(url, parameters) elif method==METHOD_POST_REQUEST_BODY: body = urllib.urlencode(parameters) response = self.c.post(url, body, content_type="application/x-www-form-urlencoded") else: raise NotImplementedError return response def test_resource_some_scope_view_authorized(self): """Tests view that was created using @oauth_required("some") decorator """ #ensure there is a Scope object for this scope self.scope = Scope.objects.create(name="some") #set scope for requested token self._request_token(scope=self.scope.name) self._authorize_and_access_token_using_form() response = self._oauth_signed_get("/oauth/some/") self.assertEqual(response.status_code, 200) def test_scope_some_scope_view_not_authorized(self): """Tests that view created with @oauth_required("some") decorator won't give access when requested using token with different scope """ self._request_token() self._authorize_and_access_token_using_form() response = self._oauth_signed_get("/oauth/some/") self.assertEqual(response.status_code, 401) def test_resource_None_view(self): """Tests that view created using @oauth_required decorator gives access when requested using token without scope specified """ #request token without setting scope self._request_token() self._authorize_and_access_token_using_form() response = self._oauth_signed_get("/oauth/none/") self.assertEqual(response.status_code, 200) def test_resource_None_scope_view_not_authorized(self): """Tests that view created with @oauth_required decorator won't give access when requested using token with scope!="all" """ #ensure there is a Scope object for this scope self.scope = Scope.objects.create(name="some_new_scope") self._request_token(scope=self.scope.name) self._authorize_and_access_token_using_form() response = self._oauth_signed_get("/oauth/some/") self.assertEqual(response.status_code, 401) def test_get_with_header_auth(self): #request token without setting scope self._request_token() self._authorize_and_access_token_using_form() response = self._oauth_signed_get("/oauth/none/", method=METHOD_AUTHORIZATION_HEADER) self.assertEqual(response.status_code, 200) def test_get_with_url_query_auth(self): #request token without setting scope self._request_token() self._authorize_and_access_token_using_form() response = self._oauth_signed_get("/oauth/none/", method=METHOD_URL_QUERY) self.assertEqual(response.status_code, 200) def test_get_with_request_body_auth(self): #request token without setting scope self._request_token() self._authorize_and_access_token_using_form() response = self._oauth_signed_get("/oauth/none/", method=METHOD_POST_REQUEST_BODY) self.assertEqual(response.status_code, 200)david-django-oauth-plus-91f6df5e8a28/oauth_provider/tests/issues.py0000644000000000000000000005153512251631323023554 0ustar 00000000000000import time import urllib import json import datetime from urlparse import parse_qs, urlparse from django.conf import settings from django.test.client import RequestFactory import oauth2 as oauth from oauth_provider.tests.auth import BaseOAuthTestCase, METHOD_AUTHORIZATION_HEADER from oauth_provider.models import Token, Scope from oauth_provider import utils, responses from oauth_provider.store import store as oauth_provider_store class OAuthTestsBug10(BaseOAuthTestCase): """ See https://code.welldev.org/django-oauth-plus/issue/10/malformed-callback-url-when-user-denies """ def test_Request_token_request_succeeds_with_valid_request_token_parameters(self): response = self._request_token() token = self.request_token self.assertEqual(token.callback, self.callback_token) self.assertEqual( token.callback_confirmed, self.callback_confirmed) def test_Requesting_user_authorization_fails_when_user_denies_authorization(self): self._request_token() self.c.login(username=self.username, password=self.password) parameters = authorization_parameters = {'oauth_token': self.request_token.key} response = self.c.get("/oauth/authorize/", parameters) self.assertEqual( response.status_code, 200) # fake access not granted by the user (set session parameter again) authorization_parameters['authorize_access'] = False response = self.c.post("/oauth/authorize/", authorization_parameters) self.assertEqual( response.status_code, 302) self.assertEqual('http://printer.example.com/request_token_ready?error=Access+not+granted+by+user.', response['Location']) self.c.logout() class OAuthOutOfBoundTests(BaseOAuthTestCase): def test_Requesting_user_authorization_succeeds_when_oob(self): self._request_token(oauth_callback="oob") self.c.login(username=self.username, password=self.password) parameters = self.authorization_parameters = {'oauth_token': self.request_token.key} response = self.c.get("/oauth/authorize/", parameters) self.assertEqual( response.status_code, 200) class OauthTestIssue24(BaseOAuthTestCase): """ See https://bitbucket.org/david/django-oauth-plus/issue/24/utilspy-initialize_server_request-should """ def setUp(self): super(OauthTestIssue24, self).setUp() #setting the access key/secret to made-up strings self.access_token = Token( key="key", secret="secret", consumer=self.consumer, user=self.jane, token_type=2, scope=self.scope ) self.access_token.save() def __make_querystring_with_HMAC_SHA1(self, http_method, path, data, content_type): """ Utility method for creating a request which is signed using HMAC_SHA1 method """ consumer = oauth.Consumer(key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET) token = oauth.Token(key=self.access_token.key, secret=self.access_token.secret) url = "http://testserver:80" + path #if data is json, we want it in the body, else as parameters (i.e. queryparams on get) parameters=None body = "" if content_type=="application/json": body = data else: parameters = data request = oauth.Request.from_consumer_and_token( consumer=consumer, token=token, http_method=http_method, http_url=url, parameters=parameters, body=body ) # Sign the request. signature_method = oauth.SignatureMethod_HMAC_SHA1() request.sign_request(signature_method, consumer, token) return request.to_url() def test_that_initialize_server_request_when_custom_content_type(self): """Chceck if post data is not included in params when constent type is not application/x-www-form-urlencoded. It would cause problems only when signature method is HMAC-SHA1 """ data = json.dumps({"data": {"foo": "bar"}}) content_type = "application/json" querystring = self.__make_querystring_with_HMAC_SHA1("POST", "/path/to/post", data, content_type) #we're just using the request, don't bother faking sending it rf = RequestFactory() request = rf.post(querystring, data, content_type) #this is basically a "remake" of the relevant parts of OAuthAuthentication in django-rest-framework oauth_request = utils.get_oauth_request(request) consumer_key = oauth_request.get_parameter('oauth_consumer_key') consumer = oauth_provider_store.get_consumer(request, oauth_request, consumer_key) token_param = oauth_request.get_parameter('oauth_token') token = oauth_provider_store.get_access_token(request, oauth_request, consumer, token_param) oauth_server, oauth_request = utils.initialize_server_request(request) #check that this does not throw an oauth.Error oauth_server.verify_request(oauth_request, consumer, token) def test_post_using_in_authorization_header_and_PLAINTEXT(self): self._request_token() self._authorize_and_access_token_using_form() parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_signature_method': "PLAINTEXT", 'oauth_version': "1.0", 'oauth_token': self.ACCESS_TOKEN_KEY, 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': str(int(time.time()))+"nonce", 'oauth_signature': "%s&%s" % (self.CONSUMER_SECRET, self.ACCESS_TOKEN_SECRET), } header = self._get_http_authorization_header(parameters) response = self.c.post("/oauth/photo/", HTTP_AUTHORIZATION=header) self.assertEqual(response.status_code, 200) def test_post_using_auth_in_post_body_and_PLAINTEXT(self): """Check if auth works when authorization data is in post body when content type is pplication/x-www-form-urlencoded """ self._request_token() self._authorize_and_access_token_using_form() parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_signature_method': "PLAINTEXT", 'oauth_version': "1.0", 'oauth_token': self.ACCESS_TOKEN_KEY, 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': str(int(time.time()))+"nonce", 'oauth_signature': "%s&%s" % (self.CONSUMER_SECRET, self.ACCESS_TOKEN_SECRET), "additional_data": "whoop" # additional data } response = self.c.post("/oauth/photo/", urllib.urlencode(parameters, True), content_type="application/x-www-form-urlencoded") self.assertEqual(response.status_code, 200) def test_post_using_auth_in_header_with_content_type_json_and_PLAINTEXT(self): self._request_token() self._authorize_and_access_token_using_form() parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_signature_method': "PLAINTEXT", 'oauth_version': "1.0", 'oauth_token': self.ACCESS_TOKEN_KEY, 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': str(int(time.time()))+"nonce", 'oauth_signature': "%s&%s" % (self.CONSUMER_SECRET, self.ACCESS_TOKEN_SECRET), } header = self._get_http_authorization_header(parameters) response = self.c.post("/oauth/photo/", HTTP_AUTHORIZATION=header, CONTENT_TYPE="application/json") self.assertEqual(response.status_code, 200) def test_post_using_auth_in_body_content_type_and_application_x_www_form_urlencoded(self): """Opposite of test_that_initialize_server_request_when_custom_content_type, If content type is application/x-www-form-urlencoded, post data should be added to params, and it affects signature """ self._request_token() self._authorize_and_access_token_using_form() data={"foo": "bar"} content_type = "application/x-www-form-urlencoded" querystring = self.__make_querystring_with_HMAC_SHA1("POST", "/path/to/post", data, content_type) #we're just using the request, don't bother faking sending it rf = RequestFactory() request = rf.post(querystring, urllib.urlencode(data), content_type) #this is basically a "remake" of the relevant parts of OAuthAuthentication in django-rest-framework oauth_request = utils.get_oauth_request(request) consumer_key = oauth_request.get_parameter('oauth_consumer_key') consumer = oauth_provider_store.get_consumer(request, oauth_request, consumer_key) token_param = oauth_request.get_parameter('oauth_token') token = oauth_provider_store.get_access_token(request, oauth_request, consumer, token_param) oauth_server, oauth_request = utils.initialize_server_request(request) #check that this does not throw an oauth.Error oauth_server.verify_request(oauth_request, consumer, token) class OAuthTestsBug2UrlParseNonHttpScheme(BaseOAuthTestCase): def test_non_http_url_callback_scheme(self): # @vmihailenco callback example self._request_token(oauth_callback='ftp://fnaffgdfmcfbjiifjkhbfbnjljaabiaj.com/chrome_ex_oauth.html?q=1') self.c.login(username=self.username, password=self.password) parameters = self.authorization_parameters = {'oauth_token': self.request_token.key} response = self.c.get("/oauth/authorize/", parameters) self.assertEqual(response.status_code, 200) # fill form (authorize us) parameters['authorize_access'] = 1 response = self.c.post("/oauth/authorize/", parameters) self.assertEqual(response.status_code, 302) # assert query part of url is not malformed assert "?q=1&" in response["Location"] class OAuthTestIssue41XForwardedProto(BaseOAuthTestCase): def setUp(self): super(OAuthTestIssue41XForwardedProto, self).setUp() self._request_token(METHOD_AUTHORIZATION_HEADER) self._authorize_and_access_token_using_form(METHOD_AUTHORIZATION_HEADER) print def _make_GET_auth_header(self, url): token = oauth.Token(self.ACCESS_TOKEN_KEY, self.ACCESS_TOKEN_SECRET) consumer = oauth.Consumer(self.CONSUMER_KEY, self.CONSUMER_SECRET) request = oauth.Request.from_consumer_and_token( consumer=consumer, token=token, http_method="GET", http_url=url, ) # Sign the request. signature_method = oauth.SignatureMethod_HMAC_SHA1() request.sign_request(signature_method, consumer, token) return request.to_header()["Authorization"] def test_when_same_protocol(self): """Test that signature vierifies when protocol used for signing is same as used in request """ url = "http://testserver/oauth/none/" kwargs = { "HTTP_AUTHORIZATION": self._make_GET_auth_header(url), } response = self.c.get(url.replace('http', 'https'), **kwargs) self.assertEqual(response.status_code, 200) url = "https://testserver:80/oauth/none/" kwargs = { # this tells django test client to pretend it was https request 'wsgi.url_scheme': "https", "HTTP_AUTHORIZATION": self._make_GET_auth_header(url), } response = self.c.get(url, **kwargs) self.assertEqual(response.status_code, 200) def test_when_protocol_mismatch(self): """Test that signature does not vierifies when protocol is diffrent from that which was used for signing request """ url = "https://testserver:80/oauth/none/" kwargs = { 'wsgi.url_scheme': "http", "HTTP_AUTHORIZATION": self._make_GET_auth_header(url), } response = self.c.get(url.replace('https', 'http'), **kwargs) assert response == responses.COULD_NOT_VERIFY_OAUTH_REQUEST_RESPONSE self.assertEqual(response.status_code, 401) url = "http://testserver:80/oauth/none/" kwargs = { # this tells django test client to pretend it was https request 'wsgi.url_scheme': "https", "HTTP_AUTHORIZATION": self._make_GET_auth_header(url), } response = self.c.get(url.replace('http', 'https'), **kwargs) assert response == responses.COULD_NOT_VERIFY_OAUTH_REQUEST_RESPONSE self.assertEqual(response.status_code, 401) def test_when_x_forwarded_proto_header_has_valid_protocol(self): """Test that signature verifies when X-Forwarded-Proto HTTP header has same protocol as one that was used for signing request """ url = "https://testserver/oauth/none/" kwargs = { 'wsgi.url_scheme': "http", 'HTTP_AUTHORIZATION': self._make_GET_auth_header(url), 'HTTP_X_FORWARDED_PROTO': 'https', } response = self.c.get(url.replace('https', 'http'), **kwargs) self.assertEqual(response.status_code, 200) url = "http://testserver/oauth/none/" kwargs = { 'wsgi.url_scheme': "https", "HTTP_AUTHORIZATION": self._make_GET_auth_header(url), "HTTP_X_FORWARDED_PROTO": "http", } response = self.c.get(url.replace('http', 'https'), **kwargs) self.assertEqual(response.status_code, 200) class OAuthTestIssue16NoncesCheckedAgainstTimestamp(BaseOAuthTestCase): def test_timestamp_ok(self): self._request_token() self._authorize_and_access_token_using_form() parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_signature_method': "PLAINTEXT", 'oauth_version': "1.0", 'oauth_token': self.ACCESS_TOKEN_KEY, 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': str(int(time.time()))+"nonce1", 'oauth_signature': "%s&%s" % (self.CONSUMER_SECRET, self.ACCESS_TOKEN_SECRET), } response = self.c.get("/oauth/photo/", parameters) self.assertEqual(response.status_code, 200) def test_timestamp_repeated_nonce(self): self._request_token() self._authorize_and_access_token_using_form() timestamp = str(int(time.time())) nonce = timestamp + "nonce" parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_signature_method': "PLAINTEXT", 'oauth_version': "1.0", 'oauth_token': self.ACCESS_TOKEN_KEY, 'oauth_timestamp': timestamp, 'oauth_nonce': nonce, 'oauth_signature': "%s&%s" % (self.CONSUMER_SECRET, self.ACCESS_TOKEN_SECRET), } response = self.c.get("/oauth/photo/", parameters) self.assertEqual(response.status_code, 200) response = self.c.get("/oauth/photo/", parameters) self.assertEqual(response.status_code, 401) def test_timestamp_old_nonce(self): self._request_token() self._authorize_and_access_token_using_form() #make this nonce older timestamp = str(int(datetime.datetime.now().strftime("%s")) - (settings.OAUTH_NONCE_VALID_PERIOD + 1)) nonce = timestamp + "nonce" parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_signature_method': "PLAINTEXT", 'oauth_version': "1.0", 'oauth_token': self.ACCESS_TOKEN_KEY, 'oauth_timestamp': timestamp, 'oauth_nonce': nonce, 'oauth_signature': "%s&%s" % (self.CONSUMER_SECRET, self.ACCESS_TOKEN_SECRET), } response = self.c.get("/oauth/photo/", parameters) self.assertEqual(response.status_code, 401) class OAuthTestIssue39(BaseOAuthTestCase): """ See https://bitbucket.org/david/django-oauth-plus/issue/39/request-token-scope-unused. """ def setUp(self): super(OAuthTestIssue39, self).setUp() Scope.objects.create(name='scope1') Scope.objects.create(name='scope2') def test_different_token_scopes(self): self._request_token(scope='scope1') # Authorization code below copied from BaseOAuthTestCase self.c.login(username=self.username, password=self.password) parameters = self.authorization_parameters = {'oauth_token': self.request_token.key} response = self.c.get("/oauth/authorize/", parameters) self.assertEqual(response.status_code, 200) # fill form (authorize us) parameters['authorize_access'] = 1 response = self.c.post("/oauth/authorize/", parameters) self.assertEqual(response.status_code, 302) # finally access authorized access_token oauth_verifier = parse_qs(urlparse(response['Location']).query)['oauth_verifier'][0] # logout to ensure that will not authorize with session self.c.logout() # Changed line - change the scope of access token # access token's scope should be same as request token self._access_token(oauth_verifier=oauth_verifier, oauth_token=self.request_token.key, scope='scope2') access_token = Token.objects.get(key=self.ACCESS_TOKEN_KEY) self.assertEqual(access_token.scope.name, 'scope1') class OAuthTestIssue44PostRequestBodyInSignature(BaseOAuthTestCase): def test_POST_with_x_www_form_urlencoded_body_params_and_auth_header(self): """Test issue when user's request has authorization header and uses application/x-www-form-urlencoded content type with some request body parameters. note: In this case both POST and GET parameters should be included in signature base string, so we test GET and POST together note: behaviour defined in http://tools.ietf.org/html/rfc5849#section-3.4.1.3.1 """ # get valid access token self._request_token() self._authorize_and_access_token_using_form() # init request params and headers get_params = {"foo": "bar"} body_params = {"some": "param", "other": "param"} content_type = "application/x-www-form-urlencoded" header = self._make_auth_header_with_HMAC_SHA1('post', "/oauth/photo/", get_params, body_params, True) body = urllib.urlencode(body_params) response = self.c.post( # this is workaround to have both POST & GET params in this request "/oauth/photo/?%s" % urllib.urlencode(get_params), data=body, HTTP_AUTHORIZATION=header["Authorization"], content_type=content_type ) self.assertEqual(response.status_code, 200) def test_POST_with_x_www_form_urlencoded_body_params_and_auth_header_unauthorized(self): """Test issue when user's request has authorization header and uses application/x-www-form-urlencoded content type with some request body parameters, but signature was generated without body params. """ # get valid access token self._request_token() self._authorize_and_access_token_using_form() # init request params and headers get_params = {"foo": "bar"} body_params = {"some": "param", "other": "param"} content_type = "application/x-www-form-urlencoded" header = self._make_auth_header_with_HMAC_SHA1('post', "/oauth/photo/", get_params, {}, True) body = urllib.urlencode(body_params) response = self.c.post( # this is workaround to have both POST & GET params in this request "/oauth/photo/?%s" % urllib.urlencode(get_params), data=body, HTTP_AUTHORIZATION=header["Authorization"], content_type=content_type ) self.assertEqual(response.status_code, 401) def _make_auth_header_with_HMAC_SHA1(self, http_method, path, get_params, body_params, is_form_encoded): """make auth header, take in consideration both get and post body_params """ consumer = oauth.Consumer(key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET) token = oauth.Token(key=self.ACCESS_TOKEN_KEY, secret=self.ACCESS_TOKEN_SECRET) url = "http://testserver:80" + path body = urllib.urlencode(body_params) params = {} params.update(get_params) params.update(body_params) request = oauth.Request.from_consumer_and_token( consumer=consumer, token=token, http_method=http_method, http_url=url, is_form_encoded=is_form_encoded, body=body, # it seems that body parameter isn't enough to have body params # in signature base string parameters=params ) # Sign the request. signature_method = oauth.SignatureMethod_HMAC_SHA1() request.sign_request(signature_method, consumer, token) return request.to_header()david-django-oauth-plus-91f6df5e8a28/oauth_provider/tests/models.py0000644000000000000000000000002712251631323023512 0ustar 00000000000000# -*- coding: utf-8 -*-david-django-oauth-plus-91f6df5e8a28/oauth_provider/tests/protocol.py0000644000000000000000000004251612251631323024101 0ustar 00000000000000import time import cgi import oauth2 as oauth from django.test import Client from oauth_provider.tests.auth import BaseOAuthTestCase from oauth_provider.models import Token, Consumer, Resource, Scope from oauth_provider.compat import get_user_model User = get_user_model() class ProtocolExample(BaseOAuthTestCase): """Set of tests, based on ProtocolExample document """ def _last_created_request_token(self): return list(Token.objects.filter(token_type=Token.REQUEST))[-1] def _last_created_access_token(self): return list(Token.objects.filter(token_type=Token.ACCESS))[-1] def _update_token_from_db(self, request_token): """Get fresh copy of the token from the DB""" return Token.objects.get(key=request_token.key) def _make_request_token_parameters(self): return { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_signature_method': 'PLAINTEXT', 'oauth_signature': '%s&' % self.CONSUMER_SECRET, 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': 'requestnonce', 'oauth_version': '1.0', 'oauth_callback': 'http://printer.example.com/request_token_ready', 'scope': 'photos', # custom argument to specify Protected Resource } def _make_access_token_parameters(self, token): return { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_token': token.key, 'oauth_signature_method': 'PLAINTEXT', 'oauth_signature': '%s&%s' % (self.CONSUMER_SECRET, token.secret), 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': 'accessnonce', 'oauth_version': '1.0', 'oauth_verifier': token.verifier, 'scope': 'photos', } def _make_protected_access_parameters(self, access_token): return { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_token': access_token.key, 'oauth_signature_method': 'HMAC-SHA1', 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': 'accessresourcenonce', 'oauth_version': '1.0', } def test_returns_invalid_params_empty_request(self): """Printer website tries to access the photo and receives HTTP 401 Unauthorized indicating it is private. The Service Provider includes the following header with the response: """ response = self.c.get("/oauth/request_token/") self.assertEqual(response.status_code, 401) self.assertEqual(response._headers['www-authenticate'], ('WWW-Authenticate', 'OAuth realm=""')) self.assertEqual(response.content, 'Invalid request parameters.') def test_returns_401_wrong_callback(self): #If you try to put a wrong callback, it will return an error parameters = self._make_request_token_parameters() parameters['oauth_callback'] = 'wrongcallback' parameters['oauth_nonce'] = 'requestnoncewrongcallback' response = self.c.get("/oauth/request_token/", parameters) self.assertEqual(response.status_code, 401) self.assertEqual(response.content, 'Invalid callback URL.') def test_401_for_wrong_scope(self): # If you try to access a resource with a wrong scope, it will return an error parameters = self._make_request_token_parameters() parameters['scope'] = 'videos' parameters['oauth_nonce'] = 'requestnoncevideos' response = self.c.get("/oauth/request_token/", parameters) self.assertEqual(response.status_code, 401) self.assertEqual(response.content, 'Scope does not exist.') def test_oob_callback(self): # If you do not provide any callback (i.e. oob), the Service Provider SHOULD display the value of the verification code parameters = self._make_request_token_parameters() parameters['oauth_callback'] = 'oob' parameters['oauth_nonce'] = 'requestnonceoob' response = self.c.get("/oauth/request_token/", parameters) self.assertEqual(response.status_code, 200) response_params = cgi.parse_qs(response.content) oob_token = self._last_created_request_token() self.assertTrue(oob_token.key in response_params['oauth_token']) self.assertTrue(oob_token.secret in response_params['oauth_token_secret']) self.assertFalse(oob_token.callback_confirmed) self.assertIsNone(oob_token.callback) def _validate_request_token_response(self, response): self.assertEqual(response.status_code, 200) response_params = cgi.parse_qs(response.content) last_token = self._last_created_request_token() self.assertTrue(last_token.key in response_params['oauth_token']) self.assertTrue(last_token.secret in response_params['oauth_token_secret']) self.assertTrue(response_params['oauth_callback_confirmed']) def _obtain_request_token(self): parameters = self._make_request_token_parameters() response = self.c.get("/oauth/request_token/", parameters) # The Service Provider checks the signature and replies with an unauthorized Request Token in the body of the HTTP response self._validate_request_token_response(response) return self._last_created_request_token() def test_obtain_request_token(self): self._obtain_request_token() def test_provider_redirects_to_login_page(self): """The Service Provider asks Jane to sign-in using her username and password """ token = self._obtain_request_token() parameters = { 'oauth_token': token.key, } response = self.c.get("/oauth/authorize/", parameters) self.assertEqual(response.status_code, 302) self.assertTrue(token.key in response['Location']) self.c.login(username='jane', password='toto') response = self.c.get("/oauth/authorize/", parameters) self.assertEqual(response.status_code, 200) def test_authorize_without_session_parameter(self): # Then consumer obtains a Request Token token = self._obtain_request_token() parameters = {'oauth_token': token.key} self.c.login(username='jane', password='toto') parameters['authorize_access'] = True response = self.c.post("/oauth/authorize/", parameters) # without session parameter (previous POST removed it) response = self.c.post("/oauth/authorize/", parameters) self.assertEqual(response.status_code, 401) self.assertEqual(response.content, 'Action not allowed.') def test_access_not_granted_by_the_user(self): token = self._obtain_request_token() parameters = {'oauth_token': token.key} self.c.login(username='jane', password='toto') self.c.get("/oauth/authorize/", parameters) # set session id parameters['authorize_access'] = False response = self.c.post("/oauth/authorize/", parameters) self.assertTrue('error=Access+not+granted+by+user' in response['Location']) def _request_authorization(self, request_token): """Request authorization for the request token. """ self.assertFalse(request_token.is_approved) parameters = {'oauth_token': request_token.key} self.c.login(username='jane', password='toto') response = self.c.get("/oauth/authorize/", parameters) parameters['authorize_access'] = 1 response = self.c.post("/oauth/authorize/", parameters) request_token = self._update_token_from_db(request_token) self.assertTrue(request_token.is_approved) def test_request_authorization(self): token = self._obtain_request_token() self._request_authorization(token) def _obtain_access_token(self, request_token): parameters = self._make_access_token_parameters(request_token) response = self.c.get("/oauth/access_token/", parameters) response_params = cgi.parse_qs(response.content) access_token = self._last_created_access_token() self.assertEqual(response.status_code, 200) self.assertEqual(response_params['oauth_token'][0], access_token.key) self.assertEqual(response_params['oauth_token_secret'][0], access_token.secret) self.assertEqual(access_token.user.username, 'jane') return access_token def test_request_another_access_token(self): """The Consumer will not be able to request another Access Token with the same parameters because the Request Token has been deleted once Access Token is created """ request_token = self._obtain_request_token() self._request_authorization(request_token) request_token = self._update_token_from_db(request_token) self._obtain_access_token(request_token) parameters = self._make_access_token_parameters(request_token) response = self.c.get("/oauth/access_token/", parameters) self.assertEqual(response.status_code, 400) self.assertEqual(response.content, 'Invalid request token.') def test_request_access_token_invalid_verifier(self): """The Consumer will not be able to request another Access Token with a missing or invalid verifier """ jane = User.objects.get(username='jane') new_request_token = Token.objects.create_token( token_type=Token.REQUEST, timestamp=str(int(time.time())), consumer=Consumer.objects.get(key=self.CONSUMER_KEY), user=jane, scope=Scope.objects.get(name='photos')) new_request_token.is_approved = True new_request_token.save() parameters = self._make_access_token_parameters(new_request_token) parameters['oauth_token'] = new_request_token.key parameters['oauth_signature'] = '%s&%s' % (self.CONSUMER_SECRET, new_request_token.secret) parameters['oauth_verifier'] = 'invalidverifier' response = self.c.get("/oauth/access_token/", parameters) self.assertEqual(response.status_code, 400) self.assertEqual(response.content, 'Invalid OAuth verifier.') def test_request_access_token_not_approved_request_token(self): """The Consumer will not be able to request an Access Token if the token is not approved """ jane = User.objects.get(username='jane') new_request_token = Token.objects.create_token( token_type=Token.REQUEST, timestamp=str(int(time.time())), consumer=Consumer.objects.get(key=self.CONSUMER_KEY), user=jane, scope=Scope.objects.get(name='photos')) new_request_token.is_approved = False new_request_token.save() parameters = self._make_access_token_parameters(new_request_token) response = self.c.get("/oauth/access_token/", parameters) self.assertEqual(response.status_code, 400) self.assertEqual(response.content, 'Request Token not approved by the user.') def test_error_accessing_protected_resource(self): request_token = self._obtain_request_token() self._request_authorization(request_token) request_token = self._update_token_from_db(request_token) access_token = self._obtain_access_token(request_token) parameters = self._make_protected_access_parameters(access_token) parameters['oauth_signature'] = 'wrongsignature' parameters['oauth_nonce'] = 'anotheraccessresourcenonce' response = self.c.get("/oauth/photo/", parameters) self.assertEqual(response.status_code, 401) self.assertTrue(response.content.startswith('Could not verify OAuth request.')) response = self.c.get("/oauth/photo/") self.assertEqual(response.status_code, 401) self.assertEqual(response.content, 'Invalid request parameters.') def test_positive(self): # Then consumer obtains a Request Token parameters = self._make_request_token_parameters() response = self.c.get("/oauth/request_token/", parameters) # The Service Provider checks the signature and replies with an unauthorized Request Token in the body of the HTTP response self._validate_request_token_response(response) token = self._last_created_request_token() parameters = {'oauth_token': token.key} """The Consumer redirects Jane's browser to the Service Provider User Authorization URL to obtain Jane's approval for accessing her private photos. """ response = self.c.get("/oauth/authorize/", parameters) """The Service Provider asks Jane to sign-in using her username and password """ self.assertEqual(response.status_code, 302) expected_redirect = 'http://testserver/accounts/login/?next=/oauth/authorize/%3Foauth_token%3D{0}'.format(token.key) self.assertEqual(response['Location'], expected_redirect) # Jane logins self.c.login(username='jane', password='toto') """If successful, Service Provider asks her if she approves granting printer.example.com access to her private photos. """ response = self.c.get("/oauth/authorize/", parameters) self.assertEqual(response.status_code, 200) self.assertTrue(response.content.startswith( 'Fake authorize view for printer.example.com with params: oauth_token=')) # Jane approves the request. self.assertEqual(token.is_approved, 0) # token is not approved yet parameters['authorize_access'] = 1 response = self.c.post("/oauth/authorize/", parameters) # The Service Provider redirects her back to the Consumer's callback URL self.assertEqual(response.status_code, 302) self.assertTrue(response['Location'].startswith( 'http://printer.example.com/request_token_ready?oauth_verifier=')) self.assertTrue('oauth_token=' in response['Location']) token = self._last_created_request_token() # get from the DB updated token self.assertTrue(token.is_approved) """ Obtaining an Access Token """ """Now that the Consumer knows Jane approved the Request Token, it asks the Service Provider to exchange it for an Access Token """ # reset Client self.c = Client() parameters = self._make_access_token_parameters(token) response = self.c.get("/oauth/access_token/", parameters) """The Service Provider checks the signature and replies with an Access Token in the body of the HTTP response """ self.assertEqual(response.status_code, 200) response_params = cgi.parse_qs(response.content) access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1] self.assertEqual(response_params['oauth_token'][0], access_token.key) self.assertEqual(response_params['oauth_token_secret'][0], access_token.secret) self.assertEqual(access_token.user.username, 'jane') """ Accessing protected resources """ """The Consumer is now ready to request the private photo. Since the photo URL is not secure (HTTP), it must use HMAC-SHA1. """ """ Generating Signature Base String To generate the signature, it first needs to generate the Signature Base String. The request contains the following parameters (oauth_signature excluded) which are ordered and concatenated into a normalized string """ parameters = self._make_protected_access_parameters(access_token) """ Calculating Signature Value HMAC-SHA1 produces the following digest value as a base64-encoded string (using the Signature Base String as text and self.CONSUMER_SECRET as key) """ oauth_request = oauth.Request.from_token_and_callback(access_token, http_url='http://testserver/oauth/photo/', parameters=parameters) signature_method = oauth.SignatureMethod_HMAC_SHA1() signature = signature_method.sign(oauth_request, self.consumer, access_token) """ Requesting Protected Resource All together, the Consumer request for the photo is: """ parameters['oauth_signature'] = signature response = self.c.get("/oauth/photo/", parameters) self.assertEqual(response.status_code, 200) self.assertEqual(response.content, 'Protected Resource access!') """ Revoking Access If Jane deletes the Access Token of printer.example.com, the Consumer will not be able to access the Protected Resource anymore """ access_token.delete() # Note that an "Invalid signature" error will be raised here if the # token is not revoked by Jane because we reuse a previously used one. parameters['oauth_signature'] = signature parameters['oauth_nonce'] = 'yetanotheraccessscopenonce' response = self.c.get(self.scope.url, parameters) self.assertEqual(response.status_code, 401) self.assertTrue(response.content.startswith('Invalid access token:')) david-django-oauth-plus-91f6df5e8a28/oauth_provider/tests/tests.py0000644000000000000000000000103112251631323023365 0ustar 00000000000000""" Force import of all modules in this package in order to get the standard test runner to pick up the tests. """ # https://github.com/swistakm/django-rest-framework/blob/master/rest_framework/tests/tests.py from __future__ import unicode_literals import os modules = [filename.rsplit('.', 1)[0] for filename in os.listdir(os.path.dirname(__file__)) if filename.endswith('.py') and not filename.startswith('_')] __test__ = dict() for module in modules: exec("from oauth_provider.tests.%s import *" % module) david-django-oauth-plus-91f6df5e8a28/oauth_provider/tests/xauth.py0000644000000000000000000000454012251631323023364 0ustar 00000000000000# -*- coding: utf-8 -*- import time import urllib from urlparse import parse_qs from oauth_provider.models import Scope from oauth_provider.tests.auth import BaseOAuthTestCase, METHOD_URL_QUERY, METHOD_AUTHORIZATION_HEADER, METHOD_POST_REQUEST_BODY class XAuthTestCase(BaseOAuthTestCase): def setUp(self): super(XAuthTestCase, self).setUp() self.consumer.xauth_allowed = True self.consumer.save() def _accesss_token(self, method=METHOD_URL_QUERY): parameters = { "oauth_consumer_key": self.CONSUMER_KEY, "oauth_consumer_secret": self.CONSUMER_SECRET, "oauth_nonce": "12981230918711", 'oauth_signature_method': 'PLAINTEXT', 'oauth_signature': "%s&%s" % (self.CONSUMER_SECRET, ""), 'oauth_timestamp': str(int(time.time())), 'oauth_version': '1.0', 'x_auth_mode': "client_auth", 'x_auth_password': self.password, 'x_auth_username': self.username, } if method==METHOD_AUTHORIZATION_HEADER: header = self._get_http_authorization_header(parameters) response = self.c.get("/oauth/access_token/", HTTP_AUTHORIZATION=header) elif method==METHOD_URL_QUERY: response = self.c.get("/oauth/access_token/", parameters) elif method==METHOD_POST_REQUEST_BODY: body = urllib.urlencode(parameters) response = self.c.post("/oauth/access_token/", body, content_type="application/x-www-form-urlencoded") else: raise NotImplementedError self.assertEqual(response.status_code, 200) response_params = parse_qs(response.content) self.ACCESS_TOKEN_KEY = response_params['oauth_token'][0] self.ACCESS_TOKEN_SECRET = response_params['oauth_token_secret'][0] def test_xauth(self): self._access_token(x_auth_mode="client_auth", x_auth_password=self.password, x_auth_username=self.username) assert self.ACCESS_TOKEN_KEY assert self.ACCESS_TOKEN_SECRET def test_xauth_using_email(self): self._access_token(x_auth_mode="client_auth", x_auth_password=self.password, x_auth_username=self.email) assert self.ACCESS_TOKEN_KEY assert self.ACCESS_TOKEN_SECRETdavid-django-oauth-plus-91f6df5e8a28/oauth_provider/urls.py0000644000000000000000000000062112251631323022052 0ustar 00000000000000from oauth_provider.compat import url, patterns, include from views import request_token, user_authorization, access_token urlpatterns = patterns('', url(r'^request_token/$', request_token, name='oauth_request_token'), url(r'^authorize/$', user_authorization, name='oauth_user_authorization'), url(r'^access_token/$', access_token, name='oauth_access_token'), ) david-django-oauth-plus-91f6df5e8a28/oauth_provider/utils.py0000644000000000000000000001204612251631323022231 0ustar 00000000000000import oauth2 as oauth from urlparse import urlparse, urlunparse from django.conf import settings from django.http import HttpResponse, HttpResponseBadRequest from django.contrib.auth import authenticate from consts import MAX_URL_LENGTH OAUTH_REALM_KEY_NAME = getattr(settings, 'OAUTH_REALM_KEY_NAME', '') OAUTH_SIGNATURE_METHODS = getattr(settings, 'OAUTH_SIGNATURE_METHODS', ['plaintext', 'hmac-sha1']) OAUTH_BLACKLISTED_HOSTNAMES = getattr(settings, 'OAUTH_BLACKLISTED_HOSTNAMES', []) def initialize_server_request(request): """Shortcut for initialization.""" oauth_request = get_oauth_request(request) if oauth_request: oauth_server = oauth.Server() if 'plaintext' in OAUTH_SIGNATURE_METHODS: oauth_server.add_signature_method(oauth.SignatureMethod_PLAINTEXT()) if 'hmac-sha1' in OAUTH_SIGNATURE_METHODS: oauth_server.add_signature_method(oauth.SignatureMethod_HMAC_SHA1()) else: oauth_server = None return oauth_server, oauth_request def send_oauth_error(err=None): """Shortcut for sending an error.""" # send a 401 error response = HttpResponse(err.message.encode('utf-8'), mimetype="text/plain") response.status_code = 401 # return the authenticate header header = oauth.build_authenticate_header(realm=OAUTH_REALM_KEY_NAME) for k, v in header.iteritems(): response[k] = v return response def get_oauth_request(request): """ Converts a Django request object into an `oauth2.Request` object. """ # Django converts Authorization header in HTTP_AUTHORIZATION # Warning: it doesn't happen in tests but it's useful, do not remove! auth_header = {} if 'Authorization' in request.META: auth_header = {'Authorization': request.META['Authorization']} elif 'HTTP_AUTHORIZATION' in request.META: auth_header = {'Authorization': request.META['HTTP_AUTHORIZATION']} # include POST parameters if content type is # 'application/x-www-form-urlencoded' and request # see: http://tools.ietf.org/html/rfc5849#section-3.4.1.3.1 parameters = {} if request.method == "POST" and request.META.get('CONTENT_TYPE') == "application/x-www-form-urlencoded": parameters = dict((k, v.encode('utf-8')) for (k, v) in request.POST.iteritems()) absolute_uri = request.build_absolute_uri(request.path) if "HTTP_X_FORWARDED_PROTO" in request.META: scheme = request.META["HTTP_X_FORWARDED_PROTO"] absolute_uri = urlunparse((scheme, ) + urlparse(absolute_uri)[1:]) return oauth.Request.from_request(request.method, absolute_uri, headers=auth_header, parameters=parameters, query_string=request.META.get('QUERY_STRING', '') ) def verify_oauth_request(request, oauth_request, consumer, token=None): """ Helper function to verify requests. """ from store import store # Check nonce if not store.check_nonce(request, oauth_request, oauth_request['oauth_nonce'], oauth_request['oauth_timestamp']): return False # Verify request try: oauth_server = oauth.Server() oauth_server.add_signature_method(oauth.SignatureMethod_HMAC_SHA1()) oauth_server.add_signature_method(oauth.SignatureMethod_PLAINTEXT()) # Ensure the passed keys and secrets are ascii, or HMAC will complain. consumer = oauth.Consumer(consumer.key.encode('ascii', 'ignore'), consumer.secret.encode('ascii', 'ignore')) if token is not None: token = oauth.Token(token.key.encode('ascii', 'ignore'), token.secret.encode('ascii', 'ignore')) oauth_server.verify_request(oauth_request, consumer, token) except oauth.Error, err: return False return True def is_xauth_request(request): return request.get('x_auth_password') and request.get('x_auth_username') def verify_xauth_request(request, oauth_request): """ Helper function to verify xAuth requests. Returns a user if valid or None otherwise """ user = authenticate( x_auth_username=oauth_request.get_parameter('x_auth_username'), x_auth_password=oauth_request.get_parameter('x_auth_password'), x_auth_mode=oauth_request.get_parameter('x_auth_mode') ) if user: request.user = user return user def require_params(oauth_request, parameters=None): """ Ensures that the request contains all required parameters. """ params = [ 'oauth_consumer_key', 'oauth_nonce', 'oauth_signature', 'oauth_signature_method', 'oauth_timestamp' ] if parameters: params.extend(parameters) missing = list(param for param in params if param not in oauth_request) if missing: return HttpResponseBadRequest('Missing OAuth parameters: %s' % (', '.join(missing))) return None def check_valid_callback(callback): """ Checks the size and nature of the callback. """ callback_url = urlparse(callback) return (callback_url.scheme and callback_url.hostname not in OAUTH_BLACKLISTED_HOSTNAMES and len(callback) < MAX_URL_LENGTH) david-django-oauth-plus-91f6df5e8a28/oauth_provider/views.py0000644000000000000000000002210012251631323022216 0ustar 00000000000000from urllib import urlencode from django.conf import settings from django.contrib.auth.decorators import login_required from django.contrib.auth import authenticate from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseRedirect from django.views.decorators.csrf import csrf_exempt from django.utils.translation import ugettext as _ from django.core.urlresolvers import get_callable import oauth2 as oauth from decorators import oauth_required from forms import AuthorizeRequestTokenForm from oauth_provider.compat import UnsafeRedirect from responses import INVALID_PARAMS_RESPONSE, INVALID_CONSUMER_RESPONSE, COULD_NOT_VERIFY_OAUTH_REQUEST_RESPONSE from store import store, InvalidConsumerError, InvalidTokenError from utils import verify_oauth_request, get_oauth_request, require_params, send_oauth_error from utils import is_xauth_request from consts import OUT_OF_BAND OAUTH_AUTHORIZE_VIEW = 'OAUTH_AUTHORIZE_VIEW' OAUTH_CALLBACK_VIEW = 'OAUTH_CALLBACK_VIEW' UNSAFE_REDIRECTS = getattr(settings, "OAUTH_UNSAFE_REDIRECTS", False) @csrf_exempt def request_token(request): oauth_request = get_oauth_request(request) if oauth_request is None: return INVALID_PARAMS_RESPONSE missing_params = require_params(oauth_request, ('oauth_callback',)) if missing_params is not None: return missing_params if is_xauth_request(oauth_request): return HttpResponseBadRequest('xAuth not allowed for this method.') try: consumer = store.get_consumer(request, oauth_request, oauth_request['oauth_consumer_key']) except InvalidConsumerError: return INVALID_CONSUMER_RESPONSE if not verify_oauth_request(request, oauth_request, consumer): return COULD_NOT_VERIFY_OAUTH_REQUEST_RESPONSE try: request_token = store.create_request_token(request, oauth_request, consumer, oauth_request['oauth_callback']) except oauth.Error, err: return send_oauth_error(err) ret = urlencode({ 'oauth_token': request_token.key, 'oauth_token_secret': request_token.secret, 'oauth_callback_confirmed': 'true' }) return HttpResponse(ret, content_type='application/x-www-form-urlencoded') @login_required def user_authorization(request, form_class=AuthorizeRequestTokenForm): if 'oauth_token' not in request.REQUEST: return HttpResponseBadRequest('No request token specified.') oauth_request = get_oauth_request(request) try: request_token = store.get_request_token(request, oauth_request, request.REQUEST['oauth_token']) except InvalidTokenError: return HttpResponseBadRequest('Invalid request token.') consumer = store.get_consumer_for_request_token(request, oauth_request, request_token) if request.method == 'POST': form = form_class(request.POST) if request.session.get('oauth', '') == request_token.key and form.is_valid(): request.session['oauth'] = '' if form.cleaned_data['authorize_access']: request_token = store.authorize_request_token(request, oauth_request, request_token) args = { 'oauth_token': request_token.key } else: args = { 'error': _('Access not granted by user.') } if request_token.callback is not None and request_token.callback != OUT_OF_BAND: callback_url = request_token.get_callback_url(args) if UNSAFE_REDIRECTS: response = UnsafeRedirect(callback_url) else: response = HttpResponseRedirect(callback_url) else: # try to get custom callback view callback_view_str = getattr(settings, OAUTH_CALLBACK_VIEW, 'oauth_provider.views.fake_callback_view') try: view_callable = get_callable(callback_view_str) except AttributeError: raise Exception, "%s view doesn't exist." % callback_view_str # try to treat it as Class Based View (CBV) try: callback_view = view_callable.as_view() except AttributeError: # if it appears not to be CBV treat it like FBV callback_view = view_callable response = callback_view(request, **args) else: response = send_oauth_error(oauth.Error(_('Action not allowed.'))) else: # try to get custom authorize view authorize_view_str = getattr(settings, OAUTH_AUTHORIZE_VIEW, 'oauth_provider.views.fake_authorize_view') try: view_callable = get_callable(authorize_view_str) except AttributeError: raise Exception, "%s view doesn't exist." % authorize_view_str # try to treat it as Class Based View (CBV) try: authorize_view = view_callable.as_view() except AttributeError: # if it appears not to be CBV treat it like FBV authorize_view = view_callable params = oauth_request.get_normalized_parameters() # set the oauth flag request.session['oauth'] = request_token.key response = authorize_view(request, request_token, request_token.get_callback_url(), params) return response @csrf_exempt def access_token(request): oauth_request = get_oauth_request(request) if oauth_request is None: return INVALID_PARAMS_RESPONSE # Consumer try: consumer = store.get_consumer(request, oauth_request, oauth_request['oauth_consumer_key']) except InvalidConsumerError: return HttpResponseBadRequest('Invalid consumer.') is_xauth = is_xauth_request(oauth_request) if not is_xauth: # Check Parameters missing_params = require_params(oauth_request, ('oauth_token', 'oauth_verifier')) if missing_params is not None: return missing_params # Check Request Token try: request_token = store.get_request_token(request, oauth_request, oauth_request['oauth_token']) except InvalidTokenError: return HttpResponseBadRequest('Invalid request token.') if not request_token.is_approved: return HttpResponseBadRequest('Request Token not approved by the user.') # Verify Signature if not verify_oauth_request(request, oauth_request, consumer, request_token): return HttpResponseBadRequest('Could not verify OAuth request.') # Check Verifier if oauth_request.get('oauth_verifier', None) != request_token.verifier: return HttpResponseBadRequest('Invalid OAuth verifier.') else: # xAuth # Check Parameters missing_params = require_params(oauth_request, ('x_auth_username', 'x_auth_password', 'x_auth_mode')) if missing_params is not None: return missing_params # Check if Consumer allows xAuth if not consumer.xauth_allowed: return HttpResponseBadRequest('xAuth not allowed for this method') # Check Signature if not verify_oauth_request(request, oauth_request, consumer): return HttpResponseBadRequest('Could not verify xAuth request.') user = authenticate( x_auth_username=oauth_request.get_parameter('x_auth_username'), x_auth_password=oauth_request.get_parameter('x_auth_password'), x_auth_mode=oauth_request.get_parameter('x_auth_mode') ) if not user: return HttpResponseBadRequest('xAuth username or password is not valid') else: request.user = user # Handle Request Token try: #request_token = store.create_request_token(request, oauth_request, consumer, oauth_request.get('oauth_callback')) request_token = store.create_request_token(request, oauth_request, consumer, OUT_OF_BAND) request_token = store.authorize_request_token(request, oauth_request, request_token) except oauth.Error, err: return send_oauth_error(err) access_token = store.create_access_token(request, oauth_request, consumer, request_token) ret = urlencode({ 'oauth_token': access_token.key, 'oauth_token_secret': access_token.secret }) return HttpResponse(ret, content_type='application/x-www-form-urlencoded') @oauth_required def protected_resource_example(request): """ Test view for accessing a Protected Resource. """ return HttpResponse('Protected Resource access!') @login_required def fake_authorize_view(request, token, callback, params): """ Fake view for tests. It must return an ``HttpResponse``. You need to define your own in ``settings.OAUTH_AUTHORIZE_VIEW``. """ return HttpResponse('Fake authorize view for %s with params: %s.' % (token.consumer.name, params)) def fake_callback_view(request, **args): """ Fake view for tests. It must return an ``HttpResponse``. You can define your own in ``settings.OAUTH_CALLBACK_VIEW``. """ return HttpResponse('Fake callback view.') david-django-oauth-plus-91f6df5e8a28/requirements.txt0000644000000000000000000000005112251631323020742 0ustar 00000000000000Django>=1.3 oauth2>=1.5.170 South>=0.7.5 david-django-oauth-plus-91f6df5e8a28/setup.py0000644000000000000000000000243012251631323017173 0ustar 00000000000000from setuptools import setup, find_packages from oauth_provider import __version__ as version import os def strip_comments(l): return l.split('#', 1)[0].strip() def reqs(*f): return list(filter(None, [strip_comments(l) for l in open( os.path.join(os.getcwd(), *f)).readlines()])) install_requires = reqs('requirements.txt') setup( name='django-oauth-plus', version=version, description='Support of OAuth 1.0a in Django using python-oauth2.', author='David Larlet', author_email='david@larlet.fr', url='http://code.welldev.org/django-oauth-plus/', packages=find_packages(), classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Framework :: Django', ], # Make setuptools include all data files under version control, # svn and CVS by default include_package_data=True, zip_safe=False, # Tells setuptools to download setuptools_hg before running setup.py so # it can find the data files under Hg version control. setup_requires=['setuptools_hg'], install_requires=install_requires, ) david-django-oauth-plus-91f6df5e8a28/tox.ini0000644000000000000000000000237412251631323017003 0ustar 00000000000000[tox] downloadcache = {toxworkdir}/cache/ envlist = py2.7-django1.6, py2.6-django1.6, py2.6-django1.5.4, py2.7-django1.5, py2.6-django1.5, py2.7-django1.4, py2.6-django1.4, py2.7-django1.3, py2.6-django1.3 [base] deps = unittest-xml-reporting==1.6.0 oauth2==1.5.170 [testenv] commands={envpython} oauth_provider/runtests/runtests.py [testenv:py2.7-django1.6] basepython = python2.7 deps = django==1.6 {[base]deps} [testenv:py2.6-django1.6] basepython = python2.6 deps = django==1.6 {[base]deps} [testenv:py2.6-django1.5.4] # test environment for issue #45 basepython = python2.6 deps = django==1.5.4 {[base]deps} [testenv:py2.7-django1.5] basepython = python2.7 deps = django==1.5.5 {[base]deps} [testenv:py2.6-django1.5] basepython = python2.6 deps = django==1.5.5 {[base]deps} [testenv:py2.7-django1.4] basepython = python2.7 deps = django==1.4.10 {[base]deps} [testenv:py2.6-django1.4] basepython = python2.6 deps = django==1.4.10 {[base]deps} [testenv:py2.7-django1.3] basepython = python2.7 deps = django==1.3.7 {[base]deps} [testenv:py2.6-django1.3] basepython = python2.6 deps = django==1.3.7 {[base]deps}