diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 1857fa42b..211047872 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -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 diff --git a/docs/topics/access-token.md b/docs/topics/access-token.md new file mode 100644 index 000000000..d6ae65235 --- /dev/null +++ b/docs/topics/access-token.md @@ -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] ... +``` + +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. diff --git a/misc/device-code-grant.sh b/misc/device-code-grant.sh new file mode 100755 index 000000000..c77101cb5 --- /dev/null +++ b/misc/device-code-grant.sh @@ -0,0 +1,110 @@ +#!/bin/sh + +set -eu + +usage() { + echo "$0 [synapse-url] ..." >&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 @- </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