fix: toAuthErrorShape() ignored backend error.code, session-expired screen unreachable
Known bug per BACKEND-API-REFERENCE.md §5: the client has dedicated session-expired/invalid-signature recovery screens fully built, but the mapper only ever derived the error code from HTTP status, never the response body - so a real 401 with error.code: 'TOKEN_EXPIRED' rendered the generic 'Unauthorized' screen instead. Frontend half of the fix: prefer error.code from the body when present (mapped via authErrorCodeFromBackendCode), fall back to status-derived code otherwise. Stays dormant until the backend actually sends the code, per the doc. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,24 @@ export interface AuthError {
|
||||
status?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the backend error envelope's `error.code` (see
|
||||
* BACKEND-API-REFERENCE.md §5) to the client's AuthErrorCode screens.
|
||||
* Only codes with a dedicated screen are mapped; anything else falls back
|
||||
* to the HTTP-status-derived code via authErrorCodeFromStatus.
|
||||
*/
|
||||
const BACKEND_ERROR_CODE_MAP: Record<string, AuthErrorCode> = {
|
||||
TOKEN_EXPIRED: 'session-expired',
|
||||
INVALID_SIGNATURE: 'invalid-signature',
|
||||
UNAUTHENTICATED: 'unauthorized',
|
||||
FORBIDDEN: 'forbidden',
|
||||
SERVICE_UNAVAILABLE: 'backend-unavailable',
|
||||
};
|
||||
|
||||
export function authErrorCodeFromBackendCode(code: unknown): AuthErrorCode | undefined {
|
||||
return typeof code === 'string' ? BACKEND_ERROR_CODE_MAP[code] : undefined;
|
||||
}
|
||||
|
||||
/** Maps a backend HTTP status to the AuthErrorCode screen it should route to. */
|
||||
export function authErrorCodeFromStatus(status: number): AuthErrorCode {
|
||||
switch (status) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { catchError, switchMap, tap, throwError } from 'rxjs';
|
||||
import { Observable } from 'rxjs';
|
||||
import { AuthTokenPair } from '../models/auth-api.model';
|
||||
import { AuthError, authErrorCodeFromStatus } from '../models/auth-error.model';
|
||||
import { AuthError, authErrorCodeFromBackendCode, authErrorCodeFromStatus } from '../models/auth-error.model';
|
||||
import { AuthApiService } from './auth-api.service';
|
||||
import { Ed25519KeypairService } from './ed25519-keypair.service';
|
||||
import { SessionService } from './session.service';
|
||||
@@ -109,7 +109,9 @@ export class AuthService {
|
||||
|
||||
private toAuthErrorShape(error: unknown, fallbackCode: AuthError['code']): AuthError {
|
||||
if (error instanceof HttpErrorResponse) {
|
||||
return { code: authErrorCodeFromStatus(error.status), message: error.message, status: error.status };
|
||||
const bodyCode = (error.error as { error?: { code?: unknown } } | null)?.error?.code;
|
||||
const code = authErrorCodeFromBackendCode(bodyCode) ?? authErrorCodeFromStatus(error.status);
|
||||
return { code, message: error.message, status: error.status };
|
||||
}
|
||||
if (error instanceof Error) {
|
||||
return { code: fallbackCode, message: error.message };
|
||||
|
||||
Reference in New Issue
Block a user