Chrome ignores HTTP WWW-Authenticate realm - http

Our web application has user/password authentication. It runs on a web server which is secured itself with HTTP Basic Auth. This is just a temporary solution / workaround. The web application's authentication will be sufficient in future, but at the moment the web server Basic Auth prevents accessing the web application at all.
The web application returns status code 401 when not authenticated on application level. The WWW-Authenticate header defines a different realm, so the browser won't get confused between web server and web application authentication: If we didn't define a different realm the browser would throw away the web server credentials as soon as the application's 401 arrives.
So far so good. However our application has its own authentication dialog. For XHR requests we want to handle the 401 status on our own and need to prevent the browser's internal basic auth window. There is a simple trick for this: Just adjust authentication header (WWW-Authenticate) to use a custom auth method:
WWW-Authenticate: CustomBasic realm="myapp"
Whereby the web server returns:
WWW-Authenticate: Basic realm="webserver"
This works with Firefox but not with Chrome. Chrome ignores the realm when using CustomBasic and discards the credentials (user / password) for realm "webserver" as if we didn't define the realm "myapp" at all.
Do you know why? Do you know a solution with following requirements:
Keep 401 status for both realms
Do not show browser's basic auth window on application level (especially for XHR requests)
Yes I know we can simply workaround this by using different HTTP status codes on application level and handle them respecitvely. But if possible I want to keep the correct status codes 401. This could also be a valid use case, e.g. if you have two web applications accessible with two different URL paths on the same host.

Related

IdentityServer4 Web Login via id_token or access_token

Context
I'm building a hybrid native/web app. Part of it will be API driven, and part of it will be webviews showing an existing website.
Once logged in with my OIDC SDK (Amplify/AppAuth), I can access the user's id_token and access_token.
However, because the webviews used in the SDK are not controllable, I cannot reuse the cookies generated by my identity server.
Question
For the reason above, I'm trying to login a user from their id_token or their access_token. (both are JWTs)
I believe this isn't supported by IdentityServer4, but I am looking to implement something myself.
What I have found so far:
1) id_token_hint
OpenID Connect Core 1.0, Section 3.1.2.1, id_token_hint parameter:
OPTIONAL. ID Token previously issued by the Authorization Server being passed as a hint about the End-User's current or past authenticated session with the Client. If the End-User identified by the ID Token is logged in or is logged in by the request, then the Authorization Server returns a positive response; otherwise, it SHOULD return an error, such as login_required. When possible, an id_token_hint SHOULD be present when prompt=none is used and an invalid_request error MAY be returned if it is not; however, the server SHOULD respond successfully when possible, even if it is not present. The Authorization Server need not be listed as an audience of the ID Token when it is used as an id_token_hint value.
If the ID Token received by the RP from the OP is encrypted, to use it as an id_token_hint, the Client MUST decrypt the signed ID Token contained within the encrypted ID Token. The Client MAY re-encrypt the signed ID token to the Authentication Server using a key that enables the server to decrypt the ID Token, and use the re-encrypted ID token as the id_token_hint value.
According to this optional spec of OpenID, I should be able to use the id_token on the /authorize endpoint to login the user. I know this isn't implemented in IdentityServer4, but I'm looking at AddCustomAuthorizeRequestValidator to do that. However I'm not sure how to "get a user from their id_token" in the code. Do you have any pointers?
2) using AddJwtBearerClientAuthentication
This method sounds like I could authenticate from my access_token, but I can't find much documentation on how to use it.
THE PROBLEM
Let me know if I am misunderstanding requirements, but it feels like you have 2 different apps and are trying to make them feel like a single integrated set of screens.
The default behaviour will be as follows since web views are private browser sessions and cannot use system browser cookies. You want to prevent the second step since it is a poor user experience:
User signs in to the mobile app
Whenever a secured web view is invoked, there is a new private browser session with no auth cookie, therefore requiring a new login
COMMON APPROACH: SUPPLY A TOKEN TO THE WEB VIEW
It can be common to forward the mobile token to the web view, if the two apps are part of the same user experience. If required, extend the mobile app's scopes to include those for the web app.
You should not need to issue any new tokens or change the security model of either app. But the mobile and web apps need to work together on a solution.
POSSIBLE WEB VIEW SOLUTION FOR A SERVER SIDE WEB APP
This might be the simplest option:
Provide new .Net Core web back end entry point URLs that require tokens instead of cookies
The mobile app could then call those endpoints from web views, and supply its own token in the Authorization Header of the web view request
The web back end could then forward mobile web view requests to your Web APIs
The code to add the Authorization Header to a web view request may be a little tricky but there are ways to do it:
Android
iOS
POSSIBLE WEB VIEW SOLUTION FOR AN SPA
An option that works for Cookieless SPAs is for the web view to ask the mobile host app for an access token via a Javascript bridge. Some code of mine does this for a cookieless SPA:
Web UI Code to Call the Mobile Host
Android Code
iOS Code
You can clone / run the mobile github repos from your local PC to see the solution. I will be writing up some notes on this in my blog's Mobile Web Integration Post.

Web API - Authentication credentials in the HTTP header vs body with SSL?

I'm sending username and password in the HTTP Body for authentication to each controller action in a Web API. I do the authentication in each controller using the username/password. It's using SSL.
Are there any security reasons why it's better to send the authentication credentials in the HTTP Header than in the HTTP body?
If I was using Basic Authentication I can see how having the credentials in the header are necessary as in this question but I'm not so I don't see the purpose. It seems just as secure in either as long as it's using SSL.
From an SSL perspective the security of the credentials in header (HTTP Basic auth) or body (e.g. form based logon) of an HTTP request is equal.
However if the client is a regular web browser you should consider the following:
Browsers cache the credentials used with HTTP basic authentication the users usually face the problem that for performing a log-out they would have to close their browser.
On the other side a form-based logon usually created a session cookie that is time restricted and can be deleted any time.

ASP.NET forms authentication w/ http 2.0

I'm experimenting with moving an existing enterprise app to HTTP 2.0 at my customer's request. The app uses ASP.NET Forms Authentication, and when accessed over HTTPS with HTTP 2.0-aware browser and server (Windows Server Tech Preview), authentication appears to succeed during the login action, redirecting to the requested URL, but then the server responds to the next request with a redirect back to the login URL again. After adding some diagnostic logging to Application_BeginRequest, I found that the auth cookie is present in the request, but an attempt to decrypt the ticket with FormsAuthentication.Decrypt() throws an exception stating that there are non-base-64 characters in the cookie. I suspect this has something to do with HTTP 2.0 header compression, but I would have thought that this should have been handled transparently by IIS and that the headers should have been decompressed by the time my code executes. Has anyone else experienced this and know of a workaround? Happy to provide additional information if I left anything out.

Will browsers send preemptive Authorization headers to sites served over different protocols (https vs http)?

I have a site (running a 3rd party app) that's available over HTTPS and HTTP. It allows people to log in with Basic Authentication. I'm trying to force all logins to happen over HTTPS rather than HTTP.
The app is odd in that the authentication "realm" is the root of the domain (/), and 401s are returned based on query string parameters rather than the URL path. I think I've got my RewriteRules set up properly so that any request that could result in a 401 is redirected to HTTPS first. However, I'm worried that after logging into the secure site, if users navigate back to the HTTP version somehow, browsers will still send Authorization headers (now unencrypted) without seeing a 401 since it's all the same domain with the /same/path/structure. That is, I'm worried about this behaviour from RFC 2617:
A client MAY preemptively send the corresponding Authorization header with requests for resources in that space without receipt of another challenge from the server.
Should I worry? Or does switching protocols (https to http) prevent browsers from sending those preemptive auth headers?
We heavily use basic auth for our application. All using https of course :)
Browsers have a good sandbox model, they know that when the protocol changes, the target machine may not be the same anymore. You don't have to worry about browsers submitting the authentication information.
Even when they run into the initial 401, they will still ask the user for the username/password pair.

Cookie is getting reset on AJAX requests

I have two virtual directories, one hosts an application the other hosts a web service layer running WCF with ASP.NET compatibility mode enabled.
The service project has an HTTP module that deals with authentication for incoming requests. The login service writes an authentication cookie to the client.
Subsequent requests are handled via AJAX (jQuery) to the services from the application project (another virtual directory on the same domain.)
Cookie domain is set correctly, the cookie path is "/", the cookie is set to HTTP ONLY so that scripts cannot interact with it.
My issue is the login service seems to be sending the SET-COOKIE header with the correct payload in the cookie, however the subsequent requests are not sending the cookie back to the server, in fact when inspecting the local store the cookie is not even there.
Potentially what could be my issues?
We tracked the issue down to Chrome. Apparently there was a prior bug that seems to be presenting itself again whereby expires cookies are not promoted to session and are instead discarded.

Resources