HumanSignal/label-studio · error · AuthenticationFailed
Authentication token no longer valid: legacy token authentic
Error message
Authentication token no longer valid: legacy token authentication has been disabled for this organization
What it means
REST-framework AuthenticationFailed raised during legacy (non-JWT) API token authentication when the user's organization has disabled legacy API tokens. The user exists and the token matches, but the org policy makes the token no longer acceptable.
Source
Thrown at label_studio/jwt_auth/auth.py:35
from core.current_request import CurrentContext
from core.feature_flags import flag_set
auth_result = super().authenticate(request)
# Update CurrentContext with authenticated user
if auth_result is not None:
user, _ = auth_result
CurrentContext.set_user(user)
JWT_ACCESS_TOKEN_ENABLED = flag_set('fflag__feature_develop__prompts__dia_1829_jwt_token_auth')
if JWT_ACCESS_TOKEN_ENABLED and (auth_result is not None):
user, _ = auth_result
org = user.active_organization
org_id = org.id if org else None
# raise 401 if legacy API token auth disabled (i.e. this token is no longer valid)
if org and (not org.jwt.legacy_api_tokens_enabled):
raise AuthenticationFailed(
'Authentication token no longer valid: legacy token authentication has been disabled for this organization'
)
logger.info(
'Legacy token authentication used',
extra={'user_id': user.id, 'organization_id': org_id, 'endpoint': request.path},
)
return auth_result
class JWTAuthScheme(OpenApiAuthenticationExtension):
target_class = 'jwt_auth.auth.TokenAuthenticationPhaseout'
name = 'Token'
def get_security_definition(self, auto_schema):
return {
'type': 'apiKey',
'name': 'Authorization',View on GitHub (pinned to 0b49e9b539)
Solutions
- Generate a new JWT-based API token via the LSAPIToken endpoint (POST /api/auth/token or /api/sts/tokens)
- Update scripts/clients to send the new token
- If legacy tokens must keep working, have the organization admin re-enable legacy API tokens for the org
- Ask the user to log out/in and re-issue credentials
Example fix
// before curl -H 'Authorization: Token <legacy-token>' http://localhost:8080/api/projects/ // after curl -H 'Authorization: Token <new-jwt-api-token>' http://localhost:8080/api/projects/
Defensive patterns
Strategy: try-catch
Validate before calling
const res = await fetch('/api/current-user/whoami', {headers:{Authorization:`Token ${tok}`}});
if (res.status === 401 && (await res.text()).includes('legacy token')) {
await migrateToJwtToken();
} Try / catch
try:
resp = requests.get(url, headers={'Authorization': f'Token {legacy_token}'})
resp.raise_for_status()
except requests.HTTPError as e:
if e.response.status_code == 401:
new_token = create_ls_api_token()
headers['Authorization'] = f'Token {new_token}'
resp = requests.get(url, headers=headers) Prevention
- Migrate to JWT LSAPITokens organization-wide
- Centralize token issuance/refresh in one client helper
- Re-issue tokens whenever org auth policy changes
- Alert on 401s mentioning legacy tokens
When it happens
Trigger: Any authenticated API request (via authenticate/__call__ of the auth class) using an old-style API token while org.jwt.legacy_api_tokens_enabled is False; also surfaced through serializer clean().
Common situations: Organization upgraded to JWT-based LSAPIToken auth and an admin toggled legacy tokens off; scripts/integrations still storing the old API token; users copied old tokens from browser settings after migration.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Invalid Label Studio token
- token_exists
- PermissionDenied
- "file_upload_ids" parameter must be a list of integers
- sample() does not accept arguments.
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/a73088310ec375f0.
Report an issue: GitHub.