Skip to content

Commit c5ef57c

Browse files
authored
Include simple script to generate an access token (#4890)
2 parents 119ebba + 5ff85b7 commit c5ef57c

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

docs/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
- [Policy engine](./topics/policy.md)
2222
- [Authorization and sessions](./topics/authorization.md)
2323
- [Use the Admin API](./topics/admin-api.md)
24+
- [Get an access token](./topics/access-token.md)
2425

2526
# Reference
2627

docs/topics/access-token.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Get an access token
2+
3+
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.
4+
It requires `sh`, `jq` and `curl` to be installed.
5+
This can be run from anywhere, not necessarily from the host where MAS is running.
6+
7+
```sh
8+
sh ./misc/device-code-grant.sh [synapse-url] <scope>...
9+
```
10+
11+
This will prompt you to open a URL in your browser, finish the authentication flow, and print the access token.
12+
13+
This can be used to get access to the MAS admin API:
14+
15+
```sh
16+
sh ./misc/device-code-grant.sh https://synapse.example.com/ urn:mas:admin
17+
```
18+
19+
Or to the Synapse admin API:
20+
21+
```sh
22+
sh ./misc/device-code-grant.sh https://synapse.example.com/ urn:matrix:org.matrix.msc2967.client:api:* urn:synapse:admin:*
23+
```
24+
25+
Or even both at the same time:
26+
27+
```sh
28+
sh ./misc/device-code-grant.sh https://synapse.example.com/ urn:matrix:org.matrix.msc2967.client:api:* urn:mas:admin urn:synapse:admin:*
29+
```
30+
31+
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.

misc/device-code-grant.sh

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#!/bin/sh
2+
3+
set -eu
4+
5+
usage() {
6+
echo "$0 [synapse-url] <scope>..." >&2
7+
exit 1
8+
}
9+
10+
req() {
11+
METHOD="$1"
12+
shift
13+
URL="$1"
14+
shift
15+
printf "> %4s %s\n" "$METHOD" "$URL" >&2
16+
curl -sL --fail-with-body -o- -H 'Accept: application/json' -X "$METHOD" "$@" "$URL"
17+
}
18+
19+
if [ "$#" -eq "0" ]; then
20+
usage
21+
fi
22+
23+
CS_API="${1%/}"
24+
shift
25+
26+
if [ -z "$*" ]; then
27+
SCOPE="urn:matrix:org.matrix.msc2967.client:api:*"
28+
else
29+
SCOPE="$*"
30+
fi
31+
32+
33+
echo "Discovering the homeserver endpoints"
34+
METADATA="$(req GET "${CS_API}/_matrix/client/unstable/org.matrix.msc2965/auth_metadata")"
35+
DEVICE_AUTHORIZATION_ENDPOINT="$(echo "$METADATA" | jq -r '.device_authorization_endpoint')"
36+
TOKEN_ENDPOINT="$(echo "$METADATA" | jq -r '.token_endpoint')"
37+
REGISTRATION_ENDPOINT="$(echo "$METADATA" | jq -r '.registration_endpoint')"
38+
39+
echo "Registering the client"
40+
# Note that the client_uri is only used as an identifier, MAS will not try to contact this URI
41+
RESP="$(
42+
req POST "${REGISTRATION_ENDPOINT}" \
43+
-H 'Content-Type: application/json' \
44+
-d @- <<EOF
45+
{
46+
"client_name": "CLI tool",
47+
"client_uri": "https://github.com/element-hq/matrix-authentication-service/",
48+
"grant_types": ["urn:ietf:params:oauth:grant-type:device_code"],
49+
"application_type": "native",
50+
"token_endpoint_auth_method": "none"
51+
}
52+
EOF
53+
)"
54+
55+
CLIENT_ID="$(echo "$RESP" | jq -r '.client_id')"
56+
57+
DEVICE_GRANT="$(
58+
req POST "${DEVICE_AUTHORIZATION_ENDPOINT}" \
59+
--data-urlencode "client_id=${CLIENT_ID}" \
60+
--data-urlencode "scope=${SCOPE}"
61+
)"
62+
63+
cat - <<EOF
64+
-----------------------
65+
Homeserver: ${CS_API}
66+
Registration endpoint: ${REGISTRATION_ENDPOINT}
67+
Device auth endpoint: ${DEVICE_AUTHORIZATION_ENDPOINT}
68+
Token endpoint: ${TOKEN_ENDPOINT}
69+
Client ID: ${CLIENT_ID}
70+
Scope: ${SCOPE}
71+
-----------------------
72+
EOF
73+
74+
echo
75+
echo "Open the following URL in your browser:"
76+
echo "$DEVICE_GRANT" | jq -r ".verification_uri_complete"
77+
echo
78+
79+
# If we have qrencode
80+
if command -v qrencode 2>/dev/null; then
81+
echo "$DEVICE_GRANT" | jq -r ".verification_uri_complete" | qrencode -t ANSI256UTF8
82+
echo
83+
fi
84+
85+
echo "Alternatively, go to $(echo "$DEVICE_GRANT" | jq -r ".verification_uri") and enter the code $(echo "$DEVICE_GRANT" | jq -r ".user_code")"
86+
echo
87+
echo -----------------------
88+
echo
89+
90+
DEVICE_CODE="$(echo "$DEVICE_GRANT" | jq -r ".device_code")"
91+
INTERVAL="$(echo "$DEVICE_GRANT" | jq -r ".interval")"
92+
93+
while true; do
94+
DEVICE_RESP="$(
95+
req POST "${TOKEN_ENDPOINT}" \
96+
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
97+
--data-urlencode "device_code=${DEVICE_CODE}" \
98+
--data-urlencode "client_id=${CLIENT_ID}" || true
99+
)"
100+
if [ "$(echo "$DEVICE_RESP" | jq -r ".error")" = "authorization_pending" ]; then
101+
echo "Waiting for authorization"
102+
sleep "${INTERVAL}"
103+
else
104+
break
105+
fi
106+
done
107+
108+
echo "$DEVICE_RESP" | jq .
109+
110+
exit 0

0 commit comments

Comments
 (0)