简体   繁体   English

使用AutoRest C#客户端访问带有承载令牌的Web API-TokenCredentials不起作用

[英]Using an AutoRest C# client to access a Web API with a bearer token - TokenCredentials does not work

EDIT 10/24 I think this was all likely user error - see my answer below for remedy before getting too deep into this question 编辑10/24 我认为这很可能是用户错误-在深入探讨此问题之前,请参阅下面的答案以寻求补救

TL;DR: For my OAuth 2.0 code flow... TL; DR:对于我的OAuth 2.0代码流...

Why does my TokenCredentials not work with my AutoRest client? 为什么我的TokenCredentials无法与AutoRest客户端一起使用? I'm getting NO bearer token applied to the request / no Authorization header set 我没有将不记名令牌应用于请求/未设置任何授权标头

I know my pipeline works already.. 我知道我的管道已经可以使用了。

Using code from this azure sample , which is NOT an AutoRest client, I can successfully get my access_token and can get JSON from my protected Web API project.. so I've ruled out all the prerequisite stuff.. I know my pipeline works 使用这个不是AutoRest客户端的azure示例中的代码,我可以成功获取我的access_token并可以从受保护的Web API项目中获取JSON ..因此,我排除了所有先决条件。.我知道我的管道可以工作

My AutoRest setup.. 我的AutoRest设置

1.) Downloaded from GitHub this AutoRest repo v1.1.0 1.)从GitHub下载此AutoRest存储库 v1.1.0

2.) Downloaded my swagger JSON to disk, saved as swagger.json 2.)将我的swagger JSON下载到磁盘,另存为swagger.json

3.) Ran this command-line to generate C# files: 3.)运行此命令行以生成C#文件:

autorest --input-file=swagger.json --csharp --output-folder=MyCorp_ApiClient_Tsl --namespace='MyCorp.ApiClient' --add-credentials

4.) Copied generated classes into my .NET 4.6.2 web site 4.)将生成的类复制到我的.NET 4.6.2网站中

5.) These are my NuGets: 5.)这些是我的NuGet:

- Microsoft.Rest.ClientRuntime version="2.3.8" 
- Microsoft.Rest.ClientRuntime.Azure.Authentication version="2.3.1" 
- Microsoft.IdentityModel.Clients.ActiveDirectory version="2.28.3" 

Here's what's not working: 这是行不通的:

   AdalTokenHelper tokenHelper = new AdalTokenHelper();//helper code further below

    string token = await tokenHelper.GetTokenString();
    var svcClientCreds = new TokenCredentials(token, "Bearer");

    client = new MyCorp.ApiClient(new Uri(apiRsrcUrl), svcClientCreds, 
    new DelegatingHandler[] { new MyAzureTracingHandler() });

    //make call to OData controller...        
    MyCorp.ApiClient.Models.ODataResponseListStatus statusList = await client.Status.GetStatusAsync(expand: "StatusType",cancellationToken: defaultCancelThreadToken);

    return View(statusList.Value);

I've tried variations of the above, using different ctor's of TokenCredentials , but no matter, I can put my breakpoint in MyAzureTracingHandler and see the request has no Authorization headers applied.. so I get the expected 401 Unauthorized response. 我已经尝试过使用不同的TokenCredentials ctor进行上述TokenCredentials ,但是无论如何,我可以将断点放在MyAzureTracingHandler然后查看请求是否未应用Authorization标头。.因此,我得到了预期的401 Unauthorized响应。

If I modify MyAzureTracingHandler to accept my instance of TokenCredentials then I can force the request to have the appropriate bearer token applied.. 如果我修改MyAzureTracingHandler以接受我的TokenCredentials实例,则可以强制该请求应用适当的承载令牌。

This works, but, feels hack-ish: 这可行,但是感觉有点黑:

I changed my original client instantiation snippet from this: 我从此更改了原始客户端实例化片段:

 client = new ApiClient(new Uri(apiRsrcUrl), svcClientCreds, 
 new DelegatingHandler[] { new MyAzureTracingHandler() });

To this: 对此:

 client = new ApiClient(new Uri(apiRsrcUrl), svcClientCreds, 
 new DelegatingHandler[] { new MyAzureTracingHandler(svcClientCreds) });

And inside the SendAsync method of MyAzureTracingHander I do this: MyAzureTracingHanderSendAsync方法中,我这样做:

await svcClientCreds.ProcessHttpRequestAsync(request, cancellationToken);

Am I doing something wrong? 难道我做错了什么? I don't think I should have to pass the ServiceClientCredentials in twice when instantiating my client. 我认为实例化客户端时不必两次传递ServiceClientCredentials

Appendix A - Getting access token via ADAL: 附录A-通过ADAL获取访问令牌:

    private string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
    private string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
    private string tslResourceID = ConfigurationManager.AppSettings["ross:TslWebApiResourceId"];
    private static string loginRedirectUri = ConfigurationManager.AppSettings["ross:LoginRedirectUri"];

    private AuthenticationContext authContext;
    private AuthenticationResult authenticationResult;

    public async Task<string> GetTokenString()
    {
        string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
        string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

        try
        {
            // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
            ClientCredential clientcred = new ClientCredential(clientId, appKey);

            // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
            authContext = new AuthenticationContext(Startup.Authority, new ADALTokenCache(userObjectID));


            UserIdentifier userIdentifier = new UserIdentifier(userObjectID, UserIdentifierType.UniqueId);

            authenticationResult = await authContext.AcquireTokenSilentAsync(tslResourceID, clientcred, userIdentifier);
        }
        catch(AdalException ex)
        {
            throw ex;
        }
        return authenticationResult.AccessToken;
    }

While I believe I ran my autorest command with --add-credentials it's possible I may have used the older syntax... --AddCredentials true 虽然我相信我使用--add-credentials运行了autorest命令,但可能我使用的是旧语法... --AddCredentials true

I also did not run autorest --reset as the docs recommend you do 我也没有运行autorest --reset因为文档建议您这样做

One of these is the culprit, because now my 1.1.0 autorest installation is generating everything correctly. 其中一个是元凶,因为现在我的1.1.0 autorest安装可以正确生成所有内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM