Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Azure Static Web Apps Dashboard

A full-stack dashboard application deployed to Azure Static Web Apps. The frontend is a React SPA authenticated via Microsoft Entra ID (PKCE). The backend is a C# Azure Functions API that uses the On-Behalf-Of (OBO) flow to execute SQL queries under the calling user's identity.

Architecture

Browser (React + MSAL)
  │
  │  PKCE login -> acquires access token scoped to the Backend API
  │
  ▼
Azure Static Web Apps
  ├── Static files (React build output)
  └── /api/* -> Azure Functions (C# .NET 8 Isolated Worker)
                  │
                  │  OBO flow: exchanges user's API token
                  │  for a SQL token (database.windows.net)
                  │
                  ▼
              Azure SQL Database
              (permissions enforced per-user by SQL RBAC)

Prerequisites

Install these before starting local development:

You also need these Azure resources already provisioned:

  • An Azure SQL Database
  • Two Microsoft Entra ID App Registrations (Frontend SPA and Backend API)
  • An Azure Static Web Apps resource (for deployment; not required for local dev)

Entra ID App Registration Setup

1. Backend API Registration

  1. Go to Azure Portal > Microsoft Entra ID > App registrations > New registration.
  2. Name it something like Dashboard-API.
  3. Set Supported account types to "Accounts in this organizational directory only."
  4. No redirect URI is needed for the backend.
  5. After creation, note the Application (client) ID. This is your BACKEND_CLIENT_ID.

Expose an API:

  1. Go to Expose an API.
  2. Set the Application ID URI to api://<BACKEND_CLIENT_ID>.
  3. Add a scope:
    • Scope name: access_as_user
    • Who can consent: Admins and users
    • Admin consent display name: "Access Dashboard API as user"
    • Admin consent description: "Allows the SPA to call the Dashboard API on behalf of the signed-in user."
    • State: Enabled

Certificates & secrets:

  1. Go to Certificates & secrets > New client secret.
  2. Copy the secret value. This is your BACKEND_CLIENT_SECRET.

API permissions:

  1. Go to API permissions > Add a permission > APIs my organization uses.
  2. Search for "Azure SQL Database" or use the well-known scope: https://database.windows.net/user_impersonation.
  3. Select Delegated permissions > user_impersonation.
  4. Click Grant admin consent for your tenant.

2. Frontend SPA Registration

  1. Create another app registration, e.g. Dashboard-SPA.
  2. Set Supported account types to "Accounts in this organizational directory only."
  3. Under Authentication > Platform configurations > Add a platform > Single-page application.
  4. Add redirect URIs:
    • http://localhost:4280 (local SWA CLI)
    • https://<your-swa-hostname>.azurestaticapps.net (production)
  5. Note the Application (client) ID. This is your FRONTEND_CLIENT_ID.

API permissions:

  1. Go to API permissions > Add a permission > My APIs.
  2. Select the Backend API registration.
  3. Check the access_as_user scope.
  4. Click Grant admin consent for your tenant.

Azure SQL Database Setup

Set the Entra Admin

  1. In the Azure Portal, go to your SQL Server (not the database, the server).
  2. Under Settings > Microsoft Entra admin, set an Entra admin user or group.

Create Tables and Users

Connect to your database as the Entra admin (e.g., via Azure Data Studio or SSMS) and run the setup.sql script. Edit it first to replace the placeholder user/group names with your actual Entra identities.

# Example using sqlcmd with Entra auth:
sqlcmd -S yourserver.database.windows.net -d yourdb --authentication-method=ActiveDirectoryInteractive -i setup.sql

Local Development

1. Configure the Backend

Copy the example settings file and fill in your values:

cp api/local.settings.json.example api/local.settings.json

Edit api/local.settings.json with your actual Tenant ID, Backend Client ID, Backend Client Secret, and SQL connection string.

The SQL connection string must not contain a username or password. Example:

Server=tcp:yourserver.database.windows.net,1433;Database=yourdb;Encrypt=True;TrustServerCertificate=False;

2. Configure the Frontend

Copy the example env file and fill in your values:

cp client/.env.example client/.env

Edit client/.env with your Tenant ID, Frontend Client ID, and Backend Client ID.

3. Install Dependencies

# Frontend
cd client
npm install

# Backend
cd ../api
dotnet restore

4. Run with SWA CLI

From the project root:

swa start client/dist --api-location api --run "cd client && npm run dev" --api-devserver-url http://localhost:7071

Or run the pieces separately in different terminals:

Terminal 1: Frontend dev server

cd client
npm run dev

Terminal 2: Azure Functions

cd api
func start

Terminal 3: SWA CLI proxy

swa start http://localhost:3000 --api-devserver-url http://localhost:7071

The SWA CLI serves on http://localhost:4280 by default. Use that URL in your browser (it must match your SPA redirect URI).

Project Structure

├── api/                              C# Azure Functions backend
│   ├── Api.csproj                    Project file with dependencies
│   ├── Program.cs                    Host builder and DI setup
│   ├── host.json                     Functions host configuration
│   ├── local.settings.json.example   Template for local secrets
│   ├── Functions/
│   │   ├── RecordsFunction.cs        POST /api/records (Table A insert)
│   │   ├── HistoryFunction.cs        GET  /api/history  (Table B read)
│   │   └── MetricsFunction.cs        GET  /api/metrics  (Table C aggregation)
│   └── Services/
│       └── DatabaseService.cs        OBO token exchange + SQL connection
├── client/                           React SPA frontend
│   ├── package.json
│   ├── tsconfig.json
│   ├── vite.config.ts
│   ├── index.html
│   ├── .env.example                  Template for frontend env vars
│   └── src/
│       ├── main.tsx                  Entry point, MSAL provider
│       ├── App.tsx                   Auth gate + tab navigation
│       ├── App.css                   Styles
│       ├── authConfig.ts             MSAL configuration
│       ├── components/
│       │   ├── Dashboard.tsx         Metrics KPI cards + charts (auto-refresh)
│       │   ├── RecordForm.tsx        Form to insert into Table A
│       │   └── HistoryTable.tsx      Table showing Table B rows
│       └── services/
│           └── apiClient.ts          Token acquisition + API calls
├── staticwebapp.config.json          SWA routing and auth config
├── setup.sql                         SQL DDL + user/permission grants
├── .github/
│   └── workflows/
│       └── azure-static-web-apps.yml CI/CD pipeline
├── .gitignore
└── README.md

Deployment

GitHub Actions

  1. In the Azure Portal, go to your Static Web App and copy the deployment token from the Overview page.

  2. In your GitHub repo, go to Settings > Secrets and variables > Actions and create these secrets:

    Secret Name Value
    AZURE_STATIC_WEB_APPS_API_TOKEN Deployment token from the SWA resource
    VITE_TENANT_ID Your Entra tenant ID
    VITE_FRONTEND_CLIENT_ID Frontend SPA app registration client ID
    VITE_BACKEND_CLIENT_ID Backend API app registration client ID
  3. Optionally, create a repository variable (not secret):

    Variable Name Value
    VITE_REFRESH_INTERVAL_SECONDS 60
  4. Set the backend environment variables in the SWA resource:

    az staticwebapp appsettings set \
      --name <your-swa-name> \
      --resource-group <your-rg> \
      --setting-names \
        TENANT_ID=<value> \
        BACKEND_CLIENT_ID=<value> \
        BACKEND_CLIENT_SECRET=<value> \
        AZURE_SQL_CONNSTR="Server=tcp:yourserver.database.windows.net,1433;Database=yourdb;Encrypt=True;TrustServerCertificate=False;"
  5. Push to main. The workflow triggers automatically.

Manual Deployment

# Build frontend
cd client
npm ci
npm run build

# Deploy
swa deploy client/dist --api-location api --deployment-token <YOUR_TOKEN>

Configuration Reference

Backend (api/local.settings.json)

Key Description
TENANT_ID Microsoft Entra ID tenant ID
BACKEND_CLIENT_ID Client ID of the Backend API app registration
BACKEND_CLIENT_SECRET Client secret for the Backend API app registration
AZURE_SQL_CONNSTR SQL connection string, no username/password (token injected at runtime)

Frontend (client/.env)

Key Description
VITE_TENANT_ID Microsoft Entra ID tenant ID
VITE_FRONTEND_CLIENT_ID Client ID of the Frontend SPA app registration
VITE_BACKEND_CLIENT_ID Client ID of the Backend API app registration
VITE_REFRESH_INTERVAL_SECONDS Dashboard auto-refresh interval in seconds (default: 60)

Customization

Tables and Columns

The table names and column names are defined as constants at the top of each function file in api/Functions/. The SQL aggregation query in MetricsFunction.cs can be modified to match your actual schema.

Dashboard Metrics

The dashboard layout, KPI cards, and chart types are defined in client/src/components/Dashboard.tsx. The component uses Recharts for visualization. Modify the JSX and chart configuration to match your data shape.

Refresh Interval

Set VITE_REFRESH_INTERVAL_SECONDS in client/.env (local) or as a GitHub Actions variable (CI). The dashboard polls the /api/metrics endpoint at this interval.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages