示例#1
0
async def test_malformed_token_handling():
    http_auth_with_malformed_token = HTTPAuthorizationCredentials(
        scheme="a",
        credentials="malformed-token",
    )

    verifier = JWKsVerifier(jwks=JWKS.null())
    with pytest.raises(HTTPException):
        await verifier._get_publickey(http_auth_with_malformed_token)
    with pytest.raises(HTTPException):
        await verifier.verify_token(http_auth_with_malformed_token)

    verifier = JWKsVerifier(jwks=JWKS.null(), auto_error=False)
    assert not await verifier._get_publickey(http_auth_with_malformed_token)
    assert not await verifier.verify_token(http_auth_with_malformed_token)

    verifier = ScopedJWKsVerifier(jwks=JWKS.null())
    with pytest.raises(HTTPException):
        verifier._verify_scope(http_auth_with_malformed_token)
    with pytest.raises(HTTPException):
        await verifier.verify_token(http_auth_with_malformed_token)

    verifier = ScopedJWKsVerifier(jwks=JWKS.null(), auto_error=False)
    assert not verifier._verify_scope(http_auth_with_malformed_token)
    assert not await verifier.verify_token(http_auth_with_malformed_token)
示例#2
0
def test_verify_scope_exeption(mocker):
    mocker.patch(
        "fastapi_cloudauth.verification.jwt.get_unverified_claims",
        return_value={"dummy key": "read:test"},
    )
    scope_key = "dummy key"
    http_auth = HTTPAuthorizationCredentials(
        scheme="a",
        credentials="dummy-token",
    )

    # trivial scope
    verifier = ScopedJWKsVerifier(jwks=JWKS.null(),
                                  scope_key=scope_key,
                                  scope_name=None)
    assert verifier._verify_scope(http_auth)

    # invalid incoming scope format
    mocker.patch(
        "fastapi_cloudauth.verification.jwt.get_unverified_claims",
        return_value={"dummy key": 100},
    )
    verifier = ScopedJWKsVerifier(jwks=JWKS.null(),
                                  scope_key=scope_key,
                                  scope_name=["read:test"])
    with pytest.raises(HTTPException):
        verifier._verify_scope(http_auth)
    # auto_error is False
    verifier = ScopedJWKsVerifier(
        jwks=JWKS.null(),
        scope_key=scope_key,
        scope_name=["read:test"],
        auto_error=False,
    )
    assert not verifier._verify_scope(http_auth)
示例#3
0
async def test_jwks_test_mode():
    # instantiate null jwks obj (no querying jwks)
    _jwks = JWKS.null()

    # instantiate fixed jwks obj (no querying jwks)
    dummy = Key(None, None)
    _jwks = JWKS(fixed_keys={"test": dummy})
    assert await _jwks.get_publickey("test") == dummy
示例#4
0
async def test_assign_user_info(auth):
    """three way to set user info schema
    1. pass it to arguments when create instance
    2. call `.claim` method and pass it to that arguments
    3. assign with `=` statements
    """
    class SubSchema(BaseModel):
        sub: str

    class NameSchema(BaseModel):
        name: str

    class IatSchema(BaseModel):
        iat: int

    # authorized token
    dummy_http_auth = HTTPAuthorizationCredentials(
        scheme="a",
        credentials=
        "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Im5hbWUiLCJpYXQiOjE1MTYyMzkwMjJ9.3ZEDmhWNZWDbJDPDlZX_I3oaalNYXdoT-bKLxIxQK4U",
    )

    user = auth(jwks=JWKS.null(), user_info=IatSchema)
    assert await user.call(dummy_http_auth) == IatSchema(iat=1516239022)

    assert await user.claim(SubSchema).call(dummy_http_auth) == SubSchema(
        sub="1234567890")

    user.user_info = NameSchema
    assert await user.call(dummy_http_auth) == NameSchema(name="name")
示例#5
0
async def test_extract_raw_user_info(auth):
    dummy_http_auth = HTTPAuthorizationCredentials(
        scheme="a",
        credentials=
        "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Im5hbWUiLCJpYXQiOjE1MTYyMzkwMjJ9.3ZEDmhWNZWDbJDPDlZX_I3oaalNYXdoT-bKLxIxQK4U",
    )

    class NameSchema(BaseModel):
        name: str

    get_current_user = auth(jwks=JWKS.null(), user_info=NameSchema)
    get_current_user.user_info = None
    res = await get_current_user.call(dummy_http_auth)
    assert res == {"sub": "1234567890", "name": "name", "iat": 1516239022}

    get_current_user = auth(jwks=JWKS.null(), user_info=NameSchema)
    res = await get_current_user.claim(None).call(dummy_http_auth)
    assert res == {"sub": "1234567890", "name": "name", "iat": 1516239022}
示例#6
0
async def test_forget_def_user_info(auth):
    dummy_http_auth = HTTPAuthorizationCredentials(
        scheme="a",
        credentials=
        "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Im5hbWUiLCJpYXQiOjE1MTYyMzkwMjJ9.3ZEDmhWNZWDbJDPDlZX_I3oaalNYXdoT-bKLxIxQK4U",
    )
    """If `.user_info` is None, return raw payload"""
    get_current_user = auth(jwks=JWKS.null())
    assert get_current_user.user_info is None
    res = await get_current_user.call(dummy_http_auth)
    assert res == {"sub": "1234567890", "name": "name", "iat": 1516239022}
示例#7
0
def test_scope_match_all(mocker, scopes):
    scope_key = "dummy key"
    http_auth = HTTPAuthorizationCredentials(
        scheme="a",
        credentials="dummy-token",
    )

    # check scope logic
    mocker.patch(
        "fastapi_cloudauth.verification.jwt.get_unverified_claims",
        return_value={"dummy key": scopes},
    )
    jwks = JWKS.null()

    # api scope < user scope
    verifier = ScopedJWKsVerifier(
        scope_name=["xxx:xxx"],
        jwks=jwks,
        scope_key=scope_key,
        auto_error=False,
    )
    assert verifier._verify_scope(http_auth)

    # api scope == user scope (in order)
    verifier = ScopedJWKsVerifier(
        scope_name=["xxx:xxx", "yyy:yyy"],
        jwks=jwks,
        scope_key=scope_key,
        auto_error=False,
    )
    assert verifier._verify_scope(http_auth)

    # api scope == user scope (disorder)
    verifier = ScopedJWKsVerifier(
        scope_name=["yyy:yyy", "xxx:xxx"],
        jwks=jwks,
        scope_key=scope_key,
        auto_error=False,
    )
    assert verifier._verify_scope(http_auth)

    # api scope > user scope
    verifier = ScopedJWKsVerifier(
        scope_name=["yyy:yyy", "xxx:xxx", "zzz:zzz"],
        jwks=jwks,
        scope_key=scope_key,
        auto_error=False,
    )
    assert not verifier._verify_scope(http_auth)
示例#8
0
def test_return_instance_with_scope():
    # scope method return new instance to give it for Depends.
    verifier = ScopedAuth(jwks=JWKS(keys=[]))
    # must set scope_key (Inherit ScopedAuth and override scope_key attribute)
    scope_key = "dummy key"
    verifier.scope_key = scope_key

    scope_name = "required-scope"
    obj = verifier.scope(scope_name)
    assert isinstance(obj, ScopedAuth)
    assert obj.scope_key == scope_key, "scope_key mustn't be cleared."
    assert obj.scope_name == scope_name, "Must set scope_name in returned instanse."
    assert (obj.verifier._jwks_to_key == verifier.verifier._jwks_to_key
            ), "return cloned objects"
    assert (obj.verifier.auto_error == verifier.verifier.auto_error
            ), "return cloned objects"
示例#9
0
def test_validation_scope(mocker, scopes):
    mocker.patch(
        "fastapi_cloudauth.verification.jwt.get_unverified_claims",
        return_value={"dummy key": scopes},
    )
    verifier = ScopedAuth(jwks=JWKS.null())
    scope_key = "dummy key"
    verifier.scope_key = scope_key

    scope_name = "user-assigned-scope"
    obj = verifier.scope(scope_name)
    assert obj.verifier._verify_scope(
        HTTPAuthorizationCredentials(scheme="", credentials=""))

    scope_name = "user-assigned-scope-invalid"
    obj = verifier.scope(scope_name)
    with pytest.raises(HTTPException):
        obj.verifier._verify_scope(
            HTTPAuthorizationCredentials(scheme="", credentials=""))

    obj.verifier.auto_error = False
    assert not obj.verifier._verify_scope(
        HTTPAuthorizationCredentials(scheme="", credentials=""))
示例#10
0
def test_raise_error_invalid_set_scope():
    # scope_key is not declaired
    token_verifier = ScopedAuth(jwks=JWKS.null())
    with pytest.raises(AttributeError):
        # raise AttributeError for invalid instanse attributes wrt scope
        token_verifier.scope("read:test")
示例#11
0
def test_verify_token():
    verifier = JWKsVerifier(jwks=JWKS.null())
    verifier_no_error = JWKsVerifier(jwks=JWKS.null(), auto_error=False)

    # correct
    token = jwt.encode(
        {
            "sub": "dummy-ID",
            "exp": datetime.utcnow() + timedelta(hours=10),
            "iat": datetime.utcnow(),
        },
        "dummy_secret",
        headers={
            "alg": "HS256",
            "typ": "JWT",
            "kid": "dummy-kid"
        },
    )
    verifier._verify_claims(
        HTTPAuthorizationCredentials(scheme="a", credentials=token))
    verifier_no_error._verify_claims(
        HTTPAuthorizationCredentials(scheme="a", credentials=token))

    # token expired
    token = jwt.encode(
        {
            "sub": "dummy-ID",
            "exp": datetime.utcnow() - timedelta(hours=10),  # 10h before
            "iat": datetime.utcnow(),
        },
        "dummy_secret",
        headers={
            "alg": "HS256",
            "typ": "JWT",
            "kid": "dummy-kid"
        },
    )
    e = _assert_verifier(token, verifier)
    assert e.status_code == HTTP_401_UNAUTHORIZED and e.detail == messages.NOT_VERIFIED
    _assert_verifier_no_error(token, verifier_no_error)

    # token created at future
    token = jwt.encode(
        {
            "sub": "dummy-ID",
            "exp": datetime.utcnow() + timedelta(hours=10),
            "iat": datetime.utcnow() + timedelta(hours=10),
        },
        "dummy_secret",
        headers={
            "alg": "HS256",
            "typ": "JWT",
            "kid": "dummy-kid"
        },
    )
    e = _assert_verifier(token, verifier)
    assert e.status_code == HTTP_401_UNAUTHORIZED and e.detail == messages.NOT_VERIFIED
    _assert_verifier_no_error(token, verifier_no_error)

    # invalid format
    token = jwt.encode(
        {
            "sub": "dummy-ID",
            "exp": datetime.utcnow() + timedelta(hours=10),
            "iat": datetime.utcnow(),
        },
        "dummy_secret",
        headers={
            "alg": "HS256",
            "typ": "JWT",
            "kid": "dummy-kid"
        },
    )
    token = token.split(".")[0]
    e = _assert_verifier(token, verifier)
    assert (e.status_code == HTTP_401_UNAUTHORIZED
            and e.detail == messages.NOT_AUTHENTICATED)
    _assert_verifier_no_error(token, verifier_no_error)