Beispiel #1
0
def fake_ras_login(username, subject, email=None, db_session=None):
    """
    Mock a login by creating a sub/iss mapping in the db and logging them into a
    session.

    Args:
        username (str): Username from IdP
        subject (str): sub id in tokens from IdP
        email (None, optional): email if provided
        db_session (None, optional): db session to use
    """
    ras_client = RASOauth2Client(
        config["OPENID_CONNECT"]["ras"],
        HTTP_PROXY=config["HTTP_PROXY"],
        logger=logger,
    )
    actual_username = ras_client.map_iss_sub_pair_to_user(
        issuer="https://stsstg.nih.gov",
        subject_id=subject,
        username=username,
        email=email,
        db_session=db_session,
    )
    logger.debug(
        f"subject: {subject}, username: {username}, actual_username: {actual_username}"
    )
    login_user(actual_username,
               provider="ras",
               email=None,
               id_from_idp=subject)
Beispiel #2
0
    def get(self):
        """Handle ``GET /login/fence/login``."""
        # Check that the state passed back from IDP fence is the same as the
        # one stored previously.
        mismatched_state = (
            'state' not in flask.request.args or 'state' not in flask.session
            or flask.request.args['state'] != flask.session.pop('state'))
        if mismatched_state:
            raise Unauthorized('authorization request failed; state mismatch')
        # Get the token response and log in the user.
        redirect_uri = flask.current_app.fence_client.session.redirect_uri
        tokens = flask.current_app.fence_client.fetch_access_token(
            redirect_uri, **flask.request.args.to_dict())
        id_token_claims = validate_jwt(tokens['id_token'],
                                       aud={'openid'},
                                       purpose='id',
                                       attempt_refresh=True)
        username = id_token_claims['context']['user']['name']
        flask.session['username'] = username
        flask.session['provider'] = IdentityProvider.fence
        login_user(flask.request, username, IdentityProvider.fence)

        if 'redirect' in flask.session:
            return flask.redirect(flask.session.get('redirect'))
        return flask.jsonify({'username': username})
Beispiel #3
0
    def get(self):
        """Handle ``GET /login/fence/login``."""
        # Check that the state passed back from IDP fence is the same as the
        # one stored previously.
        mismatched_state = (
            "state" not in flask.request.args or "state" not in flask.session
            or flask.request.args["state"] != flask.session.pop("state", ""))
        if mismatched_state and not config.get("MOCK_AUTH"):
            raise Unauthorized(
                "Login flow was interrupted (state mismatch). Please go back to the"
                " login page for the original application to continue.")
        # Get the token response and log in the user.
        redirect_uri = flask.current_app.fence_client._get_session(
        ).redirect_uri
        tokens = flask.current_app.fence_client.fetch_access_token(
            redirect_uri, **flask.request.args.to_dict())
        id_token_claims = validate_jwt(tokens["id_token"],
                                       aud={"openid"},
                                       purpose="id",
                                       attempt_refresh=True)
        username = id_token_claims["context"]["user"]["name"]
        login_user(
            username,
            IdentityProvider.fence,
            fence_idp=flask.session.get("fence_idp"),
            shib_idp=flask.session.get("shib_idp"),
        )
        self.post_login()

        if "redirect" in flask.session:
            return flask.redirect(flask.session.get("redirect"))
        return flask.jsonify({"username": username})
Beispiel #4
0
def test_login_user_already_in_db(db_session):
    """
    Test that if a user is already in the database and logs in, the session will contain
    the user's information (including additional information that may have been provided
    during the login like email and id_from_idp)
    """
    email = "*****@*****.**"
    provider = "Test Provider"
    id_from_idp = "Provider_ID_0001"

    test_user = User(username=email, is_admin=False)
    db_session.add(test_user)
    db_session.commit()
    user_id = str(test_user.id)
    assert not test_user.email
    assert not test_user.id_from_idp

    login_user(email, provider, email=email, id_from_idp=id_from_idp)

    assert test_user.identity_provider.name == provider
    assert test_user.id_from_idp == id_from_idp
    assert test_user.email == email
    assert flask.session["username"] == email
    assert flask.session["provider"] == provider
    assert flask.session["user_id"] == user_id
    assert flask.g.user == test_user
Beispiel #5
0
def test_login_user_with_idp_already_in_db(db_session):
    """
    Test that if a user is already in the database, has identity_provider
    configured, and logs in, the session will contain the user's information.
    """
    email = "*****@*****.**"
    provider = "Test Provider"
    id_from_idp = "Provider_ID_0001"

    test_user = User(username=email,
                     email=email,
                     id_from_idp=id_from_idp,
                     is_admin=False)
    test_idp = IdentityProvider(name=provider)
    test_user.identity_provider = test_idp

    db_session.add(test_user)
    db_session.commit()
    user_id = str(test_user.id)

    login_user(email, provider, email=email, id_from_idp=id_from_idp)

    assert test_user.identity_provider.name == provider
    assert test_user.id_from_idp == id_from_idp
    assert test_user.email == email
    assert flask.session["username"] == email
    assert flask.session["provider"] == provider
    assert flask.session["user_id"] == user_id
    assert flask.g.user == test_user
Beispiel #6
0
    def get(self):
        """
        Complete the shibboleth login.
        """
        shib_header = config.get("SHIBBOLETH_HEADER")
        if not shib_header:
            raise InternalError("Missing shibboleth header configuration")

        # eppn stands for eduPersonPrincipalName
        username = flask.request.headers.get("eppn")
        entityID = flask.session.get("entityID")

        # if eppn not available or logging in through NIH
        if not username or not entityID or entityID == "urn:mace:incommon:nih.gov":
            persistent_id = flask.request.headers.get(shib_header)
            username = persistent_id.split("!")[-1] if persistent_id else None
            if not username:
                # some inCommon providers are not returning eppn
                # or persistent_id. See PXP-4309
                # print("shib_header", shib_header)
                # print("flask.request.headers", flask.request.headers)
                raise Unauthorized("Unable to retrieve username")

        idp = IdentityProvider.itrust
        if entityID:
            idp = entityID
        login_user(flask.request, username, idp)

        if flask.session.get("redirect"):
            return flask.redirect(flask.session.get("redirect"))

        return "logged in"
Beispiel #7
0
def _login(email):
    """
    Login user with given email from Microsoft, then redirect if session has a saved
    redirect.
    """
    login_user(flask.request, email, IdentityProvider.microsoft)
    if flask.session.get("redirect"):
        return flask.redirect(flask.session.get("redirect"))
    return flask.jsonify({"username": email})
Beispiel #8
0
def _login(username, idp_name):
    """
    Login user with given username, then redirect if session has a saved
    redirect.
    """
    login_user(flask.request, username, idp_name)
    if flask.session.get("redirect"):
        return flask.redirect(flask.session.get("redirect"))
    return flask.jsonify({"username": username})
Beispiel #9
0
def _login(orcid):
    """
    Login user with given email from ORCID, then redirect if session has a saved
    redirect.
    """
    login_user(flask.request, orcid, IdentityProvider.orcid)
    if flask.session.get("redirect"):
        return flask.redirect(flask.session.get("redirect"))
    return flask.jsonify({"username": orcid})
Beispiel #10
0
    def get(self):
        """Handle ``GET /login/fence/login``."""
        # Check that the state passed back from IDP fence is the same as the
        # one stored previously.
        mismatched_state = (
            "state" not in flask.request.args or "state" not in flask.session
            or flask.request.args["state"] != flask.session.pop("state", ""))
        if mismatched_state and not config.get("MOCK_AUTH"):
            raise Unauthorized(
                "Login flow was interrupted (state mismatch). Please go back to the"
                " login page for the original application to continue.")
        # Get the token response and log in the user.
        redirect_uri = flask.current_app.fence_client._get_session(
        ).redirect_uri
        tokens = flask.current_app.fence_client.fetch_access_token(
            redirect_uri, **flask.request.args.to_dict())

        try:
            # For multi-Fence setup with two Fences >=5.0.0
            id_token_claims = validate_jwt(
                tokens["id_token"],
                aud=self.client.client_id,
                scope={"openid"},
                purpose="id",
                attempt_refresh=True,
            )
        except JWTError:
            # Since fenceshib cannot be updated to issue "new-style" ID tokens
            # (where scopes are in the scope claim and aud is in the aud claim),
            # allow also "old-style" Fence ID tokens.
            id_token_claims = validate_jwt(
                tokens["id_token"],
                aud="openid",
                scope=None,
                purpose="id",
                attempt_refresh=True,
            )
        username = id_token_claims["context"]["user"]["name"]
        email = id_token_claims["context"]["user"].get("email")
        login_user(
            username,
            IdentityProvider.fence,
            fence_idp=flask.session.get("fence_idp"),
            shib_idp=flask.session.get("shib_idp"),
            email=email,
        )
        self.post_login()

        if config["REGISTER_USERS_ON"]:
            if not flask.g.user.additional_info.get("registration_info"):
                return flask.redirect(config["BASE_URL"] +
                                      flask.url_for("register.register_user"))

        if "redirect" in flask.session:
            return flask.redirect(flask.session.get("redirect"))
        return flask.jsonify({"username": username})
Beispiel #11
0
 def get(self):
     code = flask.request.args.get('code')
     result = flask.current_app.google_client.get_user_id(code)
     email = result.get('email')
     if email:
         flask.session['username'] = email
         flask.session['provider'] = IdentityProvider.google
         login_user(flask.request, email, IdentityProvider.google)
         if flask.session.get('redirect'):
             return flask.redirect(flask.session.get('redirect'))
         return flask.jsonify({'username': email})
     raise UserError(result)
Beispiel #12
0
def _login(username, idp_name, email=None):
    """
    Login user with given username, then redirect if session has a saved
    redirect.
    """
    login_user(username, idp_name, email=email)

    if config["REGISTER_USERS_ON"]:
        if not flask.g.user.additional_info.get("registration_info"):
            return flask.redirect(
                config["BASE_URL"] + flask.url_for("register.register_user")
            )

    if flask.session.get("redirect"):
        return flask.redirect(flask.session.get("redirect"))
    return flask.jsonify({"username": username})
Beispiel #13
0
def test_login_new_user(db_session):
    """
    Test that if a user is not in the database and logs in, the user is added to the
    database and the session will contain the user's information.
    """
    email = "*****@*****.**"
    provider = "Test Provider"

    login_user(flask.request, email, provider)
    test_user = db_session.query(User).filter(
        User.username == email.lower()).first()

    assert flask.session["username"] == email
    assert flask.session["provider"] == provider
    assert flask.session["user_id"] == str(test_user.id)
    assert flask.g.user == test_user
Beispiel #14
0
 def get(self):
     # Check if this is a request to link account vs. actually log in
     if flask.session.get("google_link"):
         return flask.redirect(
             flask.current_app.config.get("BASE_URL", "") +
             "/link/google/callback?code={}".format(
                 flask.request.args.get("code")))
     else:
         code = flask.request.args.get("code")
         result = flask.current_app.google_client.get_user_id(code)
         email = result.get("email")
         if email:
             login_user(flask.request, email, IdentityProvider.google)
             if flask.session.get("redirect"):
                 return flask.redirect(flask.session.get("redirect"))
             return flask.jsonify({"username": email})
         raise UserError(result)
Beispiel #15
0
    def get(self):
        """
        Complete the shibboleth login.
        """
        if "SHIBBOLETH_HEADER" in config:
            eppn = flask.request.headers.get(config["SHIBBOLETH_HEADER"])

        else:
            raise InternalError("Missing shibboleth header configuration")
        username = eppn.split("!")[-1] if eppn else None
        if username:
            login_user(flask.request, username, IdentityProvider.itrust)
            if flask.session.get("redirect"):
                return flask.redirect(flask.session.get("redirect"))
            return "logged in"
        else:
            raise Unauthorized("Please login")
Beispiel #16
0
def test_login_user_already_in_db(db_session):
    """
    Test that if a user is already in the database and
    logs in, the session will contain the user's information.
    """
    email = "*****@*****.**"
    provider = "Test Provider"

    test_user = User(username=email, is_admin=False)
    db_session.add(test_user)
    db_session.commit()
    user_id = str(test_user.id)

    login_user(flask.request, email, provider)
    assert flask.session["username"] == email
    assert flask.session["provider"] == provider
    assert flask.session["user_id"] == user_id
    assert flask.g.user == test_user
Beispiel #17
0
def test_login_new_user(db_session):
    """
    Test that if a user is not in the database and logs in, the user is added to the
    database and the session will contain the user's information.
    """
    email = "*****@*****.**"
    provider = "Test Provider"
    id_from_idp = "Provider_ID_0001"

    login_user(email, provider, email=email, id_from_idp=id_from_idp)

    test_user = db_session.query(User).filter(
        User.username == email.lower()).first()

    assert test_user.identity_provider.name == provider
    assert test_user.id_from_idp == id_from_idp
    assert test_user.email == email
    assert flask.session["username"] == email
    assert flask.session["provider"] == provider
    assert flask.session["user_id"] == str(test_user.id)
    assert flask.g.user == test_user
Beispiel #18
0
    def get(self):
        """
        Complete the shibboleth login.
        """

        if 'SHIBBOLETH_HEADER' in flask.current_app.config:
            eppn = flask.request.headers.get(
                flask.current_app.config['SHIBBOLETH_HEADER'])

        else:
            raise InternalError("Missing shibboleth header configuration")
        username = eppn.split('!')[-1] if eppn else None
        if username:
            flask.session['username'] = username
            flask.session['provider'] = IdentityProvider.itrust
            login_user(flask.request, username, flask.session['provider'])
            if flask.session.get('redirect'):
                return flask.redirect(flask.session.get('redirect'))
            return "logged in"
        else:
            raise Unauthorized("Please login")