commit f1f02c3787541ba29b4a1bcbd4255c51c14c84b1
parent 2da3ea21808c036d8c5889774cb7d5c22d21e522
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Thu, 10 Jul 2025 14:14:37 +0200
Add spa scope that is not refreshable by default
Diffstat:
3 files changed, 70 insertions(+), 13 deletions(-)
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
@@ -256,13 +256,19 @@ struct ScopePermissionMap scope_permissions[] = {
.name = "write",
.permissions = "*"
},
- /* Full access */
+ /* Full access for SPA */
{
.as = TMH_AS_ALL,
.name = "all",
.permissions = "*"
},
- /* Read-only access */
+ /* Full access for SPA */
+ {
+ .as = TMH_AS_SPA,
+ .name = "spa",
+ .permissions = "*"
+ },
+ /* Read-only access */
{
.as = TMH_AS_READ_ONLY,
.name = "readonly",
@@ -360,10 +366,9 @@ permission_in_scope (const char *permission_required,
"-read"));
}
- if (refreshable &&
- (0 == strcmp ("token-refresh",
- permission_required)) )
- return true;
+ if (0 == strcmp ("token-refresh",
+ permission_required))
+ return refreshable;
permissions = GNUNET_strdup (perms_tmp);
{
const char *perm = strtok (permissions,
diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h
@@ -451,10 +451,17 @@ enum TMH_AuthScope
/**
* Full access is granted to everything.
+ * We want to deprecate and remove this!
+ * Old scope "write"
*/
TMH_AS_ALL = 7 | 1 << 30,
/**
+ * Full access is granted to everything.
+ */
+ TMH_AS_SPA = 8,
+
+ /**
* /login access to renew the token is OK.
* This is actually combined with other scopes
* and not (usually) used as a scope itself.
diff --git a/src/testing/test_merchant_instance_auth.sh b/src/testing/test_merchant_instance_auth.sh
@@ -55,7 +55,7 @@ BASIC_AUTH=$(echo -n admin:new_pw | base64)
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H "Authorization: Basic $BASIC_AUTH" \
http://localhost:9966/private/token \
- -d '{"scope":"write"}' \
+ -d '{"scope":"spa"}' \
-w "%{http_code}" -s -o $LAST_RESPONSE)
@@ -140,7 +140,7 @@ BASIC_AUTH=$(echo -n "admin:$NEW_SECRET" | base64)
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H "Authorization: Basic $BASIC_AUTH" \
http://localhost:9966/private/token \
- -d '{"scope":"write"}' \
+ -d '{"scope":"spa"}' \
-w "%{http_code}" -s -o $LAST_RESPONSE)
@@ -246,12 +246,12 @@ TOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE")
echo " OK" >&2
-echo -n "Requesting login token... (write)" >&2
+echo -n "Requesting login token... (spa)" >&2
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Basic '"$BASIC_AUTH2" \
http://localhost:9966/instances/second/private/token \
- -d '{"scope":"write","refreshable":true}' \
+ -d '{"scope":"spa"}' \
-w "%{http_code}" -s -o "$LAST_RESPONSE")
if [ "$STATUS" != "200" ]
@@ -311,12 +311,12 @@ fi
echo " OK" >&2
-echo -n "Refreshing login token..." >&2
+echo -n "Refreshing login token... (expected failure)" >&2
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer '"$TOKEN" \
http://localhost:9966/instances/second/private/token \
- -d '{"scope":"write","refreshable":true}' \
+ -d '{"scope":"spa","refreshable":true}' \
-w "%{http_code}" -s -o "$LAST_RESPONSE")
if [ "$STATUS" != "403" ]
@@ -327,6 +327,51 @@ fi
echo " OK" >&2
+echo -n "Refreshing login token... (expected failure)" >&2
+
+STATUS=$(curl -H "Content-Type: application/json" -X POST \
+ -H 'Authorization: Bearer '"$RWTOKEN" \
+ http://localhost:9966/instances/second/private/token \
+ -d '{"scope":"spa","refreshable":true}' \
+ -w "%{http_code}" -s -o "$LAST_RESPONSE")
+
+if [ "$STATUS" != "401" ]
+then
+ jq < "$LAST_RESPONSE" >&2
+ exit_fail "Expected 401, refused to upgrade login token. got: $STATUS"
+fi
+
+echo " OK" >&2
+
+STATUS=$(curl -H "Content-Type: application/json" -X POST \
+ -H 'Authorization: Basic '"$BASIC_AUTH2" \
+ http://localhost:9966/instances/second/private/token \
+ -d '{"scope":"spa:refreshable"}' \
+ -w "%{http_code}" -s -o "$LAST_RESPONSE")
+
+if [ "$STATUS" != "200" ]
+then
+ jq < "$LAST_RESPONSE" >&2
+ exit_fail "Expected 200, login token created. got: $STATUS"
+fi
+
+RWTOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE")
+
+STATUS=$(curl -H "Content-Type: application/json" -X POST \
+ -H 'Authorization: Bearer '"$RWTOKEN" \
+ http://localhost:9966/instances/second/private/token \
+ -d '{"scope":"spa","refreshable":true}' \
+ -w "%{http_code}" -s -o "$LAST_RESPONSE")
+
+if [ "$STATUS" != "200" ]
+then
+ jq < "$LAST_RESPONSE" >&2
+ exit_fail "Expected 200. got: $STATUS"
+fi
+
+echo " OK" >&2
+
+
echo -n "Requesting another login token... (read)" >&2
STATUS=$(curl -H "Content-Type: application/json" -X POST \
@@ -367,7 +412,7 @@ echo "Getting 2 login tokens with offset 2." >&2
STATUS=$(curl -H "Content-Type: application/json" \
-H "Authorization: Bearer $RWTOKEN" \
- 'http://localhost:9966/instances/second/private/tokens?limit=2&offset=2' \
+ 'http://localhost:9966/instances/second/private/tokens?limit=2&offset=4' \
-w "%{http_code}" -s -o $LAST_RESPONSE)
if [ "$STATUS" != "200" ]