Skip to content

Commit

Permalink
Fix invalid authorization bearer token error (#11)
Browse files Browse the repository at this point in the history
* Log user out who authenticates with bad token

If a token is no longer valid, or does not validate with the key on
the server, we are responding with a 401 HTTP status code. In the
front-end client, we are intercepting 401 errors and logging
the user out of the front-end.

This raises an important secondary issue, in other places we may need to
fix response code to 403 if a user is validated with system but does
not have access to a resource.

* Respond with correct error code (403) lacking perm
  • Loading branch information
KrisJordan authored Mar 20, 2023
1 parent ca6c4a8 commit c42dc98
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 11 deletions.
12 changes: 6 additions & 6 deletions backend/api/admin/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def list_roles(
try:
return role_service.list(subject)
except UserPermissionError as e:
raise HTTPException(status_code=401, detail=str(e))
raise HTTPException(status_code=403, detail=str(e))


@api.get("/{id}", tags=["Roles"])
Expand All @@ -35,7 +35,7 @@ def role_details(
try:
return role_service.details(subject, id)
except UserPermissionError as e:
raise HTTPException(status_code=401, detail=str(e))
raise HTTPException(status_code=403, detail=str(e))


@api.post('/{id}/permission', tags=["Roles"])
Expand All @@ -48,7 +48,7 @@ def grant_permission(
try:
return role_service.grant(subject, id, permission)
except UserPermissionError as e:
raise HTTPException(status_code=401, detail=str(e))
raise HTTPException(status_code=403, detail=str(e))


@api.delete("/{id}/permission/{permissionId}", tags=["Roles"])
Expand All @@ -61,7 +61,7 @@ def revoke_permission(
try:
return role_service.revoke(subject, id, permissionId)
except UserPermissionError as e:
raise HTTPException(status_code=401, detail=str(e))
raise HTTPException(status_code=403, detail=str(e))


@api.post('/{id}/member', tags=["Roles"])
Expand All @@ -74,7 +74,7 @@ def add_member(
try:
return role_service.add(subject, id, member)
except UserPermissionError as e:
raise HTTPException(status_code=401, detail=str(e))
raise HTTPException(status_code=403, detail=str(e))


@api.delete("/{id}/member/{userId}", tags=["Roles"])
Expand All @@ -87,4 +87,4 @@ def remove_member(
try:
return role_service.remove(subject, id, userId)
except UserPermissionError as e:
raise HTTPException(status_code=401, detail=str(e))
raise HTTPException(status_code=403, detail=str(e))
2 changes: 1 addition & 1 deletion backend/api/admin/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ def list_users(
page=page, page_size=page_size, order_by=order_by, filter=filter)
return user_service.list(subject, pagination_params)
except UserPermissionError as e:
raise HTTPException(status_code=401, detail=str(e))
raise HTTPException(status_code=403, detail=str(e))
10 changes: 7 additions & 3 deletions backend/api/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,16 @@ def authenticated_pid(
token: HTTPAuthorizationCredentials | None = Depends(HTTPBearer())
) -> tuple[int, str]:
if token:
auth_info = jwt.decode(
token.credentials, _JWT_SECRET, algorithms=[_JST_ALGORITHM])
return int(auth_info['pid']), auth_info['uid']
try:
auth_info = jwt.decode(
token.credentials, _JWT_SECRET, algorithms=[_JST_ALGORITHM])
return int(auth_info['pid']), auth_info['uid']
except jwt.exceptions.InvalidSignatureError:
...
raise HTTPException(status_code=401, detail='Unauthorized')



@api.get('/verify')
def auth_verify(token: str, continue_to: str = '/'):
return jwt.decode(token, _JWT_SECRET, algorithms=[_JST_ALGORITHM], options={'verify_signature': True})
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/app/navigation/http-request.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ import {
import { Observable, of } from 'rxjs';
import { catchError, tap } from 'rxjs/operators'
import { NavigationService } from './navigation.service';
import { AuthenticationService } from '../authentication.service';

@Injectable({
providedIn: 'root'
})
export class HttpRequestInterceptor implements HttpInterceptor {

constructor(
private navigationService: NavigationService
private navigationService: NavigationService,
private authService: AuthenticationService
) {}

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
Expand All @@ -36,7 +38,12 @@ export class HttpRequestInterceptor implements HttpInterceptor {
this.navigationService.setSending(false);
}
if (e instanceof HttpErrorResponse) {
if (e.status === 401) {
this.authService.signOut();
} else {
this.navigationService.error(e);
}
throw e;
}
return of(e);
}),
Expand Down

0 comments on commit c42dc98

Please sign in to comment.