예제 #1
0
def test_authentication_new_user(
    db,
    rf,
    requests_mock,
    settings,
    create_user,
    email,
    expected_count,
):
    settings.OIDC_CREATE_USER = create_user
    settings.OIDC_UPDATE_USER = create_user
    user_model = get_user_model()
    assert user_model.objects.filter(username="******").count() == 0

    userinfo = {"sub": "1", "email": email}
    requests_mock.get(settings.OIDC_OP_USER_ENDPOINT,
                      text=json.dumps(userinfo))

    request = rf.get("/openid", HTTP_AUTHORIZATION="Bearer Token")

    try:
        user, _ = OIDCAuthentication().authenticate(request)
    except AuthenticationFailed:
        assert not create_user
    else:
        assert user.email == email

    assert user_model.objects.count() == expected_count
예제 #2
0
def test_authentication_existing_identity(
    db,
    rf,
    requests_mock,
    settings,
    identity,
    get_claims,
):
    claims = get_claims(id_claim="matching_id",
                        groups_claim=[],
                        email_claim="*****@*****.**")

    requests_mock.get(settings.OIDC_OP_USER_ENDPOINT, text=json.dumps(claims))

    assert Identity.objects.count() == 1

    request = rf.get("/openid", HTTP_AUTHORIZATION="Bearer Token")
    HistoricalRecords.thread.request = request

    result = OIDCAuthentication().authenticate(request)

    user, auth = result
    assert user.is_authenticated
    assert user.identity == identity
    assert Identity.objects.count() == 1
예제 #3
0
def test_authentication(
    db,
    user,
    rf,
    authentication_header,
    authenticated,
    error,
    is_id_token,
    requests_mock,
    settings,
):
    userinfo = {"sub": "1"}
    requests_mock.get(settings.OIDC_OP_USER_ENDPOINT,
                      text=json.dumps(userinfo))

    if not is_id_token:
        userinfo = {"client_id": "test_client", "sub": "1"}
        requests_mock.get(settings.OIDC_OP_USER_ENDPOINT,
                          status_code=status.HTTP_401_UNAUTHORIZED)
        requests_mock.post(settings.OIDC_OP_INTROSPECT_ENDPOINT,
                           text=json.dumps(userinfo))

    request = rf.get("/openid", HTTP_AUTHORIZATION=authentication_header)
    try:
        result = OIDCAuthentication().authenticate(request)
    except exceptions.AuthenticationFailed:
        assert error
    else:
        if result:
            key = "userinfo" if is_id_token else "introspection"
            user, auth = result
            assert user.is_authenticated
            assert (
                cache.get(f"auth.{key}.{hashlib.sha256(b'Token').hexdigest()}")
                == userinfo)
예제 #4
0
def test_authentication_multiple_existing_identity(
    db,
    rf,
    requests_mock,
    settings,
    identity_factory,
    get_claims,
    caplog,
):
    identity = identity_factory(idp_id="matching_id")
    identity_factory(email="*****@*****.**")
    claims = get_claims(id_claim="matching_id",
                        groups_claim=[],
                        email_claim="*****@*****.**")

    requests_mock.get(settings.OIDC_OP_USER_ENDPOINT, text=json.dumps(claims))

    assert Identity.objects.count() == 2

    request = rf.get("/openid", HTTP_AUTHORIZATION="Bearer Token")
    HistoricalRecords.thread.request = request

    result = OIDCAuthentication().authenticate(request)

    user, auth = result
    assert user.is_authenticated
    assert user.identity == identity
    assert Identity.objects.count() == 2
    assert (
        caplog.records[0].msg ==
        "Found one Identity with same idp_id and one with same email. Matching on idp_id."
    )
def test_authentication_idp_502(db, rf, requests_mock, settings):
    requests_mock.get(settings.OIDC_OP_USER_ENDPOINT,
                      status_code=status.HTTP_502_BAD_GATEWAY)

    request = rf.get("/openid", HTTP_AUTHORIZATION="Bearer Token")
    with pytest.raises(HTTPError):
        OIDCAuthentication().authenticate(request)
예제 #6
0
def test_authentication_dev(
    db, rf, requests_mock, settings, debug,
):
    settings.OIDC_DRF_AUTH_BACKEND = (
        "alexandria.oidc_auth.authentication.DevelopmentAuthenticationBackend"
    )
    settings.DEBUG = debug

    request = rf.get("/openid", HTTP_AUTHORIZATION="Bearer Token")
    if debug:
        user, _ = OIDCAuthentication().authenticate(request)
        assert user.groups == ["dev-group", "secondary-group"]
        assert user.username == "dev"
    else:
        with pytest.raises(ImproperlyConfigured) as exc:
            user = OIDCAuthentication().authenticate(request)
        assert exc.match("The Dev auth backend can only be used in DEBUG mode!")
def test_authentication_idp_missing_claim(db, rf, requests_mock, settings):
    settings.OIDC_USERNAME_CLAIM = "missing"
    userinfo = {"sub": "1"}
    requests_mock.get(settings.OIDC_OP_USER_ENDPOINT, text=json.dumps(userinfo))

    request = rf.get("/openid", HTTP_AUTHORIZATION="Bearer Token")
    with pytest.raises(AuthenticationFailed):
        OIDCAuthentication().authenticate(request)
예제 #8
0
def test_authentication_no_client(db, rf, requests_mock, settings, claims):
    requests_mock.get(settings.OIDC_OP_USER_ENDPOINT,
                      status_code=status.HTTP_401_UNAUTHORIZED)
    requests_mock.post(settings.OIDC_OP_INTROSPECT_ENDPOINT,
                       text=json.dumps(claims))

    request = rf.get("/openid", HTTP_AUTHORIZATION="Bearer Token")
    with pytest.raises(AuthenticationFailed):
        OIDCAuthentication().authenticate(request)
예제 #9
0
class TestDRF(TestCase):
    @override_settings(OIDC_OP_TOKEN_ENDPOINT='https://server.example.com/token')
    @override_settings(OIDC_OP_USER_ENDPOINT='https://server.example.com/user')
    @override_settings(OIDC_RP_CLIENT_ID='example_id')
    @override_settings(OIDC_RP_CLIENT_SECRET='client_secret')
    def setUp(self):
        self.auth = OIDCAuthentication(backend=mock.Mock())
        self.request = RequestFactory().get('/', HTTP_AUTHORIZATION='Bearer faketoken')

    def test_authenticate_returns_none_if_no_access_token(self):
        with mock.patch.object(self.auth, 'get_access_token', return_value=None):
            ret = self.auth.authenticate(self.request)
        self.assertIsNone(ret)

    def test_authenticate_raises_authenticationfailed_if_backend_returns_no_user(self):
        self.auth.backend.get_or_create_user.return_value = None
        with self.assertRaises(exceptions.AuthenticationFailed):
            self.auth.authenticate(self.request)

    def test_authenticate_raises_authenticationfailed_on_suspiciousoperation(self):
        self.auth.backend.get_or_create_user.side_effect = SuspiciousOperation
        with self.assertRaises(exceptions.AuthenticationFailed):
            self.auth.authenticate(self.request)

    def test_returns_user_and_token_if_backend_returns_user(self):
        user = mock.Mock()
        self.auth.backend.get_or_create_user.return_value = user
        ret = self.auth.authenticate(self.request)
        self.assertEqual(ret[0], user)
        self.assertEqual(ret[1], 'faketoken')
예제 #10
0
def test_authentication_email_update(
    db,
    rf,
    requests_mock,
    settings,
    user,
    expected_email,
):
    userinfo = {"sub": "1", "email": expected_email}
    requests_mock.get(settings.OIDC_OP_USER_ENDPOINT,
                      text=json.dumps(userinfo))

    request = rf.get("/openid", HTTP_AUTHORIZATION="Bearer Token")

    user, _ = OIDCAuthentication().authenticate(request)
    assert user.email == expected_email
예제 #11
0
def test_authentication(
    db,
    rf,
    authentication_header,
    authenticated,
    error,
    is_id_token,
    requests_mock,
    settings,
    claims,
):
    requests_mock.get(settings.OIDC_OP_USER_ENDPOINT, text=json.dumps(claims))

    assert Identity.objects.count() == 0

    if not is_id_token:
        claims["client_id"] = "test_client"
        requests_mock.get(settings.OIDC_OP_USER_ENDPOINT,
                          status_code=status.HTTP_401_UNAUTHORIZED)
        requests_mock.post(settings.OIDC_OP_INTROSPECT_ENDPOINT,
                           text=json.dumps(claims))

    request = rf.get("/openid", HTTP_AUTHORIZATION=authentication_header)
    HistoricalRecords.thread.request = request

    try:
        result = OIDCAuthentication().authenticate(request)
    except exceptions.AuthenticationFailed:
        assert error
    else:
        if authenticated:
            key = "userinfo" if is_id_token else "introspection"
            user, auth = result
            assert user.is_authenticated
            assert auth == authentication_header.split(" ")[1]
            assert (
                cache.get(f"auth.{key}.{hashlib.sha256(b'Token').hexdigest()}")
                == claims)
            assert Identity.objects.count() == 1
        else:
            assert result is None
예제 #12
0
 def setUp(self):
     self.auth = OIDCAuthentication(backend=mock.Mock())
     self.request = RequestFactory().get(
         '/', HTTP_AUTHORIZATION='Bearer faketoken')