Discovery

S101 Profile URL is valid and can be fetched Fetched with HTTP 200.
S102 Advertises indieauth-metadata Found https://indiekit.ciccarello.me/.well-known/oauth-authorization-server in the HTML.
S103 Link header and HTML agree Only one of them is present.
S104 Metadata is a JSON document HTTP 200 with a JSON object.
S105 Issuer identifier is valid issuer is https://indiekit.ciccarello.me
S106 Authorization endpoint is listed authorization_endpoint is https://indiekit.ciccarello.me/auth
S107 Token endpoint is listed token_endpoint is https://indiekit.ciccarello.me/auth/token
S108 Introspection endpoint is listed introspection_endpoint is https://indiekit.ciccarello.me/auth/introspect
S109 PKCE S256 is supported S256 is listed.
! S110 Advertises the iss response parameter authorization_response_iss_parameter_supported is not true, so clients cannot rely on iss for mix-up protection.
S111 Lists supported scopes scopes_supported lists create, draft, update, delete, media, read, follow, mute, block, channels
S112 Response and grant types are consistent Consistent (or using the defaults).
S113 Revocation needs no client authentication No revocation_endpoint is listed.
S114 Metadata can be read by browser-based apps No CORS headers; browser-based apps cannot read the metadata directly.
S115 Legacy endpoint links match the metadata Legacy links match the metadata.
S116 Endpoints use https All endpoints use https.
· S117 Serves metadata at the RFC 8414 well-known URL

Authorization requests

S201 Returns state unmodified state was returned unmodified.
S202 Returns the iss parameter iss matched the issuer on every redirect.
S203 Issues an authorization code A code was issued.
S204 Keeps the query string of the redirect URI The query string of the redirect URI was kept.
S205 Fetches client information Your server fetched the client_id document.
S206 Consent screen identifies the application You skipped this step.
S207 Reports a denied request to the client There was no way to cancel the request.
S208 Refuses an unregistered cross-origin redirect URI Your server showed an error and did not redirect.
S209 Accepts a registered cross-origin redirect URI Your server showed an error for a request it should have allowed.
S210 Matches redirect URIs exactly Your server showed an error and did not redirect.
S211 Is not fooled by credentials in a URL Your server showed an error and did not redirect.
S212 Ignores client metadata for a different client_id Your server showed an error and did not redirect.
! S213 Rejects a repeated redirect_uri parameter Your server showed an approval screen for an unregistered redirect URI instead of an error.
S214 Is not an open redirector Your server showed an error and did not redirect.
! S215 Requires PKCE Your server showed an approval screen for this request instead of refusing it.
! S216 Refuses the plain PKCE method Your server showed an approval screen for this request instead of refusing it.
S217 Refuses the implicit flow Your server showed an error.
S218 Handles a missing state parameter Your server showed an error.
! S219 Refuses an invalid client_id Your server showed an approval screen for this request instead of refusing it.
S220 Does not trust the me parameter Your server returned https://www.ciccarello.me rather than the profile URL the request asked for.
· S221 Refuses a PKCE method without a challenge
· S222 Refuses a challenge without a method

Code redemption

S301 Exchanges a code at the token endpoint The code was exchanged for tokens.
S302 Codes can only be used once The same code was exchanged a second time.
S303 Reusing a code revokes its tokens No userinfo endpoint to check the tokens with.
S310 Refuses a wrong code_verifier The wrong verifier was refused (HTTP 401 unauthorized).
S311 Refuses a missing code_verifier Refused (HTTP 500 ERR_INVALID_ARG_TYPE).
S312 Refuses a code presented by another client Refused (HTTP 401 unauthorized).
S313 Refuses a mismatched redirect_uri The code was accepted: HTTP 200.
S320 Exchanges a code at the authorization endpoint Returned me (https://www.ciccarello.me) and no access token.
! S330 Refuses an unknown code Refused, but with HTTP 401 unauthorized instead of HTTP 400 invalid_grant.
! S331 Refuses missing or unsupported grant types Refused, but with HTTP 400 bad_request and HTTP 400 bad_request.
S332 Errors are JSON with an error code Error responses are JSON with an error code.
! S333 Token endpoint refuses GET requests The token endpoint answered a GET request with HTTP 200.
S334 Token endpoint supports CORS preflight No CORS preflight support; browser-based apps cannot call the token endpoint directly.

Token responses

S401 Token response is JSON HTTP 200 with a JSON object.
S402 Includes an access token An access token was issued.
S403 Token type is Bearer token_type is Bearer.
S404 Returns a valid me me is https://www.ciccarello.me
S405 The returned me is verified https://www.ciccarello.me declares the same authorization endpoint.
S406 Token responses are not cached The response does not send Cache-Control: no-store, so tokens could be cached.
! S407 Says when the token expires expires_in is missing, so the client cannot tell when the token expires.
! S408 Reports the granted scope scope is missing from the response.
S409 Profile information is well formed No profile information was returned, which is allowed.
S410 Access tokens are hard to guess The access token is long enough.
S420 Access token format Access tokens are JWTs, signed with HS256.
! S421 JWT header marks it an access token The JWT header says typ "JWT" rather than "at+jwt".
S422 JWT verifies against the published keys The metadata has no jwks_uri, so a resource server cannot get the key to verify the token with.
S423 JWT claims are complete The claims are not what a resource server needs: missing iss, aud, sub.

Refresh tokens

S501 Refreshes an access token No refresh token was issued.
S502 Refuses a refresh by another client No refresh token was issued.
S503 Refuses to add scopes on refresh No refresh token was issued.
S504 Old refresh tokens stop working after rotation No refresh token was issued.
S505 Refresh token reuse revokes the grant No refresh token was issued.

Revocation

S601 Revokes an access token No revocation endpoint.
S602 Revoked tokens stop working No revocation endpoint.
S603 Revokes a refresh token No revocation endpoint.
S604 Revoking an unknown token succeeds No revocation endpoint.

Userinfo

S701 Returns profile information No userinfo endpoint.
S702 Refuses a request without a token No userinfo endpoint.
S703 Refuses an invalid token No userinfo endpoint.

Introspection

S801 Introspection requires authorization Unauthenticated introspection returned HTTP 200 instead of HTTP 401.
S802 Refused introspection reveals nothing Without authorization, the response still revealed that the token is active or whose it is.

Security hygiene

S901 Token endpoint requires TLS Plain http requests are not processed (HTTP 302).
! S902 Authorization pages cannot be framed The authorization endpoint does not send X-Frame-Options or CSP frame-ancestors, so it could be framed for clickjacking.
S905 Tokens never appear in URLs No tokens appeared in redirect URLs.
S906 No credentialed wildcard CORS No credentialed wildcard CORS.