models.py 3.06 KB
Newer Older
Lukas Burgey's avatar
Lukas Burgey committed
1
2
3
4
5
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
6
from ... import models
Lukas Burgey's avatar
Lukas Burgey committed
7
8
9
10
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
import json

11
oidc_client = {}
Lukas Burgey's avatar
Lukas Burgey committed
12
13
14
15
16
17
18


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)
19
20
    enabled = db_models.BooleanField(default=False)
    name = db_models.CharField(max_length=200)
Lukas Burgey's avatar
Lukas Burgey committed
21
22
23
24
25
26
27
28
29
30

    @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
31
32
33
34
35
36
        if self.id not in oidc_client:
            new_oidc_client = Client(client_authn_method=CLIENT_AUTHN_METHOD)
            new_oidc_client.provider_config(self.issuer_uri)
            new_oidc_client.store_registration_info(self.registration_response)
            oidc_client[self.id] = new_oidc_client
        return oidc_client[self.id]
Lukas Burgey's avatar
Lukas Burgey committed
37
38
39
40
41

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

42
43
44
45
    @property
    def name(self):
        return self.issuer_uri

Lukas Burgey's avatar
Lukas Burgey committed
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    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):
60
        return self.name
Lukas Burgey's avatar
Lukas Burgey committed
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
95
96
97
98
99
100


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