【问题标题】:Azure Function App using python: How to access user groups for authorization使用 python 的 Azure Function App:如何访问用户组以进行授权
【发布时间】:2021-08-26 06:03:14
【问题描述】:

我对 Azure Function Apps 和 OAuth 非常陌生,所以请多多包涵。

我的设置

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

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 代码访问的内容。
重新加载页面(我想请求然后使用已经过身份验证的浏览器会话)使回调消失。

【问题讨论】:

    标签: python azure azure-functions usergroups easy-auth


    【解决方案1】:

    标头 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
            )
    
    

    【讨论】:

    • 哇哦!非常感谢!!这回答了我问题的最大部分。您能否证实我对此的假设:“由于我能够访问 X-MS-CLIENT-PRINCIPAL-ID 和 X-MS-CLIENT-PRINCIPAL-NAME,我想身份验证成功。”
    • @NoahMueller 是的,你可以这样做。
    猜你喜欢
    • 2020-04-25
    • 1970-01-01
    • 2018-06-11
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    相关资源
    最近更新 更多