Skip to content

Commit

Permalink
Every WebAuthnFactor email shares a user_handle
Browse files Browse the repository at this point in the history
  • Loading branch information
scotttrinh committed Feb 21, 2024
1 parent 3dd2036 commit 1431063
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
10 changes: 10 additions & 0 deletions edb/lib/ext/auth.edgeql
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ CREATE EXTENSION PACKAGE auth VERSION '1.0' {
create constraint exclusive;
};

create trigger email_shares_user_handle after insert for each do (
std::assert(
(__new__.user_handle = (
select detached ext::auth::WebAuthnFactor
filter .email = __new__.email
and not .id = __new__.id
).user_handle) ?? true,
message := "user_handle must be the same for a given email"
)
);
create constraint exclusive on ((.email, .credential_id));
};

Expand Down
50 changes: 50 additions & 0 deletions tests/test_http_ext_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from typing import Any, Callable
from jwcrypto import jwt, jwk

from edgedb import QueryAssertionError
from edb.testbase import http as tb
from edb.common import assert_data_shape

Expand Down Expand Up @@ -3639,6 +3640,55 @@ async def test_http_auth_ext_webauthn_register_options_existing_user(self):

self.assertEqual(user_id_decoded, existing_user_handle)

async def test_http_auth_ext_webauthn_emails_share_user_handle(self):
email = "[email protected]"

user_handle_one = uuid.uuid4().bytes
credential_id_one = uuid.uuid4().bytes
public_key_one = uuid.uuid4().bytes

user_handle_two = uuid.uuid4().bytes
credential_id_two = uuid.uuid4().bytes
public_key_two = uuid.uuid4().bytes

with self.assertRaisesRegex(
QueryAssertionError,
"user_handle must be the same for a given email",
):
await self.con.execute(
"""
with
factor_one := (insert ext::auth::WebAuthnFactor {
email := <str>$email,
user_handle := <bytes>$user_handle_one,
credential_id := <bytes>$credential_id_one,
public_key := <bytes>$public_key_one,
identity := (insert ext::auth::LocalIdentity {
issuer := "local",
subject := "",
}),
}),
factor_two := (insert ext::auth::WebAuthnFactor {
email := <str>$email,
user_handle := <bytes>$user_handle_two,
credential_id := <bytes>$credential_id_two,
public_key := <bytes>$public_key_two,
identity := (insert ext::auth::LocalIdentity {
issuer := "local",
subject := "",
}),
})
select true;
""",
email=email,
user_handle_one=user_handle_one,
credential_id_one=credential_id_one,
public_key_one=public_key_one,
user_handle_two=user_handle_two,
credential_id_two=credential_id_two,
public_key_two=public_key_two,
)

async def test_http_auth_ext_webauthn_authenticate_options(self):
with self.http_con() as http_con:
email = "[email protected]"
Expand Down

0 comments on commit 1431063

Please sign in to comment.