Skip to main content

Authentication

In this section we add Login, Logout, and SignUp for out website.

1. Create Login, Logout, and SignUp hooks#

These hooks are wrappers around ReactSDK hooks. They handle the logic of authentication, and we handle the behavior of our application. We use localStorage to store the apiKey.

import {useLogin as useReactSDKLogin} from "@tribeplatform/react-sdk/hooks";
import {useCallback} from "react";
export const useLogin = () => {
const {login} = useReactSDKLogin()
return useCallback((email: string, password: string) => {
login({
variables: {input: {usernameOrEmail: email, password}}
}
).then((token) => {
localStorage.setItem('apiKey', token.accessToken)
window.location.href = '/'
})
}, [login])
}

2. Create Login and SignUp pages#

We use the hooks above to create simple Login and SignUp pages.

import {useState} from "react";
import {useLogin} from "../hooks/useLogin";
export const Login = () => {
const [email, setEmail] = useState<string>('')
const [password, setPassword] = useState<string>('')
const login = useLogin()
return (
<div className="w-1/2 mx-auto mt-5">
<h1 className="text-2xl mb-5">Login</h1>
<label className="block text-gray-700 text-sm font-bold mb-2">
Email
</label>
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline mb-5"
type="email" placeholder="[email protected]" onChange={event => setEmail(event.target.value)}
/>
<label className="block text-gray-700 text-sm font-bold mb-2">
Password
</label>
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline mb-5"
type="password" placeholder="********" onChange={event => setPassword(event.target.value)}
/>
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mt-5"
onClick={() => {
login(email, password)
}}
>
Login
</button>
</div>
)
}

3. Routes and Buttons#

Now we need to add the authentication routes and a header to ease the flow of authentication. We use useAuthMember hook to retrieve the current authenticated user.

App.tsx
import React from 'react';
import {Routes, Route, Link} from "react-router-dom";
import NewsList from "./components/NewsList";
import {NewsPage} from "./components/NewsPage";
import {Composer} from "./components/Composer";
import {Login} from "./components/Login";
import {useLogout} from "./hooks/useLogout";
import {useAuthMember} from "@tribeplatform/react-sdk/hooks";
import {SignUp} from "./components/SignUp";
function App() {
const logout = useLogout()
const {data: user} = useAuthMember()
return (
<>
<nav className="bg-teal-500 flex justify-center mb-5">
<div className="flex items-center justify-between flex-wrap w-3/4 py-6">
<div className="flex items-center flex-shrink-0 text-white mr-6">
<Link to="/">
<span className="font-semibold text-xl tracking-tight">ReactSDK Tutorial</span>
</Link>
</div>
<div className="w-full block flex-grow lg:flex lg:items-center lg:w-auto">
<div className="text-sm lg:flex-grow">
<Link to="/"
className="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4">
News
</Link>
<Link to="/submit"
className="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4">
Submit
</Link>
</div>
<div>
{!user && (
<>
<Link to="/login"
className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white mt-4 lg:mt-0">
Login
</Link>
<Link to="/signup"
className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white mt-4 lg:mt-0 ml-4">
Sign Up
</Link>
</>
)}
{user && (
<>
<span className="block mt-4 lg:inline-block lg:mt-0 text-white mr-4">
Hello, {user.name}
</span>
<div
className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white mt-4 lg:mt-0 cursor-pointer"
onClick={() => {
logout()
}}
>
Logout
</div>
</>
)}
</div>
</div>
</div>
</nav>
<Routes>
<Route path="/" element={<NewsList/>}/>
<Route path="/login" element={<Login/>}/>
<Route path="/signup" element={<SignUp/>}/>
<Route path="/submit" element={<Composer/>}/>
<Route path="/:postId" element={<NewsPage/>}/>
</Routes>
</>
);
}
export default App;

4. Modify the TribeProvide#

The last step is to tell the TribeProvide to read the accessToken from the localStorage.

index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from "react-router-dom";
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {Provider as TribeProvider} from '@tribeplatform/react-sdk'
ReactDOM.render(
<React.StrictMode>
<TribeProvider config={{
baseUrl: 'https://app.tribe.so/graphql',
networkDomain: 'react-sdk-tutorial.tribeplatform.com',
accessToken: localStorage.getItem('apiKey')
}}>
<BrowserRouter>
<App/>
</BrowserRouter>
</TribeProvider>
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();