[← Back to Reviews Index](../Stewards%20Reviews%20Index.md)

# React Auth Review — Azure-AI-RAG-CSharp-Semantic-Kernel-Functions

| Field | Value |
|---|---|
| Project | Azure-AI-RAG-CSharp-Semantic-Kernel-Functions |
| Steward | React Auth Steward |
| Run Date | 2026-03-21 |
| Scope | React frontend (`src/web`) — authentication and authorization patterns |
| Critical | 2 |
| Notable | 3 |
| Minor | 1 |
| Info | 2 |
| Total | 8 |

---

## 1. Auth Architecture Overview

The React frontend (`src/web`) is a Create React App (CRA) application built with React 18, `react-router-dom` v6, and MUI v5. It serves as a chat interface that connects to a .NET RAG backend at a configurable `REACT_APP_API_HOST` endpoint.

**Auth library:** None. No MSAL, OAuth, or any authentication library is present.

**Auth flow type:** None. The application is fully unauthenticated.

**MSAL version:** Not installed. The `package.json` contains no `@azure/msal-browser` or `@azure/msal-react` dependency.

The application is self-described as a demo/sample. The README explicitly warns: *"This demo application is intended solely for educational and demonstration purposes."* However, the Bicep-based deployment (referenced in the root README) deploys the application to an Azure Web App with a public domain, which means the absence of authentication becomes a real risk if the deployment is used beyond local testing.

---

## 2. MSAL Configuration Assessment

No MSAL configuration exists anywhere in the codebase.

| Check | Status | Notes |
|---|---|---|
| `@azure/msal-browser` installed | Not present | Not in `package.json` |
| `@azure/msal-react` installed | Not present | Not in `package.json` |
| `MsalProvider` wrapping the application | Absent | `index.js` wraps app in `BrowserRouter` only |
| `clientId` / `authority` / `redirectUri` configured | Absent | No auth config file of any kind |
| `cacheLocation` set to `sessionStorage` or `memory` | Absent | N/A |

The entire authentication layer is missing.

---

## 3. Token Acquisition Assessment

No token acquisition logic exists.

| Check | Status |
|---|---|
| `acquireTokenSilent` used as primary method | Absent |
| Fallback to interactive (`acquireTokenPopup` / `acquireTokenRedirect`) | Absent |
| Correct API scopes requested | Absent |
| Token expiry handled | Absent |

API calls in `Agent.js` are plain `fetch` calls with no `Authorization` header, no bearer token, and no credential of any kind. Any caller with network access to the deployed backend URL can invoke the API freely.

---

## 4. Protected Routes Assessment

No route protection exists.

| Check | Status |
|---|---|
| Routes wrapped in auth guards or `AuthenticatedTemplate` | Absent |
| Unauthenticated users redirected to login | Absent |
| Redirect back to original route after login | Absent |
| Content rendered before auth check | N/A — no auth check at all |

`App.js` defines a single route (`/`) that renders `Main` directly. There is no guard, no loading state, and no redirect logic. All content is immediately accessible to any visitor.

---

## 5. Token Storage Assessment

No tokens are stored anywhere — because no authentication exists and no tokens are ever acquired.

| Check | Status |
|---|---|
| Tokens stored in `localStorage` | Not applicable — no tokens |
| MSAL handles token storage internally | Not applicable — no MSAL |
| Tokens logged to console or error tracking | See RAUTH-LOG-001 |

One related concern: `Agent.js` line 38 contains `console.log(res)` which logs the full raw API response to the browser console. If the API were to return any user-sensitive data or session tokens in its response body, they would be exposed in the developer console of every user's browser.

---

## 6. Logout Assessment

No logout mechanism exists.

| Check | Status |
|---|---|
| Logout clears MSAL cache and application state | Absent — no auth state |
| Logout calls `logoutPopup()` or `logoutRedirect()` | Absent |
| Logout does not silently clear only local state | N/A |

There is no login flow, therefore no logout flow. No session termination logic is present.

---

## 7. Auth Error Handling Assessment

No auth error handling exists.

| Check | Status |
|---|---|
| `InteractionRequiredAuthError` caught and handled | Absent |
| Expired tokens trigger re-authentication | Absent |
| Auth errors show user-friendly messages | Absent |

The application has no mechanism to detect, handle, or surface authentication errors of any kind.

---

## 8. Findings

| Severity | ID | Title | File |
|---|---|---|---|
| 🔴 Critical | RAUTH-NOAUTH-001 | No authentication layer — API fully open | `src/web/src/SupportAgent/Agent.js` |
| 🔴 Critical | RAUTH-ROUTE-001 | No route protection — all content accessible without login | `src/web/src/App.js` |
| 🟡 Notable | RAUTH-MSAL-001 | No MSAL library installed or configured | `src/web/package.json` |
| 🟡 Notable | RAUTH-TOKEN-001 | API calls carry no credentials or Authorization header | `src/web/src/SupportAgent/Agent.js` |
| 🟡 Notable | RAUTH-SESSION-001 | No logout or session termination mechanism | N/A |
| 🟢 Minor | RAUTH-LOG-001 | API response logged to console — sensitive data exposure risk | `src/web/src/SupportAgent/Agent.js` |
| ℹ️ Info | RAUTH-DEMO-001 | Application is self-described as demo-only | `README.md` |
| ℹ️ Info | RAUTH-DEPLOY-001 | Bicep deployment exposes app at public Azure Web App URL | `infra/` (out of scope for this steward) |

### Finding Details

#### RAUTH-NOAUTH-001 — No authentication layer — API fully open
**Severity:** 🔴 Critical

No authentication library (MSAL or otherwise) is installed or configured. The frontend communicates with the backend over unauthenticated plain `fetch` calls. Any user or automated client with network access to `REACT_APP_API_HOST` can freely invoke the `/chat` and `/session` endpoints. When deployed to the public Azure Web App described in the README, this means anyone on the internet can consume the RAG pipeline, Azure OpenAI quota, and CosmosDB reads without restriction.

**Recommendation:** Install `@azure/msal-browser` and `@azure/msal-react`. Register the application in Azure Entra ID. Wrap `<App />` in `<MsalProvider>` and require authentication before API calls.

---

#### RAUTH-ROUTE-001 — No route protection — all content accessible without login
**Severity:** 🔴 Critical

`App.js` renders `<Main />` directly under the `/` route with no auth guard, no `<AuthenticatedTemplate>`, and no redirect to a login page. The full UI — including the AI chat interface — renders immediately for any visitor regardless of identity.

**Recommendation:** Wrap protected routes with `<AuthenticatedTemplate>` from `@azure/msal-react`. Redirect unauthenticated visitors to a login page or invoke `loginRedirect()` / `loginPopup()` automatically.

---

#### RAUTH-MSAL-001 — No MSAL library installed or configured
**Severity:** 🟡 Notable

Neither `@azure/msal-browser` nor `@azure/msal-react` appears in `package.json`. There is no auth configuration object (no `clientId`, `authority`, or `redirectUri`). This is a prerequisite for any Azure AD / Entra ID authentication.

**Recommendation:** Add `@azure/msal-browser` and `@azure/msal-react` to dependencies. Create an `authConfig.js` that sets `clientId`, `authority` (tenant-specific, not `common` for single-tenant apps), `redirectUri` (from an environment variable, not hardcoded), and `cacheLocation: "sessionStorage"`.

---

#### RAUTH-TOKEN-001 — API calls carry no credentials or Authorization header
**Severity:** 🟡 Notable

The `fetch` calls in `Agent.js` (lines 29–44 and 48–52) send no `Authorization` header. Even if the backend were secured, the frontend would receive 401 errors and have no mechanism to acquire and attach a bearer token.

**Recommendation:** Use `acquireTokenSilent` before each API call to obtain a token, with fallback to `acquireTokenPopup` on `InteractionRequiredAuthError`. Attach the token as `Authorization: Bearer <token>` in the `fetch` headers. This concern may be coordinated with the React API Client Steward for injection patterns.

---

#### RAUTH-SESSION-001 — No logout or session termination mechanism
**Severity:** 🟡 Notable

There is no logout button, no session expiry handling, and no mechanism to call `logoutRedirect()` or `logoutPopup()`. Once authentication is added, users will have no way to end their session, and tokens will persist until MSAL's internal cache expiry without server-side invalidation.

**Recommendation:** Add a logout button that calls `msalInstance.logoutRedirect()` or `msalInstance.logoutPopup()` to clear both the client-side MSAL cache and the server-side session cookie.

---

#### RAUTH-LOG-001 — API response logged to console — sensitive data exposure risk
**Severity:** 🟢 Minor

`Agent.js` line 38: `console.log(res)` logs the full raw API JSON response object on every chat message. Currently the response contains only an AI text reply, but if the API evolves to return session tokens, user identifiers, or other sensitive data, these will appear in any user's browser developer console and in any browser extension that monitors console output.

**Recommendation:** Remove the `console.log(res)` statement. If debug logging is needed, gate it behind a development-only environment check: `if (process.env.NODE_ENV === 'development') console.log(res)`.

---

#### RAUTH-DEMO-001 — Application is self-described as demo-only
**Severity:** ℹ️ Info

The root `README.md` and `src/web/README.md` both include disclaimers that the application is for educational and demonstration purposes only. The `Main.js` component also renders an in-UI disclaimer. This context is noted and may explain the absence of authentication as an intentional simplification for demo use.

---

#### RAUTH-DEPLOY-001 — Bicep deployment exposes app at public Azure Web App URL
**Severity:** ℹ️ Info

The root README describes a Bicep deployment that provisions the React app to a publicly accessible Azure Web App domain. The absence of auth combined with a public deployment URL is a compounding risk factor. This finding is informational from the auth steward's perspective; infrastructure access controls are owned by the Infra Security Steward.

---

## 9. Recommended Improvements

| Finding | Recommended Action | Priority |
|---|---|---|
| RAUTH-NOAUTH-001 | Install `@azure/msal-browser` + `@azure/msal-react`; create `authConfig.js`; wrap app in `MsalProvider`; acquire tokens before API calls | High |
| RAUTH-ROUTE-001 | Wrap `<Main />` route in `<AuthenticatedTemplate>`; redirect unauthenticated users to login | High |
| RAUTH-MSAL-001 | Configure MSAL with `clientId`, `authority`, `redirectUri` (env var), `cacheLocation: "sessionStorage"` | High |
| RAUTH-TOKEN-001 | Add `acquireTokenSilent` + `InteractionRequiredAuthError` fallback; attach bearer token to `fetch` headers | High |
| RAUTH-SESSION-001 | Add a logout action that calls `msalInstance.logoutRedirect()` or `logoutPopup()` | Medium |
| RAUTH-LOG-001 | Remove `console.log(res)` or gate behind `NODE_ENV === 'development'` check | Low |

---

## Summary

The React frontend has **no authentication or authorization layer whatsoever**. There is no MSAL integration, no protected routes, no token acquisition, and no session management. All application content and the backend API are freely accessible to any visitor. While the project is explicitly labeled as a demo, the Bicep deployment provisions it to a public Azure Web App endpoint, which means these gaps become real security concerns if the deployment is used beyond local development.

The two critical findings (RAUTH-NOAUTH-001 and RAUTH-ROUTE-001) represent the absence of an entire security layer, not isolated defects. Addressing them requires adding MSAL as a dependency and introducing auth guards — a meaningful but well-understood addition for an Azure-hosted React application.

---

*This review is based on static analysis of source files and configuration only. It does not reflect runtime behavior, deployed environment state, or network-level access controls. Generated by the React Auth Steward on 2026-03-21.*
