Commit 1b218b64 authored by Yakubov, Sergey's avatar Yakubov, Sergey
Browse files

refactor token refresh, logout on failed refresh

parent 78b60271
Loading
Loading
Loading
Loading
+0 −10
Original line number Diff line number Diff line
@@ -821,16 +821,6 @@ class UniverseApplication(StructuredApp, GalaxyManagerApplication):
            self.authnz_manager = managers.AuthnzManager(
                self, self.config.oidc_config_file, self.config.oidc_backends_config_file
            )
            if self.is_webapp:
                self.refresh_oidc_tokens_task = IntervalTask(
                    func=lambda: self.authnz_manager.refresh_expiring_oidc_tokens(self.model.session),
                    name="RefreshOIDCTokensTask",
                    interval=self.config.oidc_refresh_tokens_interval,
                    immediate_start=True,
                    time_execution=True,
                )
                self.application_stack.register_postfork_function(self.refresh_oidc_tokens_task.start)
                self.haltables.append(("RefreshOIDCTokensTask", self.refresh_oidc_tokens_task.shutdown))

            # If there is only a single external authentication provider in use
            # TODO: Future work will expand on this and provide an interface for
+23 −15
Original line number Diff line number Diff line
import builtins
import logging
import fcntl

from galaxy import (
    exceptions,
@@ -282,16 +283,21 @@ class AuthnzManager:
            raise exceptions.ItemAccessibilityException(msg)

    def refresh_expiring_oidc_tokens_for_provider(self, trans, auth):
        with open("/dev/null", "w") as lock:
            try:
                fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
                success, message, backend = self._get_authnz_backend(auth.provider)
                if success is False:
                    msg = f"An error occurred when refreshing user token on `{auth.provider}` identity provider: {message}"
                    log.error(msg)
                    return False
            refreshed = backend.refresh(trans, auth)
                refreshed = backend.refresh(trans, auth, 30)
                if refreshed:
                    log.debug(f"Refreshed user token via `{auth.provider}` identity provider")
                return True
            except BlockingIOError:
                log.debug("Another process is refreshing, skipping")
                return True
            except Exception:
                log.exception("An error occurred when refreshing user token")
                return False
@@ -299,11 +305,13 @@ class AuthnzManager:
    def refresh_expiring_oidc_tokens(self, trans, user=None):
        user = trans.user or user
        if not isinstance(user, model.User):
            return
            return True
        success = False
        for auth in user.custos_auth or []:
            self.refresh_expiring_oidc_tokens_for_provider(trans, auth)
            success |= self.refresh_expiring_oidc_tokens_for_provider(trans, auth)
        for auth in user.social_auth or []:
            self.refresh_expiring_oidc_tokens_for_provider(trans, auth)
            success |= self.refresh_expiring_oidc_tokens_for_provider(trans, auth)
        return success

    def authenticate(self, provider, trans, idphint=None):
        """
+20 −0
Original line number Diff line number Diff line
@@ -347,6 +347,26 @@ class GalaxyWebTransaction(base.DefaultWebTransaction, context.ProvidesHistoryCo
            self._ensure_valid_session(session_cookie)

        if self.galaxy_session:
            success = True
            if hasattr(self.app, "authnz_manager") and self.app.authnz_manager:
                success = self.app.authnz_manager.refresh_expiring_oidc_tokens(self)
            if not success:
                self.handle_user_logout()
                if self.environ.get("is_api_request", False):
                    self.response.status = 401
                    self.user = None
                    self.galaxy_session = None
                else:
                    self.response.send_redirect(
                        url_for(
                            controller="login",
                            action="start",
                            message="You have been logged from your identity provider.  Please log in again to continue using Galaxy.",
                            status="info",
                            use_panels=True,
                        )
                    )
                return
            # When we've authenticated by session, we have to check the
            # following.
            # Prevent deleted users from accessing Galaxy