Azure AD 身份验证 Python Web API
Azure AD Authentication Python Web API
我正在尝试使用 OAuth2 对用户进行身份验证并访问资源。但是,我在这样做时遇到了一些问题。详情如下。
- 我已经在 Azure 门户上将应用程序注册为 Web Api
- 我想编写一个 python 脚本,通过它我可以请求授权码,然后是访问令牌
挑战:
- 我没有重定向 url。我不确定我可以在这里使用什么
- 当我在浏览器中使用link获取授权码时,它要求我登录到Azure。我怎样才能确保它也要求我通过 Python API 登录?
这是我用来获取验证码的 python 脚本:
import requests
import json
'''Request Authorization code template
https://login.microsoftonline.com/{tenant}/oauth2/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&response_mode=query
&resource=https%3A%2F%2Fservice.contoso.com%2F
&state=12345
'''
payload = {'client_id': '***', 'response_type': 'code', 'response_mode': 'query',
'resource': '***'}
get_authorization_code = requests.get('https://login.microsoftonline.com/tenant/oauth2/authorize',
params=payload, verify=False)
print get_authorization_code
我得到的对此代码的响应是:响应 [200]
授权码授予流程 (response_type=code
) 希望您在用户代理(即浏览器或浏览器控件)中实际将用户发送到 URL。用户将看到登录过程(例如用户名、密码、多重身份验证等),完成所有这些后,浏览器将被重定向到 redirect_uri
.
如果您将 Web 应用程序编码为客户端(您只需将用户(在他们的浏览器中)发送到您构建的 URL,并将页面托管在redirect_uri
登录完成后接收授权码)。但是,您似乎正在编写控制台应用程序脚本(或其他应用程序,将用户发送到浏览器控件是不切实际的,您可以在其中捕获最终重定向)。您有几个选项,具体取决于脚本是否 运行 在高度安全的环境中。
将API作为应用程序调用
这可能是最简单的实现方式,但要求客户端 运行 处于高度信任的安全环境中。该应用程序将 作为自己 (而不是作为用户)进行身份验证,获取访问令牌,并发出 API 请求。这是 OAuth 2.0 Client Credentials Grant 流程。
您将需要:
- 在 Azure AD 中将您的客户端应用注册为 Web app/web API(这很重要,因为它告诉 Azure AD 这是一个 机密客户端,并允许您为应用程序关联凭据(密码或证书)。
- 声明您的客户端应用程序需要访问您的 API(这将注册为不同的网站 app/web API)。
使用 Python,最简单的方法是使用 ADAL for Python。例如,要在使用证书进行身份验证时获取访问令牌:
import adal
context = adal.AuthenticationContext('https://login.microsoftonline.com/{tenant-id}')
token = context.acquire_token_with_client_certificate(
"https://api.example.com",
"{client-id}",
'{certificate-content}',
'{certificate-thumbprint}')
见additional details on GitHub。
以用户身份调用API,使用设备代码流
设备流程允许有限的输入体验(例如电视或很少使用的控制台应用程序)在 用户 的上下文中获取 OAuth 2.0 访问令牌,同时允许用户在具有更好输入功能的不同设备(例如智能手机或台式计算机)上执行实际登录。
您将需要:
- 在 Azure AD 中将您的客户端应用程序注册为本机客户端应用程序(这很重要,因为它告诉 Azure AD 这是一个 public 客户端,它允许应用程序在没有应用程序身份验证的情况下获取具有委派权限的访问令牌(因为 public 客户端无法对用户保密)。
- 声明您的客户端应用程序需要访问您的 API(它将注册为单独的网站 app/web API)。
设备代码流包括:
- 客户端应用程序向 Azure AD 发出请求以获取设备代码。此设备代码显示给用户(连同 URL)。
- 在单独的设备上(或者,例如,在同一设备的完整浏览器中),用户访问给定的 URL,并输入给定的设备代码。系统会提示用户登录,并在用户登录时显示一条成功消息。
- 同时,客户端应用程序定期轮询 Azure AD 以查看用户是否已兑换设备代码(并登录)。如果是,则客户端应用程序收到访问令牌。
对于 Python,对 Python 使用 ADAL 再次有用。获取设备代码的请求如下所示:
context = adal.AuthenticationContext('https://login.microsoftonline.com/{tenant-id}')
code = context.acquire_user_code('https://api.example.com', '{client-id}')
print(code['message'])
定期轮询请求如下所示:
token = context.acquire_token_with_device_code('https://api.example.com', code, '{client-id}')
我刚刚接受了这个挑战,从一些使用 oauth2 和 azure 的 webapi 获取数据。
不喜欢使用 adal 库的想法,因为我们的案例不再支持 adal 并且看起来像使用 oauth2 我可以在不需要新库的情况下获得令牌。
我做到了:
import requests
import json
def get_token(auth_url, client_id, scope, client_secret, grant_type = 'client_credentials'):
"""
return: tuple dict with access_token, status_code
{'access_token': 'tokenid'
'expires_in': 3600,
'ext_expires_in': 0,
'token_type': 'Bearer'}, 200
"""
# Request access token:
# https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#request-an-access-token
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
url =auth_url
data = { "client_id": client_id,
"scope": scope,
"client_secret": client_secret,
"grant_type": grant_type
}
# requests doc http://docs.python-requests.org/en/v0.10.7/user/quickstart/#custom-headers
r = requests.post(url=url, data=data, headers=headers)
return r.json(), r.status_code
# Change these vars to test:
auth_url = 'https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token'
client_id = '6731de76-14a6-49ae-97bc-6eba6914391e'
scope = 'https://company.onmicrosoft.com/some-unique-number-for-scope/.default'
client_secret = "client password secret here"
url = 'http://bioforestws-sandbox.group.upm.com/api/interface/sap/stockmovement'
get_token = get_token(auth_url, client_id, scope, client_secret)
access_token = get_token[0]['access_token']
header_token = {"Authorization": "Bearer {}".format(access_token)}
rt = requests.get(url=url_check, headers=header_token)
我正在尝试使用 OAuth2 对用户进行身份验证并访问资源。但是,我在这样做时遇到了一些问题。详情如下。
- 我已经在 Azure 门户上将应用程序注册为 Web Api
- 我想编写一个 python 脚本,通过它我可以请求授权码,然后是访问令牌
挑战:
- 我没有重定向 url。我不确定我可以在这里使用什么
- 当我在浏览器中使用link获取授权码时,它要求我登录到Azure。我怎样才能确保它也要求我通过 Python API 登录?
这是我用来获取验证码的 python 脚本:
import requests
import json
'''Request Authorization code template
https://login.microsoftonline.com/{tenant}/oauth2/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&response_mode=query
&resource=https%3A%2F%2Fservice.contoso.com%2F
&state=12345
'''
payload = {'client_id': '***', 'response_type': 'code', 'response_mode': 'query',
'resource': '***'}
get_authorization_code = requests.get('https://login.microsoftonline.com/tenant/oauth2/authorize',
params=payload, verify=False)
print get_authorization_code
我得到的对此代码的响应是:响应 [200]
授权码授予流程 (response_type=code
) 希望您在用户代理(即浏览器或浏览器控件)中实际将用户发送到 URL。用户将看到登录过程(例如用户名、密码、多重身份验证等),完成所有这些后,浏览器将被重定向到 redirect_uri
.
如果您将 Web 应用程序编码为客户端(您只需将用户(在他们的浏览器中)发送到您构建的 URL,并将页面托管在redirect_uri
登录完成后接收授权码)。但是,您似乎正在编写控制台应用程序脚本(或其他应用程序,将用户发送到浏览器控件是不切实际的,您可以在其中捕获最终重定向)。您有几个选项,具体取决于脚本是否 运行 在高度安全的环境中。
将API作为应用程序调用
这可能是最简单的实现方式,但要求客户端 运行 处于高度信任的安全环境中。该应用程序将 作为自己 (而不是作为用户)进行身份验证,获取访问令牌,并发出 API 请求。这是 OAuth 2.0 Client Credentials Grant 流程。
您将需要:
- 在 Azure AD 中将您的客户端应用注册为 Web app/web API(这很重要,因为它告诉 Azure AD 这是一个 机密客户端,并允许您为应用程序关联凭据(密码或证书)。
- 声明您的客户端应用程序需要访问您的 API(这将注册为不同的网站 app/web API)。
使用 Python,最简单的方法是使用 ADAL for Python。例如,要在使用证书进行身份验证时获取访问令牌:
import adal
context = adal.AuthenticationContext('https://login.microsoftonline.com/{tenant-id}')
token = context.acquire_token_with_client_certificate(
"https://api.example.com",
"{client-id}",
'{certificate-content}',
'{certificate-thumbprint}')
见additional details on GitHub。
以用户身份调用API,使用设备代码流
设备流程允许有限的输入体验(例如电视或很少使用的控制台应用程序)在 用户 的上下文中获取 OAuth 2.0 访问令牌,同时允许用户在具有更好输入功能的不同设备(例如智能手机或台式计算机)上执行实际登录。
您将需要:
- 在 Azure AD 中将您的客户端应用程序注册为本机客户端应用程序(这很重要,因为它告诉 Azure AD 这是一个 public 客户端,它允许应用程序在没有应用程序身份验证的情况下获取具有委派权限的访问令牌(因为 public 客户端无法对用户保密)。
- 声明您的客户端应用程序需要访问您的 API(它将注册为单独的网站 app/web API)。
设备代码流包括:
- 客户端应用程序向 Azure AD 发出请求以获取设备代码。此设备代码显示给用户(连同 URL)。
- 在单独的设备上(或者,例如,在同一设备的完整浏览器中),用户访问给定的 URL,并输入给定的设备代码。系统会提示用户登录,并在用户登录时显示一条成功消息。
- 同时,客户端应用程序定期轮询 Azure AD 以查看用户是否已兑换设备代码(并登录)。如果是,则客户端应用程序收到访问令牌。
对于 Python,对 Python 使用 ADAL 再次有用。获取设备代码的请求如下所示:
context = adal.AuthenticationContext('https://login.microsoftonline.com/{tenant-id}')
code = context.acquire_user_code('https://api.example.com', '{client-id}')
print(code['message'])
定期轮询请求如下所示:
token = context.acquire_token_with_device_code('https://api.example.com', code, '{client-id}')
我刚刚接受了这个挑战,从一些使用 oauth2 和 azure 的 webapi 获取数据。
不喜欢使用 adal 库的想法,因为我们的案例不再支持 adal 并且看起来像使用 oauth2 我可以在不需要新库的情况下获得令牌。
我做到了:
import requests
import json
def get_token(auth_url, client_id, scope, client_secret, grant_type = 'client_credentials'):
"""
return: tuple dict with access_token, status_code
{'access_token': 'tokenid'
'expires_in': 3600,
'ext_expires_in': 0,
'token_type': 'Bearer'}, 200
"""
# Request access token:
# https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#request-an-access-token
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
url =auth_url
data = { "client_id": client_id,
"scope": scope,
"client_secret": client_secret,
"grant_type": grant_type
}
# requests doc http://docs.python-requests.org/en/v0.10.7/user/quickstart/#custom-headers
r = requests.post(url=url, data=data, headers=headers)
return r.json(), r.status_code
# Change these vars to test:
auth_url = 'https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token'
client_id = '6731de76-14a6-49ae-97bc-6eba6914391e'
scope = 'https://company.onmicrosoft.com/some-unique-number-for-scope/.default'
client_secret = "client password secret here"
url = 'http://bioforestws-sandbox.group.upm.com/api/interface/sap/stockmovement'
get_token = get_token(auth_url, client_id, scope, client_secret)
access_token = get_token[0]['access_token']
header_token = {"Authorization": "Bearer {}".format(access_token)}
rt = requests.get(url=url_check, headers=header_token)