aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_mnp_token.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests/test_mnp_token.py')
-rw-r--r--packages/meshbay-hub/tests/test_mnp_token.py58
1 files changed, 52 insertions, 6 deletions
diff --git a/packages/meshbay-hub/tests/test_mnp_token.py b/packages/meshbay-hub/tests/test_mnp_token.py
index 3aa3115..ef6423d 100644
--- a/packages/meshbay-hub/tests/test_mnp_token.py
+++ b/packages/meshbay-hub/tests/test_mnp_token.py
@@ -8,9 +8,7 @@ these tests pin that it authorises to a node and is refused by the hub API.
"""
import pytest
-
from meshbay_common.handshake import HandshakeError, authorize_token
-from meshbay_common.tokens import MNP_AUD
async def _session_token(client, username="mnp_user_test"):
@@ -21,6 +19,12 @@ async def _session_token(client, username="mnp_user_test"):
return r.json()["access_token"]
+async def _own_group(client, tok, name="g"):
+ return (await client.post("/v1/groups", headers={"Authorization": f"Bearer {tok}"},
+ json={"name": name, "visibility": "private",
+ "join_policy": "invite"})).json()["group_id"]
+
+
@pytest.mark.asyncio
async def test_mnp_token_endpoint_needs_a_session(client):
# No Authorization header at all — FastAPI rejects the required header (422),
@@ -32,7 +36,8 @@ async def test_mnp_token_endpoint_needs_a_session(client):
@pytest.mark.asyncio
async def test_mnp_token_is_minted_for_a_member(client):
tok = await _session_token(client)
- r = await client.post("/v1/nodes/mnp-token",
+ gid = await _own_group(client, tok)
+ r = await client.post("/v1/nodes/mnp-token", json={"group_id": gid},
headers={"Authorization": f"Bearer {tok}"})
assert r.status_code == 200
assert r.json().get("mnp_token")
@@ -42,7 +47,8 @@ async def test_mnp_token_is_minted_for_a_member(client):
async def test_mnp_token_is_refused_at_the_hub_api(client):
"""The whole point: the credential a node receives opens nothing at the hub."""
tok = await _session_token(client, "mnp_api_test")
- mnp = (await client.post("/v1/nodes/mnp-token",
+ gid = await _own_group(client, tok)
+ mnp = (await client.post("/v1/nodes/mnp-token", json={"group_id": gid},
headers={"Authorization": f"Bearer {tok}"})).json()["mnp_token"]
# Presenting it to a hub endpoint fails.
r = await client.get("/v1/users/me", headers={"Authorization": f"Bearer {mnp}"})
@@ -60,7 +66,8 @@ async def test_a_session_token_is_refused_by_a_node_but_the_mnp_token_is_not(cli
H = {"Authorization": f"Bearer {tok}"}
gid = (await client.post("/v1/groups", headers=H, json={
"name": "g", "visibility": "private", "join_policy": "invite"})).json()["group_id"]
- mnp = (await client.post("/v1/nodes/mnp-token", headers=H)).json()["mnp_token"]
+ mnp = (await client.post("/v1/nodes/mnp-token", headers=H,
+ json={"group_id": gid})).json()["mnp_token"]
pk = hub_public_key_pem()
# The session token is refused by the node handshake (wrong audience).
@@ -83,10 +90,49 @@ async def test_the_mnp_token_is_bound_to_the_node_it_names(client):
"name": "g", "visibility": "private", "join_policy": "invite"})).json()["group_id"]
# A token bound to node A's key.
mnp = (await client.post("/v1/nodes/mnp-token", headers=H,
- json={"node_pk": "node-A-pk"})).json()["mnp_token"]
+ json={"node_pk": "node-A-pk", "group_id": gid})).json()["mnp_token"]
pk = hub_public_key_pem()
# Node B refuses it; node A accepts it.
with pytest.raises(HandshakeError, match="this node"):
authorize_token(mnp, pk, group_id=gid, node_pk_b64="node-B-pk")
peer = authorize_token(mnp, pk, group_id=gid, node_pk_b64="node-A-pk")
assert peer.group_id == gid
+
+
+@pytest.mark.asyncio
+async def test_the_mnp_token_names_only_the_group_asked_for(client):
+ """It is handed to that group's node operator, who has no business learning
+ every other group the member belongs to."""
+ import jwt as _jwt
+
+ tok = await _session_token(client, "mnp_scope_test")
+ H = {"Authorization": f"Bearer {tok}"}
+ one = await _own_group(client, tok, "one")
+ await _own_group(client, tok, "two")
+ await _own_group(client, tok, "three")
+ mnp = (await client.post("/v1/nodes/mnp-token", headers=H,
+ json={"group_id": one})).json()["mnp_token"]
+ claims = _jwt.decode(mnp, options={"verify_signature": False})
+ assert claims["groups"] == [one]
+
+
+@pytest.mark.asyncio
+async def test_no_group_is_named_for_a_non_member(client):
+ from meshbay_hub.auth import hub_public_key_pem
+
+ owner = await _session_token(client, "mnp_owner_test")
+ gid = await _own_group(client, owner)
+ stranger = await _session_token(client, "mnp_stranger")
+ mnp = (await client.post("/v1/nodes/mnp-token", json={"group_id": gid},
+ headers={"Authorization": f"Bearer {stranger}"})).json()["mnp_token"]
+ with pytest.raises(HandshakeError) as refused:
+ authorize_token(mnp, hub_public_key_pem(), group_id=gid)
+ assert refused.value.code == "not_a_member"
+
+
+@pytest.mark.asyncio
+async def test_a_token_must_name_its_group(client):
+ tok = await _session_token(client, "mnp_nogroup_test")
+ r = await client.post("/v1/nodes/mnp-token", json={},
+ headers={"Authorization": f"Bearer {tok}"})
+ assert r.status_code == 422