I am having a bit trouble understanding the following code
run.$inject = ['$http'];
function run($http) {
$http.defaults.xsrfHeaderName = 'X-CSRFToken';
$http.defaults.xsrfCookieName = 'csrftoken';
}
as I always thought that csrf is injected into html forms or ajax calls and not cookie, since csrf is a protection against any adversary trying to use your cookie for authentication.
Can someone give a detail explanation on how angular is handling csrf and how does it get the token from the backend?
I can't answer this better than the angular docs themselves do, so I'll just quote:
Cross Site Request Forgery (XSRF) Protection
XSRF is a technique by which an unauthorized site can gain your user's private data.
Angular provides a mechanism to counter XSRF. When performing XHR
requests, the $http service reads a token from a cookie (by default,
XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only
JavaScript that runs on your domain could read the cookie, your server
can be assured that the XHR came from JavaScript running on your
domain. The header will not be set for cross-domain requests.
To take advantage of this, your server needs to set a token in a
JavaScript readable session cookie called XSRF-TOKEN on the first HTTP
GET request. On subsequent XHR requests the server can verify that the
cookie matches X-XSRF-TOKEN HTTP header, and therefore be sure that
only JavaScript running on your domain could have sent the request.
The token must be unique for each user and must be verifiable by the
server (to prevent the JavaScript from making up its own tokens). We
recommend that the token is a digest of your site's authentication
cookie with a salt for added security.
The name of the headers can be specified using the xsrfHeaderName and
xsrfCookieName properties of either $httpProvider.defaults at
config-time, $http.defaults at run-time, or the per-request config
object.
The $http.defaults.xsrfCookieName is just allowing you to specify what the name of the cookie is, otherwise it's going to look for the default XSRF-TOKEN.
On the server side implementation, I'd recommend using some node.js middleware to handle the setting of the initial cookie instead of rolling your own. Take a look at csurf in particular as it seems to be the most popular. You could also try senchalab's csrf middleware. Either of those ought to be enough to get you started.
Related
Generally, there are at least 2 options of securing applications using Keycloak OpenID Connect stack:
Use it on the application using Keycloak adapters (in my case, a SPA javascript front end)
Use it on Apache using mod_auth_openidc
If I choose to use number 2, how can I obtain the user data (username, for example)?
------------------------Edit due to #Cyril Dangerville answer -----------------
While I understand the general approach, my way is seemed very forced.
Now my authenticated, my request has session cookie and access token headers, but cannot access any header due to being initial page load
Perform an call to any protected resource to get access Header value
Use the access token to call the userinfo end point (But this is on another domain so the cookie wont get submitted)
Can you help me by explain where I should go here?
With mod_auth_openidc, you pass user data to applications as Apache environment variables and/or HTTP headers. The latter is useful if using Apache as reverse proxy for remote apps (mod_proxy). The proxy case is addressed briefly in mod_auth_openidc project's FAQ.
You can find more details about how to configure this translation of OpenID Connect token claims - including the authenticated user data - to environment variables/headers in the configuration file: auth_openidc.conf; two properties in particular:
For the REMOTE_USER variable: OIDCOAuthRemoteUserClaim <claim-name> [<regular-expression>]
For others: OIDCPassClaimsAs [none|headers|environment|both].
In our application we validate user name/password. Once validation is done, credentials are encoded using base64 and then needs to be set at request header for subsequent rest calls.
Need to set below in request header.
Authorization:Basic AQNLzR69OFTNJE8X
In the response setting as below from the java code,
javax.ws.rs.core.Response.status(200).entity("").header("Authorization:","Basic AQNLzR69OFTNJE8X").build();
And in the javascript tried setting as below,
sessionStorage.setItem('Authorization:', 'Basic AQNLzR69OFTNJE8X');
But in the subsequent rest service calls in the same session can see the header request is not set with authorization. Request to provide some pointers on setting the Authorization in javascript, so that it is retained for the entire session.
I think you misunderstand how authentication works (or should work).
You are supposed to send the Authorization header only once during the authentication. If the authentication is successful, the server sends you back a session cookie and your session is marked as authenticated (server-side).
You never send back the content of the header, and you don't have to send it each request.
1) The Authorization header is not automatically added. But the cookie will be automatically sent.
2) You should not send the credential and return them: for security purposes, you want to transport them the less you can.
3) You don't want to store the credential in the sessionStorage, I don't know if this is a secure place for a password (i doubt it), but here, the password is only encoded in B64, and it's reversable. So it's as well as cleartext (which is bad for a password).
Hopes this helps!
I have read about CSRF and how the Unpredictable Synchronizer Token Pattern is used to prevent it. I didn't quite understand how it works.
Let's take this scenario :
A user is logged into a site with this form:
<form action="changePassword" method="POST">
<input type="text" name="password"><br>
<input type="hidden" name="token" value='asdjkldssdk22332nkadjf' >
</form>
The server also stores the token in the session. When the request is sent it compares the token in the form data to the token in the session.
How does that prevent CSRF when the hacker can write JavaScript code that will:
Send a GET request to the site
Receive html text containing the request form.
Search the html text for the CSRF token.
Make the malicious request using that token.
Am missing something?
The attacker can't use JavaScript to read the token from the site, because it would be a cross-origin request and access to the data from it is blocked (by default) by the Same Origin Policy (MDN, W3C).
Take this for example:
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://google.com");
xhr.addEventListener('load', function (ev) {
console.log(this.responseText);
});
xhr.send();
The JS console reports:
XMLHttpRequest cannot load http://google.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource.
It's important to realize that CSRF attacks only happen in the browser. The user's session with the target server is used by the malicious server to forge requests. So how does #1 happen? Two options: you could make the #1 request from the malicious server, but that would simply return a CSRF token for the server's session, or you could make the #1 request using AJAX which, as you correctly identified, would return the CSRF token of the victim user.
Browsers have implemented HTTP access control for this very reason. You must use the Access-Control-Allow-Origin header to restrict which domains may make AJAX requests to your server. In other words your server will ensure the browser doesn't let the malicious site do #1. Unfortunately the documents I've read on the matter aren't very clear about it, but I think that's because servers by default do not send an Access-Control-Allow-Origin header unless configured to do so. If you do need to allow AJAX requests, you must either trust any origins in the header not to perform a CSRF attack, you can selectively lock down sensitive portions of your application to not allow AJAX requests, or use the other Access-Control-* headers to protect yourself.
Using a Synchronizer Token is one way that an application can rely
upon the Same-Origin Policy to prevent CSRF by maintaining a secret
token to authenticate requests
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
You should read up on Cross-Origin Resource Sharing (CORS).
I am trying to implement CSRF with Angular.js and CodeIgniter, however, I am not sure if my method is secure.
When Angular sends a post, put, or delete request, I have a custom security class in PHP check $_SERVER['HTTP_COOKIE'] from the request. If it includes the CSRF cookie, I verify it against the value in the $_COOKIE variable.
I am not sure if these are just always the same values and not actually doing anything or what. Is there a better way I should be handling this?
I have not worked with angular JS but with codeigniter. For csrf protection codeigniter provides security class for providing the security token(or the csrf cookie) for respective requests either via form. Now you only need to enable this feature under the config file:
Location: application/config/config.php
Default Code: $config['csrf_protection'] = FALSE;
Change it to: $config['csrf_protection'] = TRUE;
By making it true, it automatically inserts a security token in form, that is verified at the server end.
You can change the token name & cookie name in the same file via below config settings:
$config['csrf_token_name']
$config['csrf_cookie_name']
One important thing is that, if you refresh the page, security token doesn't change, or think it as same security token for current user session. This is somewhat drawback I have found with Codeigniter.
If you want same implementation with ajax, either you need to add manual code for passing the token name or value or use ajaxSetup for all requests.
By this way you can achieve the csrf protection at a level, if you want some more security then you can check for httponly cookies or ssl deployemnt subject to your project need.
i have a question about how we can capture request headers(only request not response) in a browser using javascript(specifically Authentication header related to http basic authentication ).
have you any idea about these??
thanks all
If you're talking about seeing the request headers sent to you, it can't be done. Accessing the web page's HTTP Headers in JavaScript
As Javascript is executed in an HTTP response, you will only get access to the headers which are exposed via the in-built browser/document classes, e.g. document.referrer, navigator.language and similar.
Others you'll have to pass through manually, e.g. by setting a cookie or hidden field, or coding up an XHR.