summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Dauvergne <bdauvergne@entrouvert.com>2014-03-06 14:57:27 (GMT)
committerBenjamin Dauvergne <bdauvergne@entrouvert.com>2014-03-06 14:57:27 (GMT)
commit42fa36551b7b2c43366ad262f95edecf05ab3a58 (patch)
tree8caf129af6f4bb27e589aa4c87aeb8a3b39a4174
downloadauthentic2-idp-oauth2-42fa36551b7b2c43366ad262f95edecf05ab3a58.zip
authentic2-idp-oauth2-42fa36551b7b2c43366ad262f95edecf05ab3a58.tar.gz
authentic2-idp-oauth2-42fa36551b7b2c43366ad262f95edecf05ab3a58.tar.bz2
first commit
-rw-r--r--README.txt18
-rw-r--r--authentic2_idp_oauth2/__init__.py7
-rw-r--r--authentic2_idp_oauth2/app_settings.py24
-rw-r--r--authentic2_idp_oauth2/forms.py11
-rw-r--r--authentic2_idp_oauth2/models.py0
-rw-r--r--authentic2_idp_oauth2/templates/rest_framework/api.html1
-rw-r--r--authentic2_idp_oauth2/urls.py12
-rw-r--r--authentic2_idp_oauth2/views.py39
-rwxr-xr-xsetup.py21
9 files changed, 133 insertions, 0 deletions
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..832025b
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,18 @@
+Install
+=======
+
+You just have to install the package in your virtualenv and relaunch, it will
+be automatically loaded by the plugin framework.
+
+
+Settings
+========
+
+AUTOMATIC_GRANT:
+
+ A list of URL prefix which are automatically granted scopes without asking
+ the user. Example::
+
+ A2_OAUTH2_AUTOMATIC_GRANT = (
+ ('http://localhost:8000/', ('read',)),
+ )
diff --git a/authentic2_idp_oauth2/__init__.py b/authentic2_idp_oauth2/__init__.py
new file mode 100644
index 0000000..5713c12
--- /dev/null
+++ b/authentic2_idp_oauth2/__init__.py
@@ -0,0 +1,7 @@
+class Plugin(object):
+ def get_before_urls(self):
+ from . import urls
+ return urls.urlpatterns
+
+ def get_apps(self):
+ return [__name__, 'rest_framework', 'provider', 'provider.oauth2']
diff --git a/authentic2_idp_oauth2/app_settings.py b/authentic2_idp_oauth2/app_settings.py
new file mode 100644
index 0000000..29819a6
--- /dev/null
+++ b/authentic2_idp_oauth2/app_settings.py
@@ -0,0 +1,24 @@
+class AppSettings(object):
+
+ def __init__(self, prefix):
+ self.prefix = prefix
+
+ @property
+ def AUTOMATIC_GRANT(self):
+ return self._setting('AUTOMATIC_GRANT', ())
+
+ def _setting(self, name, dflt):
+ from django.conf import settings
+ getter = getattr(settings,
+ 'ALLAUTH_SETTING_GETTER',
+ lambda name, dflt: getattr(settings, name, dflt))
+ return getter(self.prefix + name, dflt)
+
+
+
+# Ugly? Guido recommends this himself ...
+# http://mail.python.org/pipermail/python-ideas/2012-May/014969.html
+import sys
+app_settings = AppSettings('A2_OAUTH2_')
+app_settings.__name__ = __name__
+sys.modules[__name__] = app_settings
diff --git a/authentic2_idp_oauth2/forms.py b/authentic2_idp_oauth2/forms.py
new file mode 100644
index 0000000..10366fb
--- /dev/null
+++ b/authentic2_idp_oauth2/forms.py
@@ -0,0 +1,11 @@
+from django.forms import Form
+
+from provider.oauth2.models import Grant
+
+class EmptyForm(Form):
+ def __init__(self, *args, **kwargs):
+ self.scope = kwargs.pop('scope')
+ super(EmptyForm, self).__init__(*args, **kwargs)
+
+ def save(self, **kwargs):
+ return Grant(scope=self.scope)
diff --git a/authentic2_idp_oauth2/models.py b/authentic2_idp_oauth2/models.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/authentic2_idp_oauth2/models.py
diff --git a/authentic2_idp_oauth2/templates/rest_framework/api.html b/authentic2_idp_oauth2/templates/rest_framework/api.html
new file mode 100644
index 0000000..9c44916
--- /dev/null
+++ b/authentic2_idp_oauth2/templates/rest_framework/api.html
@@ -0,0 +1 @@
+{% extends "rest_framework/base.html" %}
diff --git a/authentic2_idp_oauth2/urls.py b/authentic2_idp_oauth2/urls.py
new file mode 100644
index 0000000..c257d8e
--- /dev/null
+++ b/authentic2_idp_oauth2/urls.py
@@ -0,0 +1,12 @@
+from django.conf.urls import patterns, url, include
+from django.contrib.auth.decorators import login_required
+
+from .views import Authorize
+
+urlpatterns = patterns('authentic2_idp_oauth2.views',
+ url('^idp/oauth2/authorize/confirm/?$',
+ login_required(Authorize.as_view()), name='authorize'),
+ url('^idp/oauth2/', include('provider.oauth2.urls', namespace='oauth2')),
+ url('^idp/oauth2/federation/$', 'user_info', name='user-info'),
+ url('^idp/oauth2/user-info/$', 'user_info', name='user-info'),
+)
diff --git a/authentic2_idp_oauth2/views.py b/authentic2_idp_oauth2/views.py
new file mode 100644
index 0000000..8ee9c41
--- /dev/null
+++ b/authentic2_idp_oauth2/views.py
@@ -0,0 +1,39 @@
+from django.conf import settings
+
+from rest_framework.decorators import (api_view, authentication_classes,
+ permission_classes)
+from rest_framework.authentication import (OAuth2Authentication,
+ SessionAuthentication)
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.response import Response
+
+from provider.oauth2.views import Authorize
+from provider import scope
+
+from . import forms, app_settings
+
+@api_view(['GET'])
+@authentication_classes([OAuth2Authentication, SessionAuthentication])
+@permission_classes([IsAuthenticated])
+def user_info(request):
+ user = request.user
+ return Response({
+ 'username': user.username,
+ 'first_name': user.first_name,
+ 'last_name': user.last_name,
+ 'email': user.email,
+ 'display_name': user.get_full_name(),
+ 'role': user.groups.values_list('name', flat=True),
+ })
+
+class Authorize(Authorize):
+ def get_authorization_form(self, request, client, data, client_data):
+ for url_prefix, scopes in app_settings.AUTOMATIC_GRANT:
+ if client.url.startswith(url_prefix) and \
+ scope.check(client_data['scope'], scope.to_int(*scopes)):
+ # return an always valid form
+ return forms.EmptyForm({}, scope=client_data['scope'])
+ return super(Authorize, self).get_authorization_form(
+ request, client, data, client_data)
+
+
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..337557c
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+from setuptools import setup, find_packages
+import os
+
+setup(name='authentic2-idp-oauth2',
+ version='1.0',
+ license='AGPLv3',
+ description='Authentic2 IdP OAuth2',
+ author="Entr'ouvert",
+ author_email="info@entrouvert.com",
+ packages=find_packages(os.path.dirname(__file__) or '.'),
+ install_requires=[
+ 'django-oauth2-provider',
+ 'djangorestframework',
+ ],
+ entry_points={
+ 'authentic2.plugin': [
+ 'authentic-idp-oauth2 = authentic2_idp_oauth2:Plugin',
+ ],
+ },
+)