diff --git a/src/App.tsx b/src/App.tsx
index 7aa58b9..f0fab75 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -16,6 +16,7 @@ import Main from './components/Main';
 import 'bootstrap/dist/css/bootstrap.min.css';
 import 'bootstrap/dist/js/bootstrap.bundle.min';
 import './App.css';
+import Authenticator from './components/Authenticator';
 
 function App() {
 	return (
@@ -24,6 +25,7 @@ function App() {
 				<Nav />
 				<Switch>
 					<Route component={Main} path="/about" />
+					<Route component={Authenticator} path="/auth/:provider/callback" />
 					<Route component={CreatePool} path="/create_pool" />
 					<Route component={CreateGroup} path="/create_group" />
 					<Route component={Groups} path="/groups" />
diff --git a/src/api.ts b/src/api.ts
index 82300fa..58a692b 100644
--- a/src/api.ts
+++ b/src/api.ts
@@ -2,4 +2,4 @@
 const dev = process.env.NODE_ENV === 'development';
 export const API_ENDPOINT = 'http://localhost/api';
 export const ION_AUTHORIZATION_ENDPOINT =
-	'https://ion.tjhsst.edu/oauth/authorize?response_type=code&client_id=ScL9QdZ9m3iGmHG11uznwABg4ZSkabQJan05ZYsk&scope=read&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fauth%2Fion%2Fsuccess;';
+	'https://ion.tjhsst.edu/oauth/authorize?response_type=code&client_id=rNa6n9YSg8ftINdyVPpUsaMuxNbHLo9dh1OsOktR&scope=read&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fion%2Fcallback';
diff --git a/src/components/Authenticator.tsx b/src/components/Authenticator.tsx
new file mode 100644
index 0000000..db19a85
--- /dev/null
+++ b/src/components/Authenticator.tsx
@@ -0,0 +1,44 @@
+import { useEffect, useState } from 'react';
+import { Redirect, useLocation, useParams } from 'react-router-dom';
+import { API_ENDPOINT } from '../api';
+
+export default function Authenticator() {
+	const { provider } = useParams<{ provider: string }>();
+	const query = new URLSearchParams(useLocation().search);
+	const code = query.get('code');
+	const [status, setStatus] = useState<'pending' | 'errored' | 'authenticated'>(
+		'pending'
+	);
+
+	useEffect(() => {
+		fetch(`${API_ENDPOINT}/create_session`, {
+			method: 'post',
+			body: JSON.stringify({
+				code,
+				provider,
+			}),
+		})
+			.then((response) => {
+				response.json().then((json) => {
+					if (json.status === 'success') {
+						localStorage.setItem('session_token', json.token);
+						setStatus('authenticated');
+					} else {
+						setStatus('errored');
+					}
+				});
+			})
+			.catch(() => {
+				setStatus('errored');
+			});
+	}, [code, provider]);
+
+	switch (status) {
+		case 'authenticated':
+			return <Redirect to="/" />;
+		case 'errored':
+			return <h1>Sign In Error</h1>;
+		case 'pending':
+			return <h1>Signing In</h1>;
+	}
+}
diff --git a/src/components/Home.tsx b/src/components/Home.tsx
index 116ca78..306df15 100644
--- a/src/components/Home.tsx
+++ b/src/components/Home.tsx
@@ -1,3 +1,5 @@
+import { ION_AUTHORIZATION_ENDPOINT } from '../api';
+
 export default function Home() {
 	return (
 		<div
@@ -9,7 +11,7 @@ export default function Home() {
 		>
 			<h1>Home</h1>
 			<div style={{ display: 'flex', flexDirection: 'row' }}>
-				<a href="/">Log In with Ion</a>
+				<a href={ION_AUTHORIZATION_ENDPOINT}>Log In with Ion</a>
 			</div>
 		</div>
 	);