Skip to content

Commit 05a80f5

Browse files
committed
Merge branch 'tester' into dev
2 parents fa17457 + e3963c9 commit 05a80f5

File tree

1 file changed

+51
-44
lines changed

1 file changed

+51
-44
lines changed

tests/msaltest.py renamed to msal/__main__.py

Lines changed: 51 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1+
# It is currently shipped inside msal library.
2+
# Pros: It is always available wherever msal is installed.
3+
# Cons: Its 3rd-party dependencies (if any) may become msal's dependency.
4+
"""MSAL Python Tester
5+
6+
Usage 1: Run it on the fly.
7+
python -m msal
8+
9+
Usage 2: Build an all-in-one executable file for bug bash.
10+
shiv -e msal.__main__._main -o msaltest-on-os-name.pyz .
11+
Note: We choose to not define a console script to avoid name conflict.
12+
"""
113
import base64, getpass, json, logging, sys, msal
214

3-
4-
AZURE_CLI = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"
5-
VISUAL_STUDIO = "04f0c124-f2bc-4f59-8241-bf6df9866bbd"
15+
_AZURE_CLI = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"
16+
_VISUAL_STUDIO = "04f0c124-f2bc-4f59-8241-bf6df9866bbd"
617

718
def print_json(blob):
819
print(json.dumps(blob, indent=2, sort_keys=True))
@@ -61,7 +72,7 @@ def _select_account(app):
6172
else:
6273
print("No account available inside MSAL Python. Use other methods to acquire token first.")
6374

64-
def acquire_token_silent(app):
75+
def _acquire_token_silent(app):
6576
"""acquire_token_silent() - with an account already signed into MSAL Python."""
6677
account = _select_account(app)
6778
if account:
@@ -71,7 +82,8 @@ def acquire_token_silent(app):
7182
force_refresh=_input_boolean("Bypass MSAL Python's token cache?"),
7283
))
7384

74-
def _acquire_token_interactive(app, scopes, data=None):
85+
def _acquire_token_interactive(app, scopes=None, data=None):
86+
"""acquire_token_interactive() - User will be prompted if app opts to do select_account."""
7587
prompt = _select_options([
7688
{"value": None, "description": "Unspecified. Proceed silently with a default account (if any), fallback to prompt."},
7789
{"value": "none", "description": "none. Proceed silently with a default account (if any), or error out."},
@@ -88,78 +100,73 @@ def _acquire_token_interactive(app, scopes, data=None):
88100
)
89101
login_hint = raw_login_hint["username"] if isinstance(raw_login_hint, dict) else raw_login_hint
90102
result = app.acquire_token_interactive(
91-
scopes,
103+
scopes or _input_scopes(),
92104
parent_window_handle=app.CONSOLE_WINDOW_HANDLE, # This test app is a console app
93105
enable_msa_passthrough=app.client_id in [ # Apps are expected to set this right
94-
AZURE_CLI, VISUAL_STUDIO,
106+
_AZURE_CLI, _VISUAL_STUDIO,
95107
], # Here this test app mimics the setting for some known MSA-PT apps
96108
prompt=prompt, login_hint=login_hint, data=data or {})
97109
if login_hint and "id_token_claims" in result:
98110
signed_in_user = result.get("id_token_claims", {}).get("preferred_username")
99111
if signed_in_user != login_hint:
100112
logging.warning('Signed-in user "%s" does not match login_hint', signed_in_user)
113+
print_json(result)
101114
return result
102115

103-
def acquire_token_interactive(app):
104-
"""acquire_token_interactive() - User will be prompted if app opts to do select_account."""
105-
print_json(_acquire_token_interactive(app, _input_scopes()))
106-
107-
def acquire_token_by_username_password(app):
116+
def _acquire_token_by_username_password(app):
108117
"""acquire_token_by_username_password() - See constraints here: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#constraints-for-ropc"""
109118
print_json(app.acquire_token_by_username_password(
110119
_input("username: "), getpass.getpass("password: "), scopes=_input_scopes()))
111120

112121
_JWK1 = """{"kty":"RSA", "n":"2tNr73xwcj6lH7bqRZrFzgSLj7OeLfbn8216uOMDHuaZ6TEUBDN8Uz0ve8jAlKsP9CQFCSVoSNovdE-fs7c15MxEGHjDcNKLWonznximj8pDGZQjVdfK-7mG6P6z-lgVcLuYu5JcWU_PeEqIKg5llOaz-qeQ4LEDS4T1D2qWRGpAra4rJX1-kmrWmX_XIamq30C9EIO0gGuT4rc2hJBWQ-4-FnE1NXmy125wfT3NdotAJGq5lMIfhjfglDbJCwhc8Oe17ORjO3FsB5CLuBRpYmP7Nzn66lRY3Fe11Xz8AEBl3anKFSJcTvlMnFtu3EpD-eiaHfTgRBU7CztGQqVbiQ", "e":"AQAB"}"""
113-
SSH_CERT_DATA = {"token_type": "ssh-cert", "key_id": "key1", "req_cnf": _JWK1}
114-
SSH_CERT_SCOPE = ["https://pas.windows.net/CheckMyAccess/Linux/.default"]
122+
_SSH_CERT_DATA = {"token_type": "ssh-cert", "key_id": "key1", "req_cnf": _JWK1}
123+
_SSH_CERT_SCOPE = ["https://pas.windows.net/CheckMyAccess/Linux/.default"]
115124

116-
def acquire_ssh_cert_silently(app):
125+
def _acquire_ssh_cert_silently(app):
117126
"""Acquire an SSH Cert silently- This typically only works with Azure CLI"""
118127
account = _select_account(app)
119128
if account:
120129
result = app.acquire_token_silent(
121-
SSH_CERT_SCOPE,
130+
_SSH_CERT_SCOPE,
122131
account,
123-
data=SSH_CERT_DATA,
132+
data=_SSH_CERT_DATA,
124133
force_refresh=_input_boolean("Bypass MSAL Python's token cache?"),
125134
)
126135
print_json(result)
127136
if result and result.get("token_type") != "ssh-cert":
128137
logging.error("Unable to acquire an ssh-cert.")
129138

130-
def acquire_ssh_cert_interactive(app):
139+
def _acquire_ssh_cert_interactive(app):
131140
"""Acquire an SSH Cert interactively - This typically only works with Azure CLI"""
132-
result = _acquire_token_interactive(app, SSH_CERT_SCOPE, data=SSH_CERT_DATA)
133-
print_json(result)
141+
result = _acquire_token_interactive(app, scopes=_SSH_CERT_SCOPE, data=_SSH_CERT_DATA)
134142
if result.get("token_type") != "ssh-cert":
135143
logging.error("Unable to acquire an ssh-cert")
136144

137-
POP_KEY_ID = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-AAAAAAAA' # Fake key with a certain format and length
138-
RAW_REQ_CNF = json.dumps({"kid": POP_KEY_ID, "xms_ksl": "sw"})
139-
POP_DATA = { # Sampled from Azure CLI's plugin connectedk8s
145+
_POP_KEY_ID = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-AAAAAAAA' # Fake key with a certain format and length
146+
_RAW_REQ_CNF = json.dumps({"kid": _POP_KEY_ID, "xms_ksl": "sw"})
147+
_POP_DATA = { # Sampled from Azure CLI's plugin connectedk8s
140148
'token_type': 'pop',
141-
'key_id': POP_KEY_ID,
142-
"req_cnf": base64.urlsafe_b64encode(RAW_REQ_CNF.encode('utf-8')).decode('utf-8').rstrip('='),
143-
# Note: Sending RAW_REQ_CNF without base64 encoding would result in an http 500 error
149+
'key_id': _POP_KEY_ID,
150+
"req_cnf": base64.urlsafe_b64encode(_RAW_REQ_CNF.encode('utf-8')).decode('utf-8').rstrip('='),
151+
# Note: Sending _RAW_REQ_CNF without base64 encoding would result in an http 500 error
144152
} # See also https://github.com/Azure/azure-cli-extensions/blob/main/src/connectedk8s/azext_connectedk8s/_clientproxyutils.py#L86-L92
145153

146-
def acquire_pop_token_interactive(app):
154+
def _acquire_pop_token_interactive(app):
147155
"""Acquire a POP token interactively - This typically only works with Azure CLI"""
148156
POP_SCOPE = ['6256c85f-0aad-4d50-b960-e6e9b21efe35/.default'] # KAP 1P Server App Scope, obtained from https://github.com/Azure/azure-cli-extensions/pull/4468/files#diff-a47efa3186c7eb4f1176e07d0b858ead0bf4a58bfd51e448ee3607a5b4ef47f6R116
149-
result = _acquire_token_interactive(app, POP_SCOPE, data=POP_DATA)
157+
result = _acquire_token_interactive(app, scopes=POP_SCOPE, data=_POP_DATA)
150158
print_json(result)
151159
if result.get("token_type") != "pop":
152160
logging.error("Unable to acquire a pop token")
153161

154-
155-
def remove_account(app):
162+
def _remove_account(app):
156163
"""remove_account() - Invalidate account and/or token(s) from cache, so that acquire_token_silent() would be reset"""
157164
account = _select_account(app)
158165
if account:
159166
app.remove_account(account)
160167
print('Account "{}" and/or its token(s) are signed out from MSAL Python'.format(account["username"]))
161168

162-
def exit(app):
169+
def _exit(app):
163170
"""Exit"""
164171
bug_link = (
165172
"https://identitydivision.visualstudio.com/Engineering/_queries/query/79b3a352-a775-406f-87cd-a487c382a8ed/"
@@ -169,11 +176,11 @@ def exit(app):
169176
print("Bye. If you found a bug, please report it here: {}".format(bug_link))
170177
sys.exit()
171178

172-
def main():
173-
print("Welcome to the Msal Python {} Tester\n".format(msal.__version__))
179+
def _main():
180+
print("Welcome to the Msal Python {} Tester (Experimental)\n".format(msal.__version__))
174181
chosen_app = _select_options([
175-
{"client_id": AZURE_CLI, "name": "Azure CLI (Correctly configured for MSA-PT)"},
176-
{"client_id": VISUAL_STUDIO, "name": "Visual Studio (Correctly configured for MSA-PT)"},
182+
{"client_id": _AZURE_CLI, "name": "Azure CLI (Correctly configured for MSA-PT)"},
183+
{"client_id": _VISUAL_STUDIO, "name": "Visual Studio (Correctly configured for MSA-PT)"},
177184
{"client_id": "95de633a-083e-42f5-b444-a4295d8e9314", "name": "Whiteboard Services (Non MSA-PT app. Accepts AAD & MSA accounts.)"},
178185
],
179186
option_renderer=lambda a: a["name"],
@@ -201,14 +208,14 @@ def main():
201208
logging.basicConfig(level=logging.DEBUG)
202209
while True:
203210
func = _select_options([
204-
acquire_token_silent,
205-
acquire_token_interactive,
206-
acquire_token_by_username_password,
207-
acquire_ssh_cert_silently,
208-
acquire_ssh_cert_interactive,
209-
acquire_pop_token_interactive,
210-
remove_account,
211-
exit,
211+
_acquire_token_silent,
212+
_acquire_token_interactive,
213+
_acquire_token_by_username_password,
214+
_acquire_ssh_cert_silently,
215+
_acquire_ssh_cert_interactive,
216+
_acquire_pop_token_interactive,
217+
_remove_account,
218+
_exit,
212219
], option_renderer=lambda f: f.__doc__, header="MSAL Python APIs:")
213220
try:
214221
func(app)
@@ -218,5 +225,5 @@ def main():
218225
print("Aborted")
219226

220227
if __name__ == "__main__":
221-
main()
228+
_main()
222229

0 commit comments

Comments
 (0)