Azure-Samples / ms-identity-python-webapp

A Python web application calling Microsoft graph that is secured using the Microsoft identity platform
MIT License
293 stars 140 forks source link

how to incorporate this in an existing python flask #50

Closed SSASI74 closed 1 year ago

SSASI74 commented 3 years ago

i have written an python flask app in visual studio, which i want to add ms-identity-python-webapp to:

the app sample works correctly on its own

so i added the app.py code to my views.py

and added the config files and the html files from the sample to my visual studio solution.

is that the wrong way to do it?

really need help, im sure its something simple, my app works and the sample works, how do i put them together?

here is the start of my views.py

""" Routes and views for the flask application. """ from CDK_Auth import AccessCode import requests import json from flask import request

from datetime import datetime from flask import render_template, session, redirect, url_for from FlaskSSASI import app import urllib3 import os import getpass import msal

import uuid

from flask import Flask, render_template, session, request, redirect, url_for from flask_session import Session # https://pythonhosted.org/Flask-Session

import app_config

app = Flask(name) app.config.from_object(app_config) Session(app)

from werkzeug.middleware.proxy_fix import ProxyFix app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)

@app.route('/')

def index(): if not session.get("user"): return redirect(url_for("login")) return render_template('index.html', user=session["user"], version=msal.version)

@app.route("/login") def login(): session["state"] = str(uuid.uuid4())

Technically we could use empty list [] as scopes to do just sign in,

# here we choose to also collect end user consent upfront
auth_url = _build_auth_url(scopes=app_config.SCOPE, state=session["state"])
return render_template("login.html", auth_url=auth_url, version=msal.__version__)

@app.route(app_config.REDIRECT_PATH) # Its absolute URL must match your app's redirect_uri set in AAD def authorized(): if request.args.get('state') != session.get("state"): return redirect(url_for("index")) # No-OP. Goes back to Index page if "error" in request.args: # Authentication/Authorization failure return render_template("auth_error.html", result=request.args) if request.args.get('code'): cache = _load_cache() result = _build_msal_app(cache=cache).acquire_token_by_authorization_code( request.args['code'], scopes=app_config.SCOPE, # Misspelled scope would cause an HTTP 400 error here redirect_uri=url_for("authorized", _external=True)) if "error" in result: return render_template("auth_error.html", result=result) session["user"] = result.get("id_token_claims") _save_cache(cache) return redirect(url_for("index"))

@app.route("/logout") def logout(): session.clear() # Wipe out user and its token cache from session return redirect( # Also logout from your tenant's web session app_config.AUTHORITY + "/oauth2/v2.0/logout" + "?post_logout_redirect_uri=" + url_for("index", _external=True))

@app.route("/graphcall") def graphcall(): token = _get_token_from_cache(app_config.SCOPE) if not token: return redirect(url_for("login")) graph_data = requests.get( # Use token to call downstream service app_config.ENDPOINT, headers={'Authorization': 'Bearer ' + token['access_token']}, ).json() return render_template('display.html', result=graph_data)

def _load_cache(): cache = msal.SerializableTokenCache() if session.get("token_cache"): cache.deserialize(session["token_cache"]) return cache

def _save_cache(cache): if cache.has_state_changed: session["token_cache"] = cache.serialize()

def _build_msal_app(cache=None, authority=None): return msal.ConfidentialClientApplication( app_config.CLIENT_ID, authority=authority or app_config.AUTHORITY, client_credential=app_config.CLIENT_SECRET, token_cache=cache)

def _build_auth_url(authority=None, scopes=None, state=None): return _build_msal_app(authority=authority).get_authorization_request_url( scopes or [], state=state or str(uuid.uuid4()), redirect_uri=url_for("authorized", _external=True))

def _get_token_from_cache(scope=None): cache = _load_cache() # This web app maintains one cache per session cca = _build_msal_app(cache=cache) accounts = cca.get_accounts() if accounts: # So all account(s) belong to the current signed-in user result = cca.acquire_token_silent(scope, account=accounts[0]) _save_cache(cache) return result

app.jinja_env.globals.update(_build_auth_url=_build_auth_url) # Used in template

if name == "main": app.run()

@app.route('/home')

def home():

"""Renders the home page."""

return render_template(

'indexOLD.html',

title='Home Page',

year=datetime.now().year,

user=MSAL23.result.json(),

)

@app.route('/contact') def contact(): """Renders the contact page.""" return render_template( 'contact.html', title='Contact', year=datetime.now().year, message='Your contact page.' )

@app.route('/service') def service(): """Renders the about page.""" return render_template( 'service.html', title='Service', year=datetime.now().year, message='This is SSASI Service Portal' )

@app.route('/OrderLog') def OrderLog(): """Renders the about page.""" return render_template( 'OrderLog.html', title='Order Log', year=datetime.now().year, message='This is SSASI Sales Portal' )

rayluo commented 3 years ago

Q: How to incorporate this sample into an existing python flask app?

i have written an python flask app in visual studio, which i want to add ms-identity-python-webapp to:

the app sample works correctly on its own

so i added the app.py code to my views.py

and added the config files and the html files from the sample to my visual studio solution.

is that the wrong way to do it?

really need help, im sure its something simple, my app works and the sample works, how do i put them together?

Dear customer, we hear you. Rest assured, you are not alone. Merging two separately developed projects is not always as straightforward as we want it to be. You would need to understand both projects well, in order to cherry-pick parts and fit them together. This ms-identity-python-webapp sample app here tries to make it easier for you, by being a minimalist app which does not even use css or UI layout etc.. In that sense, all the parts in this sample, including logic in its html pages, are necessary for it to function purposely. If you are adding this sample into your existing project, add ALL content (except helper scripts in AppCreationScripts and ReadmeFiles, of course).

Meanwhile, this sample was developed to be a self-contained template. If you start from this template and build your business logic on top of it, create your new project using our sample as a template, by visiting this sample's repo homepage, clicking the green "Use this template" button, and then adding your app's logic little by little, it would probably be a smooth ride.

Use this template

P.S.: With regard to another question "is there a way to create a new visual studio solution from the sample ?" below, please create a standalone github issue for it.

SSASI74 commented 3 years ago

hi rayluo is there a way to create a new visual studio solution from the sample ?

rayluo commented 3 years ago

This sample was not previously developed inside visual studio. We will need to take a look into this. Thanks for providing this good idea!

For now, if you are trying to avoid the "Use this template" route that I mentioned 2 days ago, you may also try to download this sample as a zip file, unzip it, and then just use it as-is inside visual studio.

phelimo commented 3 years ago

Hi rayluo,

Checking if you had any luck finding a sample developed inside VS?

Thanks, Phelim

rayluo commented 3 years ago

@phelimo, I am not aware of one, but we would love to take a look into this in future.