]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | # -*- coding: utf-8 -*- |
2 | from __future__ import absolute_import | |
3 | ||
11fdf7f2 TL |
4 | import cherrypy |
5 | ||
6 | try: | |
7 | from onelogin.saml2.auth import OneLogin_Saml2_Auth | |
8 | from onelogin.saml2.errors import OneLogin_Saml2_Error | |
9 | from onelogin.saml2.settings import OneLogin_Saml2_Settings | |
10 | ||
11 | python_saml_imported = True | |
12 | except ImportError: | |
13 | python_saml_imported = False | |
14 | ||
eafe8130 | 15 | from .. import mgr |
11fdf7f2 TL |
16 | from ..exceptions import UserDoesNotExist |
17 | from ..services.auth import JwtManager | |
18 | from ..tools import prepare_url_prefix | |
adb31ebb | 19 | from . import BaseController, Controller, Endpoint, allow_empty_body, set_cookies |
11fdf7f2 TL |
20 | |
21 | ||
22 | @Controller('/auth/saml2', secure=False) | |
23 | class Saml2(BaseController): | |
24 | ||
25 | @staticmethod | |
26 | def _build_req(request, post_data): | |
27 | return { | |
28 | 'https': 'on' if request.scheme == 'https' else 'off', | |
29 | 'http_host': request.host, | |
30 | 'script_name': request.path_info, | |
31 | 'server_port': str(request.port), | |
32 | 'get_data': {}, | |
33 | 'post_data': post_data | |
34 | } | |
35 | ||
36 | @staticmethod | |
37 | def _check_python_saml(): | |
38 | if not python_saml_imported: | |
9f95a23c | 39 | raise cherrypy.HTTPError(400, 'Required library not found: `python3-saml`') |
11fdf7f2 TL |
40 | try: |
41 | OneLogin_Saml2_Settings(mgr.SSO_DB.saml2.onelogin_settings) | |
42 | except OneLogin_Saml2_Error: | |
43 | raise cherrypy.HTTPError(400, 'Single Sign-On is not configured.') | |
44 | ||
45 | @Endpoint('POST', path="") | |
adb31ebb | 46 | @allow_empty_body |
11fdf7f2 TL |
47 | def auth_response(self, **kwargs): |
48 | Saml2._check_python_saml() | |
49 | req = Saml2._build_req(self._request, kwargs) | |
50 | auth = OneLogin_Saml2_Auth(req, mgr.SSO_DB.saml2.onelogin_settings) | |
51 | auth.process_response() | |
52 | errors = auth.get_errors() | |
53 | ||
54 | if auth.is_authenticated(): | |
55 | JwtManager.reset_user() | |
56 | username_attribute = auth.get_attribute(mgr.SSO_DB.saml2.get_username_attribute()) | |
57 | if username_attribute is None: | |
58 | raise cherrypy.HTTPError(400, | |
59 | 'SSO error - `{}` not found in auth attributes. ' | |
60 | 'Received attributes: {}' | |
61 | .format( | |
62 | mgr.SSO_DB.saml2.get_username_attribute(), | |
63 | auth.get_attributes())) | |
64 | username = username_attribute[0] | |
65 | url_prefix = prepare_url_prefix(mgr.get_module_option('url_prefix', default='')) | |
66 | try: | |
67 | mgr.ACCESS_CTRL_DB.get_user(username) | |
68 | except UserDoesNotExist: | |
69 | raise cherrypy.HTTPRedirect("{}/#/sso/404".format(url_prefix)) | |
70 | ||
71 | token = JwtManager.gen_token(username) | |
72 | JwtManager.set_user(JwtManager.decode_token(token)) | |
73 | token = token.decode('utf-8') | |
adb31ebb | 74 | set_cookies(url_prefix, token) |
11fdf7f2 | 75 | raise cherrypy.HTTPRedirect("{}/#/login?access_token={}".format(url_prefix, token)) |
9f95a23c TL |
76 | |
77 | return { | |
78 | 'is_authenticated': auth.is_authenticated(), | |
79 | 'errors': errors, | |
80 | 'reason': auth.get_last_error_reason() | |
81 | } | |
11fdf7f2 TL |
82 | |
83 | @Endpoint(xml=True) | |
84 | def metadata(self): | |
85 | Saml2._check_python_saml() | |
86 | saml_settings = OneLogin_Saml2_Settings(mgr.SSO_DB.saml2.onelogin_settings) | |
87 | return saml_settings.get_sp_metadata() | |
88 | ||
89 | @Endpoint(json_response=False) | |
90 | def login(self): | |
91 | Saml2._check_python_saml() | |
92 | req = Saml2._build_req(self._request, {}) | |
93 | auth = OneLogin_Saml2_Auth(req, mgr.SSO_DB.saml2.onelogin_settings) | |
94 | raise cherrypy.HTTPRedirect(auth.login()) | |
95 | ||
96 | @Endpoint(json_response=False) | |
97 | def slo(self): | |
98 | Saml2._check_python_saml() | |
99 | req = Saml2._build_req(self._request, {}) | |
100 | auth = OneLogin_Saml2_Auth(req, mgr.SSO_DB.saml2.onelogin_settings) | |
101 | raise cherrypy.HTTPRedirect(auth.logout()) | |
102 | ||
103 | @Endpoint(json_response=False) | |
104 | def logout(self, **kwargs): | |
105 | # pylint: disable=unused-argument | |
106 | Saml2._check_python_saml() | |
107 | JwtManager.reset_user() | |
adb31ebb | 108 | cherrypy.response.cookie['token'] = {'expires': 0, 'max-age': 0} |
11fdf7f2 TL |
109 | url_prefix = prepare_url_prefix(mgr.get_module_option('url_prefix', default='')) |
110 | raise cherrypy.HTTPRedirect("{}/#/login".format(url_prefix)) |