A simple Flask web application that displays Microsoft Entra ID (Azure AD) profile pictures using Microsoft Graph API.
- π Microsoft Authentication (OAuth2)
- πΌοΈ Display user profile pictures from Azure Blob Storage
- π€ Show user profile information
- πΈ Gallery view with 4-6 images across
- π Browse individual profiles with navigation
- π€ NEW: CNN Classifier API for image categorization
- π― Categorize images as: human, avatar, or animal
- π¨ Clean, modern UI
- βοΈ Deployed to Azure App Service
- Python 3.13+
- Azure subscription
- Microsoft Entra ID (Azure AD) tenant
- Go to Azure Portal
- Navigate to Microsoft Entra ID (formerly Azure AD)
- Select App registrations β New registration
- Configure your app:
- Name:
ProfilePicApp(or your preferred name) - Supported account types: Choose appropriate option (single or multi-tenant)
- Redirect URI: Select
Weband enterhttp://localhost:5000/auth/callback
- Name:
- Click Register
- Note down the Application (client) ID and Directory (tenant) ID
- Go to Certificates & secrets β New client secret
- Add a description and select expiration period
- Copy the secret value immediately (you won't see it again!)
- Go to API permissions:
- Click Add a permission β Microsoft Graph β Delegated permissions
- Add:
User.ReadandUser.ReadBasic.All - Click Add permissions
- (Optional) Click Grant admin consent if required
-
Copy the example environment file:
Copy-Item .env.example .env -
Edit
.envfile with your Azure app details:CLIENT_ID=your-application-client-id CLIENT_SECRET=your-client-secret-value TENANT_ID=your-directory-tenant-id FLASK_SECRET_KEY=your-random-secret-key REDIRECT_URI=http://localhost:5000/auth/callback -
Generate a secure Flask secret key (optional but recommended):
.\venv\Scripts\Activate.ps1 python -c "import secrets; print(secrets.token_hex(32))"
# Activate virtual environment
.\venv\Scripts\Activate.ps1
# Install packages (already done if you followed setup)
pip install -r requirements.txt# Make sure virtual environment is activated
.\venv\Scripts\Activate.ps1
# Run the Flask app
python app.pyVisit http://localhost:5000 in your browser.
profilepicapp/
βββ app.py # Main Flask application
βββ config.py # Configuration settings
βββ requirements.txt # Main app dependencies
βββ profile_upload_map.csv # User to image mapping
βββ .env.example # Example environment variables
βββ .gitignore # Git ignore rules
β
βββ templates/ # HTML templates
β βββ index.html # Login page
β βββ profile.html # Home page with links
β βββ gallery.html # Multi-image grid view
β βββ browse.html # Single profile navigation
β
βββ scripts/ # PowerShell scripts
β βββ Create-EntraTestUsers.ps1 # Create test users
β βββ Upload-ProfilePhotos-ToStorage.ps1
β βββ Shuffle-ProfilePhotos.ps1 # Randomize assignments
β βββ test_images/ # Training images (101 images)
β βββ human/ # 51 diverse human faces
β βββ avatar/ # 25 cartoon faces
β βββ animal/ # 25 cat/dog images
β
βββ models/ # CNN model directory
β βββ README.md # Model specifications
β βββ .gitkeep # (Add your .keras file here)
β
βββ classifier_api.py # CNN classifier Flask API
βββ classifier_requirements.txt # Classifier dependencies
βββ test_classifier_api.py # API test client
βββ setup_classifier.py # Automated setup script
βββ train_model_example.py # Model training template
βββ CLASSIFIER_API.md # Full API documentation
βββ QUICKSTART.md # Quick start guide
β
βββ venv/ # Virtual environment (not in git)
-
Login to Azure CLI:
az login
-
Create a resource group:
az group create --name profilepic-rg --location eastus
-
Create an App Service Plan:
az appservice plan create --name profilepic-plan --resource-group profilepic-rg --sku B1 --is-linux
-
Create the Web App:
az webapp create --resource-group profilepic-rg --plan profilepic-plan --name your-unique-app-name --runtime "PYTHON:3.13"
-
Configure environment variables:
az webapp config appsettings set --resource-group profilepic-rg --name your-unique-app-name --settings CLIENT_ID="your-client-id" CLIENT_SECRET="your-client-secret" TENANT_ID="your-tenant-id" FLASK_SECRET_KEY="your-secret-key" REDIRECT_URI="https://your-unique-app-name.azurewebsites.net/auth/callback"
-
Update Azure App Registration:
- Go back to your app registration in Azure Portal
- Add the production redirect URI:
https://your-unique-app-name.azurewebsites.net/auth/callback
-
Deploy the app:
# Using Azure CLI az webapp up --resource-group profilepic-rg --name your-unique-app-name --runtime "PYTHON:3.13"
Coming soon...
- Make sure you've created a
.envfile from.env.example - Verify all required values are filled in
- Check that your Client ID, Client Secret, and Tenant ID are correct
- Verify the redirect URI matches exactly in both
.envand Azure app registration - Ensure API permissions are granted in Azure Portal
- Some users may not have profile photos set in Entra ID
- The app will show a placeholder image in this case
- Never commit
.envfile to git (it's in.gitignore) - Use different secrets for development and production
- Rotate client secrets regularly
- Use managed identities when possible in Azure
This project includes a separate Flask API for classifying profile pictures using a CNN model.
-
Setup the classifier environment:
python setup_classifier.py
-
Add your trained model to
models/directory:- Place
profile_classifier.kerasorprofile_classifier.h5 - Or use mock predictions for testing
- Place
-
Start the classifier API:
python classifier_api.py
-
Test the API:
python test_classifier_api.py
- Full API docs: CLASSIFIER_API.md
- Quick start: QUICKSTART.md
- Model specs: models/README.md
GET /api/health- Check API and model statusPOST /api/classify- Classify uploaded image filePOST /api/classify/url- Classify image from URL
The API expects a trained CNN model with:
- Input: (128, 128, 3) RGB images
- Output: (3,) probabilities for [animal, avatar, human]
- Format:
.kerasor.h5file
See train_model_example.py for a training template.
The project includes 121 test users with profile pictures:
- 51 human faces: Diverse faces from FairFace dataset (ages 18-70)
- 25 avatars: Cartoon human faces from CartoonSet100k
- 25 animals: Cat and dog images
- 20 no picture: Accounts without profile photos
Images are stored in Azure Blob Storage and mapped in profile_upload_map.csv.
- Flask 3.1.0 - Web framework
- MSAL 1.31.1 - OAuth2 authentication
- TensorFlow 2.18.0 - CNN model framework
- Pillow 11.0.0 - Image preprocessing
- Azure Blob Storage - Profile picture hosting
- Microsoft Entra ID - User authentication
- Azure App Service - Production hosting
- Main App: https://profilepicapp-c2p7wl.azurewebsites.net
- Storage: profilepicsto7826.blob.core.windows.net
- Tenant: lobralicloud.onmicrosoft.com
MIT License