From e363e739f16e9f2eedfa554cdbdee5937d9f6b68 Mon Sep 17 00:00:00 2001 From: Lukas Garberg Date: Thu, 9 Jan 2025 08:16:15 +0100 Subject: [PATCH] nipapd: Support multiple claims in JWT auth Add support for a list of group claim names in JWT authentication. --- nipap/nipap.conf.dist | 3 ++- nipap/nipap/authlib.py | 39 ++++++++++++++++++++++++++------------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/nipap/nipap.conf.dist b/nipap/nipap.conf.dist index cd5483675..6cfce6686 100644 --- a/nipap/nipap.conf.dist +++ b/nipap/nipap.conf.dist @@ -183,9 +183,10 @@ db_path = /etc/nipap/local_auth.db ; path to SQLite database used # Group permissions enables granting read-write or read-only privileges based # on a users group membership in JWT. # -#group_claim_name = # name of claim containing groups #rw_group = #ro_group = +# name of claim containing groups. Can be a comma-separated list. +#group_claim_name = # # Options for the WWW UI # ---------------------- diff --git a/nipap/nipap/authlib.py b/nipap/nipap/authlib.py index 14169b9cc..7eca7b724 100644 --- a/nipap/nipap/authlib.py +++ b/nipap/nipap/authlib.py @@ -384,23 +384,36 @@ def authenticate(self): algorithms=[jwt_headers['alg']], options={"verify_aud": False}) - # Setting read and write rights + # Fetch group names from list of claims given in config group_claim_name = self._cfg.get('auth.backends.' + self.auth_backend, - 'group_claim_name', - fallback="groups") - if group_claim_name in payload: - if self._jwt_ro_group in payload[group_claim_name]: - self.readonly = True - self._authenticated = True - elif self._jwt_rw_group in payload[group_claim_name]: - self.readonly = False - self._authenticated = True - else: - self._authenticated = False + 'group_claim_name') + if group_claim_name is None: + self._logger.error("Missing group_claim_name in JWT auth configuration") + raise AuthError("Authentication error") + claim_groups = [] + for claim_name in map(str.strip, group_claim_name.split(",")): + if claim_name in payload: + if type(payload[claim_name]) is str: + claim_groups.append(payload[claim_name]) + elif type(payload[claim_name]) is list: + claim_groups += payload[claim_name] + else: + self._logger.error("Unknown type of claim %s (%s)", claim_name, payload[claim_name]) + + self._logger.debug("Found groups %s in JWT claims", claim_groups) + + # Validate if the user have RO, RW or nothing + if self._jwt_ro_group in claim_groups: + self.readonly = True + self._authenticated = True + elif self._jwt_rw_group in claim_groups: + self.readonly = False + self._authenticated = True else: - raise AuthError("Missing claim with group belonging in JWT") + self._authenticated = False + self._logger.debug("Login failed: JWT missing authorized groups") # auth failed except jwt.exceptions.DecodeError: