Exemple #1
0
def _get_optional_userinfo(user, claims):
    info = {}
    for claim in claims:
        if claim == "linked_google_account":
            google_email = get_linked_google_account_email(user.id)
            info["linked_google_account"] = google_email
        if claim == "linked_google_account_exp":
            google_account_exp = get_linked_google_account_exp(user.id)
            info["linked_google_account_exp"] = google_account_exp

    return info
def test_google_id_token_linked(db_session, encoded_creds_jwt,
                                oauth_test_client):
    """
    Test google email and link expiration are in id_token for a linked account
    """
    user_id = encoded_creds_jwt["user_id"]
    proxy_group_id = encoded_creds_jwt["proxy_group_id"]

    original_expiration = 1000
    google_account = "*****@*****.**"

    # add google account and link
    existing_account = UserGoogleAccount(email=google_account, user_id=user_id)
    db_session.add(existing_account)
    db_session.commit()
    g_account_access = UserGoogleAccountToProxyGroup(
        user_google_account_id=existing_account.id,
        proxy_group_id=proxy_group_id,
        expires=original_expiration,
    )
    db_session.add(g_account_access)
    db_session.commit()

    # get google account info with utility function
    assert get_linked_google_account_email(user_id) == google_account
    assert get_linked_google_account_exp(user_id) == original_expiration

    # get the id token through endpoint
    data = {"confirm": "yes"}
    oauth_test_client.authorize(data=data)
    tokens = oauth_test_client.token()
    id_token = jwt.decode(tokens.id_token, verify=False)

    assert "google" in id_token["context"]["user"]
    assert (id_token["context"]["user"]["google"].get("linked_google_account")
            == google_account)
    assert (id_token["context"]["user"]["google"].get(
        "linked_google_account_exp") == original_expiration)
Exemple #3
0
def generate_implicit_response(client,
                               grant_type,
                               include_access_token=True,
                               expires_in=None,
                               user=None,
                               scope=None,
                               nonce=None,
                               **kwargs):
    # prevent those bothersome "not bound to session" errors
    if user not in current_session:
        user = current_session.query(User).filter_by(id=user.id).first()

    if not user:
        raise OIDCError("user not authenticated")

    keypair = flask.current_app.keypairs[0]

    linked_google_email = get_linked_google_account_email(user.id)
    linked_google_account_exp = get_linked_google_account_exp(user.id)

    if not isinstance(scope, list):
        scope = scope.split(" ")

    if not "user" in scope:
        scope.append("user")

    # ``expires_in`` is just the token expiration time.
    expires_in = config["ACCESS_TOKEN_EXPIRES_IN"]

    response = {
        "token_type": "Bearer",
        "expires_in": expires_in,
        # "state" handled in authlib
    }

    # don't provide user projects access in access_tokens for implicit flow
    # due to issues with "Location" header size during redirect (and b/c
    # of general deprecation of user access information in tokens)
    if include_access_token:
        access_token = generate_signed_access_token(
            kid=keypair.kid,
            private_key=keypair.private_key,
            user=user,
            expires_in=config["ACCESS_TOKEN_EXPIRES_IN"],
            scopes=scope,
            client_id=client.client_id,
            linked_google_email=linked_google_email,
            include_project_access=False,
        ).token
        response["access_token"] = access_token

    # don't provide user projects access in id_tokens for implicit flow
    # due to issues with "Location" header size during redirect (and b/c
    # of general deprecation of user access information in tokens)
    id_token = generate_signed_id_token(
        kid=keypair.kid,
        private_key=keypair.private_key,
        user=user,
        expires_in=config["ACCESS_TOKEN_EXPIRES_IN"],
        client_id=client.client_id,
        audiences=scope,
        nonce=nonce,
        linked_google_email=linked_google_email,
        linked_google_account_exp=linked_google_account_exp,
        include_project_access=False,
        auth_flow_type=AuthFlowTypes.IMPLICIT,
        access_token=access_token if include_access_token else None,
    ).token
    response["id_token"] = id_token

    return response
Exemple #4
0
def generate_token_response(client,
                            grant_type,
                            expires_in=None,
                            user=None,
                            scope=None,
                            include_refresh_token=True,
                            nonce=None,
                            refresh_token=None,
                            refresh_token_claims=None,
                            **kwargs):
    # prevent those bothersome "not bound to session" errors
    if user not in current_session:
        user = current_session.query(User).filter_by(id=user.id).first()

    if not user:
        # Find the ``User`` model.
        # The way to do this depends on the grant type.
        if grant_type == "authorization_code":
            # For authorization code grant, get the code from either the query
            # string or the form data, and use that to look up the user.
            if flask.request.method == "GET":
                code = flask.request.args.get("code")
            else:
                code = flask.request.form.get("code")
            user = (current_session.query(AuthorizationCode).filter_by(
                code=code).first().user)
        if grant_type == "refresh_token":
            # For refresh token, the user ID is the ``sub`` field in the token.
            user = (current_session.query(User).filter_by(
                id=int(refresh_token_claims["sub"])).first())

    keypair = flask.current_app.keypairs[0]

    linked_google_email = get_linked_google_account_email(user.id)
    linked_google_account_exp = get_linked_google_account_exp(user.id)

    if not isinstance(scope, list):
        scope = scope.split(" ")

    access_token = generate_signed_access_token(
        kid=keypair.kid,
        private_key=keypair.private_key,
        user=user,
        expires_in=config["ACCESS_TOKEN_EXPIRES_IN"],
        scopes=scope,
        client_id=client.client_id,
        linked_google_email=linked_google_email,
    ).token
    id_token = generate_signed_id_token(
        kid=keypair.kid,
        private_key=keypair.private_key,
        user=user,
        expires_in=config["ACCESS_TOKEN_EXPIRES_IN"],
        client_id=client.client_id,
        audiences=scope,
        nonce=nonce,
        linked_google_email=linked_google_email,
        linked_google_account_exp=linked_google_account_exp,
        auth_flow_type=AuthFlowTypes.CODE,
        access_token=access_token,
    ).token
    # If ``refresh_token`` was passed (for instance from the refresh
    # grant), use that instead of generating a new one.
    if refresh_token is None:
        refresh_token = generate_signed_refresh_token(
            kid=keypair.kid,
            private_key=keypair.private_key,
            user=user,
            expires_in=config["REFRESH_TOKEN_EXPIRES_IN"],
            scopes=scope,
            client_id=client.client_id,
        ).token
    # ``expires_in`` is just the access token expiration time.
    expires_in = config["ACCESS_TOKEN_EXPIRES_IN"]
    return {
        "token_type": "Bearer",
        "id_token": id_token,
        "access_token": access_token,
        "refresh_token": refresh_token,
        "expires_in": expires_in,
    }
Exemple #5
0
def generate_implicit_response(client,
                               grant_type,
                               include_access_token=True,
                               expires_in=None,
                               user=None,
                               scope=None,
                               nonce=None,
                               **kwargs):
    # prevent those bothersome "not bound to session" errors
    if user not in current_session:
        user = current_session.query(User).filter_by(id=user.id).first()

    if not user:
        raise OIDCError("user not authenticated")

    keypair = flask.current_app.keypairs[0]

    linked_google_email = get_linked_google_account_email(user.id)
    linked_google_account_exp = get_linked_google_account_exp(user.id)

    if not isinstance(scope, list):
        scope = scope.split(" ")

    if not "user" in scope:
        scope.append("user")

    id_token = generate_signed_id_token(
        kid=keypair.kid,
        private_key=keypair.private_key,
        user=user,
        expires_in=ACCESS_TOKEN_EXPIRES_IN,
        client_id=client.client_id,
        audiences=scope,
        nonce=nonce,
        linked_google_email=linked_google_email,
        linked_google_account_exp=linked_google_account_exp,
    ).token

    # ``expires_in`` is just the token expiration time.
    expires_in = ACCESS_TOKEN_EXPIRES_IN

    response = {
        "token_type": "Bearer",
        "id_token": id_token,
        "expires_in": expires_in,
        # "state" handled in authlib
    }

    if include_access_token:
        access_token = generate_signed_access_token(
            kid=keypair.kid,
            private_key=keypair.private_key,
            user=user,
            expires_in=ACCESS_TOKEN_EXPIRES_IN,
            scopes=scope,
            client_id=client.client_id,
            linked_google_email=linked_google_email,
        ).token
        response["access_token"] = access_token

    return response