-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Setup Authentication (login/logout only) ππππ©βπ¬π©βπ¬π©βπ¬
- requests to AWS Cognito UserPool π΅οΈ - this can be extended to add forgot password and reset password methods too - this can replaced to use different auth providers - giving all CMS routes access to authentication context
- Loading branch information
Showing
5 changed files
with
315 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
"use client"; | ||
|
||
import React from "react"; | ||
import AuthProvider from "@/app/cms-authentication/AuthContext"; | ||
|
||
export default function CMSLayout({ children, }: { children: React.ReactNode }) { | ||
return ( | ||
<div> | ||
{/*<div className={"absolute right-12 -z-50"}>*/} | ||
{/* <p className={"opacity-55 text-sm text-blue-500"}>CMS Layout</p>*/} | ||
{/*</div>*/} | ||
{children} | ||
</div> | ||
) | ||
export default function CMSLayout({ children }: { children: React.ReactNode }) { | ||
return ( | ||
<AuthProvider> | ||
<div>{children}</div> | ||
</AuthProvider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import React, { useContext, useState, useEffect } from "react"; | ||
import { | ||
AuthenticationDetails, | ||
CognitoUser, | ||
CognitoUserPool, | ||
CognitoUserSession, | ||
CognitoIdToken, | ||
} from "amazon-cognito-identity-js"; | ||
import { redirect } from "next/navigation"; | ||
|
||
type AuthContextValue = { | ||
currentUser: null | CognitoIdToken["payload"]; | ||
login: any; | ||
logout: any; | ||
}; | ||
|
||
const openRoutes = ["/login", "/forgot-password"]; | ||
|
||
// where to authenticate users from | ||
const adminUserPool = new CognitoUserPool({ | ||
ClientId: "7dv8g7lsl2ht3uv29q9npt0a84", | ||
UserPoolId: "us-east-1_1GuGm8wMs", | ||
}); | ||
|
||
const AuthContext = React.createContext({ | ||
currentUser: null, | ||
login: () => {}, | ||
} as AuthContextValue); | ||
|
||
export function useAuth() { | ||
return useContext(AuthContext); | ||
} | ||
|
||
export default function AuthProvider({ children }: React.PropsWithChildren) { | ||
const [currentUserSession, setCurrentUserSession] = useState( | ||
null as AuthContextValue["currentUser"] | ||
); | ||
const [loading, setLoading] = useState(true); | ||
|
||
useEffect(() => { | ||
const currentUser = adminUserPool.getCurrentUser(); | ||
|
||
if (!currentUser) return setLoading(false); | ||
|
||
currentUser.getSession( | ||
(error: Error | null, session: CognitoUserSession | null) => { | ||
error && console.log("Error in getting user session:", error); | ||
session && setCurrentUserSession(session.getIdToken().payload); | ||
setLoading(false); | ||
} | ||
); | ||
}, []); | ||
|
||
useEffect(() => { | ||
if (loading) return; // we don't know if user is logged in or not | ||
|
||
const currentRoute = window.location.pathname; | ||
|
||
if (!currentUserSession && !openRoutes.includes(currentRoute)) { | ||
redirect(openRoutes[0]); | ||
} | ||
|
||
if (currentUserSession && openRoutes.includes(currentRoute)) { | ||
redirect("/news/publish/"); | ||
} | ||
|
||
setLoading(false); | ||
}, [currentUserSession, loading]); | ||
|
||
async function login(email: string, password: string) { | ||
const user = new CognitoUser({ | ||
Username: email, | ||
Pool: adminUserPool, | ||
}); | ||
|
||
const authDetails = new AuthenticationDetails({ | ||
Username: email, | ||
Password: password, | ||
}); | ||
|
||
try { | ||
const result: CognitoUserSession = await new Promise( | ||
(resolve, reject) => { | ||
user.authenticateUser(authDetails, { | ||
onSuccess: resolve, | ||
onFailure: reject, | ||
}); | ||
} | ||
); | ||
|
||
setCurrentUserSession(result.getIdToken().payload); | ||
} catch (error) { | ||
console.error("Login failed:", error); | ||
} | ||
} | ||
|
||
function logout() { | ||
adminUserPool.getCurrentUser()?.signOut(); | ||
setCurrentUserSession(null); | ||
} | ||
|
||
// expose useful auth methods/values | ||
const authDetails = { | ||
currentUser: currentUserSession, | ||
login, | ||
logout, | ||
}; | ||
|
||
return ( | ||
<AuthContext.Provider value={authDetails}> | ||
{!loading && children} | ||
</AuthContext.Provider> | ||
); | ||
} |
Oops, something went wrong.