models.py 2.83 KB
Newer Older
Lukas Burgey's avatar
Lukas Burgey committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

from django.db import models as db_models
from oic.oic import Client
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
from oic.oic.message import RegistrationResponse
from urllib.request import Request, urlopen
from .. import models
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
import json

oidc_client = None


class OIDCConfig(db_models.Model):
    client_id = db_models.CharField(max_length=200)
    client_secret = db_models.CharField(max_length=200)
    redirect_uri = db_models.CharField(max_length=200)
    issuer_uri = db_models.CharField(max_length=200)

    @property
    def registration_response(self):
        info = {"client_id": self.client_id,
                "client_secret": self.client_secret}
        return RegistrationResponse(**info)

    @property
    def oidc_client(self):
        global oidc_client
        if oidc_client is None:
            oidc_client = Client(client_authn_method=CLIENT_AUTHN_METHOD)
            oidc_client.provider_config(self.issuer_uri)
            oidc_client.store_registration_info(self.registration_response)
        return oidc_client

    @property
    def provider_info(self):
        return self.oidc_client.provider_info

    def get_auth_request(self, client, state):
        args = {
            'client_id': self.client_id,
            'response_type': 'code',
            'scope': ['openid', 'profile', 'email'],
            'redirect_uri': self.redirect_uri,
            'state': state,
        }

        auth_req = client.construct_AuthorizationRequest(
                request_args=args)
        return auth_req.request(client.authorization_endpoint)

    def __str__(self):
        return self.issuer_uri


def get_oidc_client():
    # TODO dubious
    oidc_config = OIDCConfig.objects.all()[settings.OIDC_CONFIG_INDEX]
    return oidc_config.oidc_client


class OIDCTokenAuthBackend(object):
    def get_user_info(self, access_token, token_type='Bearer'):
        q = Request(get_oidc_client().provider_info['userinfo_endpoint'])
        auth = (token_type + ' ' + access_token)
        q.add_header('Authorization', auth)

        userinfo_bytes = urlopen(q).read()
        return json.loads(userinfo_bytes.decode('UTF-8'))

    def authenticate(self, request, token=None):
        if token is None:
            return None

        user_info = self.get_user_info(token)
        try:
            user = models.User.objects.get(
                    sub=user_info['sub'])

            return user
        except ObjectDoesNotExist:
            # if we do not know the user yet, we create him
            user = models.construct_user(user_info)
            user.save()
            return user

        return None

    def get_user(self, user_id):
        try:
            return models.User.objects.get(pk=user_id)
        except models.User.DoesNotExist:
            return None