# CONTEXT & PROVIDERS

**Context** and **Provider** are React mechanisms that allow data to be shared between components without passing props. In our case:

<table data-header-hidden><thead><tr><th width="228"></th><th></th></tr></thead><tbody><tr><td><strong><code>ExternalAuthContext</code></strong></td><td><em>stores information about whether the user is logged in</em></td></tr><tr><td><strong><code>ExternalAuthProvider</code></strong></td><td><em>manages authorization logic and automatic redirects</em></td></tr></tbody></table>

{% stepper %}
{% step %}

#### Creating context

Create file name **`ExternalAuthContext.ts`** in **`web/src/contexts`** and paste following code:

{% tabs %}
{% tab title="web/src/contexts/ExternalAuthContext.ts" %}

```typescript
import { createContext, useContext } from "react";

export type ExternalAuthContextValue = {
    isAuth: boolean;
    logoutUser: () => void;
};

export const ExternalAuthContext = createContext<ExternalAuthContextValue | null>(null);

export const useExternalAuth = () => {
    const ctx = useContext(ExternalAuthContext);
    if (!ctx) {
        throw new Error("useExternalAuth must be used within <ExternalAuthProvider>");
    }
    return ctx;
};
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Creating Provider

Create file name **`ExternalAuthProvider.tsx`** in **`web/src/providers`** and paste following code:

{% tabs %}
{% tab title="web/src/providers/ExternalAuthProvider.tsx" %}

```typescript
import { ExternalAuthContext } from "@/contexts/ExternalAuthContext";
import { useNavigateWithApps } from "@/hooks/useNavigateWithApps";
import { useEffect, useCallback } from "react";
import { useLocation } from "react-router-dom";

export const ExternalAuthProvider = ({
    authPage,
    homePage,
    children,
}: {
    authPage: string;
    homePage: string;
    children: React.ReactNode;
}) => {
    const isAuth = useIsAuthenticated();
    const location = useLocation();
    const navigate = useNavigateWithApps();

    const path = location.pathname;
    const isInsideAuth = path === authPage || path.startsWith(authPage + "/");

    const logoutUser = useCallback(() => {
        useSignOut();
        navigate(authPage);
    }, [navigate, authPage]);

    useEffect(() => {
        if (!isAuth) {
            if (!isInsideAuth) navigate(authPage);
            return;
        }

        if (isAuth && isInsideAuth) {
            navigate(homePage);
            return;
        }
    }, [isAuth, isInsideAuth, authPage, homePage, navigate]);

    if (!isAuth && !isInsideAuth) return null;
    if (isAuth && isInsideAuth) return null;

    return (
        <ExternalAuthContext.Provider value={{ isAuth, logoutUser }}>
            {children}
        </ExternalAuthContext.Provider>
    );
};
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Integrating the External Authentication Provider

To enable external authentication, the **`ExternalAuthProvider`** must be integrated into the main provider chain within the **`ProvidersManager`** component. Go to **`web/src/providers/index.tsx`**.

1. Import the **`ExternalAuthProvider`** component:

```typescript
import { ExternalAuthProvider } from './ExternalAuthProvider';
```

2. Wrap the **`NuiProvider`** and its children with the **`ExternalAuthProvider`** inside the **`ProvidersManager`**. The new provider should be placed between the **`NavigateProvider`** and the **`NuiProvider`**.

{% tabs %}
{% tab title="web/src/providers/index.tsx" %}

```typescript
import type { ReactNode } from 'react';
import { Provider } from 'react-redux';

import store from '@/store';

import LanguageProvider from './LanguageProvider';
import NavigateProvider from './NavigateProvider';
import NuiProvider from './NuiProvider';
import { ExternalAuthProvider } from './ExternalAuthProvider'

const ProvidersManager = ({ children }: { children: ReactNode }) => {
    return (
        <Provider store={store}>
            <NavigateProvider>
                <ExternalAuthProvider authPage='/auth' homePage='/'>
                    <NuiProvider>
                        <LanguageProvider>{children}</LanguageProvider>
                    </NuiProvider>
                </ExternalAuthProvider>
            </NavigateProvider>
        </Provider>
    );
};

export default ProvidersManager;
```

{% endtab %}
{% endtabs %}

The `authPage` and `homePage` props are required to configure the redirect paths for authentication handling.
{% endstep %}
{% endstepper %}
