Search code examples
c#jsonvisual-studiodotnet-httpclient

C# httpclient authorize header not working for me?


I'm trying to make an app that lets me query the database from discogs.

According to the API documentation I can do this with just a token, so I registered and got a user token.

Now when I use postman with https://api.discogs.com/database/search?release_title=nevermind&artist=nirvana&per_page=3&page=1&token=<my_user_token> I receive the JSON like I would expect.

But when I make a httpclient in C# with the token:

    public string token = <my_user_token>;
    public static HttpClient client { get; set; }
    public static async Task InitilizeClient()
    {
        await GetAccesToken();
    }

    private static async Task GetAccesToken()
    {
        client = new HttpClient();
        client.DefaultRequestHeaders.Accept.Clear();
        client.BaseAddress = new Uri(@"https://api.discogs.com");
        //client.DefaultRequestHeaders.Authorization=new AuthenticationHeaderValue("Discogs", "token="+token);
        client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization","Discogs token=" + token);
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    }

and then use the client like this

    public static async Task QueryDataBaseAsync(string query)
    {
       if (query == null)
        {
            throw new Exception("query is empty");
        }
        string url = "";
        url = @"https://api.discogs.com/database/search?release_title="+query;
        if (client == null)
        {
            await InitilizeClient();
        }
        using (HttpResponseMessage response = await client.GetAsync(url))
        {
            if (response.IsSuccessStatusCode)
            {

            }
            else
            {
                throw new Exception(response.ReasonPhrase + " \n" + response.RequestMessage.ToString());
            }
        }

    }

then I always get:

ReasonPhrase "forbidden","statuscode: 403"

when I put a breakpoint on my HttpResponseMessage response I can see that under "headers"=>"responsemessage"=>"headers"=>"authorization" it has my token.

What am I doing wrong?

PS. I'm new at programming so I would appreciate it if you could explain what I did wrong


Solution

  • You may need to provide user-agent in the headers. Something along these lines:

    client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36");
    

    like this:

    public class DiscConsumer
    {
        //https://www.discogs.com/developers#page:authentication,header:authentication-discogs-auth-flow
        //curl "https://api.discogs.com/database/search?q=Nirvana" -H "Authorization: Discogs key=foo123, secret=bar456"
    
        private const string _urlQuery = "https://api.discogs.com/database/search?q={query}";
        private const string _key = "<....your key....>";
        private const string _secret = "<....your secret...>";
    
        private System.Net.Http.HttpClient _httpClient;
        public async Task InitilizeClient()
        {
            //ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
            var sslhandler = new HttpClientHandler()
            {
                //...in System.Security.Authentication.SslProtocols
                SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
            };
            _httpClient = new System.Net.Http.HttpClient(sslhandler);
            string authorization = $"Discogs key={_key}, secret={_secret}";
            _httpClient.DefaultRequestHeaders.Add("Authorization", authorization);
            _httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36");
        }
    
        public async Task QueryDataBaseAsync(string query)
        {
            if (String.IsNullOrWhiteSpace( query ))
            {
                throw new Exception("query is empty");
            }
            string url = "";
            url = _urlQuery.Replace("{query}", query);
            if (_httpClient == null)
            {
                await InitilizeClient();
            }
            using (HttpResponseMessage response = await _httpClient.GetAsync(url))
            {
                if (response.IsSuccessStatusCode)
                {
                    string s = await response.Content.ReadAsStringAsync();
                    Console.WriteLine(s);
                }
                else
                {
                    throw new Exception(response.ReasonPhrase + " \n" + response.RequestMessage.ToString());
                }
            }
        }
    }
    

    Per https://www.discogs.com/developers#page:authentication,header:authentication-discogs-auth-flow you can supply key+secret on every request along with search.