OWIN ClaimsIdentity not working in IE11 - asp.net-mvc

After Signing in using OWIN authentication, the identity's 'IsAuthenticated' is always false in IE11. It works just fine in Chrome though, any ideas ?
I also reloaded the page to see if secondary request worked, and it does not. I do see the cookie though in IE's dev tool.
//Setup authentication
ClaimsIdentity identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name, userName),
new Claim(ClaimTypes.NameIdentifier, webUser.User_ID.ToString())
}, "ApplicationCookie");
request.GetOwinContext().Authentication.SignIn(identity);
//Check authentication
ClaimsIdentity identity = request.GetOwinContext().Authentication.User.Identity as ClaimsIdentity;
if (!identity.IsAuthenticated) return null; // In IE11, 'IsAuthenticated' is always false and the identity is not a valid claimsIdentity
Here is my Startup code if it helps:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
LoginPath = new PathString("/Auth/"),
CookieDomain = "localhost",
CookieName = "MyCookie"
});

Related

Mixing cookie external login using Azure AD and individual account in MVC5

I am getting problems with application cookie and external cookie that are integrated login with Azure AD to my web app using MVC5. Currently, my local account work correctly but external account (Google and Azure AD) cannot map external cookie to local cookie. My code get userId return incorrect user Id.
IIdentity ident = HttpContext.Current.GetOwinContext().Request.User.Identity;
ident.GetUserId()
Below is my startup.cs
public partial class Startup
{
// The Client ID is used by the application to uniquely identify itself to Azure AD.
string clientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"];
// RedirectUri is the URL where the user will be redirected to after they sign in.
string redirectUri = System.Configuration.ConfigurationManager.AppSettings["RedirectUri"];
string postLogoutRedirectUri = System.Configuration.ConfigurationManager.AppSettings["PostLogoutRedirectUri"];
// Tenant is the tenant ID (e.g. contoso.onmicrosoft.com, or 'common' for multi-tenant)
static string tenant = System.Configuration.ConfigurationManager.AppSettings["Tenant"];
// Authority is the URL for authority, composed by Microsoft identity platform endpoint and the tenant name (e.g. https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0)
string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture, System.Configuration.ConfigurationManager.AppSettings["Authority"], tenant);
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(AppIdentityDbContext.Create);
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);
app.CreatePerOwinContext<AppSignInManager>(AppSignInManager.Create);
app.CreatePerOwinContext<AppRoleManager>(AppRoleManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
AuthenticationMode = AuthenticationMode.Active,
LoginPath = new PathString("/"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<AppUserManager, AppUser>(
validateInterval: TimeSpan.FromHours(1),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
ExpireTimeSpan = TimeSpan.FromHours(1),
//Samesite secure
CookieSameSite = SameSiteMode.Lax,
CookieHttpOnly = true,
CookieSecure = CookieSecureOption.Always,
CookieManager = new SameSiteCookieManager(new SystemWebCookieManager())
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
//Open Id Connect
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
CookieManager = new SameSiteCookieManager(new SystemWebCookieManager())
});
app.UseOpenIdConnectAuthentication(CreateOpenIdOptions());
// GOOGLE
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
{
ClientId = ConfigurationManager.AppSettings["GoogleClientID"].ToString(),
ClientSecret = ConfigurationManager.AppSettings["GoogleClientSecret"].ToString()
});
}
private OpenIdConnectAuthenticationOptions CreateOpenIdOptions()
{
var options = new OpenIdConnectAuthenticationOptions
{
Authority = authority,
ClientId = clientId,
RedirectUri = redirectUri,
AuthenticationMode = AuthenticationMode.Passive,
// PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it is using the home page
PostLogoutRedirectUri = postLogoutRedirectUri,
Scope = OpenIdConnectScope.OpenIdProfile, // a basic set of permissions for user sign in & profile access
// ResponseType is set to request the id_token - which contains basic information about the signed-in user
ResponseType = OpenIdConnectResponseType.IdToken,
TokenValidationParameters = new TokenValidationParameters
{
// In a real application you would use ValidateIssuer = true for additional checks and security.
ValidateIssuer = false,
},
Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthenticationFailed = OnAuthenticationFailed,
},
// Handling SameSite cookie according to https://learn.microsoft.com/en-us/aspnet/samesite/owin-samesite
CookieManager = new SameSiteCookieManager(
new SystemWebCookieManager()),
};
return options;
}
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
// Handle any unexpected errors during sign in
context.OwinContext.Response.Redirect("/Error?message=" + context.Exception.Message);
context.HandleResponse(); // Suppress the exception
return Task.FromResult(0);
}
}
Below is sign out method which is called before sign in
var authenticationTypes = new string[] {
DefaultAuthenticationTypes.ApplicationCookie,
DefaultAuthenticationTypes.ExternalCookie,
};
AuthManager.SignOut(authenticationTypes);
I also already tried apply many fixed posts related to this but it does not work. How can we resolve external cookie map to local cookie?
Finally, I found workaround solutions below:
First if you don want to use Open id connect use the link below
Use Azure AD only for Authentication and not Authorization
I use Kentor.OwinCookieSaver to resolve my problem
https://github.com/Sustainsys/owin-cookie-saver

Mixing ASP.net Identity and Azure AD authentication

We use ASP.Net Identity for our DB backed login currently and need to add support for Azure AD SSO.
I appreciate once logged in I will need to link the SSO user to a user in our system to assign the relevant Claims and Roles but am struggling to get the 2 authentication methods working side by side and app.UseCookieAuthentication seems to be at the root of my problems.
Currently we have:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Login/Index"),
ReturnUrlParameter = "url",
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, IdentityUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
ExpireTimeSpan = TimeSpan.FromMinutes(double.Parse(ConfigurationManager.AppSettings["AuthenticationTimeout"])),
SlidingExpiration = true
});
With this in I suspect the cookie returned by the SSO isn't getting processed correctly as the Request.IsAuthenticated is always false.
If I change it to:
app.UseCookieAuthentication(new CookieAuthenticationOptions());
Then the SSO works and returns me an authenticated request but obviously breaks the Identity login.
For info my OpenId setup is as follows, for now just trying to get it to work with our work AD but eventually will need to expand to multi tenant:
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
RedirectUri = redirectUri,
PostLogoutRedirectUri = redirectUri,
Scope = OpenIdConnectScope.OpenIdProfile,
ResponseType = OpenIdConnectResponseType.IdToken,
TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = false
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed
}
}
);
Any help or pointers appreciated.
try using the
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
before
app.UseOpenIdConnectAuthentication

Is it possible to change HttpContext.Current.User.Identity.Name after change username

I'm working on a ASP MVC application. And want to change username without making user logout. I am using Identity Provider version 1.0.11. My code looks like:
var updtUser = UserManager.FindById(model.UserId);
updtUser.UserName = model.PrivateEMail;
var res = await UserManager.UpdateAsync(updtUser);
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
updtUser.UserName,
DateTime.Now,
DateTime.Now,
false,
"someData",
FormsAuthentication.FormsCookiePath);
string encTicket = FormsAuthentication.Encrypt(ticket);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
return RedirectToAction("RedirectToDashbord", "Dashboard", new { area = "CRM"});
But after this manipulations HttpContext.Current.User.Identity.Name is not changed. Any help would be great
You should enable immediate revocation of cookies (+):
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromSeconds(0),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});

WsFederation and local user mixed authentication

I'm trying make my user login with Azure AD credentials (using OWIN WsFederation plugin) or using a local user account with microsoft asp.net identity in a MVC 5.1 Web App.
Login with local users work fine, login using a federated account works only once, and I need to restart my app to make it work again.
I suppose the problem is with the response from Microsoft login page not processed correctly
Infact, using two differente browsers (chrome+ie) in private mode and Fiddler, I can see that my cookie is set on first request but not on a subsequent request made from a different browser
First request
Second request
This is my ConfigureAuth
public void ConfigureAuth(IAppBuilder app)
{
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.SetDefaultSignInAsAuthenticationType("ExternalCookie");
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
});
// these two lines of code are needed if you are using any of the external authentication middleware
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ExternalCookie",
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,
});
app.UseWsFederationAuthentication(new Microsoft.Owin.Security.WsFederation.WsFederationAuthenticationOptions()
{
MetadataAddress = "https://login.windows.net/XXXXXXX.onmicrosoft.com/federationmetadata/2007-06/federationmetadata.xml",
Wtrealm = "https://MYREALM",
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType,
});
}
This is part of the account controller
//
// POST: /Account/ExternalLogin
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
// Request a redirect to the external login provider
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
var ctx = Request.GetOwinContext();
var result = ctx.Authentication.AuthenticateAsync("ExternalCookie").Result;
if (result != null) //null on request other than the first (!!!)
{
ctx.Authentication.SignOut("ExternalCookie");
var claims = result.Identity.Claims.ToList();
claims.Add(new Claim(ClaimTypes.AuthenticationMethod, "External Account"));
var email = claims.Where(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name").SingleOrDefault().Value;
var ci = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
ctx.Authentication.SignIn(ci);
}
return RedirectToLocal(returnUrl);
}
In the ConfgureAuth set AuthenticationMode to Passive. It worked in my workflow which seems very similar to yours.
app.UseWsFederationAuthentication(new Microsoft.Owin.Security.WsFederation.WsFederationAuthenticationOptions()
{
MetadataAddress = "https://login.windows.net/XXXXXXX.onmicrosoft.com/federationmetadata/2007-06/federationmetadata.xml",
Wtrealm = "https://MYREALM",
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType,
AuthenticationMode = AuthenticationMode.Passive
});
http://msdn.microsoft.com/en-us/library/microsoft.owin.security.authenticationmode%28v=vs.113%29.aspx

Owin, WebApi, and UseCookieAuthentication

I've configured OWIN in my ASP.NET MVC application using cookie authentication, but when I attempt to access an ApiController with an Authorize attribute on it, authorization fails and I can't figure out why. Stepping into the IsAuthorized method of the Authorize attribute, I can see that none of the identity properties that are present when accessing an MVC controller are present, so it certainly appears (at least to the authorize attribute) that the user is not authenticated.
The app is configured as follows:
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(MyAuthContext.Create);
app.CreatePerOwinContext<MyUserManager>(MyUserManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<MyUserManager, MyUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
var httpConfig = new HttpConfiguration();
WebApiConfig.Register(httpConfig);
app.UseWebApi(httpConfig);
}
Do I absolutely have to use bearer tokens for WebAPI or is there just something I'm missing.

Resources