How LogonUserIdentity information is passed from browser to server? - asp.net

I'm accessing Windows authentication information in my ASP.NET MVC application using the following code.
WindowsIdentity identity = HttpContext.Current.Request.LogonUserIdentity;
Value of identity.Name is correctly the Windows login name.
When I inspect the http request that is send from browser to the server I see the following.
GET http://localhost:12010/administration HTTP/1.1
Authorization: Negotiate YIIJqgYGKwYBBQUCoIIJnjCCCZqgMDAuBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICHgYKKwYBBAGCNwICCqKCCWQEgglgYIIJXAYJKoZIhvcSAQICAQBugglLMIIJR6ADAgEFoQMCAQ6iBwMFACAAAACjggfcYYIH2DCCB9SgAwIBBaEKGwhJVC5MT0NBTKIoMCagAwIBAqEfMB0bBEhUVFAbFWl0LWRsMzgyLWhraS5JVC5MT0NBTKOCB5UwggeRoAMCARKhAwIBIaKCB4MEggd
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-EN
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: localhost:12010
Cookie: ASP.NET_SessionId=pr0qmeomsr1rlb1ehp2sffd3
There is no Windows authentication information in the http request, but I can access it in my code.
How are the values of LogonUserIdentity properties passed from browser to server?

Note that these type of authentication is designed to employ in intranet applications.
As you can see, the Request parameters for my own test is:
Params: {ALL_HTTP=HTTP_CACHE_CONTROL%3amax-age%3d0%0d%0aHTTP_CONNECTION%3akeep-alive%0d%0aHTTP_ACCEPT%3atext%2fhtml%2capplication%2fxhtml%2bxml%2capplication%2fxml%3bq%3d0.9%2cimage%2fwebp%2c*%2f*%3bq%3d0.8%0d%0aHTTP_ACCEPT_ENCODING%3agzip%2c+deflate%2c+sdch%0d%0aHTTP_ACCEPT_LANGUAGE%3aen-US%2cen%3bq%3d0.8%2cfa%3bq%3d0.6%0d%0aHTTP_HOST%3alocalhost%3a54035%0d%0aHTTP_USER_AGENT%3aMozilla%2f5.0+(Windows+NT+6.3%3b+WOW64)+AppleWebKit%2f537.36+(KHTML%2c+like+Gecko)+Chrome%2f40.0.2214.94+Safari%2f537.36%0d%0a&ALL_RAW=Cache-Control%3a+max-age%3d0%0d%0aConnection%3a+keep-alive%0d%0aAccept%3a+text%2fhtml%2capplication%2fxhtml%2bxml%2capplication%2fxml%3bq%3d0.9%2cimage%2fwebp%2c*%2f*%3bq%3d0.8%0d%0aAccept-Encoding%3a+gzip%2c+deflate%2c+sdch%0d%0aAccept-Language%3a+en-US%2cen%3bq%3d0.8%2cfa%3bq%3d0.6%0d%0aHost%3a+localhost%3a54035%0d%0aUser-Agent%3a+Mozilla%2f5.0+(Windows+NT+6.3%3b+WOW64)+AppleWebKit%2f537.36+(KHTML%2c+like+Gecko)+Chrome%2f40.0.2214.94+Safari%2f537.36%0d%0a&APPL_MD_PATH=%2fLM%2fW3SVC%2f7%2fROOT&APPL_
PHYSICAL_PATH=c%3a%5cusers%5camirmehr%5cdocuments%5cvisual+studio+2013%5cProjects%5cWindows+Auth%5cWindows+Auth%5c&AUTH_TYPE=Negotiate&AUTH_USER=Amir%5camirmehr&AUTH_PASSWORD=&LOGON_USER=Amir%5camirmehr&REMOTE_USER=Amir%5camirmehr&CERT_COOKIE=&CERT_FLAGS=&CERT_ISSUER=&CERT_KEYSIZE=&CERT_SECRETKEYSIZE=&CERT_SERIALNUMBER=&CERT_SERVER_ISSUER=&CERT_SERVER_SUBJECT=&CERT_SUBJECT=&CONTENT_LENGTH=0&CONTENT_TYPE=&GATEWAY_INTERFACE=CGI%2f1.1&HTTPS=off&HTTPS_KEYSIZE=&HTTPS_SECRETKEYSIZE=&HTTPS_SERVER_ISSUER=&HTTPS_SERVER_SUBJECT=&INSTANCE_ID=7&INSTANCE_META_PATH=%2fLM%2fW3SVC%2f7&LOCAL_ADDR=%3a%3a1&PATH_INFO=%2f&PATH_TRANSLATED=c%3a%5cusers%5camirmehr%5cdocuments%5cvisual+studio+2013%5cProjects%5cWindows+Auth%5cWindows+Auth&QUERY_STRING=&REMOTE_ADDR=%3a%3a1&REMOTE_HOST=%3a%3a1&REMOTE_PORT=54427&REQUEST_METHOD=GET&SCRIPT_NAME=%2f&SERVER_NAME=localhost&SERVER_PORT=54035&SERVER_PORT_SECURE=0&SERVER_PROTOCOL=HTTP%2f1.1&SERVER_SOFTWARE=Microsoft-IIS%2f8.0&URL=%2f&HTTP_CACHE_CONTROL=max-age%3d0&HTTP_CONNECTION=keep-alive&HTTP_
ACCEPT=text%2fhtml%2capplication%2fxhtml%2bxml%2capplication%2fxml%3bq%3d0.9%2cimage%2fwebp%2c*%2f*%3bq%3d0.8&HTTP_ACCEPT_ENCODING=gzip%2c+deflate%2c+sdch&HTTP_ACCEPT_LANGUAGE=en-US%2cen%3bq%3d0.8%2cfa%3bq%3d0.6&HTTP_HOST=localhost%3a54035&HTTP_USER_AGENT=Mozilla%2f5.0+(Windows+NT+6.3%3b+WOW64)+AppleWebKit%2f537.36+(KHTML%2c+like+Gecko)+Chrome%2f40.0.2214.94+Safari%2f537.36}
And Server variables :
ServerVariables: {ALL_HTTP=HTTP_CACHE_CONTROL%3amax-age%3d0%0d%0aHTTP_CONNECTION%3akeep-alive%0d%0aHTTP_ACCEPT%3atext%2fhtml%2capplication%2fxhtml%2bxml%2capplication%2fxml%3bq%3d0.9%2cimage%2fwebp%2c*%2f*%3bq%3d0.8%0d%0aHTTP_ACCEPT_ENCODING%3agzip%2c+deflate%2c+sdch%0d%0aHTTP_ACCEPT_LANGUAGE%3aen-US%2cen%3bq%3d0.8%2cfa%3bq%3d0.6%0d%0aHTTP_HOST%3alocalhost%3a54035%0d%0aHTTP_USER_AGENT%3aMozilla%2f5.0+(Windows+NT+6.3%3b+WOW64)+AppleWebKit%2f537.36+(KHTML%2c+like+Gecko)+Chrome%2f40.0.2214.94+Safari%2f537.36%0d%0a&ALL_RAW=Cache-Control%3a+max-age%3d0%0d%0aConnection%3a+keep-alive%0d%0aAccept%3a+text%2fhtml%2capplication%2fxhtml%2bxml%2capplication%2fxml%3bq%3d0.9%2cimage%2fwebp%2c*%2f*%3bq%3d0.8%0d%0aAccept-Encoding%3a+gzip%2c+deflate%2c+sdch%0d%0aAccept-Language%3a+en-US%2cen%3bq%3d0.8%2cfa%3bq%3d0.6%0d%0aHost%3a+localhost%3a54035%0d%0aUser-Agent%3a+Mozilla%2f5.0+(Windows+NT+6.3%3b+WOW64)+AppleWebKit%2f537.36+(KHTML%2c+like+Gecko)+Chrome%2f40.0.2214.94+Safari%2f537.36%0d%0a&APPL_MD_PATH=%2fLM%2fW3SVC%2f7%2fR
OOT&APPL_PHYSICAL_PATH=c%3a%5cusers%5camirmehr%5cdocuments%5cvisual+studio+2013%5cProjects%5cWindows+Auth%5cWindows+Auth%5c&AUTH_TYPE=Negotiate&AUTH_USER=Amir%5camirmehr&AUTH_PASSWORD=&LOGON_USER=Amir%5camirmehr&REMOTE_USER=Amir%5camirmehr&CERT_COOKIE=&CERT_FLAGS=&CERT_ISSUER=&CERT_KEYSIZE=&CERT_SECRETKEYSIZE=&CERT_SERIALNUMBER=&CERT_SERVER_ISSUER=&CERT_SERVER_SUBJECT=&CERT_SUBJECT=&CONTENT_LENGTH=0&CONTENT_TYPE=&GATEWAY_INTERFACE=CGI%2f1.1&HTTPS=off&HTTPS_KEYSIZE=&HTTPS_SECRETKEYSIZE=&HTTPS_SERVER_ISSUER=&HTTPS_SERVER_SUBJECT=&INSTANCE_ID=7&INSTANCE_META_PATH=%2fLM%2fW3SVC%2f7&LOCAL_ADDR=%3a%3a1&PATH_INFO=%2f&PATH_TRANSLATED=c%3a%5cusers%5camirmehr%5cdocuments%5cvisual+studio+2013%5cProjects%5cWindows+Auth%5cWindows+Auth&QUERY_STRING=&REMOTE_ADDR=%3a%3a1&REMOTE_HOST=%3a%3a1&REMOTE_PORT=54427&REQUEST_METHOD=GET&SCRIPT_NAME=%2f&SERVER_NAME=localhost&SERVER_PORT=54035&SERVER_PORT_SECURE=0&SERVER_PROTOCOL=HTTP%2f1.1&SERVER_SOFTWARE=Microsoft-IIS%2f8.0&URL=%2f&HTTP_CACHE_CONTROL=max-age%3d0&HTTP_CONNECTION=keep-al
ive&HTTP_ACCEPT=text%2fhtml%2capplication%2fxhtml%2bxml%2capplication%2fxml%3bq%3d0.9%2cimage%2fwebp%2c*%2f*%3bq%3d0.8&HTTP_ACCEPT_ENCODING=gzip%2c+deflate%2c+sdch&HTTP_ACCEPT_LANGUAGE=en-US%2cen%3bq%3d0.8%2cfa%3bq%3d0.6&HTTP_HOST=localhost%3a54035&HTTP_USER_AGENT=Mozilla%2f5.0+(Windows+NT+6.3%3b+WOW64)+AppleWebKit%2f537.36+(KHTML%2c+like+Gecko)+Chrome%2f40.0.2214.94+Safari%2f537.36}
which contains my username equal to amirmehr. But in browser request we don't see any user information which says the IIS is reading user data from OS since I'm running my project locally :). Here is browser request:
Request URL:http://localhost:54035/
Request Headers
Provisional headers are shown
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer:http://localhost:54035/
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36
After some research, I found out the question depends on test environment (besides configuration).
For Local case, take a look at Unable to get windows authentication to work through local IIS
And to understand how it works, check the Windows Authentication for
.net MVC 4 - how it works, how to test it. Both have useful
things.
Also we have configuration considerations mentioned below:
Configuration(Microsoft Link)
Configuring Windows Authentication in MVC4 with IIS Express.
For customization check ASP.NET MVC 4 Forms Authentication Customized :)

Depending on your WindowsAuthenticationMode, the browser may or may not authenticate with IIS. For example, if you allow Anonymous Authentication, then IUSR_MACHINENAME user will be used to authenticate the user. If Basic is specified, then the browser will authenticate with IIS (you will need to provide user/password) and then you will see in the requests the authentication information. Then there is NTLM authentication. More information here.

Related

ASP.NET acquire JWT token from ADFS by code or CLI

We are developing an ASP.NET (not .Net Core) API for another team to consume.
I need to get a JWT token from our ADFS to test if the security of the API is working.
I can't use the login page of ADFS, I need to do this by code, CLI or anything.
How can I do that?
Edit :
I tried to call adfs using postman (POST /adfs/oauth2/token) and got this error :
Activity ID: 4acc6a7b-dafe-4a4b-1c00-0080000000dd
Error time: Tue, 03 Aug 2021 08:59:10 GMT
Cookie: enabled
User agent string: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36
You can use the client credentials flow.
It relies on a secret key rather than a login.
You could do this via Postman.

Jetty client http error code 412

I am accessing one website (I am hiding origin website name as it is against the policy) using browser and jetty/apache httpclient.
The website works fine with web browser.
Using api I am able to login into website,gets the session cookie JSESSIONID and home page html content. But after that when I submit any form or call the links from html I receive the HTTP error code 412(Pre condition failed).
I understand this error is due problem in client header. I set all the headers from browser(checked using inspect element in chrome browser). Still I have the same error.
I am not able to track down which header is causing the problem.
Here is the Header from browser
Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Encoding:gzip, deflate
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:318
Content-Type:application/x-www-form-urlencoded
Cookie:language=en_IN; __gads=ID=14c64d8f9fd7de54:T=1424658276:S=ALNI_Mba1kvJO4mLo7R-T2jUJE9zCYck5A; SLB_Cookie=ffffffff09461c2d45525d5f4f58455e445a4a422971; JSESSIONID=36m4Oo6dCML_Wvx-Wgmm9rtLh9mbURxnZhWIVwg-zHaNzFQeUt9C!-1989013783; _ga=GA1.3.379900459.1428120216
Host:www.irctc.co.in
Origin:https://www.example.com
Referer:https://www.example.com/context/home
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36
Same header I am setting from jetty client.
Request request = httpClient.newRequest(url);
request.method(HttpMethod.POST);
request.agent(USER_AGENT);
request.accept("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
request.header(HttpHeader.REFERER,"https://www.example.com/context/home");
request.header(HttpHeader.ACCEPT_ENCODING, "gzip, deflate");
request.header(HttpHeader.ACCEPT_LANGUAGE, "en-GB,en-US;q=0.8,en;q=0.6");
request.header(HttpHeader.CACHE_CONTROL, "max-age=0");
request.header(HttpHeader.CONNECTION, "keep-alive");
request.header(HttpHeader.CONTENT_TYPE, "application/x-www-form-urlencoded");
request.header(HttpHeader.HOST, "www.example.com);
for (Map.Entry<String, String> entry : params.entrySet()){
request.param(URLEncoder.encode(entry.getKey(), "UTF-8"), URLEncoder.encode(entry.getValue(), "UTF-8"));
if(!StringUtils.isEmpty(content)){
content+="&";
}
content+=URLEncoder.encode(entry.getKey(), "UTF-8")+"="+URLEncoder.encode(entry.getValue(), "UTF-8");
}
request.header(HttpHeader.CONTENT_LENGTH, ""+content.length());
I see JSESSIONID and SLB_Cookie are present in the request. Since the website is out of our control I really can not track what is the issue.
Please help me to resolve this issue. Any pointers to resolve the issue on client side is appreciated. is there any way we can make sure which header causing this issue.
I solved the problem.
Issue with the form parameters value. I was sending encoded values where were encoded by jetty client again

XULRunner Application Request Header Information

I've developed a standalone XULRunner app that I'm using as a site-specific browser. The web application it accesses does filtering of browsers to know whether the browser being used is optimal. I'd like to add my XULRunner app to the list of optimal browsers. I figured that to do this, I'll need to know the HTTP header information that accompanies request sent by the XULRunner app. What information in the HTTP header can I use to identify my XULRunner app? Something like the Gecko Engine version, etc. I've been searching around, but no luck yet.
An application is usually identified by means of the User-Agent header. You can see it on the client side by means of the window.navigator.userAgent property, e.g. the header for Firefox 12 on Windows 7 is:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0
The important part here is Gecko/... (identifies a Gecko-based browser) and rv:... (Gecko version). The Firefox/12.0 part should be replaced by something like MyApp/1.2.3 in your case (name and version number of your application).

Is there a way to verify that Response.Cookies.Add() succeeded?

In ASP.net 2.0 Response.Cookies.Add() is a VOID (which boggles me somewhat). Is there a way to check to see if the function successfully added the cookie?
I just spent 2 hours trying to track down an authentication issue for one user. Finally I realized he was in a BUNCH of AD groups and I believe the cookie we were building for him, and trying to set, was > 4096 bytes.
Would be nice to know up front if the call to Response.Cookies.Add() failed.
We were trapping the error later in the global.asax page when we did:
HttpCookie authCookie = Context.Request.Cookies[cookieName];
and authCookie for this user was always null.
Thanks for the responses.
I've decide to check the size before calling Response.Cookies.Add() and alert the user accordingly.
int iSize = System.Text.UTF8Encoding.UTF8.GetByteCount(authCookie.Values.ToString());
if (iSize > 4096)
{
lblMessage.Text = "The authentication cookie cannot be set as it is > 4096 bytes; a limit imposed by the browser. The current size of the Cookie.Values is " + iSize.ToString() + " bytes.";
lblMessage.CssClass = "msgBox Alert";
return;
}
I setup a simple project that write a random cookie value, and used Fiddler to examine the response:
GET http://localhost.:2605/Default.aspx HTTP/1.1
Accept: */*
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: localhost.:2605
Pragma: no-cache
Cookie: ASP.NET_SessionId=wxpo32z2zxr1qlbwgx4on3z2; test1047139665=value775124204
You can see the cookie in the Cookie section of the header above. This is consistent with the documentation at: http://msdn.microsoft.com/en-us/library/system.web.httpresponse.cookies.aspx
The size limitation is documented here:
http://support.microsoft.com/kb/306070
Looks like you'll have to check yourself before writing it.
Yes, but likely not how you want to. On the subsequent page or request, check it in Request.Cookies if the cookie is available. If not, you can assume the Response.Cookies wasn't able to add the cookie (they have cookies off, cleared them, etc.).
You can't verify the Response.Add worked when it happens because it doesn't truly happen until the response is sent to the browser.
Response.Cookie.Add() succeeds always. It's the client accepting said cookie that might fail. But the Add() method has no way of knowing - since it just places the cookie in the HTTP response. You won't know until the HTTP response is sent back and the client processes it. Which happens long after Add() returns.
So the only way to verify that is to check for the cookie on subsequent requests, which seems like you're already doing by checking for the auth info.

Finding previous page Url

i am trying to find the url of previous page.Such as if a user navigates from Page A to Page B using Server.Redirect("B.aspx"), page B can display the url referring to it.
I have tried using
Response.Write(Page.PreviousPage.ToString());
Response.Write(Request.UrlReferrer.ToString());
Response.Write(Context.Request.UrlReferrer.ToString());
Response.Write(Request.ServerVariables["HTTP_REFERER"].ToString);
but all in vain it gives me null exception error
You can save you current page in the Session and then retrieve it from there:
string previousPage = Session["PreviousPage"] as string;
Session["PreviousPage"] = System.IO.Path.GetFileName(System.Web.HttpContext.Current.Request.FilePath);
This way the previousPage string will always contain the previous page's filename, and the Session variable will contain the current page, ready to be used on the next page.
This way you can also detect if the referrer is an outside link because then the previousPage string will be null.
If it's only for this scenario (where you programatically redirect to B.aspx) then why not put something on the querystring to say where the redirect came from. This would be more likely to work across muliple browser types and devices.
One advantage to this approach is that you'll be able to tell the difference between a redirect to B.aspx and a direct link (either via a link on one of your pages, or from the user entering the URL into the address base) to page B.aspx.
The referrer is something the the client provides as part of the HTTP request. As such, you can't rely on it.
By the way, this question is related:
Request.UrlReferrer null?
Update
Given your comments it's not clear that's an easy solution other than "edit all your files". I suspect that global search/replace might be your best bet.
Some more background: If you use Fiddler (or any other http debugging tool) you should be able to see that the Referrer header isn't being populated when you perform a redirect. For example, this is the result of a redirect (i.e. an HTTP 302 response causing IE to redirect to another page):
GET /webapplication1/WebForm3.aspx HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
Accept-Language: en-GB
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618; MS-RTC LM 8; Zune 3.0)
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: (removed)
Here is the HTTP request that is generated by clicking the "Questions" link on StackOverflow.com:
GET /questions HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
Referer: https://stackoverflow.com/questions/772780/finding-previous-page-url
Accept-Language: en-GB
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618; MS-RTC LM 8; Zune 3.0)
Accept-Encoding: gzip, deflate
Host: stackoverflow.com
Connection: Keep-Alive
You can see that the later, generated by a link on a page, generates the Referer header.
You can also use Server.Tansfer("B.aspx") instead of Response.Redirect("B.aspx")
Edit: Searock, if you don't want to change your existing code, Request.ServerVariables["HTTP_REFERER"].ToString() should work fine in that case.
Just to note that HTTP_REFERER is not reliable. You can't rely on that because so many clients doesn't send for various reasons (paranoid settings, security software etc.).
Also some new windows opened by JS might not have REFERER
SSL > NONE SSL pages won't have REFERER either, so be careful about relying something like that.
Better idea would be sending previous page in Querystring.
If it's ASPX you might do it in more clever way like adding a new hidden parameter to all forms or processing link just before writing out the buffer.
Could you just confirm what methods you are actually using here (ideally by editing the original question)?
HttpServerUtility (i.e. Server.) doesn't have a "Redirect" method, it has Transfer and Execute.
HttpResponse (i.e. Response.) does.
HttpResponse.Redirect will send a 302 response to the client, telling it to issue a new request for the value of the Location field. I'm then able to query Request.UrlReferrer to see the value of the page that performed the Redirect.
If you are using HttpServerUtility.Transfer or HttpServerUtility.Execute then these actions happen entirely at the server within ASP.NET, and so the "referrer" may well be null. The client browser will also think it is still on the originally requested page.
See also How to detect if an aspx page was called from Server.Execute

Resources