How does owin middleware track change in cookie - owin

How does owin middleware track change in cookie? I am using cookie authentication. After cookie is generated and attached to browser if I make any change in cookie by using F12(developer toolbar in browser) and send request to sever how is owin validating cookie?
var cookieAuthenticationOptions = new CookieAuthenticationOptions
{
CookieName = "test",
AuthenticationType = "Cookies",
ExpireTimeSpan = TimeSpan.FromHours(12),
SlidingExpiration = false
};
app.UseCookieAuthentication(cookieAuthenticationOptions);

PREFERRED BEHAVIOR
Auth cookies are strongly encrypted since they contain tokens in some cases. The pattern for auth cookies is to use properties such as these:
HTTP Only
Encrypted
SameSite=strict
Domain=web origin
Secure
Symmetric authenticated encryption is used, with an algorithm such as AES256-GCM. This means any edit to any cookie byte will fail decryption, resulting in a 401 error. You should test this.
Cookies are time restricted also. Either the exp claim of stored tokens is checked on every request, or a separate timestamp within the cookie data.
OWIN
Sone notes here on OWIN crypto. It is quite an old tech now, so does not use the most cutying edge encryption algorithms. Instead it uses machine key based encryption, which I believe uses AES + HMACSHA under the hood. The end result is essentially the same behavior as above though.

Related

Next.js Authentication with JWT

I am moving a project from React to Next.js and was wondering if the same authentication process is okay. Basically, the user enters their username and password and this is checked against database credentials via an API (Node.js/Express). So, I am not using Next.js internal api functionality, but a totally decoupled API from my Next.js project.
If the login credentials are correct, a JWT token is sent back to the client. I wanted to store that in local storage and then redirect the user. Any future HTTP requests will send the token in the header and check it is valid via the API. Is this okay to do? I ask because I see a lot of Next.js auth using cookies or sessions and don't know if that is the 'standard' approach which I should rather adopt.
My answer is purely based on my experiences and things I read. Feel free to correct it if I happened to be wrong.
So, my way is to store your token in HttpOnly cookie, and always use that cookie to authorize your requests to the Node API via Authorization header. I happen to also use Node.js API in my own project, so I know what's going on.
Following is an example of how I usually handle authentication with Next.js and Node.js API.
In order to ease up authentication problems, I'm using Next.js's built in getServerSideProps function in a page to build a new reusable higher order component that will take care of authentication. In this case, I will name it isLoggedIn.
// isLoggedIn.jsx
export default (GetServerSidePropsFunction) => async (ctx) => {
// 1. Check if there is a token in cookies. Let's assume that your JWT is stored in 'jwt'.
const token = ctx.req.cookies?.jwt || null;
// 2. Perform an authorized HTTP GET request to the private API to check if the user is genuine.
const { data } = await authenticate(...); // your code here...
// 3. If there is no user, or the user is not authenticated, then redirect to homepage.
if (!data) {
return {
redirect: {
destination: '/',
permanent: false,
},
};
}
// 4. Return your usual 'GetServerSideProps' function.
return await GetServerSidePropsFunction(ctx);
};
getServerSideProps will block rendering until the function has been resolved, so make sure your authentication is fast and does not waste much time.
You can use the higher order component like this. Let's call this one profile.jsx, for one's profile page.
// profile.jsx
export default isLoggedIn(async (ctx) => {
// In this component, do anything with the authorized user. Maybe getting his data?
const token = ctx.req.cookies.jwt;
const { data } = await getUserData(...); // don't forget to pass his token in 'Authorization' header.
return {
props: {
data,
},
},
});
This should be secure, as it is almost impossible to manipulate anything that's on server-side, unless one manages to find a way to breach into your back-end.
If you want to make a POST request, then I usually do it like this.
// profile.jsx
const handleEditProfile = async (e) => {
const apiResponse = await axios.post(API_URL, data, { withCredentials: true });
// do anything...
};
In a POST request, the HttpOnly cookie will also be sent to the server, because of the withCredentials parameter being set to true.
There is also an alternative way of using Next.js's serverless API to send the data to the server. Instead of making a POST request to the API, you'll make a POST request to the 'proxy' Next.js's serverless API, where it will perform another POST request to your API.
there is no standard approach. You should be worried about security. I read this blog post: https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/
This is a long but an awesome blog post. everyhing I post here will be quoted from there:
If a JWT is stolen, then the thief can keep using the JWT. An API
that accepts JWTs does an independent verification without depending
on the JWT source so the API server has no way of knowing if this was
a stolen token! This is why JWTs have an expiry value. And these
values are kept short. Common practice is to keep it around 15
minutes.
When server sends you the token, you have to store the JWT on the client persistently.
Doing so you make your app vulnerable to CSRF & XSS attacks, by
malicious forms or scripts to use or steal your token. We need to save our JWT token somewhere so that we can forward it to our API as a header. You might be tempted to persist it in localstorage; don’t do it! This is prone to XSS attacks.
What about saving it in a cookie?
Creating cookies on the client to save the JWT will also be prone to XSS. If it can be read on the client from Javascript outside of
your app - it can be stolen. You might think an HttpOnly cookie
(created by the server instead of the client) will help, but cookies
are vulnerable to CSRF attacks. It is important to note that HttpOnly
and sensible CORS policies cannot prevent CSRF form-submit attacks and
using cookies requires a proper CSRF mitigation strategy.
Note that a SameSite cookie will make Cookie based approaches safe
from CSRF attacks. It might not be a solution if your Auth and API
servers are hosted on different domains, but it should work really
well otherwise!
Where do we save it then?
The OWASP JWT Cheatsheet and OWASP ASVS (Application Security
Verification Standard) prescribe guidelines for handling and storing
tokens.
The sections that are relevant to this are the Token Storage on Client
Side and Token Sidejacking issues in the JWT Cheatsheet, and chapters
3 (Session Management) and 8 (Data Protection) of ASVS.
From the Cheatsheet, "Issue: Token Storage on the Client Side":
Automatically sent by the browser (Cookie storage).
Retrieved even if the browser is restarted (Use of browser localStorage container).
Retrieved in case of XSS issue (Cookie accessible to JavaScript code or Token stored in browser local/session storage).
"How to Prevent:"
Store the token using the browser sessionStorage container.
Add it as a Bearer HTTP Authentication header with JavaScript when calling services.
Add fingerprint information to the token.
By storing the token in browser sessionStorage container it exposes
the token to being stolen through a XSS attack. However, fingerprints
added to the token prevent reuse of the stolen token by the attacker
on their machine. To close a maximum of exploitation surfaces for an
attacker, add a browser Content Security Policy to harden the
execution context.
"FingerPrint"
Where a fingerprint is the implementation of the following guidelines
from the Token Sidejacking issue: This attack occurs when a token has been intercepted/stolen by an attacker and they use it to gain access to the system using targeted user identity.
"How to Prevent":
A way to prevent it is to add a "user context" in the token. A user context will be composed of the following information:
A random string will be generated during the authentication phase. It will be sent to the client as a hardened cookie (flags: HttpOnly +
Secure + SameSite + cookie prefixes).
A SHA256 hash of the random string will be stored in the token (instead of the raw value) in order to prevent any XSS issues allowing
the attacker to read the random string value and setting the expected
cookie.

Jwt authentication on node-js and react -js

I am working on jwt authentication based projects and I want to store the token which is created on user 's login request but this token can be decoded easily so where I have to store these token ?
//code to create token and cookie
const createToken=(id)=>{
return jwt.sign({id},secretkey);}
{....some code are written here.....}
const token= createToken(userid);
res.cookie('jwts',token,{httpOnly:true,maxAge:1000*60*60,sameSite:'lax'})
From your question, it feels like your JWT flow isn't clear. The token can be decoded - but it will only reveal some payload data and header - which doesn't contain any sensitive data.
Token's generation and explanation:
A JWT Token is formed of Header, Payload & Signature.
The header is metadata about the token itself.
The payload can be encoded in the token, i.e. the data e.g. user's Id.
Signature is created using header, payload, & the SECRET stored at the server. This process is called Signing. This 'SECRET' is what helps us to validate the signature's authenticity.
Well, so how do we make sure the data isn't modified?
A verification process is done at the server where JWT's header, payload, and secret are used to create a test signature. This signature is matched with the original signature (existing inside the JWT already) - then the data has not been modified.
Without secret - no one can manipulate JWT. That is, the verification will fail if the signatures do not match.
Token Storage:
There is some debate about whether to store the token in cookies or local-storage since both are prone to hacker attacks.
Login Flow:
The client sends a request to the server (POST - login).
The server validates the user and returns a JWT token in response if the provided credentials are valid.
The JWT token is stored in localStorage / cookies depending on the preferred choice (I prefer localStorage).
you need to send that token along with the API requests from client. I used to store in clients internal storage and used to send that token for each and every API call.

Utilize JWTBearer from multiple Identity Providers in ServiceStack API

Is it possible for a ServiceStack api to accept jwt tokens from multiple identity providers?
I have one admin application that will be calling all our apis across environments. I need to allow my api's to accept jwt tokens from two different identity providers. This can be accomplished in web api, by calling the .AddJwtBearer help method twice and not providing a default schema in the AddAuthentication() helper. And the providing both in the AddAuthorization helper method. I tested this out in ServiceStack and it is not working for me.
This is in the .net core startup, configure services.
services.AddAuthentication()
.AddJwtBearer("Bearer", options => {
options.Authority = Configuration["IDENTITYSRV_WEB_BASEURL"];
options.RequireHttpsMetadata = Boolean.Parse(Configuration["IDENTITY_HTTPSMETADATA"]);
options.Audience = Configuration["IDENTITY_VALIDAUDIENCE"];
})
.AddJwtBearer("Admin", options =>
{
options.Authority = "Configuration["IDENTITYSRV_WEB2_BASEURL"]";
options.RequireHttpsMetadata = Boolean.Parse(Configuration["IDENTITY_HTTPSMETADATA"]);
options.Audience = Configuration["IDENTITY_VALIDAUDIENCE"];
});
AppHost
AuthFeature auth = new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { new NetCoreIdentityAuthProvider(AppSettings), })
{
IncludeAssignRoleServices = false,
IncludeRegistrationService = false,
IncludeAuthMetadataProvider = false
};
Plugins.Add(auth);
Any suggestions or work around?
ServiceStack's JWT Auth Provider supports all HMAC and RSA crypto algorithms for its JWT or JWE tokens, but it can only be configured with the 1 algorithm you want it to use. So it's technically not possible for it to verify JWT Tokens from different authorities which would likely be configured with different keys and algorithms.
The next obstacle is that if all Identity providers were configured to use the same Key and Algorithm, they would need to encode the same contents ServiceStack uses in order for the JWT to be correctly deserialized into an Authenticated ServiceStack Session. Most of the names used in ServiceStack's JWT's have well-known names however there are others that don't like roles and perms, in which case ServiceStack JWT's have adopted the Azure Active Directory Conventions. Although there is an opportunity to apply custom logic when inspecting the verified JWT Body and populating the Session using the PopulateSessionFilter.
Ultimately I don't think trying to funnel multiple JWT's into the same implementation is a viable strategy, instead I would be looking at creating Custom JWT Auth Providers like JwtAuthProviderReader.cs which just knows how to handle parsing JWT's from a single provider which would then know how to verify & extract the Authenticated Session Info from each JWT and use it to populate a ServiceStack Session. This could be done in a "single uber JWT Auth Provider" that has knowledge in being able to parse every JWT sent to it, but as JWT Tokens are sent with the same Authorization: Bearer {Token} HTTP Header there would need to be some information in the JWT Headers that determines which crypto algorithms it should use to validate each token. If all Identity Providers use different alg then that might be enough to be able to distinguish the identity provider.
Either way there's no pre-built solution in ServiceStack that you could configure to support multiple identity Auth Providers, the other approach you may want to look at is to maintain all Authentication in a central Identity Server Auth Provider so then your Websites only need to be configured to support Authentication from the central Identity Server.

Owin WS-Federation setting up token sliding expiration

Can somebody explain how to implement sliding expiration using the new Owin WS-Federation plugin?
On the client side, at WS-Fedeartion configuration I see that there are some events like :
Notifications = new WsFederationAuthenticationNotifications
{
SecurityTokenReceived = ...,
AuthenticationFailed = ...,
RedirectToIdentityProvider = ...,
MessageReceived = ...,
SecurityTokenValidated = ....
},
But because the lack of documentation I can't really figure it out where an how?
At the moment my STS is issuing tokens with absolute expiration:
protected override Lifetime GetTokenLifetime(Lifetime requestLifetime)
{
// 5 Minutes for token lifetime
var lifetime = new Lifetime(DateTime.UtcNow, DateTime.UtcNow.AddMinutes(5));
return lifetime;
}
Any help is higly appreciated.
TL;DR: set WsFederationAuthenticationOptions.UseTokenLifetime to false, to re-enable sliding expiration.
In OWIN/Katana, the sliding expiration concept is limited to the cookies middleware and is enabled by default (you can turn it off by setting CookieAuthenticationOptions.SlidingExpiration to false: https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.Cookies/CookieAuthenticationOptions.cs).
When you use app.UseWsFederationAuthentication (or app.UseOpenIdConnectAuthentication), it actually relies on another middleware to persist the ClaimsIdentity when you complete the authentication flow. This "persistence delegation" can be configured through the SignInAsAuthenticationType or via app.SetDefaultSignInAsAuthenticationType.
Typically, this SignInAsAuthenticationType property corresponds to a cookie middleware: this way, sliding expiration is not managed at the WS-Federation middleware level, but by the cookies middleware, that will automatically renew the authentication cookie when sliding expiration conditions are met. In this scenario, the authentication token issued by your identity provider won't be renewed. For this to work, you need to set WsFederationAuthenticationOptions.UseTokenLifetime to false, because when you use the default value, sliding expiration is disabled and the cookie lifetime matches the token lifetime.
If you use WS-Fed for authentication purposes (i.e you just want to know who your users are), using sliding expiration is probably a good idea. But if you need to make some API calls on a remote server, your users may end up being authenticated for a long time, far after the expiration of their security token.

Web API 2 OWIN Bearer Token purpose of cookie?

I am trying to understand the new OWIN Bearer Token authentication process in the Single Page App template in MVC 5. Please correct me if I'm wrong, for the OAuth password client authentication flow, Bearer Token authentication works by checking the http authorization request header for the Bearer access token code to see if a request is authenticated, it doesn't rely on cookie to check if a particular request is authenticated.
According to this post:
OWIN Bearer Token Authentication with Web API Sample
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
using (IdentityManager identityManager = _identityManagerFactory.CreateStoreManager())
{
if (!await identityManager.Passwords.CheckPasswordAsync(context.UserName, context.Password))
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
string userId = await identityManager.Logins.GetUserIdForLocalLoginAsync(context.UserName);
IEnumerable<Claim> claims = await GetClaimsAsync(identityManager, userId);
ClaimsIdentity oAuthIdentity = CreateIdentity(identityManager, claims,
context.Options.AuthenticationType);
ClaimsIdentity cookiesIdentity = CreateIdentity(identityManager, claims,
_cookieOptions.AuthenticationType);
AuthenticationProperties properties = await CreatePropertiesAsync(identityManager, userId);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
}
The GrantReourceOwnerCredentials function not only compose the ticket with this line: context.Validated(ticket); but it also compose a cookie identity and set it to the cookie with this line: context.Request.Context.Authentication.SignIn(cookiesIdentity);
So my questions are, what is the exact purpose of the cookie in this function? Shouldn't the AuthenticationTicket be good enough for authentication purpose?
In the SPA template there are actually two separate authentication mechanisms enabled- cookie authentication and token authentication. This enables authentication of both MVC and Web API controller actions, but requires some additional setup.
If you look in the WebApiConfig.Register method you'll see this line of code:
config.SuppressDefaultHostAuthentication();
That tells Web API to ignore cookie authentication, which avoids a host of problems which are explained in the link you posted in your question:
"...the SPA template enables application cookie middleware as active mode as well in order to enable other scenarios like MVC authentication. So Web API will still be authenticated if the request has session cookie but without a bearer token. That’s probably not what you want as you would be venerable to CSRF attacks for your APIs. Another negative impact is that if request is unauthorized, both middleware components will apply challenges to it. The cookie middleware will alter the 401 response to a 302 to redirect to the login page. That is also not what you want in a Web API request."
So now with the call to config.SuppressDefaultHostAuthentication() Web API calls that require authorization will ignore the cookie that is automatically sent along with the request and look for an Authorization header that begins with "Bearer". MVC controllers will continue to use cookie authentication and are ignorant of the token authentication mechanism as it's not a very good fit for web page authentication to begin with.
The existence of the cookie also left me puzzled, since it clearly is not necessary in a bearer token authentication scenario... In this post the author dissects the individual accounts template, and has the following to say about the cookie:
The method also sets an application cookie. I don’t see a good reason for that.
My guess is that the authors of the template wanted to show examples of different kinds of authentication logic, and in this particular case they wanted to show how the authentication information could be stored in both the bearer token authentication JSON payload, as well as in a standard authentication cookie.
The fact that the JSON authentication payload is set to also include an additional (unnecessary) unencrypted property (the user id), in addition to the encrypted ticket, seems to support this theory:
var properties = CreateProperties(user.UserName);
var ticket = new AuthenticationTicket(oAuthIdentity, properties);
It seems that the authors of the template wanted to provide some useful examples, rather than the bare minimum needed to achieve bearer token authentication. This is also mentioned in the linked post above.
The cookie has one important purpose. Its value contains the bearer token which can be extracted by client-side javascript on your pages. This means that if the user hits F5 or refreshes the page, the cookie will typically persist. Your client-side javascript can then grab the bearer token from the cookie when the page reloads.

Resources