Rectangle 27 30

If authenticating as another user would grant access to the requested resource, then 401 Unauthorized should be returned. 403 Forbidden is mostly used when access to the resource is forbidden to everyone or restricted to a given network or allowed only over SSL, whatever as long as it is no related to authentication.

From RFC 7235 (Hypertext Transfer Protocol (HTTP/1.1): Authentication):

The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource. The origin server MUST send a WWW-Authenticate header field (Section 4.4) containing at least one challenge applicable to the target resource. If the request included authentication credentials, then the 401 response indicates that authorization has been refused for those credentials. The client MAY repeat the request with a new or replaced Authorization header field (Section 4.1). If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user agent SHOULD present the enclosed representation to the user, since it usually contains relevant diagnostic information.

And this is from RFC 2616:

The server understood the request, but is refusing to fulfill it.Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.

Edit: RFC 7231 (Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content) changes the meaning of 403:

The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it. A server that wishes to make public why the request has been forbidden can describe that reason in the response payload (if any).

If authentication credentials were provided in the request, the server considers them insufficient to grant access. The client SHOULD NOT automatically repeat the request with the same credentials. The client MAY repeat the request with new or different credentials. However, a request might be forbidden for reasons unrelated to the credentials.

An origin server that wishes to "hide" the current existence of a forbidden target resource MAY instead respond with a status code of 404 (Not Found).

Thus, a 403 might now mean about anything. Providing new credentials might help... or it might not.

This is interesting. Based on RFC 7231 and RFC 7235, I don't see an obvious distinction between 401 and 403

403 means "I know you but you can't see this resource." There's no reason for confusion.

403 Forbidden vs 401 Unauthorized HTTP responses - Stack Overflow

http-headers http-status-code-403 http-status-codes http-status-code-401 http-response-codes
Rectangle 27 4

401 Unauthorized is specifically for when authorization is required but not provided (or not provided correctly.

In your scenario, you'd only send the WWW-Authenticate header for requests that require authentication - if the auth is cancelled or not satisfactory, you then return 401.

Users would not be prompted to auth until making a request that requires it. No requests have optional authentication - the request is either allowed to anonymous users or not.

It's worth noting that HTTP auth is a bad choice for website logins, for a few reasons:

  • there is no concept of logging out
  • authentication details are sent in plain text (unless over SSL)
  • there is no such thing as a password reminder, self-registration, minimum password requirements etc

I was not going to use it for login, but thanks for the clarification about "No requests have optional authentication"

authentication - optional http basic auth - Stack Overflow

http authentication wget
Rectangle 27 280

When it was first developed, System.Web.Mvc.AuthorizeAttribute was doing the right thing - older revisions of the HTTP specification used status code 401 for both "unauthorized" and "unauthenticated".

If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials.

In fact, you can see the confusion right there - it uses the word "authorization" when it means "authentication". In everyday practice, however, it makes more sense to return a 403 Forbidden when the user is authenticated but not authorized. It's unlikely the user would have a second set of credentials that would give them access - bad user experience all around.

Consider most operating systems - when you attempt to read a file you don't have permission to access, you aren't shown a login screen!

Thankfully, the HTTP specifications were updated (June 2014) to remove the ambiguity.

From "Hyper Text Transport Protocol (HTTP/1.1): Authentication" (RFC 7235):

The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource.

From "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content" (RFC 7231):

The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it.

Interestingly enough, at the time ASP.NET MVC 1 was released the behavior of AuthorizeAttribute was correct. Now, the behavior is incorrect - the HTTP/1.1 specification was fixed.

Rather than attempt to change ASP.NET's login page redirects, it's easier just to fix the problem at the source. You can create a new attribute with the same name (AuthorizeAttribute) in your website's default namespace (this is very important) then the compiler will automatically pick it up instead of MVC's standard one. Of course, you could always give the attribute a new name if you'd rather take that approach.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}
filterContext.HttpContext.User.Identity.IsAuthenticated
filterContext.HttpContext.Request.IsAuthenticated

Great idea - I've updated the answer.

> You can create a new attribute with the same name (AuthorizeAttribute) in your website's default namespace then the compiler will automatically pick it up instead of MVC's standard one. This results in an error: The type or namespace 'Authorize' could not be found ( are you missing a directive or an assembly reference?) Both using System.Web.Mvc; and the namespace for my custom AuthorizeAttribute class are referenced in the controller. To solve this I had to use [MyNamepace.Authorize]

@DePeter the spec never says anything about a redirect so why is a redirect a better solution? This alone kills ajax requests without a hack in place to solve it.

asp.net mvc - Why does AuthorizeAttribute redirect to the login page f...

asp.net-mvc authentication authorization
Rectangle 27 280

When it was first developed, System.Web.Mvc.AuthorizeAttribute was doing the right thing - older revisions of the HTTP specification used status code 401 for both "unauthorized" and "unauthenticated".

If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials.

In fact, you can see the confusion right there - it uses the word "authorization" when it means "authentication". In everyday practice, however, it makes more sense to return a 403 Forbidden when the user is authenticated but not authorized. It's unlikely the user would have a second set of credentials that would give them access - bad user experience all around.

Consider most operating systems - when you attempt to read a file you don't have permission to access, you aren't shown a login screen!

Thankfully, the HTTP specifications were updated (June 2014) to remove the ambiguity.

From "Hyper Text Transport Protocol (HTTP/1.1): Authentication" (RFC 7235):

The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource.

From "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content" (RFC 7231):

The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it.

Interestingly enough, at the time ASP.NET MVC 1 was released the behavior of AuthorizeAttribute was correct. Now, the behavior is incorrect - the HTTP/1.1 specification was fixed.

Rather than attempt to change ASP.NET's login page redirects, it's easier just to fix the problem at the source. You can create a new attribute with the same name (AuthorizeAttribute) in your website's default namespace (this is very important) then the compiler will automatically pick it up instead of MVC's standard one. Of course, you could always give the attribute a new name if you'd rather take that approach.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}
filterContext.HttpContext.User.Identity.IsAuthenticated
filterContext.HttpContext.Request.IsAuthenticated

Great idea - I've updated the answer.

> You can create a new attribute with the same name (AuthorizeAttribute) in your website's default namespace then the compiler will automatically pick it up instead of MVC's standard one. This results in an error: The type or namespace 'Authorize' could not be found ( are you missing a directive or an assembly reference?) Both using System.Web.Mvc; and the namespace for my custom AuthorizeAttribute class are referenced in the controller. To solve this I had to use [MyNamepace.Authorize]

@DePeter the spec never says anything about a redirect so why is a redirect a better solution? This alone kills ajax requests without a hack in place to solve it.

asp.net mvc - Why does AuthorizeAttribute redirect to the login page f...

asp.net-mvc authentication authorization
Rectangle 27 279

When it was first developed, System.Web.Mvc.AuthorizeAttribute was doing the right thing - older revisions of the HTTP specification used status code 401 for both "unauthorized" and "unauthenticated".

If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials.

In fact, you can see the confusion right there - it uses the word "authorization" when it means "authentication". In everyday practice, however, it makes more sense to return a 403 Forbidden when the user is authenticated but not authorized. It's unlikely the user would have a second set of credentials that would give them access - bad user experience all around.

Consider most operating systems - when you attempt to read a file you don't have permission to access, you aren't shown a login screen!

Thankfully, the HTTP specifications were updated (June 2014) to remove the ambiguity.

From "Hyper Text Transport Protocol (HTTP/1.1): Authentication" (RFC 7235):

The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource.

From "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content" (RFC 7231):

The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it.

Interestingly enough, at the time ASP.NET MVC 1 was released the behavior of AuthorizeAttribute was correct. Now, the behavior is incorrect - the HTTP/1.1 specification was fixed.

Rather than attempt to change ASP.NET's login page redirects, it's easier just to fix the problem at the source. You can create a new attribute with the same name (AuthorizeAttribute) in your website's default namespace (this is very important) then the compiler will automatically pick it up instead of MVC's standard one. Of course, you could always give the attribute a new name if you'd rather take that approach.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}
filterContext.HttpContext.User.Identity.IsAuthenticated
filterContext.HttpContext.Request.IsAuthenticated

Great idea - I've updated the answer.

> You can create a new attribute with the same name (AuthorizeAttribute) in your website's default namespace then the compiler will automatically pick it up instead of MVC's standard one. This results in an error: The type or namespace 'Authorize' could not be found ( are you missing a directive or an assembly reference?) Both using System.Web.Mvc; and the namespace for my custom AuthorizeAttribute class are referenced in the controller. To solve this I had to use [MyNamepace.Authorize]

@DePeter the spec never says anything about a redirect so why is a redirect a better solution? This alone kills ajax requests without a hack in place to solve it.

asp.net mvc - Why does AuthorizeAttribute redirect to the login page f...

asp.net-mvc authentication authorization
Rectangle 27 45

This error happens because the server sends a 401 (Unauthorized) but does not give a WWW-Authenticate header which is a hint to the client what to do next. The WWW-Authenticate header tells the client, which kind of authentication is needed (either Basic or Digest). This is probably not very useful in headless http clients, but that's how the HTTP 1.1 RFC is defined. The error occurs because the lib tries to parse the WWW-Authenticate header but can't.

(...)The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource.(...)

Possible solutions if you can change the server:

  • Add a fake "WWW-Authenticate" header like: WWW-Authenticate: Basic realm="fake". This is a mere workaround not a solution, but it should work and the http client is satisfied (see here a discussion of what you can put in the header). But beware that some http clients may automatically retry the request resulting in multiple requests (e.g. increments the wrong login count too often). This was observed with the iOS http client.
  • As proposed by loudvchar in this blog to avoid automatic reactions to the challenge like a pop-up login form in a browser, you can use a non-standard authentication method like so: WWW-Authenticate: xBasic realm="fake". The important point is that the realm has to be included.
  • Use HTTP status code 403 instead of 401. It's semantic is not the same and usually when working with login 401 is a correct response (see here for a detailed discussion) but the safer solution in terms of compatibility.

Possible solutions if you can't change the server:

  • As @ErikZ wrote in his post you could use a try&catch HttpURLConnection connection = ...; try { // Will throw IOException if server responds with 401. connection.getResponseCode(); } catch (IOException e) { // Will return 401, because now connection has the correct internal state. int responsecode = connection.getResponseCode(); }

Cool man, I swear I saw a different behavior, anyway just tested what you are saying and is correct +1...

I'm having this problem on one Android device but not another, I guess some OEMs overwrite the HttpUrlConnection class? Either way, this fix worked.

You are a god among men.

android - java.io.IOException : No authentication challenges found - S...

java android authentication httpurlconnection ioexception
Rectangle 27 45

This error happens because the server sends a 401 (Unauthorized) but does not give a WWW-Authenticate header which is a hint to the client what to do next. The WWW-Authenticate header tells the client, which kind of authentication is needed (either Basic or Digest). This is probably not very useful in headless http clients, but that's how the HTTP 1.1 RFC is defined. The error occurs because the lib tries to parse the WWW-Authenticate header but can't.

(...)The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource.(...)

Possible solutions if you can change the server:

  • Add a fake "WWW-Authenticate" header like: WWW-Authenticate: Basic realm="fake". This is a mere workaround not a solution, but it should work and the http client is satisfied (see here a discussion of what you can put in the header). But beware that some http clients may automatically retry the request resulting in multiple requests (e.g. increments the wrong login count too often). This was observed with the iOS http client.
  • As proposed by loudvchar in this blog to avoid automatic reactions to the challenge like a pop-up login form in a browser, you can use a non-standard authentication method like so: WWW-Authenticate: xBasic realm="fake". The important point is that the realm has to be included.
  • Use HTTP status code 403 instead of 401. It's semantic is not the same and usually when working with login 401 is a correct response (see here for a detailed discussion) but the safer solution in terms of compatibility.

Possible solutions if you can't change the server:

  • As @ErikZ wrote in his post you could use a try&catch HttpURLConnection connection = ...; try { // Will throw IOException if server responds with 401. connection.getResponseCode(); } catch (IOException e) { // Will return 401, because now connection has the correct internal state. int responsecode = connection.getResponseCode(); }

Cool man, I swear I saw a different behavior, anyway just tested what you are saying and is correct +1...

I'm having this problem on one Android device but not another, I guess some OEMs overwrite the HttpUrlConnection class? Either way, this fix worked.

You are a god among men.

android - java.io.IOException : No authentication challenges found - S...

java android authentication httpurlconnection ioexception
Rectangle 27 8

This error happens because the server sends a 401 (Unauthorized) but does not give a "WWW-Authenticate" which is a hint for the client what to do next. The "WWW-Authenticate" Header tells the client which kind of authentication is needed (either Basic or Digest). This is usually not very useful in headless http clients, but that's how the standard is defined. The error occurs because the lib tries to parse the "WWW-Authenticate" header but can't.

Possible solutions if you can change the server:

  • Add a fake "WWW-Authenticate" header like: WWW-Authenticate: Basic realm="fake". This is a mere workaround not a solution, but it should work and the http client is satisfied.
  • Use HTTP status code 403 instead of 401. It's semantic is not the same and usually when working with login 401 is a correct response (see here for a detailed discussion) but its close enough.

Possible solutions if you can't change the server:

As @ErikZ wrote in his post you could use a try&catch

HttpURLConnection connection = ...;
try {
    // Will throw IOException if server responds with 401.
    connection.getResponseCode(); 
} catch (IOException e) {
    // Will return 401, because now connection has the correct internal state.
    int responsecode = connection.getResponseCode(); 
}

I'm trying to send a header with Digest authentication, but can't figured out how to do it (still searching for an answer). Do you have any sample on how to do a Digest (or even basic) authentication in Android-Volley?

Basic and Digest is just putting a header that looks like this "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" in Basic and more complicated in digest - this is not special to volley, you just put set headers (google on how to do that in volley)

I'm sorry I asked this question so long ago I don't even remember what it relates to, plus that legacy project has been shut down. I'll upvote your answer for effort you've put in, but have no way of checking it's right so won't select it as the answer I'm afraid.

Fair enough. Ill leave it since it took me quite a while to understand the problem - learning REST/HTTP spec isn't sometimes as straight forward as you think :)

how to add WWW-Authenticate header in the server response

android - volley error No authentication challenges found - Stack Over...

android authentication android-volley
Rectangle 27 229

Brief and Terse

Something the other answers are missing is that it must be understood that Authentication and Authorization in the context of RFC 2616 refers ONLY to the HTTP Authentication protocol of RFC 2617. Authentication by schemes outside of RFC2617 are not supported in HTTP status codes and are not considered when deciding whether to use 401 or 403..

Unauthorized indicates that the client is not RFC2617 authenticated and the server is initiating the authentication process. Forbidden indicates either that the client is RFC2617 authenticated and does not have authorization or that the server does not support RFC2617 for the requested resource.

Meaning if you have your own roll-your-own login process and never use HTTP Authentication, 403 is always the proper response and 401 should never be used.

The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8).

and

10.4.4 403 Forbidden The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated.

The first thing to keep in mind is that "Authentication" and "Authorization" in the context of this document refer specifically to the HTTP Authentication protocols from RFC 2617. They do not refer to any roll-your-own authentication protocols you may have created using login pages, etc. I will use "login" to refer to authentication and authorization by methods other than RFC2617

So the real difference is not what the problem is or even if there is a solution. The difference is what the server expects the client to do next.

401 indicates that the resource can not be provided, but the server is REQUESTING that the client log in through HTTP Authentication and has sent reply headers to initiate the process. Possibly there are authorizations that will permit access to the resource, possibly there are not, but lets give it a try and see what happens.

403 indicates that the resource can not be provided and there is, for the current user, no way to solve this through RFC2617 and no point in trying. This may be because it is known that no level of authentication is sufficient (for instance because of an IP blacklist), but it may be because the user is already authenticated and does not have authority. The RFC2617 model is one-user, one-credentials so the case where the user may have a second set of credentials that could be authorized may be ignored. It neither suggests nor implies that some sort of login page or other non-RFC2617 authentication protocol may or may not help - that is outside the RFC2616 standards and definition.

So what should we do when the user requests a page that requires non-http authentication? Send status code 403?

This is important: "if you have your own roll-your-own login process and never use HTTP Authentication, 403 is always the proper response and 401 should never be used."

Doesn't RFC7235 provide for "roll-your-own" or alternate auth challenges? Why can't my app's login flow present its challenge in the form of a WWW-Authenticate header? Even if a browser doesn't support it, my React app can...

403 Forbidden vs 401 Unauthorized HTTP responses - Stack Overflow

http-headers http-status-code-403 http-status-codes http-status-code-401 http-response-codes
Rectangle 27 4

<?php
    /*
    ** Define a couple of functions for
    ** starting and ending an HTML document
    */
    function startPage()
    {
        print("<html>\n");
        print("<head>\n");
        print("<title>Listing 24-1</title>\n");
        print("</head>\n");
        print("<body>\n");
    }

    function endPage()
    {
        print("</body>\n");
        print("</html>\n");
    }
    /*
    ** test for username/password
    */
    if( ( isset($_SERVER['PHP_AUTH_USER'] ) && ( $_SERVER['PHP_AUTH_USER'] == "leon" ) ) AND
      ( isset($_SERVER['PHP_AUTH_PW'] ) && ( $_SERVER['PHP_AUTH_PW'] == "secret" )) )
    {
        startPage();

        print("You have logged in successfully!<br>\n");

        endPage();
    }
    else
    {
        //Send headers to cause a browser to request
        //username and password from user
        header("WWW-Authenticate: " .
            "Basic realm=\"Leon's Protected Area\"");
        header("HTTP/1.0 401 Unauthorized");

        //Show failure text, which browsers usually
        //show only after several failed attempts
        print("This page is protected by HTTP " .
            "Authentication.<br>\nUse <b>leon</b> " .
            "for the username, and <b>secret</b> " .
            "for the password.<br>\n");
    }
?>

How can I use Basic HTTP Authentication in PHP? - Stack Overflow

php authentication http-authentication http-basic-authentication server-variables
Rectangle 27 1

Your problem is not with AJAX request, your problem is returning HTTP 401 Unauthorized response, because you use forms authentication. This response code tells the framework that it should redirect the user-agent to your login page with a HTTP 302 response instead. That's why it was easy to setup the "normal" request redirect - it's done automatically. To answer your question, I had similar problem and the solution I ended up with was not using forms authentication. I implemented a custom authorization attribute that handles both cases manually instead. I'm not sure if this is the best approach, but it does work. I'm interested in what others think of this solution or what other solutions there are. Fortunately, you can still use the FormsAuthentication class to handle cookies for you, but you have to delete the forms authentication configuration from your Web.config file. When the user logs in you use FormsAuthentication.SetAuthCookie to, well, set a cookie (you are probably doing this already). Second, in your authorization attribute, you get the cookie from the request and use FormsAuthentication.Decrypt to decrypt it. If it exists and is valid, you set the user in the HttpContext based on this cookie, because forms authentication won't do it for you anymore. If it doesn't you either redirect to the login page or return 401, depending on whether it's an AJAX call or not.

security - Asp.net Mvc custom mechanism to handle unauthorized request...

asp.net-mvc security asp.net-mvc-3 asp.net-mvc-2 unauthorized
Rectangle 27 2

If the origin server does not wish to accept the credentials sent
with a request, it SHOULD return a 401 (Unauthorized) response. The
response MUST include a WWW-Authenticate header field containing at
least one (possibly new) challenge applicable to the requested
resource. If a proxy does not accept the credentials sent with a
request, it SHOULD return a 407 (Proxy Authentication Required). The
response MUST include a Proxy-Authenticate header field containing a
(possibly new) challenge applicable to the proxy for the requested
resource.

So, when a client gets a 401 response, can it always assume it is an auth failure on the origin server? Likewise, if it gets a 407, can it always assume it is from a proxy?

According to spec - yes, but I don't work with wide range of web/application servers and proxies to provide example of exception from rule...

HTTP Response Code for Proxy Authorization Failure - Stack Overflow

http http-status-codes http-status-code-401 http-status-code-407
Rectangle 27 1

This error happens beause the server sends a 401 (Unauthorized) but does not give a "WWW-Authenticate" which is a hint for the client what to do next. The "WWW-Authenticate" Header tells the client which kind of authentication is needed (either Basic or Digest). This is usually not very useful in headless http clients, but thats how the standard is defined. The error occurs because the lib tries to parse the "WWW-Authenticate" header but can't.

Possible solutions if you can change the server:

  • Add a fake "WWW-Authenticate" header like: WWW-Authenticate: Basic realm="fake". This is a mere workaround not a solution, but it should work and the http client is satisfied.
  • Use HTTP status code 403 instead of 401. It's semantic is not the same and usually when working with login 401 is a correct response (see here for detailed discussion) but its close enough.

Possible solutions if you can't change the server:

As @ErikZ wrote in his post you could use a try&catch

HttpURLConnection connection = ...;
try {
    // Will throw IOException if server responds with 401.
    connection.getResponseCode(); 
} catch (IOException e) {
    // Will return 401, because now connection has the correct internal state.
    int responsecode = connection.getResponseCode(); 
}

android - java.io.IOException: Received authentication challenge is nu...

android httpurlconnection
Rectangle 27 1

This error happens beause the server sends a 401 (Unauthorized) but does not give a "WWW-Authenticate" which is a hint for the client what to do next. The "WWW-Authenticate" Header tells the client which kind of authentication is needed (either Basic or Digest). This is usually not very useful in headless http clients, but thats how the standard is defined. The error occurs because the lib tries to parse the "WWW-Authenticate" header but can't.

Possible solutions if you can change the server:

  • Add a fake "WWW-Authenticate" header like: WWW-Authenticate: Basic realm="fake". This is a mere workaround not a solution, but it should work and the http client is satisfied.
  • Use HTTP status code 403 instead of 401. It's semantic is not the same and usually when working with login 401 is a correct response (see here for detailed discussion) but its close enough.

Possible solutions if you can't change the server:

As @ErikZ wrote in his post you could use a try&catch

HttpURLConnection connection = ...;
try {
    // Will throw IOException if server responds with 401.
    connection.getResponseCode(); 
} catch (IOException e) {
    // Will return 401, because now connection has the correct internal state.
    int responsecode = connection.getResponseCode(); 
}

android - java.io.IOException: Received authentication challenge is nu...

android httpurlconnection
Rectangle 27 1

For basic authentication, the server writes a "401 Unauthorized" header and then looks for an error document based on a pre-defined path. Most of the time, the error document won't exist in the directory that you want to protect, so the request gets handled by the rewrite engine which throws a 404 error.

The solution is simple: return a 401 and turn off mod_rewrite in the protected directories.

So each of those .htaccess files had to be edited as such:

# new
ErrorDocument 401 "Unauthorized Access"
RewriteEngine off

# as before
AuthType Basic
AuthName "MyName"
AuthUserFile "/home/mysite/.htpasswds/public_html/my/path/"
require valid-user

php - Stop .htaccess rewriting for files in protected directory - Stac...

php .htaccess mod-rewrite typo3 typo3-6.2.x
Rectangle 27 2

The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity might include relevant diagnostic information. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication" [43].

php - [function.fopen]: failed to open stream: HTTP request failed! HT...

php fopen
Rectangle 27 1

// I used Apache HttpClient.
// For URL, you need to find end point URL.
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.PrintWriter;
import java.io.StringWriter;

// Input parameter
String username = "";
String password = "";
String url = "";

// Variables 
int responseCode = 0;
String errorMessage = "";
String responseContent = "";
String content = ""

HttpResponse response;

try
{
    content = 
        "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:log=\"LogsGet\" xmlns:mal=\"MalteseGlobal\" xmlns:job=\"JobGlobal\">" + 
        "\n  <soapenv:Body>" +
        "\n    <log:LogsGetReq Cmd=\"Start\" OpV=\"01.00.00\" Sev=\"Info to critical\"/>" + 
        "\n  </soapenv:Body>" +
        "\n</soapenv:Envelope>";

    // Create the POST object and add the parameters
    HttpPost httpPost = new HttpPost(url);
    httpPost.addHeader("Content-Type", "text/xml; charset=utf-8");

    // Enable preemptive authentication within HttpClient so that HttpClient will 
    // send the basic authentications reponse before the server gives an unauthorized reponse. 
    String host = httpPost.getURI().getHost();
    int port = httpPost.getURI().getPort();   
    AuthScope authScope = new AuthScope(host, port);
    DefaultHttpClient httpClient = new DefaultHttpClient();
    UsernamePasswordCredentials credentials = new     UsernamePasswordCredentials(username, password);
    httpClient.getCredentialsProvider().setCredentials(authScope, credentials);   

    StringEntity input = new StringEntity(content);
    input.setContentType("application/json");
    httpPost.setEntity(input);   
    response = httpClient.execute(httpPost);

    if (response != null && response.getStatusLine() != null)
    {
        responseCode = response.getStatusLine().getStatusCode();
        responseContent = EntityUtils.toString(response.getEntity());
    }

    System.out.println("\n\n-----------------------------");
    System.out.println("\nResponse code: " + responseCode);
    System.out.println("\nResponse content: " + responseContent);
}
catch (Exception e)
{
    errorMessage  += "\nUnexpected Exception: " + e.getMessage();
    StringWriter sWriter = new StringWriter();
    PrintWriter pWriter = new PrintWriter(sWriter, true);
    e.printStackTrace(pWriter);
    errorMessage += "\n" + sWriter.getBuffer().toString();

    errorMessage += "\n------------Error Detail------------";
    errorMessage += "\n" + e;
    errorMessage += "\n" + e.getMessage();
    errorMessage += "\n" + e.getLocalizedMessage();
    errorMessage += "\n" + e.getCause();
    errorMessage += "\n" + Arrays.toString(e.getStackTrace());
    errorMessage += "\n" + e.printStackTrace();
    errorMessage += "\n------------------------------------";
}
finally
{
    if(response)
    {
        EntityUtils.consume(response.getEntity());    
    }
}

if(errorMessage != "")
{
    System.out.println("Error: " + errorMessage);
}

xml - How to send SOAP request over HTTP use digest authentication HTT...

java xml soap wsdl digest-authentication
Rectangle 27 3

With the latest version of fiddler, you only need to navigate to localhost.fiddler:port. However, doing that alone didn't help me and I was still getting access denied when using Windows Authentication. To fix this, I found this blog entry: http://www.parago.de/2013/01/fiddler-and-the-401-unauthorized-error-with-asp-net-web-api-using-integrated-windows-authentication-wia/

Using Fiddler with IIS7 Express - Stack Overflow

fiddler iis-express
Rectangle 27 3

With the latest version of fiddler, you only need to navigate to localhost.fiddler:port. However, doing that alone didn't help me and I was still getting access denied when using Windows Authentication. To fix this, I found this blog entry: http://www.parago.de/2013/01/fiddler-and-the-401-unauthorized-error-with-asp-net-web-api-using-integrated-windows-authentication-wia/

Using Fiddler with IIS7 Express - Stack Overflow

fiddler iis-express
Rectangle 27 0

This error happens beause the server sends a 401 (Unauthorized) but does not give a "WWW-Authenticate" which is a hint for the client what to do next. The "WWW-Authenticate" Header tells the client which kind of authentication is needed (either Basic or Digest). This is usually not very useful in headless http clients, but thats how the standard is defined. The error occurs because the lib tries to parse the "WWW-Authenticate" header but can't.

Possible solutions if you can change the server:

  • Add a fake "WWW-Authenticate" header like: WWW-Authenticate: Basic realm="fake". This is a mere workaround not a solution, but it should work and the http client is satisfied.
  • Use HTTP status code 403 instead of 401. It's semantic is not the same and usually when working with login 401 is a correct response (see here for detailed discussion) but its close enough.

Possible solutions if you can't change the server:

As @ErikZ wrote in his post you could use a try&catch

HttpURLConnection connection = ...;
try {
    // Will throw IOException if server responds with 401.
    connection.getResponseCode(); 
} catch (IOException e) {
    // Will return 401, because now connection has the correct internal state.
    int responsecode = connection.getResponseCode(); 
}

android - java.io.IOException: Received authentication challenge is nu...

android httpurlconnection