mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2026-03-15 17:37:22 +01:00
Set a cookie for /admin/munin pages to grant access to Munin reports
The /admin/munin routes used the same Authorization: header logic as the other API routes, but they are browsed directly in the browser because they are handled as static pages or as a proxy to a CGI script. This required users to enter their email username/password for HTTP basic authentication in the standard browser auth prompt, which wasn't ideal (and may leak the password in browser storage). It also stopped working when MFA was enabled for user accounts. A token is now set in a cookie when visiting /admin/munin which is then checked in the routes that proxy the Munin pages. The cookie's lifetime is kept limited to limit the opportunity for any unknown CSRF attacks via the Munin CGI script.
This commit is contained in:
@@ -72,14 +72,9 @@ class AuthService:
|
||||
return (None, ["admin"])
|
||||
|
||||
# If the password corresponds with a session token for the user, grant access for that user.
|
||||
if password in self.sessions and self.sessions[password]["email"] == username and not login_only:
|
||||
if self.get_session(username, password, "login", env) and not login_only:
|
||||
sessionid = password
|
||||
session = self.sessions[sessionid]
|
||||
if session["password_token"] != self.create_user_password_state_token(username, env):
|
||||
# This session is invalid because the user's password/MFA state changed
|
||||
# after the session was created.
|
||||
del self.sessions[sessionid]
|
||||
raise ValueError("Session expired.")
|
||||
if logout:
|
||||
# Clear the session.
|
||||
del self.sessions[sessionid]
|
||||
@@ -158,5 +153,14 @@ class AuthService:
|
||||
self.sessions[token] = {
|
||||
"email": username,
|
||||
"password_token": self.create_user_password_state_token(username, env),
|
||||
"type": type,
|
||||
}
|
||||
return token
|
||||
|
||||
def get_session(self, user_email, session_key, session_type, env):
|
||||
if session_key not in self.sessions: return None
|
||||
session = self.sessions[session_key]
|
||||
if session_type == "login" and session["email"] != user_email: return None
|
||||
if session["type"] != session_type: return None
|
||||
if session["password_token"] != self.create_user_password_state_token(session["email"], env): return None
|
||||
return session
|
||||
|
||||
Reference in New Issue
Block a user