Я реализую поток авторизации_кода с помощью AzureAD OIDC для своего приложения на Python, используя библиотеку MSAL.
Мне нужно использовать конечные точки OAuth2 версии 1, чтобы требовать аутентификацию MFA (которая, похоже, недоступна в версии 2.0), поэтому:
https://login.microsoftonline.com/{tenant}/oauth2/
Вместо
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/
Вот пример кода:
msal_app = ConfidentialClientApplication(
client_id = "xxx",
client_credential = "yyy",
oidc_authority = "https://sts.windows.net/{tenant}", # Force OAuth2 v1.0
)
...
flow = msal_app.initiate_auth_code_flow(
scopes=["User.Read"],
redirect_uri = "zzz",
)
# Redirect to: flow["auth_uri"] + "&amr_values=ngcmfa" # OAuth2 v2.0 does not accept amr_values which requires the MFA authentication
...
payload = msal_app.acquire_token_by_auth_code_flow(flow, dict(request.query_params))
Вот что содержит payload:
Это сработало, но access_token странно: похоже, это не токен JWT (который обычно начинается с ey).
Если я попытаюсь использовать его с Microsoft Graph, чтобы использовать запрошенную мной область User.Read, это не удастся:
requests.get(
"https://graph.microsoft.com/v1.0/me",
headers = {"Authorization": f"Bearer {payload['access_token']}"}
).json()
{'error': {'code': 'InvalidAuthenticationToken', 'message': "IDX14100: JWT is not well formed, there are no dots (.).\nThe token needs to be in JWS or JWE Compact Serialization Format. (JWS): 'EncodedHeader.EndcodedPayload.EncodedSignature'. (JWE): 'EncodedProtectedHeader.EncodedEncryptedKey.EncodedInitializationVector.EncodedCiphertext.EncodedAuthenticationTag'.", 'innerError': {'date': '2024-06-03T08:58:59', 'request-id': 'qqq', 'client-request-id': 'www'}}}
Итак, вопрос: почему он дает access_token, который нельзя использовать?
Примечание. Если я переключусь на OAuth2 v2.0, он будет работать без проблем и вернет действительный токен JWT в access_token, однако я не смогу использовать amr_values для обеспечения соблюдения MFA, что является обязательным требованием.
Можете ли вы помочь мне понять, что происходит?


Обратите внимание: чтобы принудительно использовать многофакторную аутентификацию, вам необходимо передать
amr_valuesв URL-адрес авторизации. Обратитесь к этому МсДок
https://login.microsoftonline.com/TenantID. Обратитесь сюда MsDocНапример, я изменил код, передав URL-адрес авторизации напрямую, и успешно получил результаты:
# Create a Flask web application
app = Flask(__name__)
app.secret_key = 'os.urandom(24)'
client_id = "ClientID"
tenant_id = "TenantID"
redirect_uri = "RedirectURL"
msal_app = ConfidentialClientApplication(
client_id=client_id,
authority = "https://login.microsoftonline.com/" + tenant_id
)
# Define the authorization endpoint URL
auth_url = (
"https://login.microsoftonline.com/"
+ tenant_id
+ "/oauth2/authorize?"
+ "response_type=code&"
+ "client_id = " + client_id + "&"
+ "state=12345&"
+ "resource=https://graph.microsoft.com&"
+ "client-request-id=67890&"
+ "amr_values=ngcmfa&"
+ "redirect_uri = " + redirect_uri
)
@app.route("/")
def home():
return redirect(auth_url)
@app.route("/get_a_token")
def get_a_token():
auth_code = request.args.get('code')
# Acquire an access token using the authorization code
try:
token_response = msal_app.acquire_token_by_authorization_code(
auth_code,
scopes=["User.Read"],
redirect_uri=redirect_uri
)
except Exception as e:
return f"Token acquisition failed: {str(e)}"
if "access_token" in token_response:
access_token = token_response["access_token"]
print("Access Token:", access_token)
# Use the access token to make a request to Microsoft Graph
graph_response = requests.get(
"https://graph.microsoft.com/v1.0/me",
headers = {"Authorization": f"Bearer {access_token}"}
)
if graph_response.status_code == 200:
user_data = graph_response.json()
return f"User: {user_data['displayName']}, Email: {user_data['mail']}"
else:
return f"Failed to fetch user data from Microsoft Graph: {graph_response.text}"
else:
error_message = token_response.get("error_description", "Unknown error")
return f"Token acquisition failed: {error_message}"
# Run the Flask application
if __name__ == "__main__":
app.run(debug=True)
Пользователь перенаправляется на страницу MFA:

И после успешного входа я получил токен доступа:

Используя токен доступа, я могу успешно запросить API Micrsoft Graph, как показано ниже:

Ссылка:
Многофакторная проверка авторизации Azure Active Directory - Stack Overflow на русском