WebClient GET Request Fails With 401 Unauthorized











up vote
0
down vote

favorite












I am trying to make a GET api request with the below C# code but it fails with



System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
at System.Net.WebClient.DownloadString(Uri address)
at System.Net.WebClient.DownloadString(String address)
at Rextester.Program.callAPI()
at Rextester.Program.Main(String args)


Note that the same API request works through postman.



private static void callAPI()
{

WebClient client = new WebClient();
client.UseDefaultCredentials = false;

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

client.Headers.Add("Authorization", "Basic " + Base64Encode("<id:password>"));
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("Environment-Id", "325");

client.QueryString.Add("query", "%7B%7D");

string reply = client.DownloadString("https://<server-api-url>");

Console.WriteLine(reply);
}


private static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
var encodedS = System.Convert.ToBase64String(plainTextBytes);
Console.WriteLine(encodedS);
return encodedS;
}


One more strange fact is that I see the exception printed before the encoded string. It should I think the other way round. The encoded string should be printed before since the method call happens before making the api call.










share|improve this question
























  • Where's the API request that works with Postman? If you use a debugging proxy like Fiddler to see what's actually going on I'll bet you'll find the requests are not the same.
    – Panagiotis Kanavos
    Nov 19 at 8:14










  • What does "<id:password>" represent? In Basic authentication the string should be username:password, eg $"{username}:{password}" or username + ":" + password or String.Format("{0}:{1}", username,password)
    – Panagiotis Kanavos
    Nov 19 at 8:20












  • I have added dummy values for not exposing production environment details. You are right about the format of the authentication string. It is in the format "username:password".
    – Andy Dufresne
    Nov 19 at 8:25












  • You are forcing people to guess right now. Are you using <> or not? If yes, that's a mistake. If not, there's nothing else that can help understand what's wrong. What should the request look like? What did the Postman request look like in Fiddler? What did the WebClient look like? If the authentication headers are different you'll know the Base64Encode methods is wrong.If there's another difference, what is it?
    – Panagiotis Kanavos
    Nov 19 at 8:30












  • Thanks for pointing me in the right direction. Through fiddler I understood that the api call is actually getting redirected (with http status code 307) and on the second request the authorization header is not being passed. How do I enable redirects in C#?
    – Andy Dufresne
    Nov 19 at 9:06















up vote
0
down vote

favorite












I am trying to make a GET api request with the below C# code but it fails with



System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
at System.Net.WebClient.DownloadString(Uri address)
at System.Net.WebClient.DownloadString(String address)
at Rextester.Program.callAPI()
at Rextester.Program.Main(String args)


Note that the same API request works through postman.



private static void callAPI()
{

WebClient client = new WebClient();
client.UseDefaultCredentials = false;

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

client.Headers.Add("Authorization", "Basic " + Base64Encode("<id:password>"));
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("Environment-Id", "325");

client.QueryString.Add("query", "%7B%7D");

string reply = client.DownloadString("https://<server-api-url>");

Console.WriteLine(reply);
}


private static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
var encodedS = System.Convert.ToBase64String(plainTextBytes);
Console.WriteLine(encodedS);
return encodedS;
}


One more strange fact is that I see the exception printed before the encoded string. It should I think the other way round. The encoded string should be printed before since the method call happens before making the api call.










share|improve this question
























  • Where's the API request that works with Postman? If you use a debugging proxy like Fiddler to see what's actually going on I'll bet you'll find the requests are not the same.
    – Panagiotis Kanavos
    Nov 19 at 8:14










  • What does "<id:password>" represent? In Basic authentication the string should be username:password, eg $"{username}:{password}" or username + ":" + password or String.Format("{0}:{1}", username,password)
    – Panagiotis Kanavos
    Nov 19 at 8:20












  • I have added dummy values for not exposing production environment details. You are right about the format of the authentication string. It is in the format "username:password".
    – Andy Dufresne
    Nov 19 at 8:25












  • You are forcing people to guess right now. Are you using <> or not? If yes, that's a mistake. If not, there's nothing else that can help understand what's wrong. What should the request look like? What did the Postman request look like in Fiddler? What did the WebClient look like? If the authentication headers are different you'll know the Base64Encode methods is wrong.If there's another difference, what is it?
    – Panagiotis Kanavos
    Nov 19 at 8:30












  • Thanks for pointing me in the right direction. Through fiddler I understood that the api call is actually getting redirected (with http status code 307) and on the second request the authorization header is not being passed. How do I enable redirects in C#?
    – Andy Dufresne
    Nov 19 at 9:06













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I am trying to make a GET api request with the below C# code but it fails with



System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
at System.Net.WebClient.DownloadString(Uri address)
at System.Net.WebClient.DownloadString(String address)
at Rextester.Program.callAPI()
at Rextester.Program.Main(String args)


Note that the same API request works through postman.



private static void callAPI()
{

WebClient client = new WebClient();
client.UseDefaultCredentials = false;

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

client.Headers.Add("Authorization", "Basic " + Base64Encode("<id:password>"));
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("Environment-Id", "325");

client.QueryString.Add("query", "%7B%7D");

string reply = client.DownloadString("https://<server-api-url>");

Console.WriteLine(reply);
}


private static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
var encodedS = System.Convert.ToBase64String(plainTextBytes);
Console.WriteLine(encodedS);
return encodedS;
}


One more strange fact is that I see the exception printed before the encoded string. It should I think the other way round. The encoded string should be printed before since the method call happens before making the api call.










share|improve this question















I am trying to make a GET api request with the below C# code but it fails with



System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
at System.Net.WebClient.DownloadString(Uri address)
at System.Net.WebClient.DownloadString(String address)
at Rextester.Program.callAPI()
at Rextester.Program.Main(String args)


Note that the same API request works through postman.



private static void callAPI()
{

WebClient client = new WebClient();
client.UseDefaultCredentials = false;

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

client.Headers.Add("Authorization", "Basic " + Base64Encode("<id:password>"));
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("Environment-Id", "325");

client.QueryString.Add("query", "%7B%7D");

string reply = client.DownloadString("https://<server-api-url>");

Console.WriteLine(reply);
}


private static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
var encodedS = System.Convert.ToBase64String(plainTextBytes);
Console.WriteLine(encodedS);
return encodedS;
}


One more strange fact is that I see the exception printed before the encoded string. It should I think the other way round. The encoded string should be printed before since the method call happens before making the api call.







c# api webclient unauthorized






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 19 at 10:05









Ashish Kamble

629419




629419










asked Nov 19 at 8:10









Andy Dufresne

3,51362964




3,51362964












  • Where's the API request that works with Postman? If you use a debugging proxy like Fiddler to see what's actually going on I'll bet you'll find the requests are not the same.
    – Panagiotis Kanavos
    Nov 19 at 8:14










  • What does "<id:password>" represent? In Basic authentication the string should be username:password, eg $"{username}:{password}" or username + ":" + password or String.Format("{0}:{1}", username,password)
    – Panagiotis Kanavos
    Nov 19 at 8:20












  • I have added dummy values for not exposing production environment details. You are right about the format of the authentication string. It is in the format "username:password".
    – Andy Dufresne
    Nov 19 at 8:25












  • You are forcing people to guess right now. Are you using <> or not? If yes, that's a mistake. If not, there's nothing else that can help understand what's wrong. What should the request look like? What did the Postman request look like in Fiddler? What did the WebClient look like? If the authentication headers are different you'll know the Base64Encode methods is wrong.If there's another difference, what is it?
    – Panagiotis Kanavos
    Nov 19 at 8:30












  • Thanks for pointing me in the right direction. Through fiddler I understood that the api call is actually getting redirected (with http status code 307) and on the second request the authorization header is not being passed. How do I enable redirects in C#?
    – Andy Dufresne
    Nov 19 at 9:06


















  • Where's the API request that works with Postman? If you use a debugging proxy like Fiddler to see what's actually going on I'll bet you'll find the requests are not the same.
    – Panagiotis Kanavos
    Nov 19 at 8:14










  • What does "<id:password>" represent? In Basic authentication the string should be username:password, eg $"{username}:{password}" or username + ":" + password or String.Format("{0}:{1}", username,password)
    – Panagiotis Kanavos
    Nov 19 at 8:20












  • I have added dummy values for not exposing production environment details. You are right about the format of the authentication string. It is in the format "username:password".
    – Andy Dufresne
    Nov 19 at 8:25












  • You are forcing people to guess right now. Are you using <> or not? If yes, that's a mistake. If not, there's nothing else that can help understand what's wrong. What should the request look like? What did the Postman request look like in Fiddler? What did the WebClient look like? If the authentication headers are different you'll know the Base64Encode methods is wrong.If there's another difference, what is it?
    – Panagiotis Kanavos
    Nov 19 at 8:30












  • Thanks for pointing me in the right direction. Through fiddler I understood that the api call is actually getting redirected (with http status code 307) and on the second request the authorization header is not being passed. How do I enable redirects in C#?
    – Andy Dufresne
    Nov 19 at 9:06
















Where's the API request that works with Postman? If you use a debugging proxy like Fiddler to see what's actually going on I'll bet you'll find the requests are not the same.
– Panagiotis Kanavos
Nov 19 at 8:14




Where's the API request that works with Postman? If you use a debugging proxy like Fiddler to see what's actually going on I'll bet you'll find the requests are not the same.
– Panagiotis Kanavos
Nov 19 at 8:14












What does "<id:password>" represent? In Basic authentication the string should be username:password, eg $"{username}:{password}" or username + ":" + password or String.Format("{0}:{1}", username,password)
– Panagiotis Kanavos
Nov 19 at 8:20






What does "<id:password>" represent? In Basic authentication the string should be username:password, eg $"{username}:{password}" or username + ":" + password or String.Format("{0}:{1}", username,password)
– Panagiotis Kanavos
Nov 19 at 8:20














I have added dummy values for not exposing production environment details. You are right about the format of the authentication string. It is in the format "username:password".
– Andy Dufresne
Nov 19 at 8:25






I have added dummy values for not exposing production environment details. You are right about the format of the authentication string. It is in the format "username:password".
– Andy Dufresne
Nov 19 at 8:25














You are forcing people to guess right now. Are you using <> or not? If yes, that's a mistake. If not, there's nothing else that can help understand what's wrong. What should the request look like? What did the Postman request look like in Fiddler? What did the WebClient look like? If the authentication headers are different you'll know the Base64Encode methods is wrong.If there's another difference, what is it?
– Panagiotis Kanavos
Nov 19 at 8:30






You are forcing people to guess right now. Are you using <> or not? If yes, that's a mistake. If not, there's nothing else that can help understand what's wrong. What should the request look like? What did the Postman request look like in Fiddler? What did the WebClient look like? If the authentication headers are different you'll know the Base64Encode methods is wrong.If there's another difference, what is it?
– Panagiotis Kanavos
Nov 19 at 8:30














Thanks for pointing me in the right direction. Through fiddler I understood that the api call is actually getting redirected (with http status code 307) and on the second request the authorization header is not being passed. How do I enable redirects in C#?
– Andy Dufresne
Nov 19 at 9:06




Thanks for pointing me in the right direction. Through fiddler I understood that the api call is actually getting redirected (with http status code 307) and on the second request the authorization header is not being passed. How do I enable redirects in C#?
– Andy Dufresne
Nov 19 at 9:06












1 Answer
1






active

oldest

votes

















up vote
0
down vote



accepted










After getting some guidance from @Panagiotis Kanavos I traced the api calls from Fiddler and understood that the api call was getting redirected (http status code - 307). The C# client is by default configured to not pass the authorization header on a redirect. Hence I got a 401 Unauthorized error.
This was fixed by adding a check for 401 status code and resending the api request with the authorization header.



Thanks @Panagiotis Kanavos for the help






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53370591%2fwebclient-get-request-fails-with-401-unauthorized%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote



    accepted










    After getting some guidance from @Panagiotis Kanavos I traced the api calls from Fiddler and understood that the api call was getting redirected (http status code - 307). The C# client is by default configured to not pass the authorization header on a redirect. Hence I got a 401 Unauthorized error.
    This was fixed by adding a check for 401 status code and resending the api request with the authorization header.



    Thanks @Panagiotis Kanavos for the help






    share|improve this answer

























      up vote
      0
      down vote



      accepted










      After getting some guidance from @Panagiotis Kanavos I traced the api calls from Fiddler and understood that the api call was getting redirected (http status code - 307). The C# client is by default configured to not pass the authorization header on a redirect. Hence I got a 401 Unauthorized error.
      This was fixed by adding a check for 401 status code and resending the api request with the authorization header.



      Thanks @Panagiotis Kanavos for the help






      share|improve this answer























        up vote
        0
        down vote



        accepted







        up vote
        0
        down vote



        accepted






        After getting some guidance from @Panagiotis Kanavos I traced the api calls from Fiddler and understood that the api call was getting redirected (http status code - 307). The C# client is by default configured to not pass the authorization header on a redirect. Hence I got a 401 Unauthorized error.
        This was fixed by adding a check for 401 status code and resending the api request with the authorization header.



        Thanks @Panagiotis Kanavos for the help






        share|improve this answer












        After getting some guidance from @Panagiotis Kanavos I traced the api calls from Fiddler and understood that the api call was getting redirected (http status code - 307). The C# client is by default configured to not pass the authorization header on a redirect. Hence I got a 401 Unauthorized error.
        This was fixed by adding a check for 401 status code and resending the api request with the authorization header.



        Thanks @Panagiotis Kanavos for the help







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 22 at 3:49









        Andy Dufresne

        3,51362964




        3,51362964






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53370591%2fwebclient-get-request-fails-with-401-unauthorized%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

            Alcedinidae

            RAC Tourist Trophy