Skip to content

User session still active when verify_claims() returns False #547

@sbanoeon

Description

@sbanoeon

I have specified AUTHENTICATION_BACKENDS = CustomOIDCAB and inherited OIDCAuthenticationBackend in this way:

class CustomOIDCAB(OIDCAuthenticationBackend):
    def create_user(self, claims):
        user = super(CustomOIDCAB, self).create_user(claims)
        return self.__set_user_values(user, claims)

    def update_user(self, user, claims):
        return self.__set_user_values(user, claims)

    def __set_user_values(self, user, claims):
        path = settings.OIDC_TOKEN_ROLE_PATH
        parsed_result = parse(path).find(claims)
        if len(parsed_result) > 0:
            roles = parsed_result[0].value

        user.first_name = claims.get("given_name", "")
        user.last_name = claims.get("family_name", "")
        user.username = claims.get("preferred_username", "")
        user.email = claims.get("email", "")

        user.is_superuser = user.is_staff = settings.OIDC_SUPER_ADMIN_ROLE in roles
        user.is_server_admin = settings.OIDC_SERVER_ADMIN_ROLE in roles
        user.is_project_admin = settings.OIDC_PROJECT_ADMIN_ROLE in roles

        # Overwriting password field in model also possible (allow None),
        # but then additional testing for local authentication is needed (None not allowed for local users)
        user.password = "This is not a real password!"

        user.save()

        logger.info(user.username + " is accessing with roles " + roles.__str__())
        return user

    def verify_claims(self, claims):
        logger.info("User " + claims.get("preferred_username") + " is verifying claim")
        verified = super(CustomOIDCAB, self).verify_claims(claims)
        path = settings.OIDC_TOKEN_ROLE_PATH
        parsed_result = parse(path).find(claims)
        if len(parsed_result) > 0:
            value = parsed_result[0].value
        else:
            value = []
        is_user = settings.OIDC_USER_ROLE in value

        if not claims.get("email"):
            messages.error(self.request, "User must have email configured")
            return False
        elif verified and is_user:
            return True
        else:
            messages.error(
                self.request,
                "User must have at least the role " + settings.OIDC_USER_ROLE,
            )
            return False

    def authenticate(self, request, **kwargs):
        try:
            user = super().authenticate(request, **kwargs)
            return user
        except Exception as e:
            messages.error(self.request, "Authentication Error: " + e.__str__())
            return None

I expect if the verify_claims function returns False then the user should not be saved in session and upon clicking on Login, the user must be asked to login again. But even when the verify_claims is returning False, I am redirected to my home page, but upon clicking on Login button, the old unverified user is fetched from the session.

I am using Keycloak as the oidc server with mozilla_django_oidc==2.0.0.

Am I doing something wrong here or is this not the expected workflow of the library?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions