feat: authorize routes added
This commit is contained in:
5
.env
5
.env
@@ -1,3 +1,6 @@
|
|||||||
VITE_GOOGLE_CLIENT_ID=https://272098283932-bft2gvlgjn8edopg0lnqjq1i9ekdmipt.apps.googleusercontent.com/
|
VITE_GOOGLE_CLIENT_ID=https://272098283932-bft2gvlgjn8edopg0lnqjq1i9ekdmipt.apps.googleusercontent.com/
|
||||||
VITE_DEFUALT_AUTH_RETURN_URL=/setting/profile
|
VITE_DEFUALT_AUTH_RETURN_URL=/setting/profile
|
||||||
VITE_API_URL=https://accounts.business-harmony.com/api/
|
VITE_API_URL=https://accounts.business-harmony.com/api/
|
||||||
|
VITE_IDENTITY_URL=https://accounts.business-harmony.com/connect/token
|
||||||
|
VITE_IDENTITY_CLIENT_ID=harmony_identity
|
||||||
|
VITE_IDENTITY_SCOPE=openid profile offline_access harmony_identity
|
||||||
13
src/components/ProtectedRoute.tsx
Normal file
13
src/components/ProtectedRoute.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { getAccessToken } from '@/lib/apiClient';
|
||||||
|
import { type PropsWithChildren } from 'react';
|
||||||
|
import { Navigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
export const ProtectedRoute = ({ children }: PropsWithChildren) => {
|
||||||
|
if (!getAccessToken()) {
|
||||||
|
// If no token, redirect to login page
|
||||||
|
return <Navigate to="/login" replace />;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If token exists, render the children components
|
||||||
|
return children;
|
||||||
|
};
|
||||||
0
src/features/authorization/types/identityTypes.ts
Normal file
0
src/features/authorization/types/identityTypes.ts
Normal file
@@ -1,7 +1,8 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
// Function to get the token from local storage or state management
|
// Function to get the token from local storage or state management
|
||||||
const getToken = () => sessionStorage.getItem('authToken');
|
export const ACCESS_TOKEN_KEY: 'access_token' = 'access_token' as const;
|
||||||
|
export const getAccessToken = () => sessionStorage.getItem(ACCESS_TOKEN_KEY);
|
||||||
|
|
||||||
const apiClient = axios.create({
|
const apiClient = axios.create({
|
||||||
// Define the base URL for all API requests
|
// Define the base URL for all API requests
|
||||||
@@ -21,7 +22,7 @@ const apiClient = axios.create({
|
|||||||
// This runs BEFORE each request is sent
|
// This runs BEFORE each request is sent
|
||||||
apiClient.interceptors.request.use(
|
apiClient.interceptors.request.use(
|
||||||
(config) => {
|
(config) => {
|
||||||
const token = getToken();
|
const token = getAccessToken();
|
||||||
if (token) {
|
if (token) {
|
||||||
// Add the authorization token to the headers
|
// Add the authorization token to the headers
|
||||||
config.headers.Authorization = `Bearer ${token}`;
|
config.headers.Authorization = `Bearer ${token}`;
|
||||||
|
|||||||
14
src/lib/identityClient.ts
Normal file
14
src/lib/identityClient.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const identityClient = axios.create({
|
||||||
|
// Define the base URL for all API requests
|
||||||
|
baseURL: import.meta.env.VITE_IDENTITY_URL,
|
||||||
|
|
||||||
|
// Set a timeout for requests (e.g., 10 seconds)
|
||||||
|
timeout: 10000,
|
||||||
|
|
||||||
|
// Set default headers
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -22,6 +22,7 @@ import { Navigate } from 'react-router-dom';
|
|||||||
export interface RouteConfig {
|
export interface RouteConfig {
|
||||||
path: string;
|
path: string;
|
||||||
element?: ReactNode;
|
element?: ReactNode;
|
||||||
|
authorize?: boolean;
|
||||||
navConfig?: {
|
navConfig?: {
|
||||||
title: string; // Translation key
|
title: string; // Translation key
|
||||||
icon?: Icon;
|
icon?: Icon;
|
||||||
@@ -38,10 +39,12 @@ export const appRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
element: <AuthenticationPage />,
|
element: <AuthenticationPage />,
|
||||||
|
authorize: l,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/forget-password',
|
path: '/forget-password',
|
||||||
element: <ForgetPasswordPage />,
|
element: <ForgetPasswordPage />,
|
||||||
|
authorize: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Suspense, type ReactNode } from 'react';
|
import { Suspense, type ReactNode } from 'react';
|
||||||
import { createBrowserRouter, type RouteObject } from 'react-router-dom';
|
import { createBrowserRouter, type RouteObject } from 'react-router-dom';
|
||||||
import { appRoutes, type RouteConfig } from './config';
|
import { appRoutes, type RouteConfig } from './config';
|
||||||
|
import { ProtectedRoute } from '@/components/ProtectedRoute';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A recursive function to map our custom route config to the format
|
* A recursive function to map our custom route config to the format
|
||||||
@@ -18,10 +19,9 @@ function mapRoutes(routes: RouteConfig[]): RouteObject[] {
|
|||||||
// element = <route.layout>{element}</route.layout>;
|
// element = <route.layout>{element}</route.layout>;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Conditionally wrap the element in the authentication guard
|
if (route.authorize) {
|
||||||
// if (route.authRequired) {
|
element = <ProtectedRoute>{element}</ProtectedRoute>;
|
||||||
// element = <ProtectedRoute>{element}</ProtectedRoute>;
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
path: route.path,
|
path: route.path,
|
||||||
|
|||||||
Reference in New Issue
Block a user