diff options
Diffstat (limited to 'microservices/04-react-app/src/contexts')
| -rw-r--r-- | microservices/04-react-app/src/contexts/AuthContext.jsx | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/microservices/04-react-app/src/contexts/AuthContext.jsx b/microservices/04-react-app/src/contexts/AuthContext.jsx new file mode 100644 index 0000000..9bb5937 --- /dev/null +++ b/microservices/04-react-app/src/contexts/AuthContext.jsx @@ -0,0 +1,99 @@ +import { createContext, useState, useEffect, use } from 'react'; +import axios from 'axios'; + +// 1. Initialize Context +const AuthContext = createContext(null); + +// 2. Create a Custom Provider Component +export function AuthProvider({ children }) { + const [user, setUser] = useState(null); + + useEffect(() => { + // Fetch user data from your backend API + const fetchUser = async () => { + // axios is directly used from Axios library to avoid interceptor + // added in services/api.js + try { + const response = await axios.get("/bff/api/security/me", { + timeout: 30000, // 30 seconds + headers: { 'Content-Type': 'application/json' }, + withCredentials: true + }); + if (response.data && 'username' in response.data) { + setUser(response.data); + } + } catch (error) { + console.log(error); + } + }; + fetchUser(); + }, []); + + const login = () => { + // Start single sign-on process (Using OAuth2, OpenID) + // Access /ui of API gateway. + // API gateway will redirect user to authorization server if the user is not logged in + // If logged in, API gateway will redirect browser to React app itself reloading the app. + window.location.href = "/bff/ui"; + } + + const logout = async () => { + // Logout from API gateway + try { + const response = await axios.post('/bff/logout', { + timeout: 30000, // 30 seconds + headers: { 'Content-Type': 'application/json' }, + withCredentials: true + }); + // Redirect browser to logout from authorization server. + window.location.href = response.headers.location; + // setUser(null) is not needed since browser is redirected. + } catch (error) { + console.log(error); + } + }; + + const isLoggedIn = () => { + if (user) { + return true; + } + + return false; + }; + + const isAdmin = () => { + return isInRole("ADMIN"); + } + + const isInRole = (role) => { + if (user && role && user.roles) { + return user.roles.includes(role); + } + + return false; + }; + + const isInRoles = (roles) => { + if (user && roles && user.roles) { + return roles.some(value => user.roles.includes(value)); + } + + return false; + } + + // Provide the state and the modifier function as a value object + return ( + <AuthContext value={{ user, login, logout, isLoggedIn, isAdmin, isInRole, isInRoles }}> + {children} + </AuthContext> + ); +} + +// 3. Create a clean Custom Hook to consume this specific context +export function useAuth() { + const context = use(AuthContext); + if (!context) { + throw new Error('useAuth must be used within an AuthProvider'); + } + return context; +} |
