Link to home
Start Free TrialLog in
Avatar of Michael Sterling
Michael SterlingFlag for United States of America

asked on

I don't know how to solve my 401/unauthorized error.

I'm trying to build an API using the following tutorial: https://jasonwatmore.com/post/2019/10/21/aspnet-core-3-basic-authentication-tutorial-with-example-api
but am getting an 401 Error: Unauthorized in swagger and when I take the url from swagger and post it in a web page chrome I get: HTTP ERROR 401. I'm still learning APIs so I'm stuck on this and am not sure what to do at this point. I will give any information that is needed to get some help with this. Please and thanks in advance.
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

I am just starting to get into .NET myself. But to figure your issue, look at where you are posting to.  If you look up the 401 error code https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401 it means unauthorized.  Are you posting to a URL that you have control over?


Avatar of Michael Sterling

ASKER

@Scott Fell: I do believe I have control over the URL, I'm doin this on my laptop. I feel like there are a lot of configurations that need to be done just right in either the Startup.cs, and or the launchSettings.json file and I'm wondering if I need to check there?

I get this back on the swagger page:

access-control-allow-credentials: false  
access-control-allow-headers: Transfer-Encoding,Server,X-Powered-By,Date  
access-control-allow-methods: GETHEADPOSTPUTDELETECONNECTOPTIONSTRACEPATCH  
access-control-allow-origin: *  
access-control-expose-headers: Transfer-EncodingServerX-Powered-ByDate  
content-type: application/json; =utf-8  
date: Fri11 Sep 2020 21:01:32 GMT  server: Microsoft-IIS/10.0  
transfer-encoding: chunked  
x-content-type-options: nosniff  
x-powered-by: ASP.NET 

Open in new window


User generated image
It could be your code, but first make sure you have permissions set properly for where the app lives on your laptop.  ie localhost:44307
@Scott Fell: How/where do I check that? What am I looking for?
Right click on the folder where the app is, select Properties, then the security tab and look for iusr or iis_iurs that have at least read/execute permissions.

I found this video that does a good job of showing this https://www.youtube.com/watch?v=qRW53_Xuhi8
@Scott Fell: I'm on it right now.
@Scott Fell: I took screen captures of the security tab. The only groups/users that didn't have full control were System and Users. I changed the Users and gave them full control but still got the same error in swaggerUser generated image
User generated image
User generated image
User generated image
@Scott Fell: My response header from the request is attached:

User generated image


User generated image
I think you need add either  iusr or iis_iurs and at least give read and read/execute.

Scrub to the 46 second mark on the video https://youtu.be/qRW53_Xuhi8?t=46 and it takes you through how to find and add those accounts.

Without doing that, if you were to just save a hello world HTML file, then surf to localhost:44307/helloworld.html are you still getting the 401 error.  This would be a good clue that the issue is coming from iis vs an unauthorized from the app because you do not have a token or other authorization.

I find when I get stuck is to follow the example in the tutorial exactly as they have it, that way you can be sure any error is not from the app if that makes sense. Then once I have that working, start to modify to my own.

@Scott Fell: I tried your suggestion, to no avail. I really think it would help for me to have some more understanding of how the whole authentication piece works in APIs. I need to know how to configure the authentication better. Any suggestions? I also think that because I'm doin it on my laptop (same origin)  there may be somethings that aren't configured correctly. I've seen some things in my research that lead me to think that.

That was just to rule out the fact the local server was not rejecting you.  If you are able to create a simple HTML file and surf to it, then the issue is in the API as far as providing credentials.

API's generally work the same in two steps.  You start out supplying credentials to obtain a token and for subsequent requests supply the token typically in the header as a bearer token.  If the token is not supplied or was incorrectly created, you get the 401.  The example you are pointing to however is showing basic authentication.

In the example you provided, https://jasonwatmore.com/post/2019/10/21/aspnet-core-3-basic-authentication-tutorial-with-example-api the first call is to /users shows if the authentication is not in the header you will get the 401.  

User generated image
Iike I said earlier, the best thing to do is start with the exact example code, just get that to run. The resaon to start there is you can be pretty certain the code is good and any error is not a result of the code but the set up or perhaps data not being supplied correctly. Then build from there.

@Scott Fell: So when I send the GET, how do I make sure that I'm sending the correct authentication in the header?
For this api, you are using "Basic Auth".  https://jasonwatmore.com/post/2019/10/21/aspnet-core-3-basic-authentication-tutorial-with-example-api#running-api
User generated image
If you click the "Code" link in postman that is towards the top right, you will get a pop up where you can view code to use in different languages.

User generated image
I think it also helps to learn what is going on in the code. If you go to the github project https://github.com/cornflourblue/aspnet-core-3-basic-authentication-api/tree/4dc2a4388c9b5b39e4391515166909ffd4d31925 and search for, "Users" selecting, "In this repository" you will get 3 results showing the controller, method and service.  Looking through these will help get an understanding of what is happening. Sometimes you have to go back a few times but it does start to make sense.
User generated image
Once you have this working in Postman, it makes it easier to jump into coding what Postman is doing because you know everything should work and any new errors you get in your code are probably easily fixable. 
@Scott Fell: Thank you I'm just not getting a chance to look into what you've suggested above. I'll spend some time looking at what you've pointed me to.
@Scott Fell: After looking closer at the material as you suggested, I now have another question: The API works fine in postman but both calls (authenticate and users) fail in swagger. What would be causing this?
Now we know that your api locally works as you can hit it with postman.  Now your issue is probably in your swagger set up. I am familiar with swagger but have not used it.

Going back to postman, if you click on the code link and this time select HTTP you will see it outputs something like

GET / HTTP/1.1
Host: localhost:44307
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

That is what you need to emulate.  Looking at the docs https://swagger.io/docs/specification/authentication/ you want to use Basic Authentication https://swagger.io/docs/specification/authentication/basic-authentication/

Note the first paragraph that explains how to create the authentication string by base64-encoding username:password.

As a test, you can look at the authorization string created by postman that works and compare that to what you are submitting.  

User generated image


@Scott Fell: I'm working on this. I spent most of the night being frustrated by links that appeared to show me the correct way to configure authentication in the ConfigureServices() method in my Startup.cs file. I feel like I'm getting close but just can't get the right configuration put together in my ConfigurServices() method just yet.
Are you working from the git hub your example shows?  https://github.com/cornflourblue/aspnet-core-3-basic-authentication-api

 Because we ruled out the issue is server permissions and you can get this to work with postman, I feel like the issue is the credentials being provided may be the issue.

Let me see if I can find somebody that has used swagger.   
@Scott Fell: Thank you and I am working from that example. I'll try to go through it again to see if I'm missing something.
Essentially Swagger is just taking the place of Postman right?  So we know postman works.

If Swagger is sending a GET just like Postman did, what I would check is to run Postman and capture what is being sent to your API. Then do the same when you are accessing the API with Swagger. That should give you a clue on what to change.

See if this helps
https://www.youtube.com/watch?v=_Q6VgW04RAA

I really think the key is submitting the credentials as basic auth

Another test to be sure Swagger is seeing your API is to add a text file with any type of text and see if swagger can do a GET to that text file without any authentication. Again, we are making sure Swagger is getting to your server just to eliminate that.
@Scott Fell: I'm gonna have to struggle with tying my api that lives on my local host with this swagger inspector site. That may take me a while and some trial and error as I have no clue how to do that. I'll see what I can figure out though.
What I would do here is to stop with the demo API you are using and start the tutorials on swagger. Yes, it may feel like a long way around but it will be shorter in the long run than a lot of trial and error.  One issue may be CORS https://app.swaggerhub.com/help/ui/cors  but start at the beginning

https://app.swaggerhub.com/help/tutorials/openapi-3-tutorial
 https://app.swaggerhub.com/help/apis/creating-api

 and even just import an API that is already set up.  The pay off will be much faster and it is easier to build on from there.Then move on to your own API.
@Scott Fell: So I spent all day Sat. and Sun trying to get this figured out and it turned out that, this entire time it was a database connection issue, at least for the most part. I had to install SQL Express 2008 and make sure that it was running and then I recreated my table(s) and VIOLA it worked. I'm not sure if there is/were/are other issues with connecting to my (localdb)\\MSSQLLocalDB instance but once my API was actually able to connect then everything worked fine.
That is odd you were able to get it to work with Postman though?  At least you figured it out. It can take many trouble shooting steps to get to an issue and sometimes you get it on the first try and other times after days as you found out.
ASKER CERTIFIED SOLUTION
Avatar of Michael Sterling
Michael Sterling
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
That just goes to show you that an error message is not always directly related to the actual error which is why I had you check first if it was a web server (local) issue. I wouldn't have expected that type of error code from not having a database but I guess it makes sense that if there is no database, there is no API back end and thus no authorization.
@Scott: Agreed. Thanks again for helping me with this.

Thank you and thank you for that very nice testimonial, I really appreciate it.
No problem!