I have a web application that relies on a persistent cookie that is marked as HttpOnly / Secure in order to securely keep the session ID.
The issue is when this web application is embedded cross-domain it no longer works with iOS which blocks third party cookies.
The normal recommendation for avoiding this would be to use jwt or something with a header (such as Auth Bearer token), which works great for REST APIs.
But what is the alternative for normal page requests (not REST) as the user is loading new pages to cookies? The only thing I can think of is a queryString value but that is very insecure since anyone can see it, even over HTTPS.
Related
I am wondering, if JWT should be attached to the header of my request manually, how can I use JWT to authenticate the users of my ASP.Net Core website?
In other words, how can I tell my browser to attach the token in the header when sending the request to my server? Let us say the user of my website got this token from one of my website's API.
Or is JWT usable only for WebAPI (where I can manually build the request)?
There are different ways to use JWT tokens. Since JWT is just a token format, it does imply the method used for authentication.
However, JWTs are mainly used for Bearer authentication scheme, which requires adding a custom header to each request. Single page applications (SPAs) that create requests in JavaScript on the client to access API endpoints can do that which is why Bearer+JWT is used a lot in SPAs. SPAs also benefit from the embedded JSON format since they can read expiration dates and other information (claims embedded in the token, ID token contents obtained via OpenID Connect etc.).
For "traditional" server-rendered views and links, using JWTs is hard since they'd have to be set as cookie or made part of the URL (practically impossible because of URL length restrictions). ASP.NET Core 2.0 does not contain any JWT-based cookie logic but it is possible to create a custom implementation using JWTs as cookies. See this GitHub project and related blog post for a sample implementation. Note that the only benefit of using JWTs in cookie authentication is that the server doesn't have to persist cookie information and share cookies across multiple instances.
To sum up the current state:
Prefer default cookie authentication when you use server-side rendering and links to avoid creating custom cookie implementations.
Prefer JWT bearer authentication if you have single page applications (SPAs) apps that build requests in javascript/typescript on the client.
We are implementing a sample application using Kong API gateway with JWT authentication plugin.
As refer in this thread, there are two ways to store JWT in the browser. Web storage or cookies. But web storage (i.e. session storage and local storage) can be vulnerable to cross-site scripting attack(XSS). So other option is cookie. (Though CSRF should be taken care off)
I have two questions,
If we use web storage to store JWT then is there any way to stop XSS. If yes then how it will work if the same page is open in the new tab or reload the same page ?
Using cookie: We are able to send the cookies in the request. But KONG is authenticating the end point URL only if the JWT is set on headers (Authorisation: Bearer token) and not authenticating using cookies. Is there any way to verify JWT which is set in cookies using KONG API Gateway ?
There is nothing wrong about storing JWT in webStorage, unless you store sensitive data in your JWT (but you should never ever do that, since you can decode it easily). The point is that your token shares a secret, that only your servers knows (that's what makes it secure), you should just put an expiration time to make it a lot safer.
And no, you cannot pass a JWT token in cookies, it's only in headers (here Authorization), I don't know about KONG API, but they should not allow that !
(ref about JWT is here)
In order to add to #antoine2vey answer,
It looks like your on page application is being served from a protected API in Kong at the "/" (slash) resource. I would suggest that you would be able to get the page content from an unprotected "/" (slash) resource and then run javascript code would have access to the cookie and would be able to perform the request to the protected resource passing the JWT token in the header where Kong would be able to validate for you.
Does this make sense?
Cookie based authentication is implemented. https://github.com/Kong/kong/pull/2973
I have a client-side angular-js application. And I have a server-side nodejs API. The client-side and the server-side application are located on different domains. The client-side use API for getting or posting some data. Also the client-side needs to get images from the server-side and show them in a browser.
I use passport nodejs module for the authentication. I don't know which authentication strategy is better for me. I think that there are two types of authentication strategies: token-based and cookie-based. And I think that both types useless in my case:
If I use token-based strategies, then I should send Authentication header with a token in each request to the API. I can send headers in AJAX requests, but if I want to show an image that is located on the server-side I have a problem. Because a browser will not send headers in <img> tag.
If I use cookies, then I don't have the problem with images. But I have problems with AJAX requests. Because the session cookie is stored on the server-side application's domain. And if I send AJAX requests from the client-side domain, then I should send cookies with each request. I use XmlHttpRequest for AJAX and I should use withCredentials option for sending cookies. But in crossdomain requests browsers will send a preflight (OPTION) request before each AJAX request. And browsers will not send cookies with OPTION request. This is a problem for me because the server-side API could not make a correct response on an OPTION request if it will be not authorized.
What is the adopted solution?
It is important to understand the difference between web applications and web services. A web application serves markup, JavaScript, CSS and image files and often uses cookie based authentication (but can use any other implicit authentication mechanism). Any request the browser makes is automatically authenticated.
Web services on the other hand often use bearer token authentication. When a client in a browser, fat client or on a mobile device communicates with the API, it sends along a token in the Authorization header of the HTTP request. The header has to be explicitly attached to the request in the JavaScript or native code executing the HTTP request.
In Single Page Applications (SPA), the web application is missing and the markup, JavaScript, CSS and images are served from the browser without authentication. Only the requests to the web services are authenticated, typically using a JWT token.
In your case, if you want only authorized users to be able to download images, and other files, you should consider building a web application. Use a security protocol like or OpenID Connect to authenticate your users. Choose an authorization server that supports both OpenID Connect for your web application and OAuth2 for your web service.
I'm building an Angular app with an API backend. On a combination of pieces of advice, I built the API with a flavor of token authentication. The flow is roughly as follows:
POST to login endpoint with credentials
Validate credentials and authorization, then generate a new token
Return token to client
Client uses token via HTTP Basic to access API resources
This is all working well. The problem arises in creating a session based on this token. I don't believe I should simply hold the token on the client in a cookie, but I do need a session to persist between page refreshes, etc. My Angular app is stateless and completely populated via API calls.
I'm looking for a recommendation as to hanging on to this token on the client. I feel there's danger in holding the token in a cookie because the cookie could be stolen and simply used to authenticate as someone else, but perhaps this is incorrect.
Thanks in advance for your assistance!
The only known way for me to identify a user is to use some token on the client.
HTTP is stateless and can't know which request is coming from which user (browser). You can't identify the user by his ip address (many users are behind a router and share a connection). You could try browser fingerprinting, it can work on some browsers but not on all.
I would recommend using a cookie to store this token on the client.
They are send to the server on every request and you can do some protection to keep them from getting stolen.
To protect this cookie from man in the middle attacks you need to use an encrypted connection over HTTPS to the server.
Set the following attributes on the cookie:
HTTPOnly: cookie can't be accessed by javascript (XSS protection)
Secure: cookie will only be send over https
Path: cookie will only be send on specified path e.g. /login
I would also define an expiration date on the cookie, so the cookie is invalid in like 2 days or something.
But you are right. If this token gets stolen someone else can login as this user.
Since its an Angular app, I'd assume all authenticated methods will only be served to ajax requests (you can tell your server to only respond to ajax) in which case CORS will help you.
The only way to be completely secure is HTTPS, however this method is probably more secure than you think. Read up on CORS a bit for more info, but essentially the idea is that servers will only respond to ajax requests coming from html pages that were served by that same domain.
Pre-flight OPTIONS requests are often sent to verify this. The browser sends an OPTIONS request with an Origin header (the origin of the page) before the actual request. If the origin matches the domain of the server receiving it, the subsequent request is allowed. Otherwise, it violates the Same Origin Policy and will be rejected.
This prevents someone from sniffing out the token and sending a request with the token from a page that your server didn't serve (like something running on the hackers local machine).
If you are doing credit card transactions or anything super secure, you should use HTTPS though.
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
The web application framework we use has built-in support for handling Cross-site Request Forgery. This works well when data is posted with a browser to our webserver.
Currently we are developing an API in which an uploaded XML file is processed by the same application framework. Our API requires a unique token in the uploaded XML file for authentication. Since CSRF detection is enabled by default and the XML file does not contain a CSRF token we currently can not upload any data through this API.
However, we can quite easily disable CSRF detection, but is this safe?
A post here states -- quite boldly -- the following.
It is safe to remove csrf for API calls as the particular vulnerability can only be executed through a web browser.
Is this true? Can nothing similar to a CSRF attack happen through an API?
That depends on how you use the API. Say if the website using the API is vulnerable to CSRF, that means the API is also vulnerable.
Wekipedia says that
CSRF exploits the trust that a site has in a user's browser.
To support API calls the server requires that the credentials be sent along with every request (or some equivalent like digest, security handle, hash). If the credentials are stored in application memory (like mobile app) API is not vulnerable to CSRF. But if the credentials are saved in a session or cookie the API is exposed to CSRF
It depends on what you mean by "disable CSRF detection".
Some pointers:
As long as you do validate the unique authentication token without fail, then there is no way the attacker can spoof a valid request without a valid token. This is straightforward.
"unique authentication token" here refers to something that is not sent by browsers automatically. (So no using stuff like HTTP Basic / Digest, Cookie header and etc.) It must be something unique that you (the API creator) came up with. This can be as easy as an additional Foobar:the_unique_token header.
Note that it is perfectly fine to identify the client based on the Cookie (or other tokens that browsers automatically send), but you must only allow entry when the unique token is provided.
As long as the attacker can spoof a valid request as long as he is able to guess/obtain the token (the_unique_token). So the token needs to be long, random, and single-use to be secure.