> For the complete documentation index, see [llms.txt](https://intercode.gitbook.io/intercode-saas-kit/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://intercode.gitbook.io/intercode-saas-kit/pages/auth.md).

# Auth

### Functionality

The Auth module ensures secure access to the system by managing user login, registration, password recovery, and session handling. It includes role-based access controls and integrates with OAuth providers.

### Auth Provider

The `AuthProvider` component and `AuthContext` provide authentication management and user context for the application. It handles storing and managing authentication tokens, user information, and team-related updates.

#### Key Features:

**1. State Management:**

* **`token` & `refreshToken`:** Stored in localStorage using the `useLocalStorage` hook. These hold the access token and refresh token for authenticated sessions.
* **`currentUser`:** Holds the currently authenticated user's data.

**2. Functions:**

* **`fetchUser`:**
  * Fetches the current user data from the API using `userService.getUser()`.
  * Updates user roles and checks if the user has a team. If no team exists, it navigates to the team creation page.
* **`setAuth`:** Stores the access token and refresh token in localStorage.
* **`logout`:**
  * Logs the user out by deactivating their membership (if applicable) and clears the authentication tokens.
  * Redirects to the sign-in page.
* **`changeTeam`:**
  * Switches the active team by calling the `authService.changeTeam` API and updating tokens.
  * Re-fetches the user data after changing the team.

**3. Context Usage:**

* **`AuthContext.Provider`:** Provides the authentication-related values and functions (`token`, `setAuth`, `logout`, etc.) to the component tree.
* **`useAuth`:** Hook to access the `AuthContext` values and functions within any component.

#### Usage Example:

To access the authentication context:

```jsx
const { token, logout, fetchUser, currentUser } = useAuth();
```

This structure allows centralized control of authentication, token management, and user/team updates throughout the app.

{% code title="AuthContext.js" %}

```javascript
import { createContext, useCallback, useContext, useState } from 'react';
import { useLocalStorage } from '../common/hooks/useLocalStorage';
import { useNavigate } from 'react-router-dom';
import { useUserService } from '../services/userService';
import { REFRESH_TOKEN, TOKEN, USER_ROLES } from '../common/constants/localStorage';
import { updateToken } from '../services/tokenService';
import { useAuthService } from '../services/authService';
import globalNotification from '../common/hooks/globalNotification';
import { useTeamService } from '../services/teamService';

export const AuthContext = createContext(null);

export const AuthProvider = ({ children }) => {
    const [token, setToken] = useLocalStorage(TOKEN, null);
    const [refreshToken, setRefreshToken] = useLocalStorage(REFRESH_TOKEN, null);
    const [currentUser, setCurrentUser] = useState();
    const [isUserLoading, setIsUserLoading] = useState(true);

    const navigate = useNavigate();
    const userService = useUserService();
    const authService = useAuthService();
    const { updateMembership, findUserMembership } = useTeamService();

    const fetchUser = useCallback(async () => {
        try {
            if (token) {
                setIsUserLoading(true);
                const { data } = await userService.getUser();

                setCurrentUser(data);
                updateToken(USER_ROLES, data.userRoleNames);
                setTimeout(() => {
                    setIsUserLoading(false);
                }, 1000);

                if (!data.teamId) {
                    navigate('/create-team');
                }
            }
        } catch (e) {
            logout();
            console.error(e);
        }
    }, []);

    const setAuth = (token, refreshToken) => {
        setToken(token);
        setRefreshToken(refreshToken);
    };

    const logout = async () => {
        try {
            if (!currentUser) {
                throw new Error();
            }

            const { data } = await findUserMembership(currentUser.id);

            if (!data) {
                throw new Error();
            }

            await updateMembership({ id: data.id, isActive: false });
        } catch (e) {
            console.log(e);
        } finally {
            updateToken(TOKEN, null);
            updateToken(REFRESH_TOKEN, null);
            updateToken(USER_ROLES, null);
            navigate('/auth/sign-in');
        }
    };

    const changeTeam = async teamId => {
        try {
            const { data } = await authService.changeTeam(teamId);

            setAuth(data.accessToken, data.refreshToken || data.accessToken);
        } catch (error) {
            globalNotification.open({ message: 'This membership is not valid' });
        } finally {
            await fetchUser();
        }
    };

    return (
        <AuthContext.Provider
            value={{
                token,
                setAuth,
                logout,
                fetchUser,
                currentUser,
                isUserLoading,
                changeTeam,
            }}
        >
            {children}
        </AuthContext.Provider>
    );
};

export const useAuth = () => {
    return useContext(AuthContext);
};
```

{% endcode %}

### Components

Components Necessary for Optimal Functioning of the Auth Module

#### Auth Guard

The `AuthGuard` component is a route protection mechanism that checks if a user is authenticated before granting access to specific routes.

#### Key Features:

1. **Authentication Check:**
   * It verifies if the user is on an "auth" route (e.g., `/auth/sign-in`) by checking the URL path.
   * If the user is already authenticated (i.e., has valid tokens stored), they are redirected to the dashboard route.
2. **Route Protection:**
   * If the user is accessing a non-auth route and doesn't have valid tokens (`TOKEN` and `REFRESH_TOKEN` in localStorage), they are redirected to the sign-in page (`auth/sign-in`).

```javascript
import { useLocation } from 'react-router-dom';
import { Navigate } from 'react-router-dom';
import { routesPath } from '../../common/constants/routesPath';
import { TOKEN, REFRESH_TOKEN } from '../../common/constants/localStorage';

function AuthGuard({ children }) {
    const location = useLocation();
    const isAuth = location.pathname.split('/')[1] === 'auth';
    if (isAuth) {
        return getToken(TOKEN) && getToken(REFRESH_TOKEN) ? <Navigate to={routesPath.ROOT.DASHBOARD} /> : children;
    } else {
        return getToken(TOKEN) && getToken(REFRESH_TOKEN) ? children : <Navigate to={'auth/sign-in'} />;
    }
}

const getToken = tokenName => {
    const token = localStorage.getItem(tokenName);

    if (token === null || token === 'undefined') {
        return null;
    }
    return JSON.parse(localStorage.getItem(tokenName));
};

export default AuthGuard;
```

#### GetUser Decorator

This decorator retrieves user data parsed by JwtAuthenticationGuard

```typescript
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { JwtUserPayload } from 'src/common/interfaces/jwt-user-payload.interface';

export const GetUser = createParamDecorator((data, ctx: ExecutionContext): JwtUserPayload => {
    const req = ctx.switchToHttp().getRequest();
    return req.user;
});
```

### Auth Flow Schema

<figure><img src="/files/DCrThtuQZAJP7ORVIkBs" alt="" width="279"><figcaption><p>Auth Flow Block Schema</p></figcaption></figure>
