| 59 | }; |
| 60 | |
| 61 | const translateJwtError = (err: unknown): never => { |
| 62 | if (err instanceof ApiError) { |
| 63 | throw err; |
| 64 | } |
| 65 | |
| 66 | if ( |
| 67 | err !== null && |
| 68 | typeof err === "object" && |
| 69 | "name" in err && |
| 70 | typeof err.name === "string" |
| 71 | ) { |
| 72 | if (err.name === "TokenExpiredError") { |
| 73 | throw ApiErrors.tokenExpired(); |
| 74 | } |
| 75 | |
| 76 | if (err.name === "JsonWebTokenError") { |
| 77 | throw ApiErrors.unauthorized("Invalid token"); |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | throw ApiErrors.unauthorized("Authentication failed"); |
| 82 | }; |
| 83 | |
| 84 | /** |
| 85 | * Shared verify core for the two guards below. Encodes the contract that |