1
0
Files
spring-security-demo/service-to-service/scripts/user-token.sh

49 lines
2.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Drive a complete authorization_code + PKCE flow with curl and print the access token.
#
# TOKEN=$(./scripts/user-token.sh)
#
# There is no browser here and none is needed: the "browser flow" is four HTTP requests and a
# cookie jar. Doing it by hand once is the fastest way to understand what your SPA's OIDC
# library is actually doing, and it makes every transcript in docs/output/ reproducible.
set -eu
AS=http://127.0.0.1:9000
JAR=$(mktemp)
trap 'rm -f "$JAR"' EXIT
# 1. PKCE: a random verifier, and its base64url-encoded SHA-256 as the challenge.
VERIFIER=$(head -c 48 /dev/urandom | base64 | tr -d '=+/' | cut -c1-64)
CHALLENGE=$(printf '%s' "$VERIFIER" | openssl dgst -binary -sha256 | base64 | tr '+/' '-_' | tr -d '=')
AUTHORIZE="$AS/oauth2/authorize?response_type=code&client_id=spa-client\
&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2Fauthorized&scope=orders.read%20orders.write\
&code_challenge=$CHALLENGE&code_challenge_method=S256"
# 2. Ask for the code. Unauthenticated, so this saves the request and redirects to /login.
curl -s -o /dev/null -c "$JAR" -b "$JAR" "$AUTHORIZE"
# 3. Log in. The login page is CSRF-protected, so read the token out of the form.
CSRF=$(curl -s -c "$JAR" -b "$JAR" "$AS/login" \
| grep -oiE 'name="_csrf"[^>]*value="[^"]*"' | head -1 | sed 's/.*value="//; s/"//')
curl -s -o /dev/null -c "$JAR" -b "$JAR" -X POST "$AS/login" \
-d "username=alice" -d "password=password" -d "_csrf=$CSRF"
# 4. Follow the saved request. Now authenticated, so this redirects to the redirect_uri
# carrying ?code=... We never let curl follow it; we just read the Location header.
CODE=$(curl -s -o /dev/null -D- -c "$JAR" -b "$JAR" "$AUTHORIZE" \
| grep -i '^location:' | sed 's/.*code=//; s/[&\r].*//')
if [ -z "$CODE" ]; then
echo "no authorization code was issued - is the auth server up?" >&2
exit 1
fi
# 5. Redeem it. A public client, so no client secret: the code_verifier is the proof.
curl -s -X POST "$AS/oauth2/token" \
-d grant_type=authorization_code \
-d "code=$CODE" \
-d "redirect_uri=http://127.0.0.1:8080/authorized" \
-d client_id=spa-client \
-d "code_verifier=$VERIFIER" \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["access_token"])'