Include simple script to generate an access token

This commit is contained in:
Quentin Gliech
2025-08-12 16:58:00 +02:00
parent 8fea19f92a
commit 199926b1b7
3 changed files with 142 additions and 0 deletions

View File

@@ -21,6 +21,7 @@
- [Policy engine](./topics/policy.md)
- [Authorization and sessions](./topics/authorization.md)
- [Use the Admin API](./topics/admin-api.md)
- [Get an access token](./topics/access-token.md)
# Reference

View File

@@ -0,0 +1,31 @@
# Get an access token
The [Matrix Authentication Service repository contains a simple shell script](https://github.com/element-hq/matrix-authentication-service/blob/main/misc/device-code-grant.sh) to get interatively get an access token with arbitrary scopes.
It requires `sh`, `jq` and `curl` to be installed.
This can be run from anywhere, not necessarily from the host where MAS is running.
```sh
sh ./misc/device-code-grant.sh [synapse-url] <scope>...
```
This will prompt you to open a URL in your browser, finish the authentication flow, and print the access token.
This can be used to get access to the MAS admin API:
```sh
sh ./misc/device-code-grant.sh https://synapse.example.com/ urn:mas:admin
```
Or to the Synapse admin API:
```sh
sh ./misc/device-code-grant.sh https://synapse.example.com/ urn:matrix:org.matrix.msc2967.client:api:* urn:synapse:admin:*
```
Or even both at the same time:
```sh
sh ./misc/device-code-grant.sh https://synapse.example.com/ urn:matrix:org.matrix.msc2967.client:api:* urn:mas:admin urn:synapse:admin:*
```
Note that the token will be valid for a short time (5 minutes by default) and needs to be revoked manually from the MAS user interface.

110
misc/device-code-grant.sh Executable file
View File

@@ -0,0 +1,110 @@
#!/bin/sh
set -eu
usage() {
echo "$0 [synapse-url] <scope>..." >&2
exit 1
}
req() {
METHOD="$1"
shift
URL="$1"
shift
printf "> %4s %s\n" "$METHOD" "$URL" >&2
curl -sL --fail-with-body -o- -H 'Accept: application/json' -X "$METHOD" "$@" "$URL"
}
if [ "$#" -eq "0" ]; then
usage
fi
CS_API="${1%/}"
shift
if [ -z "$*" ]; then
SCOPE="urn:matrix:org.matrix.msc2967.client:api:*"
else
SCOPE="$*"
fi
echo "Discovering the homeserver endpoints"
METADATA="$(req GET "${CS_API}/_matrix/client/unstable/org.matrix.msc2965/auth_metadata")"
DEVICE_AUTHORIZATION_ENDPOINT="$(echo "$METADATA" | jq -r '.device_authorization_endpoint')"
TOKEN_ENDPOINT="$(echo "$METADATA" | jq -r '.token_endpoint')"
REGISTRATION_ENDPOINT="$(echo "$METADATA" | jq -r '.registration_endpoint')"
echo "Registering the client"
# Note that the client_uri is only used as an identifier, MAS will not try to contact this URI
RESP="$(
req POST "${REGISTRATION_ENDPOINT}" \
-H 'Content-Type: application/json' \
-d @- <<EOF
{
"client_name": "CLI tool",
"client_uri": "https://github.com/element-hq/matrix-authentication-service/",
"grant_types": ["urn:ietf:params:oauth:grant-type:device_code"],
"application_type": "native",
"token_endpoint_auth_method": "none"
}
EOF
)"
CLIENT_ID="$(echo "$RESP" | jq -r '.client_id')"
DEVICE_GRANT="$(
req POST "${DEVICE_AUTHORIZATION_ENDPOINT}" \
--data-urlencode "client_id=${CLIENT_ID}" \
--data-urlencode "scope=${SCOPE}"
)"
cat - <<EOF
-----------------------
Homeserver: ${CS_API}
Registration endpoint: ${REGISTRATION_ENDPOINT}
Device auth endpoint: ${DEVICE_AUTHORIZATION_ENDPOINT}
Token endpoint: ${TOKEN_ENDPOINT}
Client ID: ${CLIENT_ID}
Scope: ${SCOPE}
-----------------------
EOF
echo
echo "Open the following URL in your browser:"
echo "$DEVICE_GRANT" | jq -r ".verification_uri_complete"
echo
# If we have qrencode
if command -v qrencode 2>/dev/null; then
echo "$DEVICE_GRANT" | jq -r ".verification_uri_complete" | qrencode -t ANSI256UTF8
echo
fi
echo "Alternatively, go to $(echo "$DEVICE_GRANT" | jq -r ".verification_uri") and enter the code $(echo "$DEVICE_GRANT" | jq -r ".user_code")"
echo
echo -----------------------
echo
DEVICE_CODE="$(echo "$DEVICE_GRANT" | jq -r ".device_code")"
INTERVAL="$(echo "$DEVICE_GRANT" | jq -r ".interval")"
while true; do
DEVICE_RESP="$(
req POST "${TOKEN_ENDPOINT}" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
--data-urlencode "device_code=${DEVICE_CODE}" \
--data-urlencode "client_id=${CLIENT_ID}" || true
)"
if [ "$(echo "$DEVICE_RESP" | jq -r ".error")" = "authorization_pending" ]; then
echo "Waiting for authorization"
sleep "${INTERVAL}"
else
break
fi
done
echo "$DEVICE_RESP" | jq .
exit 0