#!/bin/bash # MS Entra (Azure AD) Setup Script for Miracles In Motion # This script helps configure Azure AD authentication for the application set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration APP_NAME="Miracles In Motion Web App" DOMAIN="miraclesinmotion.org" STATIC_WEB_APP_NAME="${STATIC_WEB_APP_NAME:-mim-prod-web}" AZURE_RESOURCE_GROUP="${AZURE_RESOURCE_GROUP:-rg-miraclesinmotion-prod}" echo -e "${GREEN}🔐 MS Entra (Azure AD) Setup Script${NC}" echo "==========================================" echo "" # Check if Azure CLI is installed if ! command -v az &> /dev/null; then echo -e "${RED}❌ Azure CLI not found. Please install it first.${NC}" echo "Install from: https://docs.microsoft.com/cli/azure/install-azure-cli" exit 1 fi # Check if logged in to Azure echo -e "${BLUE}📋 Checking Azure login status...${NC}" CURRENT_USER=$(az account show --query "user.name" -o tsv 2>/dev/null || echo "") if [ -z "$CURRENT_USER" ]; then echo -e "${YELLOW}⚠️ Not logged in to Azure. Please log in...${NC}" az login CURRENT_USER=$(az account show --query "user.name" -o tsv) fi echo -e "${GREEN}✅ Logged in as: $CURRENT_USER${NC}" echo "" # Get Azure Static Web App URL echo -e "${BLUE}📋 Getting Azure Static Web App information...${NC}" AZURE_STATIC_WEB_APP_URL=$(az staticwebapp show \ --name "$STATIC_WEB_APP_NAME" \ --resource-group "$AZURE_RESOURCE_GROUP" \ --query "defaultHostname" -o tsv 2>/dev/null || echo "") if [ -z "$AZURE_STATIC_WEB_APP_URL" ]; then echo -e "${YELLOW}⚠️ Static Web App not found. Using default URL format.${NC}" AZURE_STATIC_WEB_APP_URL="${STATIC_WEB_APP_NAME}.azurestaticapps.net" fi FULL_STATIC_WEB_APP_URL="https://${AZURE_STATIC_WEB_APP_URL}" PRODUCTION_URL="https://${DOMAIN}" WWW_URL="https://www.${DOMAIN}" echo -e "${GREEN}✅ Static Web App URL: $FULL_STATIC_WEB_APP_URL${NC}" echo "" # Get Tenant ID TENANT_ID=$(az account show --query "tenantId" -o tsv) echo -e "${GREEN}✅ Tenant ID: $TENANT_ID${NC}" echo "" # Check if app registration already exists echo -e "${BLUE}🔍 Checking for existing app registration...${NC}" EXISTING_APP_ID=$(az ad app list --display-name "$APP_NAME" --query "[0].appId" -o tsv 2>/dev/null || echo "") if [ -n "$EXISTING_APP_ID" ] && [ "$EXISTING_APP_ID" != "null" ]; then echo -e "${YELLOW}⚠️ App registration already exists: $EXISTING_APP_ID${NC}" read -p "Do you want to update it? (y/n): " UPDATE_APP if [ "$UPDATE_APP" != "y" ]; then APP_ID=$EXISTING_APP_ID echo -e "${GREEN}✅ Using existing app registration${NC}" else echo -e "${BLUE}📝 Updating app registration...${NC}" APP_ID=$EXISTING_APP_ID fi else # Create app registration echo -e "${BLUE}📝 Creating app registration...${NC}" APP_ID=$(az ad app create \ --display-name "$APP_NAME" \ --sign-in-audience "AzureADMultipleOrgs" \ --web-redirect-uris "$PRODUCTION_URL" "$WWW_URL" "$FULL_STATIC_WEB_APP_URL" \ --query "appId" -o tsv) echo -e "${GREEN}✅ App registration created: $APP_ID${NC}" fi echo "" # Update redirect URIs echo -e "${BLUE}📝 Updating redirect URIs...${NC}" az ad app update --id "$APP_ID" \ --web-redirect-uris "$PRODUCTION_URL" "$WWW_URL" "$FULL_STATIC_WEB_APP_URL" \ --enable-id-token-issuance true \ --enable-access-token-issuance false \ --query "appId" -o tsv > /dev/null echo -e "${GREEN}✅ Redirect URIs updated${NC}" echo " - $PRODUCTION_URL" echo " - $WWW_URL" echo " - $FULL_STATIC_WEB_APP_URL" echo "" # Configure API permissions echo -e "${BLUE}📝 Configuring API permissions...${NC}" # Microsoft Graph permissions GRAPH_PERMISSIONS=( "User.Read" "User.ReadBasic.All" "email" "openid" "profile" ) GRAPH_RESOURCE_ID=$(az ad sp show --id "00000003-0000-0000-c000-000000000000" --query "id" -o tsv) for PERMISSION in "${GRAPH_PERMISSIONS[@]}"; do PERMISSION_ID=$(az ad sp show --id "00000003-0000-0000-c000-000000000000" --query "oauth2PermissionScopes[?value=='$PERMISSION'].id" -o tsv) if [ -n "$PERMISSION_ID" ]; then echo " Adding permission: $PERMISSION" az ad app permission add \ --id "$APP_ID" \ --api "00000003-0000-0000-c000-000000000000" \ --api-permissions "$PERMISSION_ID=Scope" \ --query "appId" -o tsv > /dev/null 2>&1 || echo " (may already exist)" fi done echo -e "${GREEN}✅ API permissions configured${NC}" echo "" # Create app roles echo -e "${BLUE}📝 Creating app roles...${NC}" # Function to create app role create_app_role() { local role_name=$1 local role_value=$2 local role_description=$3 echo " Creating role: $role_name" local role_json=$(cat </dev/null || echo "") if [ -z "$role_exists" ]; then # Add new role to existing roles local updated_roles=$(echo "$existing_roles" | jq ". + [$role_json]") az ad app update --id "$APP_ID" --app-roles "$updated_roles" > /dev/null 2>&1 echo " ✅ Role created" else echo " ⚠️ Role already exists" fi } # Create app roles create_app_role "Admin" "Admin" "Administrator access to all features" create_app_role "Volunteer" "Volunteer" "Volunteer access to assigned tasks" create_app_role "Resource" "Resource" "Resource provider access" echo -e "${GREEN}✅ App roles created${NC}" echo "" # Create service principal echo -e "${BLUE}📝 Creating service principal...${NC}" SP_ID=$(az ad sp create --id "$APP_ID" --query "id" -o tsv 2>/dev/null || \ az ad sp show --id "$APP_ID" --query "id" -o tsv) echo -e "${GREEN}✅ Service principal created: $SP_ID${NC}" echo "" # Grant admin consent (requires admin privileges) echo -e "${BLUE}📝 Granting admin consent for API permissions...${NC}" read -p "Do you have admin privileges to grant consent? (y/n): " HAS_ADMIN if [ "$HAS_ADMIN" == "y" ]; then az ad app permission admin-consent --id "$APP_ID" && \ echo -e "${GREEN}✅ Admin consent granted${NC}" || \ echo -e "${YELLOW}⚠️ Could not grant admin consent. You may need to do this manually.${NC}" else echo -e "${YELLOW}⚠️ Skipping admin consent. Please grant consent manually in Azure Portal.${NC}" echo " Go to: Azure Portal → Microsoft Entra ID → App registrations → $APP_NAME → API permissions → Grant admin consent" fi echo "" # Create client secret (optional) echo -e "${BLUE}📝 Client Secret Configuration...${NC}" read -p "Do you want to create a client secret? (y/n): " CREATE_SECRET if [ "$CREATE_SECRET" == "y" ]; then SECRET_NAME="Miracles In Motion Secret $(date +%Y%m%d)" SECRET=$(az ad app credential reset --id "$APP_ID" --display-name "$SECRET_NAME" --years 2 --query "password" -o tsv) echo -e "${GREEN}✅ Client secret created${NC}" echo -e "${RED}⚠️ IMPORTANT: Save this secret now - it won't be shown again!${NC}" echo "Secret: $SECRET" echo "" read -p "Press Enter to continue after saving the secret..." else echo -e "${YELLOW}⚠️ Skipping client secret creation${NC}" SECRET="" fi echo "" # Store configuration in Key Vault (if available) echo -e "${BLUE}📝 Storing configuration in Key Vault...${NC}" KEY_VAULT_NAME=$(az keyvault list --resource-group "$AZURE_RESOURCE_GROUP" --query "[0].name" -o tsv 2>/dev/null || echo "") if [ -n "$KEY_VAULT_NAME" ]; then echo "Storing in Key Vault: $KEY_VAULT_NAME" az keyvault secret set \ --vault-name "$KEY_VAULT_NAME" \ --name "azure-client-id" \ --value "$APP_ID" > /dev/null 2>&1 && echo -e "${GREEN}✅ Client ID stored${NC}" || echo -e "${YELLOW}⚠️ Could not store Client ID${NC}" az keyvault secret set \ --vault-name "$KEY_VAULT_NAME" \ --name "azure-tenant-id" \ --value "$TENANT_ID" > /dev/null 2>&1 && echo -e "${GREEN}✅ Tenant ID stored${NC}" || echo -e "${YELLOW}⚠️ Could not store Tenant ID${NC}" if [ -n "$SECRET" ]; then az keyvault secret set \ --vault-name "$KEY_VAULT_NAME" \ --name "azure-client-secret" \ --value "$SECRET" > /dev/null 2>&1 && echo -e "${GREEN}✅ Client Secret stored${NC}" || echo -e "${YELLOW}⚠️ Could not store Client Secret${NC}" fi else echo -e "${YELLOW}⚠️ Key Vault not found. Skipping secret storage.${NC}" fi echo "" # Summary echo -e "${GREEN}✅ MS Entra Setup Complete!${NC}" echo "==================================" echo "" echo "Configuration Summary:" echo " App Registration ID: $APP_ID" echo " Tenant ID: $TENANT_ID" echo " Service Principal ID: $SP_ID" echo "" echo "Redirect URIs:" echo " - $PRODUCTION_URL" echo " - $WWW_URL" echo " - $FULL_STATIC_WEB_APP_URL" echo "" echo "App Roles:" echo " - Admin" echo " - Volunteer" echo " - Resource" echo "" echo "Next Steps:" echo "1. Assign users to app roles in Azure Portal" echo "2. Update staticwebapp.config.json with authentication configuration" echo "3. Update application code to use Azure AD authentication" echo "4. Test authentication flow" echo "" echo "Azure Portal Links:" echo " App Registration: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Overview/appId/$APP_ID" echo " API Permissions: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/CallAnAPI/appId/$APP_ID" echo " App Roles: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/AppRoles/appId/$APP_ID" echo "" # Export variables for use in other scripts cat > .azure-entra-config.env <