Looking at ASP.NET Identity (new membership implementation in ASP.NET), I came across this interface when implementing my own UserStore:
//Microsoft.AspNet.Identity.Core.dll
namespace Microsoft.AspNet.Identity
{
public interface IUserSecurityStampStore<TUser> :
{
// Methods
Task<string> GetSecurityStampAsync(TUser user);
Task SetSecurityStampAsync(TUser user, string stamp);
}
}
IUserSecurityStampStore is implemented by the default EntityFramework.UserStore<TUser> which essentially get and set the TUser.SecurityStamp property.
After some more digging, it appears that a SecurityStamp is a Guid that is newly generated at key points in the UserManager (for example, changing passwords).
I can't really decipher much beyond this since I'm examining this code in Reflector. Almost all the symbol and async information has been optimized out.
Also, Google hasn't been much help.
Questions are:
What is a SecurityStamp in ASP.NET Identity and what is it used for?
Does the SecurityStamp play any role when authentication cookies are created?
Are there any security ramifications or precautions that need to be taken with this? For example, don't send this value downstream to clients?
Update (9/16/2014)
Source code available here:
https://github.com/aspnet/Identity/
https://github.com/aspnet/Security/
This is meant to represent the current snapshot of your user's credentials. So if nothing changes, the stamp will stay the same. But if the user's password is changed, or a login is removed (unlink your google/fb account), the stamp will change. This is needed for things like automatically signing users/rejecting old cookies when this occurs, which is a feature that's coming in 2.0.
Identity is not open source yet, its currently in the pipeline still.
Edit: Updated for 2.0.0. So the primary purpose of the SecurityStamp is to enable sign out everywhere. The basic idea is that whenever something security related is changed on the user, like a password, it is a good idea to automatically invalidate any existing sign in cookies, so if your password/account was previously compromised, the attacker no longer has access.
In 2.0.0 we added the following configuration to hook the OnValidateIdentity method in the CookieMiddleware to look at the SecurityStamp and reject cookies when it has changed. It also automatically refreshes the user's claims from the database every refreshInterval if the stamp is unchanged (which takes care of things like changing roles etc)
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.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
If your app wants to trigger this behavior explicitly, it can call:
UserManager.UpdateSecurityStampAsync(userId);
The UseCookieAuthentication is deprecated by now. I managed to configure it using
services.Configure<SecurityStampValidatorOptions>(o =>
o.ValidationInterval = TimeSpan.FromSeconds(10));
Moved from reply to answer per request.
I observed the SecurityStamp to be required for token verification.
To repo:
Set SecurityStamp to null in the databsae
Generate a token (works ok)
Verify token (fails)
Related
I have an ASP.net WebForms application, which I have configured to work with Azure Active Directory and OpenIDConnect based on this article:
http://www.cloudidentity.com/blog/2014/07/24/protecting-an-asp-net-webforms-app-with-openid-connect-and-azure-ad/
Generally speaking, it works fine. But sometimes, after a longer period of inactivity (e.g. filling out a big form), the user is redirected to the main page of the app and his data from the form is lost. This is of course very confusing.
It seems that at some point the session (token?) expires and it needs to re-authenticate. I was able to track a HTTP 302 to https://login.windows.net/... at the point of the redirect. So it would confirm my assumption about re-authentication via AAD.
I cannot exactly tell how often this happens - for me it does not seem to be in regular intervals. I was trying to reproduce the behavior by deleting the cookies AspNet.Cookies and ASP.NET_SessionId but it did not cause the redirect. Interacting with the application just recreated those cookies automatically.
My questions are:
Is there some other location (local storage?) where the information about the login is saved?
How can I (silently, in the background) make sure that the session/token is valid?
In your initialisation code, assuming you've followed the instructions in the article you've linked, there's a line like so,
app.UseCookieAuthentication(new CookieAuthenticationOptions());
When delegating authentication to an Identity Provider, your application still drops some cookies based on the authentication result that control lifetimes. You can tweak these settings to your requirements....e.g.
appBuilder.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType ="Cookies",
ExpireTimeSpan = TimeSpan.FromMinutes(60), // Expire after an hour
SlidingExpiration = true // use sliding expiration..
});
Have a look at the docs for the things you can configure - https://learn.microsoft.com/en-us/previous-versions/aspnet/dn385599(v%3Dvs.113)
Also, an event will be raised whenever it thinks it needs to interact with the Identity Provider, handler optoions available under the Notifications object on OpenIdConnectAuthenticationOptions. One you might be interested in is RedirectToIdentityProvider
private void ConfigureOpenIdConnect()
{
var openIdConnectAuthenticationOptions = new OpenIdConnectAuthenticationOptions
{
// the rest of your settings....then
Notifications =
new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider =
async context => await RedirectToIdentityProviderHandler(context)
},
UseTokenLifetime = false
};
}
private static Task RedirectToIdentityProviderHandler(
RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
// do some logging whenever you app is redirecting to the IDP
return Task.FromResult(0);
}
UseTokenLifetime is interesting here, as your identity token has an expiration time and by default the cookie lifetime in the application is the life of the token. If you want to control the cookie lifetime yourself (as per the first code snippet), set this to false here and explicitly control this yourself.
You could use a combination of overriding the identity token lifetime, a longer cookie lifetime, setting sliding expiration to true + some logging on whenever Redirects happen to the Identity Provider.
Obviously though, tweaking settings too much increases attack vector, so consider your security requirements carefully.
As you know, you will get ID token after login successfully via AAD. ID token is Jwt format with an expiration time. You can change the ID token's lifetime with powershell. Please refer to this document https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-configurable-token-lifetimes#access-token-lifetime.
I am trying to get a better understanding of how jwt tokens are stored (id, access, refresh). When you add OpenIdConnect, one of the options you can set is saving tokens. With below configuration, whenever the user logs in, the jwt tokens are generated (without having to have a separate call to the authorization endpoint to retrieve tokens).
.AddOpenIdConnect("Test", options => {
options.SaveTokens = true;
}
From what I have read, they are saved in the AuthenticationProperties collection returned along with the ClaimsPrincipal. You can retrieve them via HttpContext.GetTokenAsync.
Example below:
var accessToken = await HttpContext.GetTokenAsync("access_token");
I am trying to understand more about how these values are stored and retrieved. I know that the claimsprincial is a collection of identities / claims associated with a user. But how exactly are authentication properties set? How can I access the collection of authentication properties individually? Is there a class / interface I can use to get direct access to the class properties? I didn't see anything about authentication properties in the ClaimsPrincial class.
Also, as the access token is stored in the authentication properties, is the only way to update the value is to re-authenticate (i.e. challenge the user to login again)? How can I update the value? Or would it be better off extracting the value is storing it elsewhere to update?
I have been looking into this a bit myself as well. The OpenID Connect middleware seems to usually persist data into a signed cookie via a second cookie authentication scheme, specified by the SignInScheme option. Extending your example from before with an explicitly configured example:
.AddOpenIdConnect("Test", options => {
options.SignInScheme = "MyCookieScheme";
options.SaveTokens = true;
}
This example implies that a cookie authentication scheme has also been set up with a call like this:
.AddCookie("MyCookieScheme")
From the documentation comments on SignInScheme:
Gets or sets the authentication scheme corresponding to the middleware responsible of persisting user's identity after a successful authentication. This value typically corresponds to a cookie middleware registered in the Startup class. When omitted, Microsoft.AspNetCore.Authentication.AuthenticationOptions.DefaultSignInScheme is used as a fallback value.
(Note that this property actually comes from a RemoteAuthenticationOptions class that OpenIdConnectOptions extends)
Tracing what happens in default setup scenarios where you don't explicitly give a cookie authentication scheme is a bit tricky but I imagine it sets one up by default, or relies on one being there. Also, I guess that in theory, any other type of authentication scheme could be used for this persistence (e.g. your own JWT issuing and signing scheme), but I have not seen any examples of this.
As for what is actually stored in the cookie and how it gets put there by the OpenID Connect middleware, you would probably have to do a lot of digging through all of the code to work that out for sure - the specifics of all this low-level middleware doesn't seem to have been documented much yet. All I know for sure is that the DataProtection middleware is involved in encrypting the contents of the cookie.
You could look into decrypting the cookie itself to see what's there - see the answers here: How to manually decrypt an ASP.NET Core Authentication cookie?
(oh and for the record, all these examples are based off ASP.NET Core v2.0)
Another option is to use TokenValidationParameters.SaveSigninToken
From source code
if (validationParameters.SaveSigninToken)
identity.BootstrapContext = jwtToken.RawData;
It will store the original token in the BoostrapContext property of the current identity.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication()
.AddJwtBearer(options =>
{
options.TokenValidationParameters.SaveSigninToken = true;
});
}
}
Then access the identity of the current user
((ClaimsIdentity)this.User.Identity).BoostrapContext // => original JWT token
In my application's Asp.Net Identity Auth middleware setup I have
app.UseCookieAuthentication(new CookieAuthenticationOptions {
LoginPath = new PathString("/Login/"),
//AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
Provider = new CookieAuthenticationProvider {
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<MyUserManager, MyUser>(
TimeSpan.FromMinutes(30),
(manager, user) => manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)
),
},
});
I had copied this from another app and I just noticed that if I uncomment the AuthenticationType line, login succeeds (I get a success message in my logger written from my controller) but always redirects back to the login screen.
In the documentation for CookieAuthenticationOptions it says
The AuthenticationType in the options corresponds to the IIdentity AuthenticationType property. A different value may be assigned in order to use the same authentication middleware type more than once in a pipeline.(Inherited from AuthenticationOptions.)
I don't really understand what this means, why this would cause my login request to be redirected (after a successful login no less), nor what this option would be useful for.
This is a string and can be anything. But this is an identifier for authentication type. And you can have multiple authentication types: your DB with users, Google, Facebook, etc. As far as I remember this is added as a claim to the generated cookie on sign-in.
You need to know the authentication provider when you sign user out. If your authentication middleware is defined like this:
app.UseCookieAuthentication(new CookieAuthenticationOptions {
LoginPath = new PathString("/Login/"),
AuthenticationType = "My-Magical-Authentication",
// etc...
},
});
then to sign user out you need the same magic string: AuthenticationManager.SignOut("My-Magical-Authentication")
Also this string is passed into ClaimsIdentity when principal is created. And without AuthenticationType principal can't be authenticated because:
/// <summary>
/// Gets a value that indicates whether the identity has been authenticated.
/// </summary>
///
/// <returns>
/// true if the identity has been authenticated; otherwise, false.
/// </returns>
public virtual bool IsAuthenticated
{
get
{
return !string.IsNullOrEmpty(this.m_authenticationType);
}
}
This method IsAuthenticated is used through entire MVC code-base, with all authentication mechanisms relying on this.
Also theoretically you can sign in through multiple providers and sign out only a single one of them at a time, leaving the rest of providers still authenticated. Though I have never tried this.
Another use I just found - if you don't provide CookieName in your middleware configuration, then Options.CookieName = CookieAuthenticationDefaults.CookiePrefix + Options.AuthenticationType; (see second if statement in constructor).
I'm sure there are more places where it is used. But the most important is to provide it and be consistent with the name or you'll get subtle bugs in authentication system.
I don't know the whole answer, but I have an example on what it would be useful for.
I have a multi-tenant website: the website runs as a single instance multiple domains are linked to it. Each domain is a separate tenant (with a separate set of users). To implement a Facebook login per tenant, I needed a Facebook app per tenant. To configure this, I had to set a unique CallbackPath and a unique AuthenticationType per tenant:
var facebookOptions = new FacebookAuthenticationOptions
{
AuthenticationType = "Facebook-{tenantID}",
CallbackPath = new PathString($"/signin-facebook-{tenantID}")
}
I thought it was also used as a cookie name, but that's not the case for an external login like FacebookAuthentication. What I did notice is that this value of AuthenticationType popped up when requesting:
the IdentityUserLogin.LoginProvider via authenticationManager.GetExternalLoginInfoAsync()
the AuthenticationDescription.AuthenticationType via authenticationManager.GetExternalAuthenticationTypes() (seems logical ;-))
The IdentityUserLogin.LoginProvider for each user.Logins (similar to 1)
And last but not least: the value of AuthenticationType is stored in the database column AspNetUserLogins.LoginProvider.
If you set up a fresh asp.net solution, the standard set-up code (as opposed to the code you copied from another app) in Startup.Auth includes the line AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
This creates a cookie (with a default name of .AspNet.ApplicationCookie), which you can see if you look in your browser's active cookie list, that is used (amongst other things) to check whether or not the User is Authenticated for every request. If the cookie is not there (or the User is in some way not Authenticated), the middleware redirects to the route specified in your line LoginPath = new PathString("/Login/"),
The fact that this line is commented out in your code and your app works suggests that there is some other non-standard configuration in place in your code to authenticate the User. If you uncomment this line and login succeeds but redirects back to login, this suggests that there is some conflict between the non-standard code and the middleware that results in the middleware determining that the User is not Authenticated, and gets redirected back to the LoginPath.
I would seek out whether there is non-standard authentication code in your app and determine what that specifically does, and the answer for the conflict should present itself. General advice is not to change the standard Authentication code unless you know exactly what the implications of doing this are (and it can get complicated, with plenty of traps for the unwary).
Specifically to your question, this option is not just useful, it is fundamental to standard operation of the Identity middleware. You appear to have non-standard code in your app. If so, you should fully determine what it does (and it's implications) with regards to login security, or revert back to standard Identity code if you can.
I have a AngularJS client application that uses javascript (not coffeescript or typescript) Oauth2 to authenticate against a WebAPI 2 application using the latest Identity 2. All the software in my application is the very latest and is based on this example. My client browser targets are IE9 and above.
Note that I made some minor changes from the example above in that I do not urlencode all of the data sent to the server using the transform. Instead I urlencode only in the authenticate method below:
user.authenticate = function (userName, password, rememberMe, successCallback, errorCallback) {
var config = {
method: 'POST',
url: '/Token',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: 'grant_type=password&username=' + encodeURIComponent(userName) + '&password=' + encodeURIComponent(password),
};
I am developing with VS2013 Update 2 and on the server, I use C#, the latest Entity Framework and SQL Server 2012.
To login my client calls a /Token method to the WebAPI and passes the userid and password. The WebAPI then responds with a token to the client which I store. With each request to the WebAPI the token is sent back and authenticated:
$http.defaults.headers.common.Authorization = 'Bearer ' + user.data.bearerToken;
This works very well so far but as it stands the application is unable to tell the difference between users that have different roles assigned to them.
Some of the WebAPI methods can only be executed by users who have a certain role. I would like to adjust the menus of my front-end AngularJS application so that only if the user has this role then the appropriate links will appear visible. I do realize that this would not stop a user from checking the HTML and posting but I am not concerned about this as I will still have method decoration to limit the ability of users not in a role to perform actions.
Can someone give me an example of how I can do this using just the suite of products mentioned above that I mention in the question plus JavaScript Web Tokens if they help make bring the solution up to date. From what I understand roles are handled by claims but I do not understand how to add these and send them back to the client with tokens. I have done a lot of research on the internet but I've not been able to find any good examples as I think most of this is very new and not many people have had the chance to explore how a SPA can use these very latest software components.
When answering this question please note that I am not looking for an answer that can tell the community how to set up roles on the server or an answer that explains about how important it is to provide role checks on the server. I think almost everyone is aware of this. What I really think will be of use is some very detailed technical suggestions with sample code and an explanation. To keep the answer focused it would probably be of help to everyone if answers that do not meet this need are not posted as suggested answers.
Thank you in advance.
The short answer to your question is ApplicationOAuthProvider.CreateProperties method. Its created for you by default and is found under WebApi2/Provider/ApplicationOAuthProvider.cs, By default it only sends the userName
//WepApi2/Providers/ApplicationOAuthProvider.cs
public static AuthenticationProperties CreateProperties(string userName)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName }
};
return new AuthenticationProperties(data);
}
I would make the following update (in case I need to send more user data later on):
public static AuthenticationProperties CreateProperties(string userName, ClaimsIdentity oAuthIdentity)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName},
{ "roles",string.Join(",",oAuthIdentity.Claims.Where(c=> c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray())}
};
return new AuthenticationProperties(data);
}
If you haven't made major changes to the WebApi project, ApplicationOAuthProvider.CreateProperties is only referenced in two places, just update the calling code to pass the oAuthIdentity along with user.UserName and you'll get the user roles sent along with the access token response:
{
"access_token": "ZpxAZyYuvCaWgShUz0c_XDLFqpbC0-DIeXl_tuFbr11G-5hzBzSUxFNwNPahsasBD9t6mDDJGHcuEqdvtBT4kDNQXFcjWYvFP7U2Y0EvLS3yejdSvUrh2v1N7Ntz80WKe5G_wy2t11eT0l48dgdyak8lYcl3Nx8D0cgwlQm-pePIanYZatdPFP9q5jzhD-_k9SF-ARTHgf0ePnbvhLBi1MCYQjvfgPKlbBHt0M5qjwGAeFg1IhSVj0gb4g9QTXoiPhRmxGBmjOpGgzxXixavmrpM7cCBFLoR3DCGnIJo6pwT-6VArxlB8-ZyyOZqh_6gGtptd0lIu8iJRUIGwO9HFNkROdoE9T4buwLnhPpWpy9geBjPVwsB1K3xnbch26YbklhxIHVybBxeIVXd17QTw_LjlQ5TJdqpAYfiZ5B9Nx2AFYYYe3--aemh4y1XOIvN",
"token_type": "bearer",
"expires_in": 1209599,
"userName": "MK",
"roles": "Admin,Public",
".issued": "Fri, 23 May 2014 17:36:54 GMT",
".expires": "Fri, 06 Jun 2014 17:36:54 GMT"
}
Now you have the roles available, you can use Angular conditional directives to show/hide actions according to user roles.
If you need more clarification, please let me know.
Edit:
Decorating your controller methods with Authorize attribute is valid, since the HttpContext.Current.User.Identity is actually a ClaimsIdentity. But as not to hard code security logic inside the application, I prefer using ClaimsAuthorizationManager
public ActionResult Secure()
{
if(!ClaimsPrincipalPermission.CheckAccess("resource", "action"))
return new HttpUnauthorizedResult();
ViewBag.Message = "You are allowed to perform action on resource.";
return View();
}
Roles creation using RoleManager:
RoleManager roleManger = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>());
roleManager.Create(new IdentityRole() { Name = "Admin" });
Roles assignment using UserManager:
userManager.AddToRole(user.Id, "Admin");
There are 2 ways I see you can approach your problem.
include the "Role" Information to the token by a hash or a simple string append as you are the one generating the token, then you can decipher it on the angular.
it seems you want to use ASP.NET Identity system and store and retrieve the role information there. If that is the case you can go through this post pay attention to "Initialize the database to create Admin Role and Admin User" section.
IMO, #1 will give you more flexibility on how you store and use your user data as #2 you are following Microsoft's IdentityUser , although it look magic sometimes and it tend to post limitation and you need to spend time to understand how it works behind the scene and make it work for your project.
To know more about the "Individual User Accounts" you pick during the WebAPI project you created, you can go to http://www.asp.net/visual-studio/overview/2013/creating-web-projects-in-visual-studio#indauth
I have a very similar scenario as yours, but instead of using tokens to authenticate, I use an Identity Server (Thinktecture) to handle my authentication. My app redirects to the Identity Server to authenticate and it comes back with some very basic claims (username and email). This happens as soon as someone tries to first browse to the page. Once the user is authenticated and redirected to my app I make another call to the server to get the user's permissions. These permissions are stored inside a Security service (AngularJS) which also exposes a "hasPermissions" method. I then use ng-if to decide if I am going to display certain parts of the page - including menu items. Something to this effect:
var service = {
currentUser: ...,
isAuthenticated: function() {
return ...;
},
checkAccess: function(permission) {
return service.isAuthenticated() ?
!!(service.currentUser.permissions.indexOf(permission) > -1) : false;
}
}
Remember that all all the permissions and html elements are visible to anyone who decides to hit the dev tools button and take a peek. You have to do the same checks on the server side before you perform any action. We have a custom Authorization attribute based off of this that checks if the user has the necessary permissions to execute the MVC/WebAPI action before it is executed for simple cases or actually check it within the Action or the HTTP resource before doing anything that needs elevated privileges.
If you want the client to not see any html elements or certain sections of your site you can either point your templates to a MVC action that will authenticate and then return the HTML template or redirect to another page (not the SPA realm) and have them authenticated on the server before the response is served back.
Here another answer:
In ApplicationOAuthProvider.cs
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
simply add a custom header!
context.OwinContext.Response.Headers.Add("Roles", userManager.GetRoles(user.Id).ToArray());
I have been following the OAuth 2.0 Authorization Server sample code
http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server
As well as looking at the nugget package Microsoft.aspnet.identity.samples package
(install-package Microsoft.aspnet.identity.samples -Pre)
and am trying to get my head around how passive vs. active cookie middleware works.
In the Authorization server example, the "Application" cookie is set to passive.
In the Identity samples, "ApplicationCookie" is active.
When I read about this property, it explains that passive middleware is only triggered when requested by a matching AuthenticationType.
If I edit the startup.auth.cs file in the Microsoft.aspnet.identity.samples and set the application cookie to passive, then log in, it seems to validate, but doesn't log me in.
Digging deeper into the code, I see that the account controller boil down to a call to SignInHelper.SignInAsync
This method gets a claimsidentity from the user which is a call to: CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)
I am obviously not understanding something, since from what I read and can tell, the cookie has the same AuthenticationType as the Claim, but when the Authentication.SignIn is called, the Cookie doesn't seem to get set and I am returned to the main page with options to register and login.
To duplicate the issue, start a new project empty asp.net application, then install the Identity sample package, then change startup.auth.cs's app.useCookieAuthentication to:
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,
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.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
I have tried changing the cookie name in the startup.auth.cs and adding the "custom" name to the code that generates the claim to no avail.
I am going to keep researching, but thought I would reach out to the community in the meantime.
I'm not sure of the exact question you have.
OWIN is a pipeline that runs all the middleware modules registered. You can have multiple authentication types of middleware registered.
The cookie decrypts to the identity. If you change the authentication type to external bearer it will be a bearer token in the cookie.
I'm not sure why its not working for you, this is what I use. (I haven't looked at the external logins of the template)
// Enable the application to use a cookie to store information for the signed in user
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
//just to show bearer
AuthenticationType = DefaultAuthenticationTypes.ExternalBearer,
LoginPath = new PathString("/Account/Login"),
}
Good explanation of active vs. passive, from Mr. Brock Allen himself.
Active vs Passive authentication middleware
One question that arises — if the new templates have multiple OWIN authentication middleware configured, then which one is really used? Well, OWIN authentication middleware has the concept of passive vs. active. Active middleware always look at every incoming request and attempt to authenticate the call and if successful they create a principal that represents the current user and assign that principal to the hosting environment. Passive middleware, on the other hand, only inspects the request when asked to. In the case of the default templates from Visual Studio 2013, all the middleware configured are all passive by default, except for the “main” cookie authentication middleware (turns out there are two cookie middlewares that get used in some templates — the main one and another one for external identity providers and this other one is marked as passive).
I arrived here because I was asking the same question. It turns out there is no correct way because it cannot be done. The Authentication middleware calls the "Invoke" method to test whether it should do anything in passive mode. In middleware such as the OpenIdConnect middleware, this method is over-ridden such that it checks the request path, and if it's the Options.RedirectUri then the the middleware does something, sets up the Response object to do something like a redirect and returns "true" to indicate that the request has been handled, and then the middleware stack is unwound and the response processed.
The CookieAuthenticationMiddleware's Invoke method does nothing, it only returns 'false', which means that control is passed to the next middleware in the chain.
So, the result is that CookieAuthenticationMiddleware cannot be used for authentication in passive mode.
I found this blog post really helpful: https://chris.59north.com/post/Understanding-OWIN-(Katana)-Authentication-Middleware . Also, take a look at the Katana source code: https://github.com/aspnet/AspNetKatana
page works fine when i comment below coding.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
//LoginPath = new PathString("/Login"),
Provider = new CookieAuthenticationProvider(),
CookieName = "DefaultAuthenticationTypes",
CookieHttpOnly = true,
ExpireTimeSpan = TimeSpan.FromHours(cookieActiveTime),
});
.