return _wrapper
+class ControllerAuthMixin(object):
+ @staticmethod
+ def _delete_token_cookie(token):
+ cherrypy.response.cookie['token'] = token
+ cherrypy.response.cookie['token']['expires'] = 0
+ cherrypy.response.cookie['token']['max-age'] = 0
+
+ @staticmethod
+ def _set_token_cookie(url_prefix, token):
+ cherrypy.response.cookie['token'] = token
+ if url_prefix == 'https':
+ cherrypy.response.cookie['token']['secure'] = True
+ cherrypy.response.cookie['token']['HttpOnly'] = True
+ cherrypy.response.cookie['token']['path'] = '/'
+ cherrypy.response.cookie['token']['SameSite'] = 'Strict'
+
+
# Role-based access permissions decorators
def _set_func_permissions(func, permissions):
return func(*args, **kwargs)
return validate_args
return decorator
-
-
-def set_cookies(url_prefix, token):
- cherrypy.response.cookie['token'] = token
- if url_prefix == 'https':
- cherrypy.response.cookie['token']['secure'] = True
- cherrypy.response.cookie['token']['HttpOnly'] = True
- cherrypy.response.cookie['token']['path'] = '/'
- cherrypy.response.cookie['token']['SameSite'] = 'Strict'
from ..exceptions import InvalidCredentialsError, UserDoesNotExist
from ..services.auth import AuthManager, JwtManager
from ..settings import Settings
-from . import ApiController, ControllerDoc, EndpointDoc, RESTController, \
- allow_empty_body, set_cookies
+from . import ApiController, ControllerAuthMixin, ControllerDoc, EndpointDoc, \
+ RESTController, allow_empty_body
# Python 3.8 introduced `samesite` attribute:
# https://docs.python.org/3/library/http.cookies.html#morsel-objects
@ApiController('/auth', secure=False)
@ControllerDoc("Initiate a session with Ceph", "Auth")
-class Auth(RESTController):
+class Auth(RESTController, ControllerAuthMixin):
"""
Provide authenticates and returns JWT token.
"""
+
def create(self, username, password):
user_data = AuthManager.authenticate(username, password)
user_perms, pwd_expiration_date, pwd_update_required = None, None, None
# For backward-compatibility: PyJWT versions < 2.0.0 return bytes.
token = token.decode('utf-8') if isinstance(token, bytes) else token
- set_cookies(url_prefix, token)
+ self._set_token_cookie(url_prefix, token)
return {
'token': token,
'username': username,
logger.debug('Logout successful')
token = JwtManager.get_token_from_header()
JwtManager.blocklist_token(token)
+ self._delete_token_cookie(token)
redirect_url = '#/login'
if mgr.SSO_DB.protocol == 'saml2':
redirect_url = 'auth/saml2/slo'
from ..exceptions import UserDoesNotExist
from ..services.auth import JwtManager
from ..tools import prepare_url_prefix
-from . import BaseController, Controller, Endpoint, allow_empty_body, set_cookies
+from . import BaseController, Controller, ControllerAuthMixin, Endpoint, allow_empty_body
@Controller('/auth/saml2', secure=False)
-class Saml2(BaseController):
+class Saml2(BaseController, ControllerAuthMixin):
@staticmethod
def _build_req(request, post_data):
token = JwtManager.gen_token(username)
JwtManager.set_user(JwtManager.decode_token(token))
token = token.decode('utf-8')
- set_cookies(url_prefix, token)
+ self._set_token_cookie(url_prefix, token)
raise cherrypy.HTTPRedirect("{}/#/login?access_token={}".format(url_prefix, token))
return {
# pylint: disable=unused-argument
Saml2._check_python_saml()
JwtManager.reset_user()
- cherrypy.response.cookie['token'] = {'expires': 0, 'max-age': 0}
+ token = JwtManager.get_token_from_header()
+ self._delete_token_cookie(token)
url_prefix = prepare_url_prefix(mgr.get_module_option('url_prefix', default=''))
raise cherrypy.HTTPRedirect("{}/#/login".format(url_prefix))