Skip to content

Commit 6ebe68e

Browse files
Add support for CAS auth strategy (#2246)
* add cas auth strategy * fix test case --------- Co-authored-by: Richard Dominick <[email protected]>
1 parent 283dc3d commit 6ebe68e

File tree

5 files changed

+47
-11
lines changed

5 files changed

+47
-11
lines changed

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ REACT_APP_OAUTH2_PROVIDER3_ENDPOINT=http://localhost:8000/login?provider=test&co
3737
# REACT_APP_OAUTH2_PROVIDER2_NAME=Cognito
3838
# REACT_APP_OAUTH2_PROVIDER2_ENDPOINT=
3939

40+
REACT_APP_CAS_PROVIDER1=
41+
REACT_APP_CAS_PROVIDER1_NAME=
42+
REACT_APP_CAS_PROVIDER1_ENDPOINT=
43+
4044
REACT_APP_MODULE_BACKEND_URL=https://source-academy.github.io/modules
4145
REACT_APP_SHAREDB_BACKEND_URL=
4246
REACT_APP_SICPJS_BACKEND_URL="http://127.0.0.1:8080/"

src/commons/sagas/__tests__/BackendSaga.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ import {
7878
import { mockGradingSummary } from '../../mocks/GradingMocks';
7979
import { mockNotifications } from '../../mocks/UserMocks';
8080
import { Notification } from '../../notificationBadge/NotificationBadgeTypes';
81-
import { computeRedirectUri } from '../../utils/AuthHelper';
81+
import { AuthProviderType, computeRedirectUri } from '../../utils/AuthHelper';
8282
import Constants from '../../utils/Constants';
8383
import {
8484
showSuccessMessage,
@@ -286,7 +286,8 @@ describe('Test FETCH_AUTH action', () => {
286286
Constants.authProviders.set(providerId, {
287287
name: providerId,
288288
endpoint: `https://test/?client_id=${clientId}`,
289-
isDefault: true
289+
isDefault: true,
290+
type: AuthProviderType.OAUTH2
290291
});
291292
const redirectUrl = computeRedirectUri(providerId);
292293

src/commons/utils/AuthHelper.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
11
import Constants from './Constants';
22

3+
export enum AuthProviderType {
4+
OAUTH2 = 'OAUTH2',
5+
CAS = 'CAS'
6+
}
7+
38
export function computeEndpointUrl(providerId: string): string | undefined {
49
const ep = Constants.authProviders.get(providerId);
510
if (!ep) {
611
return undefined;
712
}
813
try {
914
const epUrl = new URL(ep.endpoint);
10-
epUrl.searchParams.set('redirect_uri', computeRedirectUri(providerId)!);
15+
switch (ep.type) {
16+
case AuthProviderType.OAUTH2:
17+
epUrl.searchParams.set('redirect_uri', computeRedirectUri(providerId)!);
18+
break;
19+
case AuthProviderType.CAS:
20+
epUrl.searchParams.set('service', computeRedirectUri(providerId)!);
21+
break;
22+
}
1123
return epUrl.toString();
1224
} catch (e) {
1325
// in dev, sometimes the endpoint is a dummy; allow that

src/commons/utils/Constants.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { Chapter, Variant } from 'js-slang/dist/types';
22

3+
import { AuthProviderType } from './AuthHelper';
4+
35
function isTrue(value?: string, defaultTo?: boolean): boolean {
46
return typeof value === 'undefined' && typeof defaultTo !== 'undefined'
57
? defaultTo
@@ -46,8 +48,10 @@ const caFulfillmentLevel = isTest
4648
? 24
4749
: parseInt(process.env.REACT_APP_CA_FULFILLMENT_LEVEL || '0');
4850

49-
const authProviders: Map<string, { name: string; endpoint: string; isDefault: boolean }> =
50-
new Map();
51+
const authProviders: Map<
52+
string,
53+
{ name: string; endpoint: string; isDefault: boolean; type: AuthProviderType }
54+
> = new Map();
5155

5256
for (let i = 1; ; ++i) {
5357
const id = process.env[`REACT_APP_OAUTH2_PROVIDER${i}`];
@@ -58,7 +62,19 @@ for (let i = 1; ; ++i) {
5862
const name = process.env[`REACT_APP_OAUTH2_PROVIDER${i}_NAME`] || 'Unnamed provider';
5963
const endpoint = process.env[`REACT_APP_OAUTH2_PROVIDER${i}_ENDPOINT`] || '';
6064

61-
authProviders.set(id, { name, endpoint, isDefault: i === 1 });
65+
authProviders.set(id, { name, endpoint, isDefault: i === 1, type: AuthProviderType.OAUTH2 });
66+
}
67+
68+
for (let i = 1; ; ++i) {
69+
const id = process.env[`REACT_APP_CAS_PROVIDER${i}`];
70+
if (!id) {
71+
break;
72+
}
73+
74+
const name = process.env[`REACT_APP_CAS_PROVIDER${i}_NAME`] || 'Unnamed provider';
75+
const endpoint = process.env[`REACT_APP_CAS_PROVIDER${i}_ENDPOINT`] || '';
76+
77+
authProviders.set(id, { name, endpoint, isDefault: false, type: AuthProviderType.CAS });
6278
}
6379

6480
export enum Links {

src/pages/login/Login.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ const Login: React.FunctionComponent<{}> = () => {
3030
const location = useLocation();
3131
const { isLoggedIn, courseId } = useSession();
3232
const navigate = useNavigate();
33-
const { code, provider: providerId } = parseQuery(location.search);
33+
const { code, ticket, provider: providerId } = parseQuery(location.search);
34+
35+
// `code` parameter from OAuth2 redirect, `ticket` from CAS redirect
36+
const authCode = code || ticket;
3437

3538
const handleLogin = React.useCallback(
3639
(providerId: string) => dispatch(login(providerId)),
@@ -49,12 +52,12 @@ const Login: React.FunctionComponent<{}> = () => {
4952
}
5053

5154
// Else fetch JWT tokens and user info from backend when auth provider code is present
52-
if (code && !isLoggedIn) {
53-
dispatch(fetchAuth(code, providerId));
55+
if (authCode && !isLoggedIn) {
56+
dispatch(fetchAuth(authCode, providerId));
5457
}
55-
}, [code, providerId, dispatch, courseId, navigate, isLoggedIn]);
58+
}, [authCode, providerId, dispatch, courseId, navigate, isLoggedIn]);
5659

57-
if (code) {
60+
if (authCode) {
5861
return (
5962
<div className={classNames('Login', Classes.DARK)}>
6063
<Card className={classNames('login-card', Classes.ELEVATION_4)}>

0 commit comments

Comments
 (0)