使用 python 的 Azure Function App:如何访问用户组进行授权

问题描述

我对 Azure Function Apps 和 OAuth 非常陌生,所以请耐心等待。

我的设置

我有一个 Azure 函数应用程序,它有一个简单的 python 函数,除了打印请求标头外,什么都不做:

import logging

import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')    

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        aadIdToken = req.headers.get('X-MS-TOKEN-AAD-ID-TOKEN')
        aadAccesstoken = req.headers.get('X-MS-TOKEN-AAD-ACCESS-TOKEN')
        principalID = req.headers.get('X-MS-CLIENT-PRINCIPAL-ID')
        principalName = req.headers.get('X-MS-CLIENT-PRINCIPAL-NAME')
        idProviderId = req.headers.get('X-MS-CLIENT-PRINCIPAL-IDP')
        aadRefreshToken = req.headers.get('X-MS-TOKEN-AAD-REFRESH-TOKEN')

        clientPrincipal = req.headers.get('X-MS-CLIENT-PRINCIPAL')

        result = "\n"
        myDict = sorted(dict(req.headers))
        for key in myDict:
            result += f"{key} = {dict(req.headers)[key]}\n"

        return func.HttpResponse(
            f"Hello,{name}. How are you ? Doing well ?"\
            f"\n\nHere is some data concerning your Client principal:"\
            f"\nThis is your X-MS-CLIENT-PRINCIPAL-ID: {principalID}"\
            f"\nThis is your X-MS-CLIENT-PRINCIPAL-NAME: {principalName}"\
            f"\nThis is your X-MS-CLIENT-PRINCIPAL-IDP: {idProviderId}"\
            f"\nThis is your X-MS-CLIENT-PRINCIPAL: {clientPrincipal}"\
            f"\n\nHere is some data concerning your AAD-token:"\
            f"\nThis is your X-MS-TOKEN-AAD-ID-TOKEN: {aadIdToken}"\
            f"\nThis is your X-MS-TOKEN-AAD-ACCESS-TOKEN: {aadAccesstoken}"\
            f"\nThis is your X-MS-TOKEN-AAD-REFRESH-TOKEN: {aadRefreshToken}"\
            f"\n\n\nresult: {result}"\
        )
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",status_code=200
        )

我按照这个 guide用户调用函数之前通过 EasyAuth 进行身份验证。
这似乎工作正常。通过浏览器访问该功能时,我被重定向登录。成功登录后,我再次被重定向,并在浏览器中打印出 HTTP 响应。由于我能够访问 X-MS-CLIENT-PRINCIPAL-IDX-MS-CLIENT-PRINCIPAL-NAME,因此我认为身份验证成功。但是,在打印出整个请求标头时,我没有找到 X-MS-TOKEN-AAD-REFRESH-TOKENX-MS-TOKEN-AAD-ACCESS-TOKENX-MS-TOKEN-AAD-ID-TOKEN
这是输出输出太大;在屏幕截图中显示输出下方,我可以看到标题内容): First half of my output

我的问题

我现在要做的是通过函数的python代码访问分配给登录用户的组以进一步授权他的请求(例如“用户只能在分配组xyz时执行该函数,否则他将被提示“不允许””)。
为了实现这一点,我在我的应用注册的令牌配置中添加了“组”声明。

据我了解,通过使用 ClaimsPrinciple 对象 (source),可以通过 .NET 中编码的函数轻松访问用户组。

如何通过 python 代码访问用户分配的组?
可以吗?
我的理解是完全错误的吗?

跟进:
我现在不明白的一件事是,当我第一次通过浏览器访问该功能(触发登录)时,我可以在浏览器调试器的回调-http-request 中看到一个 id_tokenBrowser debugger: id_token in callback-request

当我使用 jwt.io 解密该令牌时,我能够看到分配的用户组的一些 ID,这似乎正是我想通过 python 代码访问的。
重新加载页面(我想请求然后使用已经过身份验证的浏览器会话)会使回调消失。

解决方法

标头 X-MS-CLIENT-PRINCIPAL 包含与 id_token 相同的声明。所以如果我们想要得到组声明,我们可以对头部进行 base64 解码。

例如

我的代码

import logging

import azure.functions as func
import base64

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        aadAccessToken = req.headers.get('X-MS-TOKEN-AAD-ACCESS-TOKEN')
        principalID = req.headers.get('X-MS-CLIENT-PRINCIPAL-ID')
        principalName = req.headers.get('X-MS-CLIENT-PRINCIPAL-NAME')
        idProviderId = req.headers.get('X-MS-CLIENT-PRINCIPAL-IDP')
        aadRefreshToken = req.headers.get('X-MS-TOKEN-AAD-REFRESH-TOKEN')

        clientPrincipal = req.headers.get('X-MS-CLIENT-PRINCIPAL')
        clientPrincipal= base64.b64decode(clientPrincipal)

        result = "\n"
        myDict = sorted(dict(req.headers))
        for key in myDict:
            result += f"{key} = {dict(req.headers)[key]}\n"

        return func.HttpResponse(
            f"Hello,{name}. How are you ? Doing well ?"\
            f"\n\nHere is some data concerning your Client principal:"\
            f"\nThis is your X-MS-CLIENT-PRINCIPAL-ID: {principalID}"\
            f"\nThis is your X-MS-CLIENT-PRINCIPAL-NAME: {principalName}"\
            f"\nThis is your X-MS-CLIENT-PRINCIPAL-IDP: {idProviderId}"\
            f"\nThis is your X-MS-CLIENT-PRINCIPAL: {clientPrincipal}"\
            f"\n\nHere is some data concerning your AAD-token:"\
            f"\nThis is your X-MS-TOKEN-AAD-ID-TOKEN: {aadIdToken}"\
            f"\nThis is your X-MS-TOKEN-AAD-ACCESS-TOKEN: {aadAccessToken}"\
            f"\nThis is your X-MS-TOKEN-AAD-REFRESH-TOKEN: {aadRefreshToken}"\
            f"\n\n\nresult: {result}"\
        )
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",status_code=200
        )

enter image description here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...