微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用应用程序 ID服务主体的令牌对 Azure Devops 进行身份验证?

如何解决如何使用应用程序 ID服务主体的令牌对 Azure Devops 进行身份验证?

我有一个 Azure Devops 管道,我在其中自动为 azure 订阅创建服务连接并触发管道的第 2 阶段。目前,管道任务使用 PAT 向 Azure Devops 进行身份验证。 我不想使用 PAT,因为它取决于一个人,不能自动重新生成。所以我已经看到我可以使用 Azure Active Directory (Azure AD) tokens 进行身份验证。这里有 constructor 的微软。所以我创建了一个 app registration 并授予他 Azure Devops user_impersonation API 权限。我还创建了 azure web app service 来运行 python 应用程序。我已使用应用程序 ID 和密钥更改了 app_config.py

import os

# To configure this application,fill in your application (client) ID,client secret,# AAD tenant ID,and Azure DevOps collection name in the placeholders below.

CLIENT_ID = "xxxxx-xxxx-xxxx-xxxx-xxxx" 
# Application (client) ID of app registration

CLIENT_SECRET = "xxxxxxxxxxxxx"
# In a production app,we recommend you use a more secure method of storing your secret,# like Azure Key Vault. Or,use an environment variable as described in Flask's documentation:
# https://flask.palletsprojects.com/en/1.1.x/config/#configuring-from-environment-variables
# CLIENT_SECRET = os.getenv("CLIENT_SECRET")
# if not CLIENT_SECRET:
#     raise ValueError("Need to define CLIENT_SECRET environment variable")

# AUTHORITY = "https://login.microsoftonline.com/Enter_the_Tenant_ID_Here"  # For multi-tenant app
AUTHORITY = "https://login.microsoftonline.com/xxxxxx-xxxx-xxxx-xxxx-xxxxx"

REDIRECT_PATH = "/getAToken"  # Used for forming an absolute URL to your redirect URI.
                              # The absolute URL must match the redirect URI you set
                              # in the app's registration in the Azure portal.

ENDPOINT = 'https://vssps.dev.azure.com/myorg/_apis/Tokens/Pats?api-version=6.1-preview' 
# fill in the url to the user's ADO collection name here

ScopE = ["499b84ac-1321-427f-aa17-267ca6975798/.default"]
# Means "All scopes for the Azure DevOps API resource"

SESSION_TYPE = "filesystem"  
# Specifies the token cache should be stored in server-side session

所以应用程序运行成功。 但问题是应用程序要求我登录a tutorial

这是我一开始就想避免的。尽管我在 app_config.py 中提供了应用 ID 及其机密,但为什么它要求我“登录”?

更新: 我按照@suomi-dev 的建议使用了

enter image description here

。我能够生成不记名令牌,但无法向 azure devops 进行身份验证。这是回复,我得到:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">




<html lang="en-US">

<head>
    <title>

        Azure DevOps Services | Sign In

    </title>
    <Meta http-equiv="X-UA-Compatible" content="IE=11;&#32;IE=10;&#32;IE=9;&#32;IE=8" />
    <link rel="SHORTCUT ICON" href="/favicon.ico" />

    <link data-bundlelength="508992" data-bundlename="commoncss"
        data-highcontrast="/_static/tfs/M188_20210614.1/_cssbundles/HighContrast/vss-bundle-commoncss-v6u3Ge4AQ3uP84WaM1_W6QGvjulv0ohK4twlMPGNhjUY="
        data-includedstyles="jQueryUI-Modified;Core;Splitter;PivotView"
        href="/_static/tfs/M188_20210614.1/_cssbundles/Default/vss-bundle-commoncss-vHQmPgPp5spmzbH-BlYoXG_Hn35TPVL28elmFhmVVmDU="
        rel="stylesheet" />
    <link data-bundlelength="116278" data-bundlename="viewcss"
        data-highcontrast="/_static/tfs/M188_20210614.1/_cssbundles/HighContrast/vss-bundle-viewcss-vfceofgWpooCKNRb2b7qGygIv-1cQRzxrP0B4pEtwImw="
        data-includedstyles="VSS.Controls"
        href="/_static/tfs/M188_20210614.1/_cssbundles/Default/vss-bundle-viewcss-vXgT3Z4VlQs_ppchNra9ZkzNQE6bqAzibhdP4ooPkmWU="
        rel="stylesheet" />

    <!--UxServices customizations -->

    <link href="/_static/tfs/M188_20210614.1/_content/Authentication.css" type="text/css" rel="stylesheet" />

</head>

<body class="platform">

    <script type="text/javascript">
        var __vsspageContext = {"webContext":{"user":{"id":"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa","name":"Anonymous","email":"","uniqueName":"TEAM FOUNDATION\\Anonymous"},"host":{"id":"7d0cc8e9-39e8-4313-9ff3-23ace0f8f4cf","name":"TEAM FOUNDATION","uri":"https://spsprodweu4.vssps.visualstudio.com/","relativeUri":"/","hostType":"deployment","scheme":"https","authority":"spsprodweu4.vssps.visualstudio.com"}},"moduleLoaderConfig":{"baseUrl":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/","paths":{"Profile/Scripts/Resources":"en-US","VSS/Resources":"en-US","Account/Scripts/Resources":"en-US","UserManagement/Scripts/Resources":"en-US","Authentication/Scripts/Resources":"en-US"},"map":{},"contributionPaths":{"VSS":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/VSS","pathType":"default"},"VSS/Resources":{"value":"en-US","pathType":"resource"},"q":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/q","knockout":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/knockout","mousetrap":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/mousetrap","mustache":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/mustache","react":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/react.15.3","react-dom":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/react-dom.15.3","react-transition-group":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/react-transition-group.15.3","jQueryUI":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/jQueryUI","jquery":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/jquery","OfficeFabric":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/OfficeFabric","tslib":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/tslib","@uifabric":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/@uifabric","VSSUI":{"value":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/VSSUI","pathType":"default"}},"shim":{"jquery":{"deps":[],"exports":"jQuery"}},"waitSeconds":30},"coreReferences":{"stylesheets":[{"url":"/_static/tfs/M188_20210614.1/_cssbundles/Default/vss-bundle-ext-core-css-vNmgDWCLCX0sHlt44FFqt9QrKVBLhz4rqsgP12zXSp8g=","highContrastUrl":null,"iscoreStylesheet":true}],"scripts":[{"identifier":"JQuery","url":"/_static/3rdParty/_scripts/jquery-2.2.4.min.js","fallbackUrl":null,"fallbackCondition":null,"iscoreModule":true},{"identifier":"JQueryXDomain","url":"/_static/3rdParty/_scripts/jquery.xdomainrequest.min.js",{"identifier":"Promise","url":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/promise.js",{"identifier":"GlobalScripts","url":"/_static/tfs/M188_20210614.1/_scripts/TFS/min/global-scripts.js",{"identifier":"LoaderFixes","url":"/_static/tfs/M188_20210614.1/_scripts/TFS/pre-loader-shim.min.js","iscoreModule":false},{"identifier":"AMDLoader","url":"/_static/3rdParty/_scripts/require.min.js","url":"/_static/tfs/M188_20210614.1/_scripts/TFS/post-loader-shim.min.js","iscoreModule":false}],"coreScriptsBundle":{"identifier":"CoreBundle","url":"/_public/_Bundling/Content?bundle=vss-bundle-basejs-v9GpWWBnsWqhM23ijhK2HfAqLowTXGUqZLDRsBCZbkfY=","extensionCoreReferences":{"identifier":"CoreBundle","url":"/_public/_Bundling/Content?bundle=vss-bundle-ext-core-vIzSYLPJCTdYZH2THb6MmQ8IGqUykR9674vJI83Yv4xM=","iscoreModule":true}},"webAccessConfiguration":{"isHosted":true,"paths":{"rootPath":"/","staticContentRootPath":"/","staticContentVersion":"M188_20210614.1","resourcesPath":"/_static/tfs/M188_20210614.1/_content/","staticRoottfs":"/_static/tfs/M188_20210614.1/","cdnFallbackStaticRoottfs":"/_static/tfs/M188_20210614.1/","staticRoot3rdParty":"/_static/3rdParty/"},"api":{"webApiVersion":"1","areaPrefix":"_","controllerPrefix":""},"mailSettings":{"enabled":false},"registryItems":{}},"microsoftAjaxConfig":{"cultureInfo":{"name":"en-US","numberFormat":{"CurrencyDecimalDigits":2,"CurrencyDecimalSeparator":".","IsReadOnly":true,"CurrencyGroupSizes":[3],"NumberGroupSizes":[3],"PercentGroupSizes":[3],"CurrencyGroupSeparator":",","CurrencySymbol":"$","NaNSymbol":"NaN","CurrencyNegativePattern":0,"NumberNegativePattern":1,"PercentPositivePattern":1,"PercentNegativePattern":1,"NegativeInfinitySymbol":"-∞","NegativeSign":"-","NumberDecimalDigits":2,"NumberDecimalSeparator":".","NumberGroupSeparator":","CurrencyPositivePattern":0,"PositiveInfinitySymbol":"∞","PositiveSign":"+","PercentDecimalDigits":2,"PercentDecimalSeparator":".","PercentGroupSeparator":","PercentSymbol":"%","PerMilleSymbol":"‰","NativeDigits":["0","1","2","3","4","5","6","7","8","9"],"DigitSubstitution":1},"dateTimeFormat":{"AMDesignator":"AM","Calendar":{"MinSupportedDateTime":"0001-01-01T00:00:00","MaxSupportedDateTime":"9999-12-31T23:59:59.9999999","AlgorithmType":1,"CalendarType":1,"Eras":[1],"TwoDigitYearMax":2029,"IsReadOnly":true},"DateSeparator":"/","FirstDayOfWeek":0,"CalendarWeekRule":0,"FullDateTimePattern":"dddd,MMMM d,yyyy h:mm:ss tt","LongDatePattern":"dddd,yyyy","LongTimePattern":"h:mm:ss tt","MonthDayPattern":"MMMM d","PMDesignator":"PM","RFC1123Pattern":"ddd,dd MMM yyyy HH':'mm':'ss 'GMT'","ShortDatePattern":"M/d/yyyy","ShortTimePattern":"h:mm tt","SortableDateTimePattern":"yyyy'-'MM'-'dd'T'HH':'mm':'ss","TimeSeparator":":","UniversalSortableDateTimePattern":"yyyy'-'MM'-'dd HH':'mm':'ss'Z'","YearMonthPattern":"MMMM yyyy","AbbreviatedDayNames":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"ShortestDayNames":["Su","Mo","Tu","We","Th","Fr","Sa"],"DayNames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"AbbreviatedMonthNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthNames":["January","February","march","April","June","July","August","September","October","November","December","NativeCalendarName":"Gregorian Calendar","AbbreviatedMonthGenitiveNames":["Jan","MonthGenitiveNames":["January",""]},"numberShortForm":{"QuantitySymbols":["K","M","B"],"NumberGroupSize":1000,"ThousandSymbol":"K"},"eras":null}},"timeZonesConfiguration":{},"featureAvailability":{"featureStates":{"VisualStudio.Services.Contribution.EnableOnPremUnsecurebrowsers":false,"VisualStudio.Service.WebPlatform.ClientErrorReporting":false,"Microsoft.VisualStudio.Services.gallery.Client.UseCdnAssetUri":false,"VisualStudio.Services.WebAccess.SubresourceIntegrity":false,"VisualStudio.Services.IdentityPicker.ReactProfileCard":true}},"appInsightsConfiguration":{"enabled":false,"instrumentationKey":"00000000-0000-0000-0000-000000000000","insightsScriptUrl":null},"diagnostics":{"sessionId":"91ddbf13-332e-4719-965a-6d5f16a576b5","activityId":"91ddbf13-332e-4719-965a-6d5f16a576b5","bundlingEnabled":true,"webPlatformVersion":"M188","serviceVersion":"Dev18.M188.1 (build: AzureDevOps_M188_20210614.1)"},"navigation":{"topMostLevel":"deployment","area":"","currentController":"Signin","currentAction":"Index","routeId":"LegacyWebAccessRoute","routeValues":{"controller":"Signin","action":"Index"}},"globalization":{"explicitTheme":"","theme":"Default","culture":"en-US","timezoneOffset":0,"timeZoneId":"UTC"},"serviceInstanceId":"951917ac-a960-4999-8464-e3f0aa25b381","hubsContext":{},"serviceLocations":{"locations":{"951917ac-a960-4999-8464-e3f0aa25b381":{"Application":"https://spsprodweu4.vssps.visualstudio.com/","Deployment":"https://spsprodweu4.vssps.visualstudio.com/"}}}};
    </script>
    <script type="text/javascript">
        var __cultureInfo = __vsspageContext.microsoftAjaxConfig.cultureInfo;
    </script>
    <script type="text/javascript">
        if (window.performance && window.performance.mark) { window.performance.mark('startLoadBundleOuter-basejs'); }
    </script>
    <script data-bundlelength="125076" data-bundlename="basejs"
        src="/_public/_Bundling/Content?bundle=vss-bundle-basejs-v9GpWWBnsWqhM23ijhK2HfAqLowTXGUqZLDRsBCZbkfY="
        type="text/javascript"></script>
    <script type="text/javascript">
        if (window.performance && window.performance.mark) { window.performance.mark('endLoadBundleOuter-basejs'); }
    </script>


    <script type="text/javascript">
        require.config(__vsspageContext.moduleLoaderConfig);
    </script>

    <input name="__RequestVerificationToken" type="hidden" value="4n1E6rTOw8fc0z_SO8fzjPWwH2GntNK14JNwSy_b6-63D4AUIHexBvld_xy8utkCB5esKsyGLQA-05YaMPklaRnZ1881" />






    <div class="account signin main-container hide">


        <div class="page-content">
            <div class="header-section" role="banner">


                <link rel="stylesheet" type="text/css" href="/_static/tfs/M188_20210614.1/_content/Combined.css">
                <div id="ux-header" class="FF ltr vsIntegrate" xmlns="http://www.w3.org/1999/xhtml">
                    <span id="isMobile"></span>
                    <div class="upperBand">
                        <div class="upperBandContent">
                            <div class="left"></div>
                            <div class="right">
                                <div class="profileImage"></div>

                                <div id="signIn">
                                    <a class=":SignedOutProfileElement: createProfileLink" href="/go/profile"
                                        title="Anonymous">Anonymous</a>
                                    <a class="scarabLink" href="/_signout">Sign out</a>
                                </div>
                            </div>
                            <div class="clear-both"></div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="content-section" role="main">


                <div class="signin-main-content">
                    <noscript>
                        <span class="error">Microsoft Internet Explorer&#39;s Enhanced Security Configuration is currently enabled on your environment. This enhanced level of security prevents our web integration experiences from displaying or performing correctly. To continue with your operation please disable this configuration or contact your administrator.</span>
                    </noscript>
                    <div class="provider-control">
                        <script class="options" defer="defer" type="application/json">
                            {"providerOptions":{"force":false,"orgIdAuthUrl":"https://login.microsoftonline.com/c611881e-e32d-4009-accc-0c1a258b602a/oauth2/authorize?client_id=499b84ac-1321-427f-aa17-267ca6975798\u0026site_id=501454\u0026response_mode=form_post\u0026response_type=code+id_token\u0026redirect_uri=https%3A%2F%2Fspsprodweu4.vssps.visualstudio.com%2F_signedin\u0026nonce=dae7c29c-fa33-46da-a7d8-3bcbe135a55b\u0026state=realm%3Ddev.azure.com%26reply_to%3Dhttps%253A%252F%252Fdev.azure.com%252Ftest%252Flab-test%252F_apis%252Fgit%252Frepositories%253Fapi-version%253D6.1-preview.1%26ht%3D2%26hid%3De82482f2-c6c4-429b-bf8a-20a4b358da6f%26nonce%3Ddae7c29c-fa33-46da-a7d8-3bcbe135a55b\u0026resource=https%3A%2F%2Fmanagement.core.windows.net%2F\u0026cid=dae7c29c-fa33-46da-a7d8-3bcbe135a55b\u0026wsucxt=1","user":null,"signInContext":"eyJodCI6MiwiaGlkIjoiNWRhZWZkMmetoGZhNS00NDFlLTgyZWItYjM3OTUwODcxNmZmIiwicXMiOnsicmVhbG0iOiJkZXYuYXp1cmUuY29tIiwicmVwbHlfdG8iOiJodHRwczovL2Rldi5henVyZS5jb20vdGVzdGRhdGF5L2xhYnYyLXRlc3QvX2FwaXMvZ2l0L3JlcG9zaXRvcmllcz9hcGktdmVyc2lvbj02LjEtcHJldmlldy4xIiwiaHQiOiIyIiwiaGlkIjoiZTgyNDgyZjItYzZjNC00MjliLWJmogEtMjBhNGIzNThkYTZmIiwibm9uY2UiOiJkYWU3YzI5Yy1mYTMzLTQ2ZGEtYTdkOC0zYmNiZTEzNWE1NWIifSwicnIiOiIiLCJ2aCI6IiIsImN2IjoiIiwiY3MiOiIifQ2"}}
                        </script>
                    </div>
                </div>


            </div>


        </div>





        <script type="text/javascript">
            if (window.performance && window.performance.mark) { window.performance.mark('startLoadBundleOuter-common'); }
        </script>
        <script data-bundlelength="212619" data-bundlename="common" data-includedscripts="VSS/Bundling"
            src="/_public/_Bundling/Content?bundle=vss-bundle-common-v9clbQjZeX8SFazwgF3HBRpCw_AYcSBPxtOpkg9Bv2-o="
            type="text/javascript"></script>
        <script type="text/javascript">
            if (window.performance && window.performance.mark) { window.performance.mark('endLoadBundleOuter-common'); }
        </script>
        <script type="text/javascript">
            if (window.performance && window.performance.mark) { window.performance.mark('startLoadBundleOuter-view'); }
        </script>
        <script data-bundlelength="159354" data-bundlename="view"
            data-includedscripts="Authentication/Scripts/SPS.Authentication.Controls;Authentication/Scripts/SPS.Authentication"
            src="/_public/_Bundling/Content?bundle=vss-bundle-view-vNUGsoXgRUC5b3kr3BUOKazaVcS2VmFUCbEtaFD5SGSA="
            type="text/javascript"></script>
        <script type="text/javascript">
            if (window.performance && window.performance.mark) { window.performance.mark('endLoadBundleOuter-view'); }
        </script>

        <script type="text/javascript">
            if (window.performance && window.performance.mark) { window.performance.mark('requireStart'); }
require(["Authentication/Scripts/SPS.Authentication.Controls","Authentication/Scripts/SPS.Authentication"],function(){  if (window.performance && window.performance.mark) { window.performance.mark('requireEnd'); } window.requiredModulesLoaded=true;  });
        </script>

</body>

</html> 

它要求我登录。但是当我用我的 PAT 尝试相同的 GET 请求时,它正在工作。

解决方法

如果您想在没有用户身份验证的情况下纯粹使用客户端 ID 和机密访问您的资源(API 端点),那么您正在寻找 client credentials flow(也称为双腿 OAuth)。您还需要使用 ACL 或通过 AD 分配应用程序权限为您的客户(应用程序注册)授予访问权限和角色。

一旦您实施客户端凭据流,您将获得访问令牌。然后,您可以在子请求端点请求中使用该访问令牌。

我没有在 python 中做过这个,但概念是一样的。您也可以使用 POSTMAN 进行测试:

// Obtain token using client credentials flow
POST //Line breaks for clarity
https://login.microsoftonline.com/{tenentId}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

client_id=xxxxxxxxxx
&scope=api://499b84ac-1321-427f-aa17-267ca6975798/.default
&client_secret=xxxxxxx
&grant_type=client_credentials

上述请求将在响应正文中为您提供访问令牌。然后,您可以在后续端点请求中使用访问令牌。

本文对其进行了更详细的描述:https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?