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

  1. Generate a new JWT-based API token via the LSAPIToken endpoint (POST /api/auth/token or /api/sts/tokens)
  2. Update scripts/clients to send the new token
  3. If legacy tokens must keep working, have the organization admin re-enable legacy API tokens for the org
  4. 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

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

Related errors


AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29). Data as JSON: /api/errors/a73088310ec375f0. Report an issue: GitHub.