Yes this is absolutely possible. I do these steps in my GitHub sample here.
Some relevant Code Snippets:
authentication.py
import requests
import appconfig as g
def create_headers(access_token):
return {
'Authorization': 'Bearer ' + access_token,
'Accept': 'application/json',
'Content-Type': 'application/json'
}
def login_url(state, redirect_uri, tenant_id='common'):
params = {
'url': g.aad_endpoint + tenant_id + '/oauth2/authorize',
'response_type': 'code',
'client_id': g.clientId,
'redirect_uri': redirect_uri,
'state': state
}
login_url = '%(url)s?response_type=%(response_type)s&client_id=%(client_id)s&redirect_uri=%(redirect_uri)s&state=%(state)s' %params
return login_url
def get_access_token_code(code, redirect_uri, resource, tenant_id='common'):
payload = {
'client_id': g.clientId,
'code': code,
'grant_type': 'authorization_code',
'redirect_uri': redirect_uri,
'resource': resource,
'client_secret': g.clientSecret
}
token_endpoint = g.aad_endpoint + tenant_id + '/oauth2/token'
r = requests.post(token_endpoint, data=payload)
return r.json()['access_token']
def get_access_token_app(resource, tenant_id):
payload = {
'client_id': g.clientId,
'grant_type': 'client_credentials',
'resource': resource,
'client_secret': g.clientSecret
}
token_endpoint = g.aad_endpoint + tenant_id + '/oauth2/token'
r = requests.post(token_endpoint, data=payload)
return r.json()['access_token']
views.py
@app.route('/<string:user_type>/login', methods = ['POST', 'GET'])
def login(user_type):
if ('access_token_arm' in session) and ('access_token_graph' in session):
return redirect(url_for(user_type))
guid = uuid.uuid4()
session['state'] = guid
redirect_uri = login_url(session['state'], url_for('authorized', user_type=user_type, _external=True))
return redirect(redirect_uri, code=301)
@app.route('/logout', methods = ['POST', 'GET'])
def logout():
session.clear()
return redirect(url_for('index'))
@app.route('/<string:user_type>/login/authorized')
def authorized(user_type):
code = request.args['code']
if str(session['state']) != str(request.args['state']):
raise Exception('State has been messed with, end authentication')
redirect_uri = url_for('authorized', user_type=user_type, _external=True)
session['access_token_arm'] = get_access_token_code(code, redirect_uri, g.resource_arm)
session['access_token_graph'] = get_access_token_code(code, redirect_uri, g.resource_graph)
return redirect(url_for(user_type))
graph.py
def get_tenant_details(access_token):
headers = create_headers(access_token)
params = {
'url': g.resource_graph,
'api_version': g.api_version_graph
}
tenant_details_url = '%(url)s/myorganization/tenantDetails?api-version=%(api_version)s' %params
r = requests.get(tenant_details_url, headers=headers)
return r.json()['value'][0]['displayName'], r.json()['value'][0]['objectId']
def get_user_details(access_token):
headers = create_headers(access_token)
params = {
'url': g.resource_graph,
'api_version': g.api_version_graph
}
user_details_url = '%(url)s/me?api-version=%(api_version)s' %params
r = requests.get(user_details_url, headers=headers)
return r.json()['userPrincipalName']