Beispiel #1
0
    def get(self):
        """
        The login flow is:
        user
        -> {fence}/login/shib?redirect={portal}
        -> user login at {nih_shibboleth_idp}
        -> nih idp POST to fence shibboleth and establish a shibboleth sp
           session
        -> redirect to {fence}/login/shib/login that sets up fence session
        -> redirect to portal
        """
        redirect_url = flask.request.args.get("redirect")
        validate_redirect(redirect_url)
        if redirect_url:
            flask.session["redirect"] = redirect_url

        # figure out which IDP to target with shibboleth
        # check out shibboleth docs here for more info:
        # https://wiki.shibboleth.net/confluence/display/SP3/SSO
        entityID = flask.request.args.get("shib_idp")
        flask.session["entityID"] = entityID
        # TODO: use OPENID_CONNECT.shibboleth.redirect_url instead of hardcoded
        actual_redirect = config["BASE_URL"] + "/login/shib/login"
        if not entityID or entityID == "urn:mace:incommon:nih.gov":
            # default to SSO_URL from the config which should be NIH login
            return flask.redirect(config["SSO_URL"] + actual_redirect)
        return flask.redirect(config["BASE_URL"] +
                              "/Shibboleth.sso/Login?entityID={}&target={}".
                              format(entityID, actual_redirect))
Beispiel #2
0
    def get(self):
        redirect_url = flask.request.args.get("redirect")
        validate_redirect(redirect_url)
        flask.redirect_url = redirect_url
        if flask.redirect_url:
            flask.session["redirect"] = flask.redirect_url

        mock_login = (
            config["OPENID_CONNECT"].get(self.idp_name.lower(), {}).get("mock", False)
        )

        # to support older cfgs, new cfgs should use the `mock` field in OPENID_CONNECT
        legacy_mock_login = config.get(
            "MOCK_{}_AUTH".format(self.idp_name.upper()), False
        )

        mock_default_user = (
            config["OPENID_CONNECT"]
            .get(self.idp_name.lower(), {})
            .get("mock_default_user", "*****@*****.**")
        )

        if mock_login or legacy_mock_login:
            # prefer dev cookie for mocked username, fallback on configuration
            username = flask.request.cookies.get(
                config.get("DEV_LOGIN_COOKIE_NAME"), mock_default_user
            )
            resp = _login(username, self.idp_name)
            prepare_login_log(self.idp_name)
            return resp

        return flask.redirect(self.client.get_auth_url())
Beispiel #3
0
    def get(self):
        """Handle ``GET /login/fence``."""
        oauth2_redirect_uri = flask.current_app.fence_client.client_kwargs.get(
            "redirect_uri")
        redirect_url = flask.request.args.get("redirect")
        if redirect_url:
            validate_redirect(redirect_url)
            flask.session["redirect"] = redirect_url
        (
            authorization_url,
            state,
        ) = flask.current_app.fence_client.generate_authorize_redirect(
            oauth2_redirect_uri, prompt="login")

        # add idp parameter to the authorization URL
        if "idp" in flask.request.args:
            idp = flask.request.args["idp"]
            flask.session["fence_idp"] = idp
            params = {"idp": idp}
            # if requesting to login through Shibboleth, also add shib_idp
            # parameter to the authorization URL
            if idp == "shibboleth" and "shib_idp" in flask.request.args:
                shib_idp = flask.request.args["shib_idp"]
                params["shib_idp"] = shib_idp
                flask.session["shib_idp"] = shib_idp
            authorization_url = add_params_to_uri(authorization_url, params)

        flask.session["state"] = state
        return flask.redirect(authorization_url)
Beispiel #4
0
 def get(self):
     """Handle ``GET /login/fence``."""
     oauth2_redirect_uri = flask.current_app.fence_client.client_kwargs.get(
         "redirect_uri")
     redirect_url = flask.request.args.get("redirect")
     if redirect_url:
         validate_redirect(redirect_url)
         flask.session["redirect"] = redirect_url
     authorization_url, state = flask.current_app.fence_client.generate_authorize_redirect(
         oauth2_redirect_uri, prompt="login")
     flask.session["state"] = state
     return flask.redirect(authorization_url)
Beispiel #5
0
 def get(self):
     """
     The login flow is:
     user
     -> {fence}/login/shib?redirect={portal}
     -> user login at {nih_shibboleth_idp}
     -> nih idp POST to fence shibboleth and establish a shibboleth sp
        session
     -> redirect to {fence}/login/shib/login that sets up fence session
     -> redirect to portal
     """
     redirect_url = flask.request.args.get("redirect")
     validate_redirect(redirect_url)
     if redirect_url:
         flask.session["redirect"] = redirect_url
     actual_redirect = config["BASE_URL"] + "/login/shib/login"
     return flask.redirect(config["SSO_URL"] + actual_redirect)
Beispiel #6
0
    def _link_google_account():
        provided_redirect = flask.request.args.get("redirect")

        # will raise UserError if invalid
        validate_redirect(provided_redirect)

        if not provided_redirect:
            raise UserError({"error": "No redirect provided."})

        user_id = current_token["sub"]
        google_email = get_users_linked_google_email(user_id)
        proxy_group = get_or_create_proxy_group_id()

        # Set session flag to signify that we're linking and not logging in
        # Save info needed for linking in session since we need to AuthN first
        flask.session["google_link"] = True
        flask.session["user_id"] = user_id
        flask.session["google_proxy_group_id"] = proxy_group
        flask.session["linked_google_email"] = google_email

        if not google_email:
            # save off provided redirect in session and initiate Google AuthN
            flask.session["redirect"] = provided_redirect

            # requested time (in seconds) during which the link will be valid
            requested_expires_in = get_valid_expiration_from_request()
            if requested_expires_in:
                flask.session["google_link_expires_in"] = requested_expires_in

            # if we're mocking Google login, skip to callback
            if config.get("MOCK_GOOGLE_AUTH", False):
                flask.redirect_url = (config["BASE_URL"].strip("/") +
                                      "/link/google/callback?code=abc")
                response = flask.redirect(flask.redirect_url)
                # pass-through the authorization header. The user's username
                # MUST be a Google email for MOCK_GOOGLE_AUTH to actually link that
                # email correctly
                response.headers["Authorization"] = flask.request.headers.get(
                    "Authorization")
                return response

            flask.redirect_url = flask.current_app.google_client.get_auth_url()

            # Tell Google to let user select an account
            flask.redirect_url = append_query_params(flask.redirect_url,
                                                     prompt="select_account")
        else:
            # double check that the token isn't stale by hitting db
            linked_email_in_db = get_linked_google_account_email(user_id)

            if linked_email_in_db:
                # skip Google AuthN, already linked, error
                redirect_with_errors = append_query_params(
                    provided_redirect,
                    error="g_acnt_link_error",
                    error_description=
                    "User already has a linked Google account.",
                )
                flask.redirect_url = redirect_with_errors
                _clear_google_link_info_from_session()
            else:
                # TODO can we handle this error?
                redirect_with_errors = append_query_params(
                    provided_redirect,
                    error="g_acnt_link_error",
                    error_description="Stale access token, please refresh.",
                )
                flask.redirect_url = redirect_with_errors
                _clear_google_link_info_from_session()

        return flask.redirect(flask.redirect_url)