/active-directory-python-webapp-graphapi-msi-kv

A Python Web App calling the Microsoft Graph API, leveraging ADAL Python, MSI and Key Vault

Primary LanguagePowerShellMIT LicenseMIT

services platforms author level client service endpoint
active-directory
python
abpati
200
Python Web App
Microsoft Graph
AAD V1

About this repo

This repo is forked from Azure-Samples/active-directory-python-webapp-graphapi.

This app runs on Azure VM and uses MSI and Key Vault, instead of putting the credentials in the code.

  1. Run the commands below. (Same thing can be done also in Azure Portal.)
$ResourceGroupName = "ResourceGroupName"
$VmName = "VmName"
$VaultName = "VaultName"
$SecretName = "testapp"
$Secret = '{"client_id": "CLIENT_ID", "client_secret": "CLIENT_SECRET"}'

# Connect to Azure Resource Manager
Connect-AzureRmAccount

# Create a key vault
New-AzureRmKeyVault -VaultName $VaultName -ResourceGroupName $ResourceGroupName -Location 'East US'

# Create a key vault access policy permitting your VM to get secrets
$VmPrincipalId = (Get-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $VmName).Identity.PrincipalId
Set-AzureRmKeyVaultAccessPolicy -VaultName $VaultName -ObjectId $VmPrincipalId  -PermissionsToSecrets get

# Create your app's secret
$SecureSecret = ConvertTo-SecureString -String $Secret -AsPlainText -Force
Set-AzureKeyVaultSecret -VaultName $VaultName -Name $SecretName -SecretValue $SecureSecret
  1. Install Key Vault module
$ pip install azure-keyvault
  1. Set VAULT_URL and APP_SECRET_NAME in config.py.

Calling Microsoft Graph from a web app using ADAL Python

About this sample

Overview

This sample demonstrates how to build a Python (Flask) web application that authorizes Azure Active Directory users and access data from the Microsoft Graph.

  1. The app uses the Active Directory Authentication Library (ADAL) to acquire a JWT access token for the Microsoft Graph.
  2. The app then uses the access token to get data about the user from the Microsoft Graph.

Overview

How to run this sample

To run this sample, you'll need:

Step 1. Clone or download this repository

From your shell or command line:

git clone https://github.com/Azure-Samples/active-directory-python-webapp-graphapi

To avoid file name length limitations in Windows, clone the repo close to your root directory.

Step 2. Register the app

To register the sample, you can:

  • either follow the steps in the paragraphs below (Step 2 and Step 3)
  • or use PowerShell scripts that:
    • automatically create for you the Azure AD applications and related objects (passwords, permissions, dependencies)
    • modify the configuration file of your project.

If you want to use this automation, read the instructions in App Creation Scripts

Choose your tenant

  1. Sign in to the Azure portal.
  2. On the top bar, click on your account, and then on Switch Directory.
  3. Once the Directory + subscription pane opens, choose the Active Directory tenant where you wish to register your application, from the Favorites or All Directories list.
  4. Click on All services in the left-hand nav, and choose Azure Active Directory.

In the next steps, you might need the tenant name (or directory name) or the tenant ID (or directory ID). These are presented in the Properties of the Azure Active Directory window respectively as Name and Directory ID

Register the app

  1. In the Azure Active Directory pane, click on App registrations and choose New application registration.

  2. Enter a friendly name for the application, for example 'PythonWebApp' and select 'Web app / API' as the Application Type.

  3. For the sign-on URL, enter the base URL for the sample. By default, this sample uses http://localhost:5000/.

  4. Click Create to create the application.

  5. In the succeeding page, Find the Application ID value and record it for later.

  6. Then click on Settings, and choose Properties.

  7. For the App ID URI, replace the guid in the generated URI 'https://<your_tenant_name>/<guid>', with the name of your service, for example, 'https://<your_tenant_name>/App' (replacing <your_tenant_name> with the name of your Azure AD tenant)

  8. From the Settings | Reply URLs page for your application, update the Reply URL for the application to be http://localhost:5000/getAToken

  9. From the Settings menu, choose Keys and add a new entry in the Password section:

    • Type a key description (of instance app secret),
    • Select a key duration of either In 1 year, In 2 years, or Never Expires.
    • When you save this page, the key value will be displayed, copy, and save the value in a safe location.
    • You'll need this key later to configure the project. This key value will not be displayed again, nor retrievable by any other means, so record it as soon as it is visible from the Azure portal.
  10. Configure Permissions for your application. In the Settings menu, choose the 'Required permissions' section and then, click on Add, then Select an API, and type Microsoft Graph in the textbox. Then, click on Select Permissions and underneath Delegated Permissions select Sign in and read user profile.

Step 3. Configure the sample

In the steps below, ClientID is the same as Application ID or AppId.

Open the config.py file to configure the project

Configure the app project

  1. Open the config.py file
  2. Find the app key TENANT and replace the existing value with your AAD tenant name.
  3. Find the app key CLIENT_SECRET and replace the existing value with the key you saved during the creation of the PythonWebApp app in the Azure portal.
  4. Find the app key CLIENT_ID and replace the existing value with the application ID (client ID) of the PythonWebApp application from the Azure portal.

Step 4. Run the sample

  • You will need to install Flask framework and the ADAL Python library using pip as follows:

    $ pip install flask
    $ pip install adal
  • If the environment variable for Flask is already set:

    Run app.py from shell or command line:

    $ python app.py
  • If the environment variable for Flask is not set:

    Type the following commands on shell or command line by navigating to the project directory:

    $ export FLASK_APP=app.py
    $ export FLASK_DEBUG=1
    $ flask run

Follow the sign-in process to complete the logging.

About the code

The code acquiring a token is located in app.py file. The sample first starts sign in by redirecting the application from @app.route("/") to @app/route("/login"). It forms an authorization url that goes to the Authorization endpoint here:

authorization_url = TEMPLATE_AUTHZ_URL.format(
        config.TENANT,
        config.CLIENT_ID,
        REDIRECT_URI,
        auth_state,
        config.RESOURCE)
resp = Response(status=307)
resp.headers['location']= authorization_url
return resp

After the user logs in, the authorization code is used acquire a token in @app.route("/getAToken"). The AuthenticationContext is created here:

auth_context = AuthenticationContext(AUTHORITY_URL, api_version=None)

The acquire_token_with_authorization_code() function requests for an access token using the authorization code here:

token_response = auth_context.acquire_token_with_authorization_code(code,REDIRECT_URI,config.RESOURCE, config.CLIENT_ID, config.CLIENT_SECRET)

This token is then used to call the Graph API in @app.route("/graphcall"):

graph_data = SESSION.get(endpoint,headers = http_headers, stream=False).json()

Community Help and Support

Use Stack Overflow to get support from the community. Ask your questions on Stack Overflow first and browse existing issues to see if someone has asked your question before. Make sure that your questions or comments are tagged with [adal python].

If you find a bug in the sample, please raise the issue on GitHub Issues.

To provide a recommendation, visit the following User Voice page.

Contributing

If you'd like to contribute to this sample, see CONTRIBUTING.MD.

This project has adopted the Microsoft Open Source Code of Conduct. For more information, see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

More information

For more information about how OAuth 2.0 protocols work in this scenario and other scenarios, see Authentication Scenarios for Azure AD.