Appearance
Troubleshooting
Token Validation Fails
Symptom: Token invalid or Unable to parse token on protected routes.
Check these in order:
- Is the
apiguard configured to usesp-jwtinconfig/auth.php? - Is
SP_JWT_ACTIVE_KIDset to a key id that exists in config? - Does the signing key exist and match the algorithm? Run
php artisan sp-jwt-auth:keys --generate --kid=testif needed. - Is the token expired? Default access TTL is 15 minutes.
- Is the
jtirow still active insp_jwt_access_tokens? Revoked rows return 401.
Refresh Token Rejected
Symptom: Invalid refresh token on rotate.
- The
id.secretformat must be passed as-is. Check the client sends the full value. - The token may have been rotated already — reuse detection fires on second use.
- The
hash_key_idused to store the secret must still be active in config.
Guard Not Found
Symptom: auth guard [api] is not defined or driver [sp-jwt] not found.
Run the install command to register the service provider:
bash
php artisan sp-jwt-auth:installThe provider registers the sp-jwt guard driver in boot(). Verify it is loaded:
bash
php artisan route:middleware | grep sp.jwtJWKS Endpoint Returns Empty
- Confirm signing keys exist in config under
keys.items. - Only keys in
activeorpreviousstate are included. - Run
php artisan sp-jwt-auth:jwks --debugto inspect.
OAuth Server Routes Not Registered
- Set
SP_JWT_OAUTH_SERVER_ENABLED=true. - Verify the config
oauth_server.enabledistrue. - Routes are registered under the configured prefix (default
oauth).
Reuse Detection Fires Unexpectedly
The refresh token was already consumed. Common causes:
- Client retries the same refresh token after a network timeout.
- Client stores old refresh token after rotation.
- Concurrent refresh requests race on the same token.
The reuse_detection config controls the cascade behaviour.