mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
api: Move cookie session management logic to the authenticator for more flexibility
This commit is contained in:
parent
83f7721fdd
commit
f49f03d11e
3 changed files with 66 additions and 3 deletions
|
@ -34,7 +34,6 @@
|
||||||
#############################
|
#############################
|
||||||
_global:
|
_global:
|
||||||
namespace: yunohost
|
namespace: yunohost
|
||||||
cookie_name: yunohost.admin
|
|
||||||
authentication:
|
authentication:
|
||||||
api: ldap_admin
|
api: ldap_admin
|
||||||
cli: null
|
cli: null
|
||||||
|
|
|
@ -8,10 +8,14 @@ import time
|
||||||
|
|
||||||
from moulinette import m18n
|
from moulinette import m18n
|
||||||
from moulinette.authentication import BaseAuthenticator
|
from moulinette.authentication import BaseAuthenticator
|
||||||
from yunohost.utils.error import YunohostError
|
from moulinette.utils.text import random_ascii
|
||||||
|
|
||||||
|
from yunohost.utils.error import YunohostError, YunohostAuthenticationError
|
||||||
|
|
||||||
logger = logging.getLogger("yunohost.authenticators.ldap_admin")
|
logger = logging.getLogger("yunohost.authenticators.ldap_admin")
|
||||||
|
|
||||||
|
session_secret = random_ascii()
|
||||||
|
|
||||||
|
|
||||||
class Authenticator(BaseAuthenticator):
|
class Authenticator(BaseAuthenticator):
|
||||||
|
|
||||||
|
@ -66,3 +70,57 @@ class Authenticator(BaseAuthenticator):
|
||||||
# Free the connection, we don't really need it to keep it open as the point is only to check authentication...
|
# Free the connection, we don't really need it to keep it open as the point is only to check authentication...
|
||||||
if con:
|
if con:
|
||||||
con.unbind_s()
|
con.unbind_s()
|
||||||
|
|
||||||
|
def set_session_cookie(self, infos):
|
||||||
|
|
||||||
|
from bottle import response
|
||||||
|
|
||||||
|
assert isinstance(infos, dict)
|
||||||
|
|
||||||
|
# This allows to generate a new session id or keep the existing one
|
||||||
|
current_infos = self.get_session_cookie(raise_if_no_session_exists=False)
|
||||||
|
new_infos = {"id": current_infos["id"]}
|
||||||
|
new_infos.update(infos)
|
||||||
|
|
||||||
|
response.set_cookie(
|
||||||
|
"yunohost.admin",
|
||||||
|
new_infos,
|
||||||
|
secure=True,
|
||||||
|
secret=session_secret,
|
||||||
|
httponly=True,
|
||||||
|
# samesite="strict", # Bottle 0.12 doesn't support samesite, to be added in next versions
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_session_cookie(self, raise_if_no_session_exists=True):
|
||||||
|
|
||||||
|
from bottle import request
|
||||||
|
|
||||||
|
try:
|
||||||
|
# N.B. : here we implicitly reauthenticate the cookie
|
||||||
|
# because it's signed via the session_secret
|
||||||
|
# If no session exists (or if session is invalid?)
|
||||||
|
# it's gonna return the default empty dict,
|
||||||
|
# which we interpret as an authentication failure
|
||||||
|
infos = request.get_cookie(
|
||||||
|
"yunohost.admin", secret=session_secret, default={}
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
if not raise_if_no_session_exists:
|
||||||
|
return {"id": random_ascii()}
|
||||||
|
raise YunohostAuthenticationError("unable_authenticate")
|
||||||
|
|
||||||
|
if "id" not in infos:
|
||||||
|
infos["id"] = random_ascii()
|
||||||
|
|
||||||
|
# FIXME: Here, maybe we want to re-authenticate the session via the authenticator
|
||||||
|
# For example to check that the username authenticated is still in the admin group...
|
||||||
|
|
||||||
|
return infos
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def delete_session_cookie(self):
|
||||||
|
|
||||||
|
from bottle import response
|
||||||
|
|
||||||
|
response.set_cookie("yunohost.admin", "", max_age=-1)
|
||||||
|
response.delete_cookie("yunohost.admin")
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from moulinette.core import MoulinetteError
|
from moulinette.core import MoulinetteError, MoulinetteAuthenticationError
|
||||||
from moulinette import m18n
|
from moulinette import m18n
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,3 +60,9 @@ class YunohostValidationError(YunohostError):
|
||||||
def content(self):
|
def content(self):
|
||||||
|
|
||||||
return {"error": self.strerror, "error_key": self.key, **self.kwargs}
|
return {"error": self.strerror, "error_key": self.key, **self.kwargs}
|
||||||
|
|
||||||
|
|
||||||
|
class YunohostAuthenticationError(MoulinetteAuthenticationError):
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue