Projet

Général

Profil

Télécharger (6,27 ko) Statistiques
| Branche: | Tag: | Révision:

oidc / ckanext / ozwillo_pyoidc / oidc.py @ b71e8531

1 c8204b73 Serghei Mihai
from oic.exception import MissingAttribute
2
from oic import oic
3
from oic.oauth2 import rndstr, ErrorResponse
4
from oic.oic import ProviderConfigurationResponse, AuthorizationResponse
5
from oic.oic import RegistrationResponse
6
from oic.oic import AuthorizationRequest
7
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
8
9
import logging
10
11
logger = logging.getLogger(__name__)
12
13 b71e8531 Serghei MIHAI
import conf
14 c8204b73 Serghei Mihai
15
class OIDCError(Exception):
16
    pass
17
18
19
class Client(oic.Client):
20
    def __init__(self, client_id=None, ca_certs=None,
21
                 client_prefs=None, client_authn_method=None, keyjar=None,
22
                 verify_ssl=True, behaviour=None):
23
        oic.Client.__init__(self, client_id, ca_certs, client_prefs,
24
                            client_authn_method, keyjar, verify_ssl)
25
        if behaviour:
26
            self.behaviour = behaviour
27
28
    def create_authn_request(self, session, acr_value=None):
29
        session["state"] = rndstr()
30
        session["nonce"] = rndstr()
31
        request_args = {
32
            "response_type": self.behaviour["response_type"],
33
            "scope": self.behaviour["scope"],
34
            "state": session["state"],
35
            # "nonce": session["nonce"],
36
            "redirect_uri": self.registration_response["redirect_uris"][0]
37
        }
38
39
        if acr_value is not None:
40
            request_args["acr_values"] = acr_value
41
42
        cis = self.construct_AuthorizationRequest(request_args=request_args)
43
        logger.debug("request: %s" % cis)
44
45
        url, body, ht_args, cis = self.uri_and_body(AuthorizationRequest, cis,
46
                                                    method="GET",
47
                                                    request_args=request_args)
48
49
        logger.debug("body: %s" % body)
50
        logger.info("URL: %s" % url)
51
        logger.debug("ht_args: %s" % ht_args)
52
53
        return str(url), ht_args
54
55
    def callback(self, response):
56
        """
57
        This is the method that should be called when an AuthN response has been
58
        received from the OP.
59
60
        :param response: The URL returned by the OP
61
        :return:
62
        """
63
        authresp = self.parse_response(AuthorizationResponse, response,
64
                                       sformat="dict", keyjar=self.keyjar)
65
66
        if isinstance(authresp, ErrorResponse):
67
            return OIDCError("Access denied")
68
69
        try:
70
            self.id_token[authresp["state"]] = authresp["id_token"]
71
        except KeyError:
72
            pass
73
74
        if self.behaviour["response_type"] == "code":
75
            # get the access token
76
            try:
77
                args = {
78
                    "grant_type": "authorization_code",
79
                    "code": authresp["code"],
80
                    "redirect_uri": self.registration_response[
81
                        "redirect_uris"][0],
82
                    "client_id": self.client_id,
83
                    "client_secret": self.client_secret
84
                }
85
86
                atresp = self.do_access_token_request(
87
                    scope="openid", state=authresp["state"], request_args=args,
88
                    authn_method=self.registration_response["token_endpoint_auth_method"])
89
            except Exception as err:
90
                logger.error("%s" % err)
91
                raise
92
93
            if isinstance(atresp, ErrorResponse):
94
                raise OIDCError("Invalid response %s." % atresp["error"])
95
96 1f01e54b Serghei MIHAI
        inforesp = self.do_user_info_request(state=authresp["state"],
97
                                             behavior='use_authorization_header')
98 c8204b73 Serghei Mihai
99
        if isinstance(inforesp, ErrorResponse):
100
            raise OIDCError("Invalid response %s." % inforesp["error"])
101
102
        userinfo = inforesp.to_dict()
103
104
        logger.debug("UserInfo: %s" % inforesp)
105
106
        return userinfo
107
108 b71e8531 Serghei MIHAI
def create_client(**kwargs):
109
    """
110
    kwargs = config.CLIENT.iteritems
111
    """
112
    _key_set = set(kwargs.keys())
113
    args = {}
114
    for param in ["verify_ssl"]:
115
        try:
116
            args[param] = kwargs[param]
117
        except KeyError:
118
            pass
119 c8204b73 Serghei Mihai
        else:
120 b71e8531 Serghei MIHAI
            _key_set.discard(param)
121 c8204b73 Serghei Mihai
122 b71e8531 Serghei MIHAI
    client = Client(client_authn_method=CLIENT_AUTHN_METHOD,
123
                    behaviour=kwargs["behaviour"],
124
                    verify_ssl=conf.VERIFY_SSL, **args)
125 c8204b73 Serghei Mihai
126 b71e8531 Serghei MIHAI
    # The behaviour parameter is not significant for the election process
127
    _key_set.discard("behaviour")
128
    for param in ["allow"]:
129 c8204b73 Serghei Mihai
        try:
130 b71e8531 Serghei MIHAI
            setattr(client, param, kwargs[param])
131 c8204b73 Serghei Mihai
        except KeyError:
132 b71e8531 Serghei MIHAI
            pass
133
        else:
134
            _key_set.discard(param)
135
136
    if _key_set == set(["client_info"]):  # Everything dynamic
137
        # There has to be a userid
138
        if not userid:
139
            raise MissingAttribute("Missing userid specification")
140 c8204b73 Serghei Mihai
141 b71e8531 Serghei MIHAI
        # Find the service that provides information about the OP
142
        issuer = client.wf.discovery_query(userid)
143
        # Gather OP information
144
        _ = client.provider_config(issuer)
145
        # register the client
146
        _ = client.register(client.provider_info["registration_endpoint"],
147
                            **kwargs["client_info"])
148
    elif _key_set == set(["client_info", "srv_discovery_url"]):
149
        # Ship the webfinger part
150
        # Gather OP information
151
        _ = client.provider_config(kwargs["srv_discovery_url"])
152
        # register the client
153
        _ = client.register(client.provider_info["registration_endpoint"],
154
                            **kwargs["client_info"])
155
    elif _key_set == set(["provider_info", "client_info"]):
156
        client.handle_provider_config(
157
            ProviderConfigurationResponse(**kwargs["provider_info"]),
158
            kwargs["provider_info"]["issuer"])
159
        _ = client.register(client.provider_info["registration_endpoint"],
160
                            **kwargs["client_info"])
161
    elif _key_set == set(["provider_info", "client_registration"]):
162
        client.handle_provider_config(
163
            ProviderConfigurationResponse(**kwargs["provider_info"]),
164
            kwargs["provider_info"]["issuer"])
165
        client.store_registration_info(RegistrationResponse(
166
            **kwargs["client_registration"]))
167
    elif _key_set == set(["srv_discovery_url", "client_registration"]):
168
        _ = client.provider_config(kwargs["srv_discovery_url"])
169
        client.store_registration_info(RegistrationResponse(
170
            **kwargs["client_registration"]))
171
    else:
172
        raise Exception("Configuration error ?")
173
174
    return client