Invalid token for impersonation - it cannot be duplicated since IIS 7 - c#

I have a site where we setup auto-login with windows authentication and if it fails, it asks for username/password to login as form.
The way it's done, we setup the authorization as Form with a specific page (Winlogin.aspx).
Winlogin.aspx is setup with authorization Windows. In the code of Winlogin.aspx.cs, it gets the this.Request.ServerVariables["LOGON_USER"] and creates a FormsAuthenticationTicket with the user's token using request.GetUserToken(), sets a cookie with an encrypted version and sends the browser to the login.aspx page for the Form authorization.
Login.aspx get the cookie, decrypt it and is suppose to set HttpContext.Current.User with a WindowsIdentity created from the user that was sent from Winlog.aspx after authorization has succeeded.
This has been working perfectly on IIS6 for more then a year now
but
we are updating our servers and moving to IIS 7 but now i get a Invalid token for impersonation - it cannot be duplicated.
This is the code that is used
// Extract the roles from the cookie, and assign to our current principal, which is attached to the HttpContext.
FormsAuthenticationTicket winAuthTicket = FormsAuthentication.Decrypt(authCookie.Value);
String token = winAuthTicket.UserData;
IntPtr userToken = new IntPtr(int.Parse(token);
-----> Line that gives error now. <-----
WindowsIdentity identity = new WindowsIdentity(userToken, "NTLM", WindowsAccountType.Normal, true);
HttpContext.Current.User = new WindowsPrincipal(identity);
I have been at it for 2 days trying to figure it out.
Anyone has an idea?

To resolve this you have to use a WindowsIdentity from a token that was not duplicated. So you have to pass HttpContext.User a WindowsPrinciple that was passed a WindowsIdentity that was generated by an original token (not duplicated). I've been trying to figure out a way to bypass this, but it looks like the only way is to store the credentials rather than the identity and Logon (see LogonUser) each time you need a WindowsIdentity.
You are unable to re-use an original token because HttpContext.User is disposed after each request (for security reasons).

I think the problem is, that you cannot reuse the same instance of WindowsPrincipal in another request, because SafeHandle instance, that probably holds some references that are assigned to WindowsPrincipal, had been disposed with the previous request and also you cannot duplicate WindowsIdentity.Token - it has to be regenerated. You have to clone the WindowsIdentity - this will get rid of reference dependencies. Then you can regenerate the web site authentication token by WindowsIdentity.Token or whatever.
I had had the same problem and I have solved it this way.
var user = new WindowsPrincipal(((WindowsIdentity)HttpContext.Current.User.Identity).Clone());
//now assign the user again to the current context's user or do some other stuff like storing the clone to session for future requests...

Related

LinkedIn Authentication Auto Redirect with Code = null once AccessToken get deleted or revoked

I am using LinkedIn oauth 2.0 api implementation and all went well to setup and retrieval of Access Token, but then i revoked the AccessToken after login in LinkedIn and also deleted the AccessToken i saved in my DB.
The idea is to give an option to Re-Authorize the account as given in point 1 below.
Once the request is made, one of the following occurs:
If the member has not previously accepted the application's permission request, or the grant has expired or been manually revoked by the member, the browser is redirected to LinkedIn's authorization screen as shown in the screenshot below. When the member completes the authorization process, the browser is redirected to the URL provided in the redirect_uri query parameter.
If there is a valid existing permission grant from the member, the authorization screen is bypassed and the member is immediately redirected to the URL provided in the redirect_uri query parameter.
What actually happen is that when ever i redirect user to the Authorization URL, it goes for option 2 written above rather than option 1, and with a null Authorization Code. Below given is my Code on click of a button.
var permissions = new string[] { "r_basicprofile", "r_emailaddress", "w_member_social" };
var authUrl = client.GetAuthorizationUrl(permissions,true);
return new RedirectResult(authUrl.ToString());
and below given is the method that get called when LinkedIn callback redirect_uri
public ActionResult LinkedInAuthentication(string code, string state)
{
//the code parameter is null here
}
This should not be the behavior, please help.
Also can i know how to request for RefreshToken?
Ahhh issue resolved, after a lot of search, i started reading complete linkedin documentation and found below given statement under integration > SignIn with LinkedIn rather under Authentication > Authorization Code Flow (3-legged OAuth) which actually explains each step of authentication. The link that explains this is
https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin?context=linkedin/consumer/context?trk=eml_mktg_gco_dev_api_comms#authenticating-members
Authenticating Members
New members logging in to your service for the first time will need to follow the Authenticating with OAuth 2.0 Guide. When requesting an authorization code in Step 2 of the OAuth 2.0 Guide, make sure to request the r_liteprofile and/or r_emailaddress scopes!
so changing
var permissions = new string[] { "r_basicprofile", "r_emailaddress", "w_member_social" };
to
var permissions = new string[] { "r_liteprofile", "r_emailaddress"};
resolved the issue.
Hope someone else will be benefited to :)
Also if someone can help how to enable basicprofile and fullprofile features in app? That will be great.

Forms Authentication SSO Logout Issue due to duplicate cookie

I am using forms authentication to handle SSO across *.mydomain.com
Upon login i create a non-persistant cookie with the ticket embedded in it and set it's domain to .mydomain.com.
However the problem is that when i visit any website on the domain, i find there are two cookie with the same name but with different domains. :
1> site1.mydomain.com [1st Forms Auth Cookie] duplicate cookie
2> .mydomain.com[2nd Forms Auth cookie]
The 1st Cookie is not created by me.Also it isn't secure.
Upon logout i successfully clear my 2nd Cookie.
However, the 1st cookie remains and for a user it appears that he is still logged in to site1 . This happpens because i check for the existence of the cookie with the same name and surely the 1st cookie is wrongly assumed to be the Forms Auth Cookie. I cannot check the domain property because in the Request the information about the domain is null .
My issue is how is the second website-specific domain cookie is getting created.
If i cannot avoid this, is there a workaround?
UPDATE : The encrypted value stored by this faulty cookie is updated on each request i make on the website,while the encrypted value in my Auth Cookie remains same
According to MSFT Docs
"The Add method allows duplicate cookies in the cookie collection. Use the Set method to ensure the uniqueness of cookies in the cookie collection."
After renewing my Forms Authentication ticket i was doing :
Response.Cookies.Add(..);
Thus a new duplicate cookie was getting generated.
To fix this do :
Response.Cookies.Set(..);
If you were like me you would have expected ASP.Net to replace the old cookie with the new one.

Where does the application cookie go when created?

I'm playing around with the authentication using Owin according to a blog and when I execute the following, I'm supposed to get an (application) cookie. I'm unsure how to verify that I actually got one. So it very well might be there, somewhere in the memory or on the disk but I'm too ignorant of security issues to determine that.
List<Claim> claims = new List<Claim> { new Claim("Donkey", "Hazaa") };
ClaimsIdentity identity = new ClaimsIdentity(
claims, DefaultAuthenticationTypes.ApplicationCookie);
HttpContext.GetOwinContext().Authentication.SignIn(new AuthenticationProperties
{
AllowRefresh = false,
IsPersistent = false,
ExpiresUtc = DateTime.Now.AddMinutes(1)
});
I can't verify by being able/unable to log in, since this is just a dummy without any backbone yet. The only thing I need to do at this stage is to confirm that something gets somewhere and that it vanishes when a minute has passed. It'd be awesomely awesome if there was an actual cookie file popping up somewhere and then poofing away after a while. Is there such?
Of course it is, but the Cookie is sent to the browser once the authentication was requested and validated. The cookie has the same behavior as in previous version of cookie auth with forms authentication, so is a task for the browser to receive and manage the cookie; on each HTTP request, the browser sends its cookies, which are processed by OWIN to check authentication.
Take the code and implement a simple authorization on memory (like user: abc, pass: 123) and check how the browser receives the cookie. By the way, the only difference between cookie and token validation is that the cookie is automatically sent on every request, whilst on token auth you need to explicitly send the token information on header.
Be aware that cookie authentication is intended for browsers, as mobile applications or other applications that need to connect to your API will not have access to the cookie response, like in a desktop app.
Regards

OWIN identity roles work locally, but seem to disappear when I publish/run the same code on a remote IIS server

Using an OWIN AuthenticationHandler within an MVC site, I sign in a user as follows:
var claims = new List<Claim> { new Claim(ClaimTypes.Role, UIRoles.PowerUser) };
var identity = session.ToClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie, claims);
Context.Authentication.SignIn(identity);
At some point at a later time, I check that the user is a PowerUser:
User.Identity.HasRole(UIRoles.PowerUser)
This works on my local IIS, but once I publish it on a remote IIS machine, it always returns False when I try to check if the user is a PowerUser. Why could this happen? Am I missing something from, say, the IIS server's configuration or within the remote machine's web.config?
I found the cause. It is a bit silly. I was reissuing cookies when I wanted to renew the user's session and the problem was that the SessionInfo object I was renewing these cookies to were being replaced with another SessionInfo object without any extra claims:
session.ToClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie);
This was wiping the extra claim of UIRoles.PowerUser from the original cookie for me.

Persisting the OAuth2 bearer token when using Thinktecture Identity Server

I've been following the Thinktecture Identity Server example of OAuth2 Resource Owner Password Flow found at http://leastprivilege.com/2012/11/01/oauth2-in-thinktecture-identityserver-v2-resource-owner-password-flow/
I have the example working and returning JWT tokens successfully via the following process
Use the Thinktecture OAuth2Client to retrieve the access token
Retrieve the signing certificate from the "Trusted People" store on the client machine
Using the certificate and creating a new JwtSecurityTokenHandler and TokenValidationParameters and calling tokenHandler.ValidateToken to get a ClaimsPrincipal
From here I am authorized, but I am uncertain of the best way to persist the token for further requests. I tried using
var sessionToken = new SessionSecurityToken(principal, TimeSpan.FromHour(8));
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
But I do not have a SessionAuthenticationModule registered. I tried using the Identity and Access wizard to get this in place, but it makes many changes to config and tries to set things up for passive authentication.
I could use a traditional FormsAuthentication cookie (.aspnetAuth) but I remember discussion that an advantage of the .FedAuth cookie was that it was naturally split into several cookies if the size grew too big.
I'm struggling to find an article that completes the picture for me. I need the bearer token for accessing various APIs further down the stack. I have working examples of this for SSO/passive authentication, because most of the work is done for you. I'm just not sure of the best pattern for use when using the Resource Owner Password flow.
So
Have I missed a more straightforward way to achieve this with Thinktecture Identity Model and Server?
Should I try to create a FedAuth cookie so that I can reuse the various Messagehandler/filter components that are already setup for WIF?
Otherwise - is there anything particularly wrong with simply putting the access token in the UserData section of the FormsAuthentication cookie?
Try to look at this question: WIF Security Token Caching.
I believe this code might do
var sessionSecurityToken = new SessionSecurityToken(principal, TimeSpan.FromHours(Convert.ToInt32(System.Web.Configuration.WebConfigurationManager.AppSettings["SessionSecurityTokenLifeTime"])))
{
IsPersistent = true, // Make persistent
IsReferenceMode = true // Cache on server
};
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionSecurityToken);

Categories

Resources