Skip to content

Commit 38ac57c

Browse files
Fix issues of unhandled OAUTH_ERROR in oauth accept/reject endpoint
1 parent 896f163 commit 38ac57c

File tree

8 files changed

+129
-25
lines changed

8 files changed

+129
-25
lines changed

lib/build/recipe/oauth2provider/api/utils.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// @ts-nocheck
22
import { UserContext } from "../../../types";
33
import { SessionContainerInterface } from "../../session/types";
4-
import { ErrorOAuth2, RecipeInterface } from "../types";
4+
import { ErrorOAuth2, RecipeInterface, OauthError } from "../types";
55
export declare function loginGET({
66
recipeImplementation,
77
loginChallenge,
@@ -20,6 +20,7 @@ export declare function loginGET({
2020
isDirectCall: boolean;
2121
}): Promise<
2222
| ErrorOAuth2
23+
| OauthError
2324
| {
2425
status: string;
2526
redirectTo: string;
@@ -54,6 +55,7 @@ export declare function handleLoginInternalRedirects({
5455
cookies?: string[];
5556
}
5657
| ErrorOAuth2
58+
| OauthError
5759
>;
5860
export declare function handleLogoutInternalRedirects({
5961
response,

lib/build/recipe/oauth2provider/api/utils.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ async function loginGET({
5858
},
5959
userContext,
6060
});
61+
if (reject.status === "OAUTH_ERROR") {
62+
return reject;
63+
}
6164
return { status: "REDIRECT", redirectTo: reject.redirectTo, cookies };
6265
}
6366
if (maxAgeParsed < 0) {
@@ -70,6 +73,9 @@ async function loginGET({
7073
},
7174
userContext,
7275
});
76+
if (reject.status === "OAUTH_ERROR") {
77+
return reject;
78+
}
7379
return { status: "REDIRECT", redirectTo: reject.redirectTo, cookies };
7480
}
7581
} catch (_c) {
@@ -82,6 +88,9 @@ async function loginGET({
8288
},
8389
userContext,
8490
});
91+
if (reject.status === "OAUTH_ERROR") {
92+
return reject;
93+
}
8594
return { status: "REDIRECT", redirectTo: reject.redirectTo, cookies };
8695
}
8796
}
@@ -101,6 +110,9 @@ async function loginGET({
101110
identityProviderSessionId: session.getHandle(),
102111
userContext,
103112
});
113+
if (accept.status === "OAUTH_ERROR") {
114+
return accept;
115+
}
104116
return { status: "REDIRECT", redirectTo: accept.redirectTo, cookies: cookies };
105117
}
106118
if (shouldTryRefresh && promptParam !== "login") {
@@ -124,6 +136,9 @@ async function loginGET({
124136
},
125137
userContext,
126138
});
139+
if (reject.status === "OAUTH_ERROR") {
140+
return reject;
141+
}
127142
return { status: "REDIRECT", redirectTo: reject.redirectTo, cookies };
128143
}
129144
return {

lib/build/recipe/oauth2provider/recipeImplementation.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,12 @@ function getRecipeInterface(
128128
},
129129
input.userContext
130130
);
131+
if (resp.status === "OAUTH_ERROR") {
132+
return resp;
133+
}
131134
return {
132135
redirectTo: getUpdatedRedirectTo(appInfo, resp.redirectTo),
136+
status: "OK",
133137
};
134138
},
135139
rejectLoginRequest: async function (input) {
@@ -145,8 +149,12 @@ function getRecipeInterface(
145149
},
146150
input.userContext
147151
);
152+
if (resp.status === "OAUTH_ERROR") {
153+
return resp;
154+
}
148155
return {
149156
redirectTo: getUpdatedRedirectTo(appInfo, resp.redirectTo),
157+
status: "OK",
150158
};
151159
},
152160
getConsentRequest: async function (input) {

lib/build/recipe/oauth2provider/types.d.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ export declare type ErrorOAuth2 = {
3838
errorDescription: string;
3939
statusCode?: number;
4040
};
41+
export declare type OauthError = {
42+
status: "OAUTH_ERROR";
43+
error: string;
44+
errorDescription: string;
45+
statusCode: number;
46+
};
4147
export declare type ConsentRequest = {
4248
acr?: string;
4349
amr?: string[];
@@ -147,12 +153,20 @@ export declare type RecipeInterface = {
147153
identityProviderSessionId?: string;
148154
subject: string;
149155
userContext: UserContext;
150-
}): Promise<{
151-
redirectTo: string;
152-
}>;
153-
rejectLoginRequest(input: { challenge: string; error: ErrorOAuth2; userContext: UserContext }): Promise<{
154-
redirectTo: string;
155-
}>;
156+
}): Promise<
157+
| {
158+
redirectTo: string;
159+
status: "OK";
160+
}
161+
| OauthError
162+
>;
163+
rejectLoginRequest(input: { challenge: string; error: ErrorOAuth2; userContext: UserContext }): Promise<
164+
| {
165+
redirectTo: string;
166+
status: "OK";
167+
}
168+
| OauthError
169+
>;
156170
getOAuth2Client(input: { clientId: string; userContext: UserContext }): Promise<
157171
| {
158172
status: "OK";
@@ -356,6 +370,7 @@ export declare type APIInterface = {
356370
cookies?: string[];
357371
}
358372
| ErrorOAuth2
373+
| OauthError
359374
| GeneralErrorResponse
360375
>);
361376
authGET:
@@ -373,6 +388,7 @@ export declare type APIInterface = {
373388
cookies?: string[];
374389
}
375390
| ErrorOAuth2
391+
| OauthError
376392
| GeneralErrorResponse
377393
>);
378394
tokenPOST:

lib/ts/core/versions/5.3/schema.d.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9574,11 +9574,13 @@ export interface operations {
95749574
[name: string]: unknown;
95759575
};
95769576
content: {
9577-
"application/json": {
9578-
status: components["schemas"]["statusOK"];
9579-
/** @example {apiDomain}/oauth/login?... */
9580-
redirectTo?: string;
9581-
};
9577+
"application/json":
9578+
| {
9579+
status: components["schemas"]["statusOK"];
9580+
/** @example {apiDomain}/oauth/login?... */
9581+
redirectTo?: string;
9582+
}
9583+
| components["schemas"]["oauthError"];
95829584
};
95839585
};
95849586
400: components["responses"]["400"];
@@ -9626,11 +9628,13 @@ export interface operations {
96269628
[name: string]: unknown;
96279629
};
96289630
content: {
9629-
"application/json": {
9630-
status: components["schemas"]["statusOK"];
9631-
/** @example {apiDomain}/oauth/login?... */
9632-
redirectTo?: string;
9633-
};
9631+
"application/json":
9632+
| {
9633+
status: components["schemas"]["statusOK"];
9634+
/** @example {apiDomain}/oauth/login?... */
9635+
redirectTo?: string;
9636+
}
9637+
| components["schemas"]["oauthError"];
96349638
};
96359639
};
96369640
400: components["responses"]["400"];

lib/ts/recipe/oauth2provider/api/utils.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { DEFAULT_TENANT_ID } from "../../multitenancy/constants";
44
import { getSessionInformation } from "../../session";
55
import { SessionContainerInterface } from "../../session/types";
66
import { AUTH_PATH, LOGIN_PATH, END_SESSION_PATH } from "../constants";
7-
import { ErrorOAuth2, RecipeInterface } from "../types";
7+
import { ErrorOAuth2, RecipeInterface, OauthError } from "../types";
88
import setCookieParser from "set-cookie-parser";
99

1010
// API implementation for the loginGET function.
@@ -58,6 +58,11 @@ export async function loginGET({
5858
},
5959
userContext,
6060
});
61+
62+
if (reject.status === "OAUTH_ERROR") {
63+
return reject;
64+
}
65+
6166
return { status: "REDIRECT", redirectTo: reject.redirectTo, cookies };
6267
}
6368

@@ -71,6 +76,11 @@ export async function loginGET({
7176
},
7277
userContext,
7378
});
79+
80+
if (reject.status === "OAUTH_ERROR") {
81+
return reject;
82+
}
83+
7484
return { status: "REDIRECT", redirectTo: reject.redirectTo, cookies };
7585
}
7686
} catch {
@@ -83,6 +93,11 @@ export async function loginGET({
8393
},
8494
userContext,
8595
});
96+
97+
if (reject.status === "OAUTH_ERROR") {
98+
return reject;
99+
}
100+
86101
return { status: "REDIRECT", redirectTo: reject.redirectTo, cookies };
87102
}
88103
}
@@ -102,6 +117,11 @@ export async function loginGET({
102117
identityProviderSessionId: session.getHandle(),
103118
userContext,
104119
});
120+
121+
if (accept.status === "OAUTH_ERROR") {
122+
return accept;
123+
}
124+
105125
return { status: "REDIRECT", redirectTo: accept.redirectTo, cookies: cookies };
106126
}
107127

@@ -126,6 +146,11 @@ export async function loginGET({
126146
},
127147
userContext,
128148
});
149+
150+
if (reject.status === "OAUTH_ERROR") {
151+
return reject;
152+
}
153+
129154
return { status: "REDIRECT", redirectTo: reject.redirectTo, cookies };
130155
}
131156

@@ -212,7 +237,7 @@ export async function handleLoginInternalRedirects({
212237
shouldTryRefresh: boolean;
213238
cookie?: string;
214239
userContext: UserContext;
215-
}): Promise<{ redirectTo: string; cookies?: string[] } | ErrorOAuth2> {
240+
}): Promise<{ redirectTo: string; cookies?: string[] } | ErrorOAuth2 | OauthError> {
216241
if (!isLoginInternalRedirect(response.redirectTo)) {
217242
return response;
218243
}

lib/ts/recipe/oauth2provider/recipeImplementation.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
ConsentRequest,
2323
PayloadBuilderFunction,
2424
UserInfoBuilderFunction,
25+
OauthError,
2526
} from "./types";
2627
import { OAuth2Client } from "./OAuth2Client";
2728
import { getUser } from "../..";
@@ -85,7 +86,10 @@ export default function getRecipeInterface(
8586
subject: resp.subject,
8687
};
8788
},
88-
acceptLoginRequest: async function (this: RecipeInterface, input): Promise<{ redirectTo: string }> {
89+
acceptLoginRequest: async function (
90+
this: RecipeInterface,
91+
input
92+
): Promise<{ redirectTo: string; status: "OK" } | OauthError> {
8993
const resp = await querier.sendPutRequest(
9094
"/recipe/oauth/auth/requests/login/accept",
9195
{
@@ -102,11 +106,19 @@ export default function getRecipeInterface(
102106
input.userContext
103107
);
104108

109+
if (resp.status === "OAUTH_ERROR") {
110+
return resp;
111+
}
112+
105113
return {
106114
redirectTo: getUpdatedRedirectTo(appInfo, resp.redirectTo),
115+
status: "OK",
107116
};
108117
},
109-
rejectLoginRequest: async function (this: RecipeInterface, input): Promise<{ redirectTo: string }> {
118+
rejectLoginRequest: async function (
119+
this: RecipeInterface,
120+
input
121+
): Promise<{ redirectTo: string; status: "OK" } | OauthError> {
110122
const resp = await querier.sendPutRequest(
111123
"/recipe/oauth/auth/requests/login/reject",
112124
{
@@ -120,8 +132,13 @@ export default function getRecipeInterface(
120132
input.userContext
121133
);
122134

135+
if (resp.status === "OAUTH_ERROR") {
136+
return resp;
137+
}
138+
123139
return {
124140
redirectTo: getUpdatedRedirectTo(appInfo, resp.redirectTo),
141+
status: "OK",
125142
};
126143
},
127144
getConsentRequest: async function (this: RecipeInterface, input): Promise<ConsentRequest> {

lib/ts/recipe/oauth2provider/types.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ export type ErrorOAuth2 = {
6565
statusCode?: number;
6666
};
6767

68+
export type OauthError = {
69+
status: "OAUTH_ERROR";
70+
71+
// The error should follow the OAuth2 error format (e.g. invalid_request, login_required).
72+
// Defaults to request_denied.
73+
error: string;
74+
75+
// Description of the error in a human readable format.
76+
errorDescription: string;
77+
78+
// Represents the HTTP status code of the error (e.g. 401 or 403)
79+
// Defaults to 400
80+
statusCode: number;
81+
};
82+
6883
export type ConsentRequest = {
6984
// ACR represents the Authentication AuthorizationContext Class Reference value for this authentication session. You can use it to express that, for example, a user authenticated using two factor authentication.
7085
acr?: string;
@@ -242,12 +257,12 @@ export type RecipeInterface = {
242257
// Subject is the user ID of the end-user that authenticated.
243258
subject: string;
244259
userContext: UserContext;
245-
}): Promise<{ redirectTo: string }>;
260+
}): Promise<{ redirectTo: string; status: "OK" } | OauthError>;
246261
rejectLoginRequest(input: {
247262
challenge: string;
248263
error: ErrorOAuth2;
249264
userContext: UserContext;
250-
}): Promise<{ redirectTo: string }>;
265+
}): Promise<{ redirectTo: string; status: "OK" } | OauthError>;
251266

252267
getOAuth2Client(input: { clientId: string; userContext: UserContext }): Promise<
253268
| {
@@ -425,7 +440,9 @@ export type APIInterface = {
425440
session?: SessionContainerInterface;
426441
shouldTryRefresh: boolean;
427442
userContext: UserContext;
428-
}) => Promise<{ frontendRedirectTo: string; cookies?: string[] } | ErrorOAuth2 | GeneralErrorResponse>);
443+
}) => Promise<
444+
{ frontendRedirectTo: string; cookies?: string[] } | ErrorOAuth2 | OauthError | GeneralErrorResponse
445+
>);
429446

430447
authGET:
431448
| undefined
@@ -436,7 +453,7 @@ export type APIInterface = {
436453
shouldTryRefresh: boolean;
437454
options: APIOptions;
438455
userContext: UserContext;
439-
}) => Promise<{ redirectTo: string; cookies?: string[] } | ErrorOAuth2 | GeneralErrorResponse>);
456+
}) => Promise<{ redirectTo: string; cookies?: string[] } | ErrorOAuth2 | OauthError | GeneralErrorResponse>);
440457
tokenPOST:
441458
| undefined
442459
| ((input: {

0 commit comments

Comments
 (0)