Skip to content

Commit daa6478

Browse files
authored
Merge pull request #283 from AzureAD/acquire-token-interactive-sample
A sample for the new acquire_token_interactive()
2 parents 84c7349 + dd1636d commit daa6478

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed

sample/interactive_sample.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
The configuration file would look like this:
3+
4+
{
5+
"authority": "https://login.microsoftonline.com/organizations",
6+
"client_id": "your_client_id",
7+
"scope": ["User.ReadBasic.All"],
8+
// You can find the other permission names from this document
9+
// https://docs.microsoft.com/en-us/graph/permissions-reference
10+
"username": "your_username@your_tenant.com", // This is optional
11+
"endpoint": "https://graph.microsoft.com/v1.0/users"
12+
// You can find more Microsoft Graph API endpoints from Graph Explorer
13+
// https://developer.microsoft.com/en-us/graph/graph-explorer
14+
}
15+
16+
You can then run this sample with a JSON configuration file:
17+
18+
python sample.py parameters.json
19+
"""
20+
21+
import sys # For simplicity, we'll read config file from 1st CLI param sys.argv[1]
22+
import json, logging, msal, requests
23+
24+
# Optional logging
25+
# logging.basicConfig(level=logging.DEBUG) # Enable DEBUG log for entire script
26+
# logging.getLogger("msal").setLevel(logging.INFO) # Optionally disable MSAL DEBUG logs
27+
28+
config = json.load(open(sys.argv[1]))
29+
30+
# Create a preferably long-lived app instance which maintains a token cache.
31+
app = msal.PublicClientApplication(
32+
config["client_id"], authority=config["authority"],
33+
# token_cache=... # Default cache is in memory only.
34+
# You can learn how to use SerializableTokenCache from
35+
# https://msal-python.rtfd.io/en/latest/#msal.SerializableTokenCache
36+
)
37+
38+
# The pattern to acquire a token looks like this.
39+
result = None
40+
41+
# Firstly, check the cache to see if this end user has signed in before
42+
accounts = app.get_accounts(username=config.get("username"))
43+
if accounts:
44+
logging.info("Account(s) exists in cache, probably with token too. Let's try.")
45+
print("Account(s) already signed in:")
46+
for a in accounts:
47+
print(a["username"])
48+
chosen = accounts[0] # Assuming the end user chose this one to proceed
49+
print("Proceed with account: %s" % chosen["username"])
50+
# Now let's try to find a token in cache for this account
51+
result = app.acquire_token_silent(config["scope"], account=chosen)
52+
53+
if not result:
54+
logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
55+
print("A local browser window will be open for you to sign in. CTRL+C to cancel.")
56+
result = app.acquire_token_interactive(
57+
config["scope"],
58+
login_hint=config.get("username"), # You can use this parameter to pre-fill
59+
# the username (or email address) field of the sign-in page for the user,
60+
# if you know the username ahead of time.
61+
# Often, apps use this parameter during reauthentication,
62+
# after already extracting the username from an earlier sign-in
63+
# by using the preferred_username claim from returned id_token_claims.
64+
)
65+
66+
if "access_token" in result:
67+
# Calling graph using the access token
68+
graph_response = requests.get( # Use token to call downstream service
69+
config["endpoint"],
70+
headers={'Authorization': 'Bearer ' + result['access_token']},)
71+
print("Graph API call result: %s ..." % graph_response.text[:100])
72+
else:
73+
print(result.get("error"))
74+
print(result.get("error_description"))
75+
print(result.get("correlation_id")) # You may need this when reporting a bug

0 commit comments

Comments
 (0)