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))
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())
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)
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)
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)
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)