【问题标题】:Azure AD Authentication Python Web APIAzure AD 身份验证 Python Web API
【发布时间】:2017-07-21 19:01:45
【问题描述】:

我正在尝试使用 OAuth2 对用户进行身份验证并访问资源。但是,我在这样做时遇到了一些问题。以下是详细信息。

  1. 我已在 Azure 门户上将应用注册为 Web Api
  2. 我想编写一个 python 脚本,通过它我可以请求授权码,然后是访问令牌

挑战:

  1. 我没有重定向网址。我不确定我可以在这里使用什么
  2. 当我使用链接在浏览器中获取授权码时,它要求我登录 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]

【问题讨论】:

    标签: python azure azure-active-directory azure-api-management


    【解决方案1】:

    授权代码授予流程 (response_type=code) 期望您在用户代理(即浏览器或浏览器控件)中实际将用户发送到该 URL。用户将看到登录过程(例如用户名、密码、多重身份验证等),当所有这些完成后,浏览器将被重定向到redirect_uri

    如果您将 Web 应用程序编码为客户端,这一切都非常简单(您只需将用户(在他们的浏览器中)发送到您构建的 URL,并在 redirect_uri 托管一个页面以接收登录完成后的授权码)。但是,您似乎正在编写控制台应用程序(或其他将用户发送到可以捕获最终重定向的浏览器控件不切实际的应用程序)的脚本。您有几个选项,具体取决于脚本是否在高度安全的环境中运行。

    将 API 作为应用程序调用

    这可能是最简单的实现方式,但需要客户端在高度信任的安全环境中运行。应用程序将以自身身份(而不是以用户身份)进行身份验证,获取访问令牌,并发出 API 请求。这是OAuth 2.0 Client Credentials Grant 流。

    您需要:

    • 在 Azure AD 中将您的客户端应用程序注册为 Web 应用程序/Web API(这很重要,因为它告诉 Azure AD 这是一个机密客户端,并允许您关联凭据(密码或证书)。
    • 声明您的客户端应用需要访问您的 API(将注册为不同的网络应用/网络 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 这是一个公共客户端,它允许应用程序通过委托获取访问令牌未经应用身份验证的权限(因为公共客户端无法对用户保密)。
    • 声明您的客户端应用需要访问您的 API(将注册为单独的网络应用/网络 API)。

    设备代码流程包括:

    1. 客户端应用程序向 Azure AD 发出请求以获取设备代码。此设备代码会显示给用户(连同 URL)。
    2. 在单独的设备上(或者,例如,在同一设备的成熟浏览器中),用户访问给定的 URL,并输入给定的设备代码。系统会提示用户登录,并在用户登录时显示成功消息。
    3. 同时,客户端应用程序会定期轮询 Azure AD,以查看用户是否已兑换设备代码(并已登录)。如果是,则客户端应用收到了访问令牌。

    对于 Python,将 ADAL 用于 Python 也很有用。获取设备代码的请求如下所示:

    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}')
    

    additional details on GitHub

    【讨论】:

    • 更具体地说,我想使用此脚本从 Azure AD 中提取管理信息。诸如在 AAD 中注册的应用程序数量、用户总数等。这是我前进的正确方向吗?由于我正在使用此脚本,因此我已将其注册为 Azure AD 上的 Web API。从这个应用程序(一旦完成)我想访问管理资源。
    【解决方案2】:

    我刚刚接受了这个挑战,从一些使用 oauth2 和 azure 的 webapi 获取数据。

    不喜欢使用 adal 库的想法,因为我们的案例不再支持 adal,并且看起来使用 oauth2 我可以在不需要新库的情况下获得令牌。

    我做到了:

    https://github.com/pablodav/curlnagios/commit/ca7462be13acb2637553ab95eadcfc0f0b7aecab#diff-332569aae421078a8053c3b1140440d5R53

    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)
    

    【讨论】:

      猜你喜欢
      • 2020-07-27
      • 1970-01-01
      • 2017-04-08
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多