Esempio n. 1
0
def test_that_user_must_have_all_permissions(app, client):

    security = FastAPISecurity()

    can_list = security.user_permission("users:list")  # noqa
    can_view = security.user_permission("users:view")  # noqa

    @app.get("/users")
    def get_user_list(user: User = Depends(security.user_holding(can_list, can_view))):
        return [user]

    security.init_oauth2_through_jwks(dummy_jwks_uri, audiences=[dummy_audience])

    bad_token = make_access_token(sub="test-user", permissions=["users:list"])
    valid_token = make_access_token(
        sub="JaneDoe",
        permissions=["users:list", "users:view"],
    )

    with aioresponses() as mock:
        mock.get(dummy_jwks_uri, payload=dummy_jwks_response_data)

        resp = client.get("/users", headers={"Authorization": f"Bearer {bad_token}"})
        assert resp.status_code == 403
        assert resp.json() == {"detail": "Missing required permission users:view"}

        resp = client.get("/users", headers={"Authorization": f"Bearer {valid_token}"})
        assert resp.status_code == 200
        (user1,) = resp.json()
        assert user1["auth"]["subject"] == "JaneDoe"
def test_that_nonexisting_permissions_are_ignored(app, client):

    security = FastAPISecurity()

    @app.get("/users/me")
    def get_user_info(user: User = Depends(security.authenticated_user_or_401)):
        return user.without_access_token()

    security.init_oauth2_through_jwks(dummy_jwks_uri, audiences=[dummy_audience])

    access_token = make_access_token(
        sub="test-subject",
        permissions=["users:list"],
    )

    with aioresponses() as mock:
        mock.get(dummy_jwks_uri, payload=dummy_jwks_response_data)

        resp = client.get(
            "/users/me", headers={"Authorization": f"Bearer {access_token}"}
        )
        assert resp.status_code == 200
        data = resp.json()["auth"]
        del data["expires_at"]
        del data["issued_at"]
        assert data == {
            "audience": ["https://some-resource"],
            "auth_method": "oauth2",
            "issuer": "https://identity-provider/",
            "permissions": [],
            "scopes": [],
            "subject": "test-subject",
        }
def test_that_header_is_returned_for_oauth2(app, client):
    security = FastAPISecurity()
    security.init_oauth2_through_jwks(dummy_jwks_uri,
                                      audiences=[dummy_audience])

    @app.get("/")
    def get_products(user: User = Depends(security.authenticated_user_or_401)):
        return []

    with aioresponses() as mock:
        mock.get(dummy_jwks_uri, payload=dummy_jwks_response_data)
        resp = client.get("/")
        assert resp.headers["WWW-Authenticate"] == "Bearer"
def test_that_headers_are_returned_for_oauth2_and_basic_auth(app, client):
    security = FastAPISecurity()
    security.init_basic_auth([{"username": "******", "password": "******"}])
    security.init_oauth2_through_jwks(dummy_jwks_uri,
                                      audiences=[dummy_audience])

    @app.get("/")
    def get_products(user: User = Depends(security.authenticated_user_or_401)):
        return []

    with aioresponses() as mock:
        mock.get(dummy_jwks_uri, payload=dummy_jwks_response_data)
        resp = client.get("/")
        # NOTE: They are actually set as separate headers
        assert resp.headers["WWW-Authenticate"] == "Basic, Bearer"
def test_that_uninitialized_basic_auth_doesnt_accept_any_credentials(
        app, client):
    security = FastAPISecurity()

    @app.get("/")
    def get_products(user: User = Depends(security.authenticated_user_or_401)):
        return []

    # NOTE: Not passing basic_auth_credentials, which means Basic Auth will be disabled
    # NOTE: We are passing
    security.init_oauth2_through_jwks(dummy_jwks_uri,
                                      audiences=[dummy_audience])

    resp = client.get("/")
    assert resp.status_code == 401

    resp = client.get("/", auth=("username", "password"))
    assert resp.status_code == 401
Esempio n. 6
0
def test_that_oauth2_rejects_expired_token(app, client):

    security = FastAPISecurity()

    @app.get("/")
    def get_products(user: User = Depends(security.authenticated_user_or_401)):
        return []

    security.init_oauth2_through_jwks(dummy_jwks_uri, audiences=[dummy_audience])

    access_token = make_access_token(sub="test-subject", expire_in=-1)

    with aioresponses() as mock:
        mock.get(dummy_jwks_uri, payload=dummy_jwks_response_data)

        resp = client.get("/", headers={"Authorization": f"Bearer {access_token}"})

        assert resp.status_code == 401
Esempio n. 7
0
def test_that_oauth2_rejects_incorrect_token(app, client):

    security = FastAPISecurity()

    @app.get("/")
    def get_products(user: User = Depends(security.authenticated_user_or_401)):
        return []

    security.init_oauth2_through_jwks(dummy_jwks_uri, audiences=[dummy_audience])

    resp = client.get("/")
    assert resp.status_code == 401

    resp = client.get("/", headers={"Authorization": "Bearer abc"})
    assert resp.status_code == 401

    resp = client.get("/", headers={"Authorization": "Bearer abc.xyz.def"})
    assert resp.status_code == 401
Esempio n. 8
0
def test_that_missing_permission_results_in_403(app, client):

    security = FastAPISecurity()

    can_list = security.user_permission("users:list")  # noqa

    @app.get("/users")
    def get_user_list(user: User = Depends(security.user_holding(can_list))):
        return [user]

    security.init_oauth2_through_jwks(dummy_jwks_uri, audiences=[dummy_audience])

    access_token = make_access_token(sub="test-user", permissions=[])

    with aioresponses() as mock:
        mock.get(dummy_jwks_uri, payload=dummy_jwks_response_data)

        resp = client.get("/users", headers={"Authorization": f"Bearer {access_token}"})
        assert resp.status_code == 403
        assert resp.json() == {"detail": "Missing required permission users:list"}
Esempio n. 9
0
def test_that_assigned_permission_result_in_200(app, client):

    security = FastAPISecurity()

    can_list = security.user_permission("users:list")  # noqa

    @app.get("/users")
    def get_user_list(user: User = Depends(security.user_holding(can_list))):
        return [user]

    security.init_oauth2_through_jwks(dummy_jwks_uri, audiences=[dummy_audience])

    access_token = make_access_token(sub="test-user", permissions=["users:list"])

    with aioresponses() as mock:
        mock.get(dummy_jwks_uri, payload=dummy_jwks_response_data)

        resp = client.get("/users", headers={"Authorization": f"Bearer {access_token}"})
        assert resp.status_code == 200
        (user1,) = resp.json()
        assert user1["auth"]["subject"] == "test-user"
Esempio n. 10
0
settings = get_settings()

security = FastAPISecurity()

if settings.basic_auth_credentials:
    security.init_basic_auth(settings.basic_auth_credentials)

if settings.oidc_discovery_url:
    security.init_oauth2_through_oidc(
        settings.oidc_discovery_url,
        audiences=settings.oauth2_audiences,
    )
elif settings.oauth2_jwks_url:
    security.init_oauth2_through_jwks(
        settings.oauth2_jwks_url,
        audiences=settings.oauth2_audiences,
    )

security.add_permission_overrides(settings.permission_overrides or {})

logger = logging.getLogger(__name__)

create_product_perm = security.user_permission("products:create")


@app.get("/users/me")
async def get_user_details(user: User = Depends(security.user_with_info)):
    """Return user details, regardless of whether user is authenticated or not"""
    return user.without_access_token()