Skip to content

Commit 1dfb9aa

Browse files
committed
Classes for standard OAuth error types
1 parent f6e47c4 commit 1dfb9aa

File tree

2 files changed

+174
-2
lines changed

2 files changed

+174
-2
lines changed

src/server/auth/errors.ts

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import { OAuthErrorResponse } from "../../shared/auth.js";
2+
3+
/**
4+
* Base class for all OAuth errors
5+
*/
6+
export class OAuthError extends Error {
7+
constructor(
8+
public readonly errorCode: string,
9+
message: string,
10+
public readonly errorUri?: string
11+
) {
12+
super(message);
13+
this.name = this.constructor.name;
14+
}
15+
16+
/**
17+
* Converts the error to a standard OAuth error response object
18+
*/
19+
toResponseObject(): OAuthErrorResponse {
20+
const response: OAuthErrorResponse = {
21+
error: this.errorCode,
22+
error_description: this.message
23+
};
24+
25+
if (this.errorUri) {
26+
response.error_uri = this.errorUri;
27+
}
28+
29+
return response;
30+
}
31+
}
32+
33+
/**
34+
* Invalid request error - The request is missing a required parameter,
35+
* includes an invalid parameter value, includes a parameter more than once,
36+
* or is otherwise malformed.
37+
*/
38+
export class InvalidRequestError extends OAuthError {
39+
constructor(message: string, errorUri?: string) {
40+
super("invalid_request", message, errorUri);
41+
}
42+
}
43+
44+
/**
45+
* Invalid client error - Client authentication failed (e.g., unknown client, no client
46+
* authentication included, or unsupported authentication method).
47+
*/
48+
export class InvalidClientError extends OAuthError {
49+
constructor(message: string, errorUri?: string) {
50+
super("invalid_client", message, errorUri);
51+
}
52+
}
53+
54+
/**
55+
* Invalid grant error - The provided authorization grant or refresh token is
56+
* invalid, expired, revoked, does not match the redirection URI used in the
57+
* authorization request, or was issued to another client.
58+
*/
59+
export class InvalidGrantError extends OAuthError {
60+
constructor(message: string, errorUri?: string) {
61+
super("invalid_grant", message, errorUri);
62+
}
63+
}
64+
65+
/**
66+
* Unauthorized client error - The authenticated client is not authorized to use
67+
* this authorization grant type.
68+
*/
69+
export class UnauthorizedClientError extends OAuthError {
70+
constructor(message: string, errorUri?: string) {
71+
super("unauthorized_client", message, errorUri);
72+
}
73+
}
74+
75+
/**
76+
* Unsupported grant type error - The authorization grant type is not supported
77+
* by the authorization server.
78+
*/
79+
export class UnsupportedGrantTypeError extends OAuthError {
80+
constructor(message: string, errorUri?: string) {
81+
super("unsupported_grant_type", message, errorUri);
82+
}
83+
}
84+
85+
/**
86+
* Invalid scope error - The requested scope is invalid, unknown, malformed, or
87+
* exceeds the scope granted by the resource owner.
88+
*/
89+
export class InvalidScopeError extends OAuthError {
90+
constructor(message: string, errorUri?: string) {
91+
super("invalid_scope", message, errorUri);
92+
}
93+
}
94+
95+
/**
96+
* Access denied error - The resource owner or authorization server denied the request.
97+
*/
98+
export class AccessDeniedError extends OAuthError {
99+
constructor(message: string, errorUri?: string) {
100+
super("access_denied", message, errorUri);
101+
}
102+
}
103+
104+
/**
105+
* Server error - The authorization server encountered an unexpected condition
106+
* that prevented it from fulfilling the request.
107+
*/
108+
export class ServerError extends OAuthError {
109+
constructor(message: string, errorUri?: string) {
110+
super("server_error", message, errorUri);
111+
}
112+
}
113+
114+
/**
115+
* Temporarily unavailable error - The authorization server is currently unable to
116+
* handle the request due to a temporary overloading or maintenance of the server.
117+
*/
118+
export class TemporarilyUnavailableError extends OAuthError {
119+
constructor(message: string, errorUri?: string) {
120+
super("temporarily_unavailable", message, errorUri);
121+
}
122+
}
123+
124+
/**
125+
* Unsupported response type error - The authorization server does not support
126+
* obtaining an authorization code using this method.
127+
*/
128+
export class UnsupportedResponseTypeError extends OAuthError {
129+
constructor(message: string, errorUri?: string) {
130+
super("unsupported_response_type", message, errorUri);
131+
}
132+
}
133+
134+
/**
135+
* Unsupported token type error - The authorization server does not support
136+
* the requested token type.
137+
*/
138+
export class UnsupportedTokenTypeError extends OAuthError {
139+
constructor(message: string, errorUri?: string) {
140+
super("unsupported_token_type", message, errorUri);
141+
}
142+
}
143+
144+
/**
145+
* Invalid token error - The access token provided is expired, revoked, malformed,
146+
* or invalid for other reasons.
147+
*/
148+
export class InvalidTokenError extends OAuthError {
149+
constructor(message: string, errorUri?: string) {
150+
super("invalid_token", message, errorUri);
151+
}
152+
}
153+
154+
/**
155+
* Method not allowed error - The HTTP method used is not allowed for this endpoint.
156+
* (Custom, non-standard error)
157+
*/
158+
export class MethodNotAllowedError extends OAuthError {
159+
constructor(message: string, errorUri?: string) {
160+
super("method_not_allowed", message, errorUri);
161+
}
162+
}
163+
164+
/**
165+
* Too many requests error - Rate limit exceeded.
166+
* (Custom, non-standard error based on RFC 6585)
167+
*/
168+
export class TooManyRequestsError extends OAuthError {
169+
constructor(message: string, errorUri?: string) {
170+
super("too_many_requests", message, errorUri);
171+
}
172+
}

src/shared/auth.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const OAuthTokensSchema = z
5050
/**
5151
* OAuth 2.1 error response
5252
*/
53-
export const OAuthErrorSchema = z
53+
export const OAuthErrorResponseSchema = z
5454
.object({
5555
error: z.string(),
5656
error_description: z.string().optional(),
@@ -111,7 +111,7 @@ export const OAuthTokenRevocationRequestSchema = z.object({
111111

112112
export type OAuthMetadata = z.infer<typeof OAuthMetadataSchema>;
113113
export type OAuthTokens = z.infer<typeof OAuthTokensSchema>;
114-
export type OAuthError = z.infer<typeof OAuthErrorSchema>;
114+
export type OAuthErrorResponse = z.infer<typeof OAuthErrorResponseSchema>;
115115
export type OAuthClientMetadata = z.infer<typeof OAuthClientMetadataSchema>;
116116
export type OAuthClientInformation = z.infer<typeof OAuthClientInformationSchema>;
117117
export type OAuthClientInformationFull = z.infer<typeof OAuthClientInformationFullSchema>;

0 commit comments

Comments
 (0)