Skip to content

How to deploy to App Service #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
FLASK_DEBUG=True
# Note: If you are using Azure App Service, go to your app's Configuration,
# and then set the following values into your app's "Application settings".

CLIENT_ID=<client id>
CLIENT_SECRET=<client secret>

# Expects a full tenant id such as "contoso.onmicrosoft.com", or its GUID
# Or leave it undefined if you are building a multi-tenant app
#TENANT_ID=<tenant id>
CLIENT_ID=<client id>
CLIENT_SECRET=<client secret>
9 changes: 5 additions & 4 deletions .env.sample.b2c
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
FLASK_DEBUG=True
# Expects the display name such as "contoso"
TENANT_NAME=<tenant name>
# Note: If you are using Azure App Service, go to your app's Configuration,
# and then set the following values into your app's "Application settings".
CLIENT_ID=<client id>
CLIENT_SECRET=<client secret>
# Expects the display name such as "contoso"
TENANT_NAME=<tenant name>
SIGNUPSIGNIN_USER_FLOW=B2C_1_profile_editing
EDITPROFILE_USER_FLOW=B2C_1_reset_password
RESETPASSWORD_USER_FLOW=B2C_1_signupsignin1
RESETPASSWORD_USER_FLOW=B2C_1_signupsignin1
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ To get started with this sample, you have two options:
[Quickstart: Add sign-in with Microsoft to a Python web app](https://docs.microsoft.com/azure/active-directory/develop/web-app-quickstart?pivots=devlang-python).
* Use PowerShell scripts that automatically create the Azure AD applications and related objects (passwords, permissions, dependencies) for you, and then modify the configuration files. Follow the steps in the [App Creation Scripts README](./AppCreationScripts/AppCreationScripts.md).

# Deployment

Once you finish testing this web app locally, you can deploy it to your production.
You may choose any web app hosting services you want.
Here we will describe how to deploy it to
[Azure App Service](https://azure.microsoft.com/en-us/products/app-service).

* Follow the ["Quickstart: Deploy a Python (Django or Flask) web app to Azure App Service"](https://learn.microsoft.com/en-us/azure/app-service/quickstart-python),
but replace its sample app (which does not do user sign-in) with this web app.

* In particular, if you choose to ["deploy using Local Git" in "step 3 - Deploy your application code to Azure"](https://learn.microsoft.com/en-us/azure/app-service/quickstart-python?tabs=flask%2Cwindows%2Cazure-cli%2Clocal-git-deploy%2Cdeploy-instructions-azportal%2Cterminal-bash%2Cdeploy-instructions-zip-azcli#3---deploy-your-application-code-to-azure),
an [application-scope credential](https://learn.microsoft.com/en-us/azure/app-service/deploy-configure-credentials?tabs=portal#appscope)
will be automatically created with the shape as `your_app_name\$your_app_name`.
But your actual git username is only the `$your_app_name` part.

* [Configure your app's settings](https://learn.microsoft.com/en-us/azure/app-service/configure-common?tabs=portal#configure-app-settings) to define [these environment variables](https://github.com/Azure-Samples/ms-identity-python-webapp/blob/master/.env.sample).


## Contributing

If you find a bug in the sample, please raise the issue on [GitHub Issues](../../issues).
Expand Down
4 changes: 4 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ def logout():

@app.route("/")
def index():
if not (app.config["CLIENT_ID"] and app.config["CLIENT_SECRET"]):
# This check is not strictly necessary.
# You can remove this check from your production code.
return render_template('config_error.html')
if not auth.get_user():
return redirect(url_for("login"))
return render_template('index.html', user=auth.get_user(), version=identity.__version__)
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Flask>=2
# Our how-to docs will use --debug parameter which is only available in Flask 2.2+
Flask>=2.2
# If Flask-Session is not maintained in future, Flask-Session2 should work as well
Flask-Session>=0.3.2,<0.5
werkzeug>=2
Expand Down
3 changes: 1 addition & 2 deletions templates/auth_error.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
<html lang="en">
<head>
<meta charset="UTF-8">

{% if config.get("B2C_RESET_PASSWORD_AUTHORITY") and "AADB2C90118" in result.get("error_description") %} <!-- This will be reached when user forgot their password -->
<!-- See also https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-policies#linking-user-flows -->
<meta http-equiv="refresh" content='0;{{config.get("B2C_RESET_PASSWORD_AUTHORITY")}}?client_id={{config.get("CLIENT_ID")}}'>
{% endif %}
<title>Microsoft Identity Python Web App: Error</title>
</head>
<body>
<h2>Login Failure</h2>
Expand All @@ -18,4 +18,3 @@ <h2>Login Failure</h2>
<a href="{{ url_for('index') }}">Homepage</a>
</body>
</html>

18 changes: 18 additions & 0 deletions templates/config_error.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Microsoft Identity Python Web App: Error</title>
</head>
<body>
<h2>Config Missing</h2>
<p>
Almost there. Did you forget to set up
<a target=_blank
href="https://learn.microsoft.com/azure/active-directory/develop/web-app-quickstart?pivots=devlang-python#step-5-configure-the-sample-app">
necessary environment variables</a> for your deployment?
</p>
<hr>
<a href="{{ url_for('index') }}">Homepage</a>
</body>
</html>
1 change: 1 addition & 0 deletions templates/display.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Microsoft Identity Python Web App: API</title>
</head>
<body>
<a href="javascript:window.history.go(-1)">Back</a> <!-- Displayed on top of a potentially large JSON response, so it will remain visible -->
Expand Down
4 changes: 4 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Microsoft Identity Python Web App: Index</title>
</head>
<body>
<h1>Microsoft Identity Python Web App</h1>
<h2>Welcome {{ user.get("name") }}!</h2>

<ul>
{% if config.get("ENDPOINT") %}
<li><a href='/call_downstream_api'>Call a downstream API</a></li>
{% endif %}
Expand All @@ -16,6 +18,8 @@ <h2>Welcome {{ user.get("name") }}!</h2>
{% endif %}

<li><a href="/logout">Logout</a></li>
</ul>

<hr>
<footer style="text-align: right">Powered by Identity Web {{ version }}</footer>
</body>
Expand Down
15 changes: 8 additions & 7 deletions templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,25 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Microsoft Identity Python Web App: Login</title>
</head>
<body>
<h1>Microsoft Identity Python Web App</h1>

{% if user_code %}
<ol>
<li>To sign in, type <b>{{ user_code }}</b> into
<a href='{{ auth_uri }}' target=_blank>{{ auth_uri }}</a>
to authenticate.
</li>
<li>And then <a href="{{ url_for('auth_response') }}">proceed</a>.</li>
<li>To sign in, type <b>{{ user_code }}</b> into
<a href='{{ auth_uri }}' target=_blank>{{ auth_uri }}</a>
to authenticate.
</li>
<li>And then <a href="{{ url_for('auth_response') }}">proceed</a>.</li>
</ol>
{% else %}
<li><a href='{{ auth_uri }}'>Sign In</a></li>
<ul><li><a href='{{ auth_uri }}'>Sign In</a></li></ul>
{% endif %}

{% if config.get("B2C_RESET_PASSWORD_AUTHORITY") %}
<li><a href="{{config.get('B2C_RESET_PASSWORD_AUTHORITY')}}?client_id={{config.get('CLIENT_ID')}}">Reset Password</a></li>
<a href="{{config.get('B2C_RESET_PASSWORD_AUTHORITY')}}?client_id={{config.get('CLIENT_ID')}}">Reset Password</a>
{% endif %}

<hr>
Expand Down