Implementation reports · Server
MIndie
https://github.com/carrvo/mindie
40 passed 10 failed 12 warnings 22 skipped
Published 2026-09-22 02:49 UTC by https://turner.enemyterritory.org/user/carrvo/index · tested with https://turner.enemyterritory.org/user/carrvo/index · suite 9e65154
Discovery
| ✓ | S101 | Profile URL is valid and can be fetched Fetched with HTTP 200. |
| ✓ | S102 | Advertises indieauth-metadata Found https://turner.enemyterritory.org/.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://turner.enemyterritory.org |
| ✓ | S106 | Authorization endpoint is listed authorization_endpoint is https://turner.enemyterritory.org/selfauth/index |
| ✓ | S107 | Token endpoint is listed token_endpoint is https://turner.enemyterritory.org/selfauth/token?action=authorize |
| ✓ | S108 | Introspection endpoint is listed introspection_endpoint is https://turner.enemyterritory.org/selfauth/token?action=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 is missing or is not a list of strings. |
| ✓ | 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 Served at https://turner.enemyterritory.org/.well-known/oauth-authorization-server with the same issuer. |
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 The approval screen showed the application name and client_id. |
| ✗ | S207 | Reports a denied request to the client There was no way to cancel the request. |
| – | S208 | Refuses an unregistered cross-origin redirect URI Inconclusive: you reported something other than the expected outcomes. |
| ✗ | S209 | Accepts a registered cross-origin redirect URI There was no way to cancel the request. |
| – | S210 | Matches redirect URIs exactly Inconclusive: you reported something other than the expected outcomes. |
| – | S211 | Is not fooled by credentials in a URL Inconclusive: you reported something other than the expected outcomes. |
| – | S212 | Ignores client metadata for a different client_id Inconclusive: you reported something other than the expected outcomes. |
| – | S213 | Rejects a repeated redirect_uri parameter Inconclusive: you reported something other than the expected outcomes. |
| ✓ | 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 approval screen for this request instead of refusing it. |
| ! | 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 refused the request. |
| ! | S221 | Refuses a PKCE method without a challenge Your server showed an approval screen for this request instead of refusing it. |
| ! | S222 | Refuses a challenge without a method Your server showed an approval screen for this request instead of refusing it. |
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 Tokens were issued for a code_verifier that does not match the challenge. |
| ✗ | S311 | Refuses a missing code_verifier The code was accepted: HTTP 200. |
| ✓ | S312 | Refuses a code presented by another client Refused (HTTP 400). |
| ✓ | S313 | Refuses a mismatched redirect_uri Refused (HTTP 400). |
| ✗ | S320 | Exchanges a code without a scope An access token was issued for a code without any scope. |
| ! | S330 | Refuses an unknown code Refused, but with HTTP 400 instead of HTTP 400 invalid_grant. |
| ! | S331 | Refuses missing or unsupported grant types Refused, but with HTTP 400 and HTTP 400. |
| ✗ | S332 | Errors are JSON with an error code Some error responses were not JSON objects with an "error" member. |
| ✓ | S333 | Token endpoint refuses GET requests GET requests are refused (HTTP 401). |
| ✓ | 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://turner.enemyterritory.org/user/carrvo/index |
| ✓ | S405 | The returned me is verified me matches a URL seen during discovery. |
| ✗ | 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 "profile". |
| ✓ | 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 opaque strings, which resource servers check by introspection. |
| – | S421 | JWT header marks it an access token The access token is not a JWT. |
| – | S422 | JWT verifies against the published keys The access token is not a JWT. |
| – | S423 | JWT claims are complete The access token is not a JWT. |
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
Userinfo
Introspection
Security hygiene
| ✓ | S901 | Token endpoint requires TLS Plain http requests are not processed (HTTP 403). |
| ! | 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. |