1
0

Add Spring Authorization Server project: OAuth2/OIDC provider, client and resource server

Three modules on Spring Boot 4.1.1 with Spring Authorization Server 7.1.1: the provider
itself, a relying party, and an API that trusts its tokens. Client registration, PKCE,
a custom consent page and token customisation, with profiles that make each failure
reproducible.

Every claim is backed by captured output in docs/output/as-*.txt, regenerated by
authorization-server/scripts/run-all.sh. Notable findings, verified against the jars:

  - OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(HttpSecurity) was deleted
    in 7.0, and both configuration classes moved into spring-security-config
  - ClientSettings.requireProofKey flipped from false to true, on the authorization server
    (1.5.8 -> 7.1.1) and on the OAuth2 client (6.5.1 -> 7.1.1)
  - requireProofKey(false) does not make PKCE optional for a public client; the code
    verifier is that client's only authentication at the token endpoint
  - MediaTypeRequestMatcher(TEXT_HTML) matches Accept: */*, so the token endpoint answers
    API callers with 302 -> /login unless setIgnoredMediaTypes(ALL) is called

Also renames the repository to spring-auth-demo and cross-links the new chapter set from
the existing documentation.
This commit is contained in:
2026-08-24 08:12:36 +05:30
parent 4dc45d5e00
commit e9381dc5be
89 changed files with 5237 additions and 9 deletions

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# The simplest grant, and what the token customiser does and does not add to it.
set -u
cd "$(dirname "$0")/.."
. scripts/lib.sh
OUT="../docs/output/${1:-as-client-credentials}.txt"
mkdir -p ../docs/output
{
section "POST /oauth2/token grant_type=client_credentials"
echo "\$ curl -su demo-service:service-secret -d grant_type=client_credentials \\"
echo " -d scope=orders.read $AS/oauth2/token"
RESP=$(curl -s -u demo-service:service-secret \
-d grant_type=client_credentials -d scope=orders.read \
"$AS/oauth2/token")
echo "$RESP" | python3 -m json.tool
TOKEN=$(echo "$RESP" | python3 -c 'import sys,json;print(json.load(sys.stdin).get("access_token",""))')
if [ -z "$TOKEN" ]; then echo "no access token - stopping"; exit 1; fi
case "$TOKEN" in
*.*.*)
section "JOSE header"
jwt_header "$TOKEN"
section "Claims"
jwt_payload "$TOKEN"
;;
*)
section "Not a JWT"
echo "The access token is an opaque reference: $TOKEN"
echo "Length ${#TOKEN}. It carries no claims; the resource server must introspect it."
section "POST /oauth2/introspect"
curl -s -u demo-service:service-secret -d "token=$TOKEN" \
"$AS/oauth2/introspect" | python3 -m json.tool
;;
esac
section "Wrong secret"
echo "\$ curl -si -u demo-service:WRONG -d grant_type=client_credentials $AS/oauth2/token"
curl -s -i -u demo-service:WRONG -d grant_type=client_credentials \
"$AS/oauth2/token" | sed -n '1p;/^WWW-Authenticate/p;/^{/p'
section "A grant the client is not registered for"
echo "\$ curl -si -u demo-service:service-secret -d grant_type=authorization_code -d code=x $AS/oauth2/token"
curl -s -i -u demo-service:service-secret -d grant_type=authorization_code -d code=x \
"$AS/oauth2/token" | sed -n '1p;/^{/p'
section "A scope the client is not registered for"
echo "\$ curl -s -u demo-service:service-secret -d grant_type=client_credentials -d scope=orders.write $AS/oauth2/token"
curl -s -u demo-service:service-secret -d grant_type=client_credentials -d scope=orders.write \
"$AS/oauth2/token"
echo
section "Calling the resource server with the token"
for path in /public /api/orders /api/admin; do
CODE=$(curl -s -o /tmp/rsbody -w '%{http_code}' -H "Authorization: Bearer $TOKEN" "$RS$path")
WWW=$(curl -s -D - -o /dev/null -H "Authorization: Bearer $TOKEN" "$RS$path" | grep -i '^WWW-Authenticate' || true)
echo "GET $path -> $CODE"
[ -n "$WWW" ] && echo " $WWW"
head -c 400 /tmp/rsbody; echo
done
} > "$OUT" 2>&1
sed -i 's/[[:space:]]*$//' "$OUT"
echo "wrote $OUT"