Azure AD身份验证Python Web API

时间:2017-07-21 19:01:45

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

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

  1. 我已将该应用注册为Azure门户网站上的Web Api
  2. 我想编写一个python脚本,通过该脚本我可以请求授权代码,然后是访问令牌
  3. 挑战:

    1. 我没有重定向网址。我不确定我能在这里使用什么
    2. 当我使用该链接在浏览器中获取授权代码时,它会要求我登录Azure。如何确保它还要求我通过Python API登录?
    3. 这是我用来获取身份验证代码的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]

2 个答案:

答案 0 :(得分:2)

授权代码授权流程(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(将其注册为单独的Web应用程序/ Web API)。

设备代码流包括:

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

答案 1 :(得分:0)

我刚刚遇到了这个挑战,需要从使用oauth2和azure的webapi中获取数据。

不喜欢使用adal库的想法,因为在我们的案例中不再支持adal,而且看起来像使用oauth2一样,我无需新库即可获取令牌。

我做到了:

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

导入请求     导入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)
相关问题