如何在C#中获取OAuth 2.0身份验证令牌

Mat*_*t C 25 c# restsharp oauth-2.0

我有一个

然后,我需要在标头中使用承载令牌进行get调用.

我可以在Postman中使用它,但是试图弄清楚如何在C#中实现它.我一直在使用RestSharp(但对其他人开放).这一切看起来都是不透明的,当我认为它非常直接时:/它是一个控制台应用程序,所以我不需要花里胡哨.

最终,我希望我的应用程序(以编程方式)获取令牌,然后将其用于后续调用.我很感激有人向我指出文档或示例,这些都解释了我明确表达的内容.我遇到的一切都是部分的,或者用于不同流程的服务.

谢谢.

Sta*_*tav 40

在Postman中,单击Generate Code,然后在Generate Code Snippets对话框中,您可以选择不同的编码语言,包括C#(RestSharp).

此外,您应该只需要访问令牌URL.然后表单参数:

grant_type=client_credentials
client_id=abc    
client_secret=123
Run Code Online (Sandbox Code Playgroud)

代码片段:

/* using RestSharp; // https://www.nuget.org/packages/RestSharp/ */

var client = new RestClient("https://service.endpoint.com/api/oauth2/token");
var request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", "grant_type=client_credentials&client_id=abc&client_secret=123", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Run Code Online (Sandbox Code Playgroud)

然后,您可以从响应正文中获取访问令牌.例如,对于Bearer令牌类型,您可以将以下标头添加到后续经过身份验证的请求中:

request.AddHeader("authorization", "Bearer <access_token>");
Run Code Online (Sandbox Code Playgroud)

  • 太棒了,工作完美 - 我会责怪菜鸟没有注意到我可以更改生成代码语言。我还发现(发布此内容后)我需要更改安全协议`ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;` 也是必需的(至少在我的情况下),遇到其他明智的状态代码“0”。 (2认同)
  • 你用的是什么命名空间,我对RestClient不熟悉 (2认同)

gra*_*der 20

Rest Client的答案非常完美!(我赞成它)

但是,以防万一你想"生"

..........

我得到了这个与HttpClient一起工作.

/*
.nuget\packages\newtonsoft.json\12.0.1
.nuget\packages\system.net.http\4.3.4
*/

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;


    private static async Task<Token> GetElibilityToken(HttpClient client)
    {
        string baseAddress = @"https://blah.blah.blah.com/token";

        string grant_type = "client_credentials";
        string client_id = "myId";
        string client_secret = "shhhhhhhhhhhhhhItsSecret";

        var form = new Dictionary<string, string>
                {
                    {"grant_type", grant_type},
                    {"client_id", client_id},
                    {"client_secret", client_secret},
                };

        HttpResponseMessage tokenResponse = await client.PostAsync(baseAddress, new FormUrlEncodedContent(form));
        var jsonContent = await tokenResponse.Content.ReadAsStringAsync();
        Token tok = JsonConvert.DeserializeObject<Token>(jsonContent);
        return tok;
    }


internal class Token
{
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }

    [JsonProperty("token_type")]
    public string TokenType { get; set; }

    [JsonProperty("expires_in")]
    public int ExpiresIn { get; set; }

    [JsonProperty("refresh_token")]
    public string RefreshToken { get; set; }
}       
Run Code Online (Sandbox Code Playgroud)

这是另一个工作示例(基于上面的答案)......还有一些调整.有时令牌服务很挑剔:

    private static async Task<Token> GetATokenToTestMyRestApiUsingHttpClient(HttpClient client)
    {
        /* this code has lots of commented out stuff with different permutations of tweaking the request  */

        /* this is a version of asking for token using HttpClient.  aka, an alternate to using default libraries instead of RestClient */

        OAuthValues oav = GetOAuthValues(); /* object has has simple string properties for TokenUrl, GrantType, ClientId and ClientSecret */

        var form = new Dictionary<string, string>
                {
                    { "grant_type", oav.GrantType },
                    { "client_id", oav.ClientId },
                    { "client_secret", oav.ClientSecret }
                };

        /* now tweak the http client */
        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Add("cache-control", "no-cache");

        /* try 1 */
        ////client.DefaultRequestHeaders.Add("content-type", "application/x-www-form-urlencoded");

        /* try 2 */
        ////client.DefaultRequestHeaders            .Accept            .Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));//ACCEPT header

        /* try 3 */
        ////does not compile */client.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

        ////application/x-www-form-urlencoded

        HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, oav.TokenUrl);
        /////req.RequestUri = new Uri(baseAddress);

        req.Content = new FormUrlEncodedContent(form);

        ////string jsonPayload = "{\"grant_type\":\"" + oav.GrantType + "\",\"client_id\":\"" + oav.ClientId + "\",\"client_secret\":\"" + oav.ClientSecret + "\"}";
        ////req.Content = new StringContent(jsonPayload,                                                Encoding.UTF8,                                                "application/json");//CONTENT-TYPE header

        req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

        /* now make the request */
        ////HttpResponseMessage tokenResponse = await client.PostAsync(baseAddress, new FormUrlEncodedContent(form));
        HttpResponseMessage tokenResponse = await client.SendAsync(req);
        Console.WriteLine(string.Format("HttpResponseMessage.ReasonPhrase='{0}'", tokenResponse.ReasonPhrase));

        if (!tokenResponse.IsSuccessStatusCode)
        {
            throw new HttpRequestException("Call to get Token with HttpClient failed.");
        }

        var jsonContent = await tokenResponse.Content.ReadAsStringAsync();
        Token tok = JsonConvert.DeserializeObject<Token>(jsonContent);

        return tok;
    }
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你!有助于尽可能将 NuGet 包保持在最低限度。 (2认同)

liv*_*ove 7

这是一个完整的例子。右键单击解决方案管理nuget包并获得Newtonsoft和RestSharp:

using Newtonsoft.Json.Linq;
using RestSharp;
using System;


namespace TestAPI
{
    class Program
    {
        static void Main(string[] args)
        {
            String id = "xxx";
            String secret = "xxx";

            var client = new RestClient("https://xxx.xxx.com/services/api/oauth2/token");
            var request = new RestRequest(Method.POST);
            request.AddHeader("cache-control", "no-cache");
            request.AddHeader("content-type", "application/x-www-form-urlencoded");
            request.AddParameter("application/x-www-form-urlencoded", "grant_type=client_credentials&scope=all&client_id=" + id + "&client_secret=" + secret, ParameterType.RequestBody);
            IRestResponse response = client.Execute(request);

            dynamic resp = JObject.Parse(response.Content);
            String token = resp.access_token;            

            client = new RestClient("https://xxx.xxx.com/services/api/x/users/v1/employees");
            request = new RestRequest(Method.GET);
            request.AddHeader("authorization", "Bearer " + token);
            request.AddHeader("cache-control", "no-cache");
            response = client.Execute(request);
        }        
    }
}
Run Code Online (Sandbox Code Playgroud)


Ank*_*jay 6

我使用 ADAL.NET/Microsoft Identity Platform来实现这一点。使用它的好处是我们可以在要获取的代码周围获得一个很好的包装器,AccessToken并且我们可以获得诸如Token Cache开箱即用的附加功能。从文档

为什么使用 ADAL.NET?

ADAL.NET V3(.NET 的 Active Directory 身份验证库)使 .NET 应用程序的开发人员能够获取令牌以调用安全的 Web API。这些 Web API 可以是 Microsoft Graph 或第 3 方 Web API。

这是代码片段:

    // Import Nuget package: Microsoft.Identity.Client
    public class AuthenticationService
    {
         private readonly List<string> _scopes;
         private readonly IConfidentialClientApplication _app;

        public AuthenticationService(AuthenticationConfiguration authentication)
        {

             _app = ConfidentialClientApplicationBuilder
                         .Create(authentication.ClientId)
                         .WithClientSecret(authentication.ClientSecret)
                         .WithAuthority(authentication.Authority)
                         .Build();

           _scopes = new List<string> {$"{authentication.Audience}/.default"};
       }

       public async Task<string> GetAccessToken()
       {
           var authenticationResult = await _app.AcquireTokenForClient(_scopes) 
                                                .ExecuteAsync();
           return authenticationResult.AccessToken;
       }
   }
Run Code Online (Sandbox Code Playgroud)

  • 不是仅限于微软代币吗? (2认同)