changeset 5636:b3484a112300

mod_rest/rest.sh: Update to use httpie-oauth2 plugin This bash implementation of OAuth2/OIDC was growing to the point where it needed a massive refactor, which made me look into alternatives where I finally settled on implementing oauth2 in a plugin for HTTPie.
author Kim Alvefur <zash@zash.se>
date Sat, 26 Aug 2023 14:37:04 +0200
parents 401356232e1b
children acd2f397ce6b
files mod_rest/example/rest.sh
diffstat 1 files changed, 7 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/mod_rest/example/rest.sh	Sat Aug 26 01:40:23 2023 +0200
+++ b/mod_rest/example/rest.sh	Sat Aug 26 14:37:04 2023 +0200
@@ -5,23 +5,23 @@
 
 # Dependencies:
 # - https://httpie.io/
-# - https://github.com/stedolan/jq
-# - some sort of XDG 'open' command
+# - https://hg.sr.ht/~zash/httpie-oauth2
 
 # Settings
 HOST=""
 DOMAIN=""
 
-AUTH_METHOD="session-read-only"
-AUTH_ID="rest"
-
 if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/restrc" ]; then
 	# Config file can contain the above settings
 	source "${XDG_CONFIG_HOME:-$HOME/.config}/restrc"
+
+	if [ -z "${SCOPE:-}" ]; then
+		SCOPE="openid xmpp"
+	fi
 fi
 
 if [[ $# == 0 ]]; then
-	echo "${0##*/} [-h HOST] [-u USER|--login] [/path] kind=(message|presence|iq) ...."
+	echo "${0##*/} [-h HOST] [/path] kind=(message|presence|iq) ...."
 	# Last arguments are handed to HTTPie, so refer to its docs for further details
 	exit 0
 fi
@@ -45,96 +45,6 @@
 	fi
 fi
 
-if [[ "$1" == "-u" ]]; then
-	# -u username
-	AUTH_METHOD="auth"
-	AUTH_ID="$2"
-	shift 2
-elif [[ "$1" == "-rw" ]]; then
-	# To e.g. save Accept headers to the session
-	AUTH_METHOD="session"
-	shift 1
-fi
-
-if [[ "$1" == "--login" ]]; then
-	shift 1
-
-	# Check cache for OAuth client
-	if [ -f "${XDG_CACHE_HOME:-$HOME/.cache}/rest/$HOST" ]; then
-		source "${XDG_CACHE_HOME:-$HOME/.cache}/rest/$HOST"
-	fi
-
-	OAUTH_META="$(http --check-status --json "https://$HOST/.well-known/oauth-authorization-server" Accept:application/json)"
-	AUTHORIZATION_ENDPOINT="$(echo "$OAUTH_META" | jq -e -r '.authorization_endpoint')"
-	TOKEN_ENDPOINT="$(echo "$OAUTH_META" | jq -e -r '.token_endpoint')"
-
-	if [ -z "${OAUTH_CLIENT_INFO:-}" ]; then
-		# Register a new OAuth client
-		REGISTRATION_ENDPOINT="$(echo "$OAUTH_META" | jq -e -r '.registration_endpoint')"
-		OAUTH_CLIENT_INFO="$(http --check-status "$REGISTRATION_ENDPOINT" Content-Type:application/json Accept:application/json client_name=rest.sh client_uri="https://modules.prosody.im/mod_rest" application_type=native software_id=0bdb0eb9-18e8-43af-a7f6-bd26613374c0 redirect_uris:='["urn:ietf:wg:oauth:2.0:oob"]')"
-		mkdir -p "${XDG_CACHE_HOME:-$HOME/.cache}/rest/"
-		typeset -p OAUTH_CLIENT_INFO >> "${XDG_CACHE_HOME:-$HOME/.cache}/rest/$HOST"
-	fi
-
-	CLIENT_ID="$(echo "$OAUTH_CLIENT_INFO" | jq -e -r '.client_id')"
-	CLIENT_SECRET="$(echo "$OAUTH_CLIENT_INFO" | jq -e -r '.client_secret')"
-
-	if [ -n "${REFRESH_TOKEN:-}" ]; then
-		TOKEN_RESPONSE="$(http --check-status --form "$TOKEN_ENDPOINT" 'grant_type=refresh_token' "client_id=$CLIENT_ID" "client_secret=$CLIENT_SECRET" "refresh_token=$REFRESH_TOKEN")"
-		ACCESS_TOKEN="$(echo "$TOKEN_RESPONSE" | jq -r '.access_token')"
-		if [ "$ACCESS_TOKEN" == "null" ]; then
-			ACCESS_TOKEN=""
-		fi
-	fi
-
-	if [ -z "${ACCESS_TOKEN:-}" ]; then
-		CODE_CHALLENGE="$(head -c 33 /dev/urandom | base64 | tr /+ _-)"
-		open "$AUTHORIZATION_ENDPOINT?response_type=code&client_id=$CLIENT_ID&code_challenge=$CODE_CHALLENGE&scope=${SCOPE:-openid+prosody:user}"
-		read -p "Paste authorization code: " -s -r AUTHORIZATION_CODE
-
-		TOKEN_RESPONSE="$(http --check-status --form "$TOKEN_ENDPOINT" 'grant_type=authorization_code' "client_id=$CLIENT_ID" "client_secret=$CLIENT_SECRET" "code=$AUTHORIZATION_CODE" code_verifier="$CODE_CHALLENGE")"
-		ACCESS_TOKEN="$(echo "$TOKEN_RESPONSE" | jq -e -r '.access_token')"
-		REFRESH_TOKEN="$(echo "$TOKEN_RESPONSE" | jq -r '.refresh_token')"
-
-		if [ "$REFRESH_TOKEN" != "null" ]; then
-			# FIXME Better type check would be nice, but nobody should ever have the
-			# string "null" as a legitimate refresh token...
-			typeset -p REFRESH_TOKEN >> "${XDG_CACHE_HOME:-$HOME/.cache}/rest/$HOST"
-		fi
-
-		if [ -n "${COLORTERM:-}" ]; then
-			echo -ne '\e[1K\e[G'
-		else
-			echo
-		fi
-	fi
-
-	USERINFO_ENDPOINT="$(echo "$OAUTH_META" | jq -e -r '.userinfo_endpoint')"
-	http --check-status -b --session rest "$USERINFO_ENDPOINT" "Authorization:Bearer $ACCESS_TOKEN" Accept:application/json >&2
-	AUTH_METHOD="session-read-only"
-	AUTH_ID="rest"
-
-elif [[ "$1" == "--logout" ]]; then
-	# Revoke token
-	source "${XDG_CACHE_HOME:-$HOME/.cache}/rest/$HOST"
-
-	OAUTH_META="$(http --check-status --json "https://$HOST/.well-known/oauth-authorization-server" Accept:application/json)"
-	REVOCATION_ENDPOINT="$(echo "$OAUTH_META" | jq -e -r '.revocation_endpoint')"
-
-	CLIENT_ID="$(echo "$OAUTH_CLIENT_INFO" | jq -e -r '.client_id')"
-	CLIENT_SECRET="$(echo "$OAUTH_CLIENT_INFO" | jq -e -r '.client_secret')"
-
-	http -h --check-status --auth "$CLIENT_ID:$CLIENT_SECRET" --form "$REVOCATION_ENDPOINT" token="$REFRESH_TOKEN"
-
-	# Overwrite the token
-	typeset -p OAUTH_CLIENT_INFO > "${XDG_CACHE_HOME:-$HOME/.cache}/rest/$HOST"
-	exit 0
-fi
-
-if [[ $# == 0 ]]; then
-	# Just login?
-	exit 0
-fi
 
 # For e.g /disco/example.com and such GET queries
 GET_PATH=""
@@ -143,4 +53,4 @@
 	shift 1
 fi
 
-http --check-status -p b "--$AUTH_METHOD" "$AUTH_ID" "https://$HOST/rest$GET_PATH" "$@"
+https --check-status -p b --session rest -A oauth2 -a "$HOST" --oauth2-scope "$SCOPE" "$HOST/rest$GET_PATH" "$@"