Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server side authentication #475

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
732 changes: 612 additions & 120 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
"less": "^3.9.0",
"luxon": "^1.11.1",
"multirange": "^2.0.0",
"oidc-client": "^1.6.1",
"postcss-loader": "^3.0.0",
"prettier": "^1.16.4",
"query-string": "^6.2.0",
Expand All @@ -75,6 +74,7 @@
"@sentry/node": "^5.6.2",
"@types/classnames": "^2.2.7",
"@types/markdown-to-jsx": "^6.11.0",
"@types/next-auth": "^3.1.5",
"@types/react-google-recaptcha": "^1.1.1",
"@types/react-redux": "^7.1.0",
"@types/react-select": "^3.0.5",
Expand All @@ -91,6 +91,7 @@
"isomorphic-fetch": "^2.2.1",
"markdown-to-jsx": "^6.11.1",
"next": "^9.5.3",
"next-auth": "^3.1.0",
"next-redux-wrapper": "^5.0.0",
"postcss-focus-visible": "^4.0.0",
"react-day-picker": "^7.3.0",
Expand Down
24 changes: 5 additions & 19 deletions src/authentication/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,26 @@
import { __CLIENT__ } from 'common/constants/environment';
import { UserManager } from 'oidc-client';
import settings from './settings';
import { IAuthUser } from 'authentication/models/User';

import { signIn, signOut, getSession } from 'next-auth/client';
/**
* @summary Basic wrapper for OIDC login.
* Redirects the user to the authentication page defined in settings.
*/

export const USER_MANAGER = __CLIENT__ ? new UserManager(settings) : null;

export const logIn = async () => {
if (USER_MANAGER) {
const user = await USER_MANAGER.signinRedirect({ data: window.location.pathname });
return user;
}
return null;
return await signIn('onlineweb4');
};

/**
* @summary Returns user if logged in
*/
export const getUser = async (): Promise<IAuthUser | undefined> => {
if (USER_MANAGER) {
const user = (await USER_MANAGER.getUser()) as IAuthUser | null;
return user || undefined;
}
return undefined;
const session = await getSession();
return (session?.user as unknown) as IAuthUser;
};

/**
* @summary Removes user from storage
*/

export const logOut = async () => {
if (USER_MANAGER) {
await USER_MANAGER.signoutRedirect();
}
return await signOut();
};
18 changes: 0 additions & 18 deletions src/authentication/api/settings.ts

This file was deleted.

28 changes: 0 additions & 28 deletions src/authentication/components/AuthenticationCallback.tsx

This file was deleted.

7 changes: 3 additions & 4 deletions src/authentication/components/PrivateLink.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import Link from 'next/link';
import React, { ComponentProps } from 'react';
import { getLoginPageUrl } from 'core/appUrls';
import { useSelector } from 'react-redux';
import { selectIsLoggedIn } from 'authentication/selectors/authentication';
import { useSession } from 'next-auth/client';

type LinkProps = ComponentProps<typeof Link>;

const PrivateLink: React.FC<LinkProps> = ({ href, ...props }) => {
const isLoggedIn = useSelector(selectIsLoggedIn());
const [session] = useSession();
// Render the href only if a user is logged in, else render a disabled link.
if (isLoggedIn) {
if (session) {
return <Link {...props} href={href} />;
} else {
return <Link {...props} {...getLoginPageUrl()} />;
Expand Down
34 changes: 0 additions & 34 deletions src/authentication/components/SilentRenew.tsx

This file was deleted.

31 changes: 27 additions & 4 deletions src/authentication/models/User.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import { Profile, User } from 'oidc-client';

export interface IAuthUser extends User {
profile: IAuthProfile;
}

interface User {
id_token: string;
session_state?: string;
access_token: string;
refresh_token?: string;
token_type: string;
profile: Profile;
expires_at: number;
}

export interface Profile {
sub: number;
name: string;
given_name: string;
family_name: string;
nickname: string;
preferred_username: string;
picture: string;
}

interface IOnlinewebScope {
field_of_study: string;
member: boolean;
Expand All @@ -12,11 +30,16 @@ interface IOnlinewebScope {
superuser: boolean;
}

interface IEmailScope {
email: string;
email_verified: boolean;
}

/**
* Profile informastion returned from authenticating with
* Profile information returned from authenticating with
* OpenID Connect to Onlineweb4.
*/
export type IAuthProfile = NonNullable<Profile> & IOnlinewebScope;
export type IAuthProfile = NonNullable<Profile> & IOnlinewebScope & Partial<IEmailScope>;

export const isOnlineUser = (user: User | IAuthUser): user is IAuthUser => user.hasOwnProperty('preferred_username');

Expand Down
82 changes: 0 additions & 82 deletions src/authentication/providers/AuthenticationProvider.tsx

This file was deleted.

9 changes: 5 additions & 4 deletions src/authentication/providers/RequiresLogin.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from 'react';
import LoginPage from 'pages/login';
import { useSelector } from 'react-redux';
import { selectIsLoggedIn } from 'authentication/selectors/authentication';
import { useSession } from 'next-auth/client';
import Spinner from 'common/components/Spinner';

const RequiresLogin: React.FC = (props) => {
const isLoggedIn = useSelector(selectIsLoggedIn());
const [session, loading] = useSession();

if (!isLoggedIn) return <LoginPage />;
if (loading) return <Spinner />;
if (!session) return <LoginPage />;
return <>{props.children}</>;
};

Expand Down
17 changes: 0 additions & 17 deletions src/authentication/selectors/authentication.ts

This file was deleted.

Loading