Angular and PHP JWT and CSRF (XSRF) Cookies - php

I have an Angular app making $http requests to a PHP server. Once a valid login request has been submitted to the server, PHP creates a JWT and
sets the token cookie using PHP's setcookie() function with the httponly flag set to true. This flag allows only the server to read the cookie. On each subsequent Angular $http request, the cookie is validated by PHP using $_COOKIE.
My question is would setting the cookie in PHP for only the server to read be safe enough from CSRF or would I need to have Angular create an additional XSRF token to be sent on each request to be evaluated as well?
I read the following Stormpath article but got a little lost on why he was setting a xsrfToken in the JWT payload. My guess was to have Angular create an XSRF token to match against.
Thanks for any advice/input.

CSRF attacks work by exploiting the fact that your authentication cookie is sent by the browser to the server automatically with each request. Normally, a JWT isn't passed to the server using a cookie, it's instead passed in the authentication header of your http request (it may be stored in a cookie on the client side but the cookie isn't used to pass the JWT to the server). Since you need to set the authentication header for each request, a CSRF attack cannot authenticate its malicious request since the browser isn't automatically sending an authentication cookie with each request. This is why JWTs help prevent CSRF attacks.
That said, if you store your JWT in a cookie and transfer the cookie back and forth, extracting the token to check authorization policies, then you are just as susceptible to CSRF attaks as standard cookie authentication. In this case you can add anti-forgery tokens to your requests to ensure that any HTTP requests that your server receives have come directly from your website.

Related

Absence of Anti-CSRF Tokens & Server Leaks Information via "X-Powered-By" : How do I set it?

I am currently using Apache server for Wamp application for my project. While doing a security scanning, the report came out with 2 errors:
Server Leaks Information via "X-Powered-By" HTTP Response Header Field(s)
Absence of Anti-CSRF Tokens
What do I need to do to solve these? Thank you.
There is a help here you can implement csrf tokens:
https://code-boxx.com/simple-csrf-token-php/
You can read more about what is csrf token and why it's useful here:https://portswigger.net/web-security/csrf/tokens
A CSRF token is a unique, secret, unpredictable value that is
generated by the server-side application and transmitted to the client
in such a way that it is included in a subsequent HTTP request made by
the client. When the later request is made, the server-side
application validates that the request includes the expected token and
rejects the request if the token is missing or invalid.
CSRF tokens can prevent CSRF attacks by making it impossible for an
attacker to construct a fully valid HTTP request suitable for feeding
to a victim user. Since the attacker cannot determine or predict the
value of a user's CSRF token, they cannot construct a request with all
the parameters that are necessary for the application to honor the
request.
And for removing X-Powered-By you can set expose_php = off in your php.ini file

PHP Token Authentication - Expiration

I have a hybrid SPA php web application that makes calls to a remote REST API for all it's needs. I'm starting to implement token authentication between the web server and api and I'm not quite sure how to handle expiration of the token. There may be some flaws in my design as well.
User submits login credentials (username & password) to the web server.
Web server sends call to the API.
API looks up creds., if good, a JWT Auth token is generated and returned to the web server where the Token is stored in a php session variable. The token is never made public.
Each call the web server makes to the api sends a request with an authorization header that includes the token pulled from the session.
My problem is, what's the best way to issue a new token if one has expired during an incoming request. The api checks each request's token to determine if it's valid and if it's expired. If the request API was GET foo/bar for example, expecting a JSON string in return, but the token has expired, what would be the expected behavior?
Hope this makes sense. Please let me know if I'm not clear enough. Have not had much luck researching this particular scenario.

CORS requests with session/cookie

My application has a PHP server and a client (a JS single-page app). They are separate projects and deployed in different domains. The client consumes a RESTful API exposed by the server.
This application is to be integrated with a third party which handles authentication, so users cannot login directly. Our server just receives an SSO token (which comes appropriately signed so that we verify its integrity).
We also enforce security at the transport layer for all requests.
What I'd like to do is, once the SSO token is verified, start a session of my own and then redirect the user to the client. I thought that once the session was created the browser would automatically send the right Cookie header in the asynchronous API calls, but it doesn't seem to be the case.
Is this deliberately disabled due to security reasons?
You must set withCredentials to true for cross-origin XHR requests to include cookies.
The CORS response must also say Access-Control-Allow-Credentials: true (which is why widthCredentials defaults to false).
I thought that once the session was created the browser would automatically send the right Cookie header in the asynchronous API calls
Not for cross-domain requests for CORS-enabled ressources (which seems to be the case here, if I understand your described setup correctly.)
To make that happen, you need to set the withCredentials flag.

PHP Curl - headers not persisting across redirect

I am writing a webservice client which runs from the command line and accesses a service which uses Oauth2.
I seem to be getting the Oauth token correctly, and the first request to the webservice recognizes the token. However the response is a 303 redirect (I have set CURLOPT_FOLLOWLOCATION => true) however the subsequent page says that I have supplied no authentication token.
Currently I am passing the oauth token by setting a header for the curl handle:
"Authorization: OAuth2 $oauth"
I suspect that the header is not being included in subsequent requests.
I tried setting CURLOPT_UNRESTRICTED_AUTH => true, to no avail (but according to the manual, that persists a username and password across redirects - not the authentication header).
The webservice allows for oauth tokens to be sent in an authentication header or in the URL (but not as a cookie). Setting the token in the URL returns the same redirect (i.e. without the token in the URL) hence I can't use this method with CURLOPT_FOLLOWLOCATION.
(the service does not allow for oauth tokens sent in cookies, PHP version is 5.6)
Having discovered that lots of other bad things are happening on the Websense proxy I was connecting via (caching content known to be expired, caching POST responses!) I tried bypassing it altogether and all the problems vanished.

Does OAuth2 verify the request domain via http headers?

I am currently learning about OAuth2, and I am slightly confused about one part of it. Does the OAuth2 server compare the domain in the JWT with the domain in the request header?
What prevents someone from ripping a bearer token out of a JS app and then using it to make fraudulent API requests? Even if HTTPS is used, the token sent back from OAuth2 still has to be stored before it can be used in subsequent requests, thus making it vulnerable. What am I missing?
Edit: what if I create an oauth2 token from a non-browser client and there is no domain name to match against?
Nothing prevents it from being used. That's why you store it safely or you don't store it at all.

Categories