Skip to content
68 changes: 62 additions & 6 deletions simple_sso/sso_client/client.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# -*- coding: utf-8 -*-
from django.conf.urls import url
from django.contrib.auth import login
from django.contrib.auth import login, logout
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
from django.views.generic import View
from itsdangerous import URLSafeTimedSerializer
from webservices.sync import SyncConsumer
from django.contrib.auth import get_user_model
from django.conf import settings

from ..compat import (
NoReverseMatch,
Expand All @@ -17,6 +20,8 @@
urlencode,
)

User = get_user_model()


class LoginView(View):
client = None
Expand All @@ -29,7 +34,42 @@ def get(self, request):
path = reverse('simple-sso-authenticate')
redirect_to = urlunparse((scheme, netloc, path, '', query, ''))
request_token = self.client.get_request_token(redirect_to)
host = urljoin(self.client.server_url, 'authorize/')
if request_token != "":
host = urljoin(self.client.server_url, 'authorize/')
url = '%s?%s' % (host, urlencode([('token', request_token)]))
return HttpResponseRedirect(url)
else:
return redirect(settings.SSO_CLIENT)

def get_next(self):
"""
Given a request, returns the URL where a user should be redirected to
after login. Defaults to '/'
"""
next = self.request.GET.get('next', None)
if not next:
return settings.SSO_DASHBOARD_REDIRECT
netloc = urlparse(next)[1]
# Heavier security check -- don't allow redirection to a different
# host.
# Taken from django.contrib.auth.views.login
if netloc and netloc != self.request.get_host():
return settings.SSO_DASHBOARD_REDIRECT
return next


class LogoutView(View):
client = None

def get(self, request):
next = self.get_next()
scheme = 'https' if request.is_secure() else 'http'
query = urlencode([('next', next)])
netloc = request.get_host()
path = reverse('simple-sso-logoutauth')
redirect_to = urlunparse((scheme, netloc, path, '', query, ''))
request_token = self.client.get_request_token(redirect_to)
host = urljoin(self.client.server_url, 'logout/')
url = '%s?%s' % (host, urlencode([('token', request_token)]))
return HttpResponseRedirect(url)

Expand All @@ -40,13 +80,13 @@ def get_next(self):
"""
next = self.request.GET.get('next', None)
if not next:
return '/'
return settings.SSO_HOME_REDIRECT
netloc = urlparse(next)[1]
# Heavier security check -- don't allow redirection to a different
# host.
# Taken from django.contrib.auth.views.login
if netloc and netloc != self.request.get_host():
return '/'
return settings.SSO_HOME_REDIRECT
return next


Expand All @@ -63,9 +103,20 @@ def get(self, request):
return HttpResponseRedirect(next)


class LogoutAuthView(LogoutView):
client = None

def get(self, request):
logout(request)
next = self.get_next()
return HttpResponseRedirect(next)


class Client(object):
login_view = LoginView
authenticate_view = AuthenticateView
logout_auth_view = LogoutAuthView
logout_view = LogoutView
backend = "%s.%s" % (ModelBackend.__module__, ModelBackend.__name__)
user_extra_data = None

Expand Down Expand Up @@ -95,7 +146,10 @@ def get_request_token(self, redirect_to):
except NoReverseMatch:
# thisisfine
url = '/request-token/'
return self.consumer.consume(url, {'redirect_to': redirect_to})['request_token']
try:
return self.consumer.consume(url, {'redirect_to': redirect_to})
except:
return {"request_token": ""}

def get_user(self, access_token):
data = {'access_token': access_token}
Expand All @@ -116,12 +170,14 @@ def build_user(self, user_data):
user = User.objects.get(username=user_data['username'])
except User.DoesNotExist:
user = User(**user_data)
user.set_unusable_password()
# user.set_unusable_password()
user.save()
return user

def get_urls(self):
return [
url(r'^$', self.login_view.as_view(client=self), name='simple-sso-login'),
url(r'^authenticate/$', self.authenticate_view.as_view(client=self), name='simple-sso-authenticate'),
url(r'^logout/$', self.logout_view.as_view(client=self), name='simple-sso-logout'),
url(r'^authlogout/$', self.logout_auth_view.as_view(client=self), name='simple-sso-logoutauth'),
]
30 changes: 28 additions & 2 deletions simple_sso/sso_server/server.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.contrib.auth import logout
from django.conf.urls import url
from django.contrib import admin
from django.contrib.admin.options import ModelAdmin
Expand All @@ -12,6 +13,7 @@
import datetime
from webservices.models import Provider
from webservices.sync import provider_for_django
from django.conf import settings

from ..compat import reverse, urlparse, urlencode, urlunparse, user_is_authenticated

Expand Down Expand Up @@ -111,7 +113,8 @@ class VerificationProvider(BaseProvider, AuthorizeView):
def provide(self, data):
token = data['access_token']
try:
self.token = Token.objects.select_related('user').get(access_token=token, consumer=self.consumer)
self.token = Token.objects.select_related('user').get(
access_token=token, consumer=self.consumer)
except Token.DoesNotExist:
return self.token_not_found()
if not self.check_token_timeout():
Expand All @@ -130,13 +133,34 @@ class ConsumerAdmin(ModelAdmin):
readonly_fields = ['public_key', 'private_key']


class LogoutView(AuthorizeView):
server = None

def handle_authenticated_user(self):
parse_result = (urlparse(self.token.redirect_to))
query_dict = QueryDict(parse_result.query, mutable=True)
url = urlunparse(
(
parse_result.scheme,
parse_result.netloc,
parse_result.path,
'',
query_dict.urlencode(), ''))
logout(self.request)
return HttpResponseRedirect(url)

def handle_unauthenticated_user(self):
return HttpResponseRedirect(self.token.redirect_to)


class Server(object):
request_token_provider = RequestTokenProvider
authorize_view = AuthorizeView
verification_provider = VerificationProvider
token_timeout = datetime.timedelta(minutes=5)
logout_view = LogoutView
client_admin = ConsumerAdmin
auth_view_name = 'login'
auth_view_name = settings.SSO_AUTH_VIEW_NAME

def __init__(self, **kwargs):
for key, value in kwargs.items():
Expand All @@ -161,6 +185,7 @@ def get_user_data(self, user, consumer, extra_data=None):
'is_staff': False,
'is_superuser': False,
'is_active': user.is_active,
'password': user.password
}
if extra_data:
user_data['extra_data'] = self.get_user_extra_data(
Expand All @@ -172,4 +197,5 @@ def get_urls(self):
url(r'^request-token/$', provider_for_django(self.request_token_provider(server=self)), name='simple-sso-request-token'),
url(r'^authorize/$', self.authorize_view.as_view(server=self), name='simple-sso-authorize'),
url(r'^verify/$', provider_for_django(self.verification_provider(server=self)), name='simple-sso-verify'),
url(r'^logout/$', self.logout_view.as_view(server=self), name='simple-sso-serverlogout'),
]