I have built a web app. The app needs to make several POST requests. Since full page reload does not happen (single page app), every time form gets generated dynamically from a template, I made the app to make a ajax GET request to the server to fetch csrf token, which later will be submitted with other form values.
To achieve, this I made a endpoint in server '/getCsrf' which returns csrf token to the user. Every time the endpoint is visited, different unique csrf token gets generated.
Is approach described above safe? I was wondering if attacker can force victim to visit that '/getCsrf' url in different server, steal 'csrf' token data, load the fabricated form page, and send an unexpected POST request to the server.
Related
I'm using JWT authentication in my node site with passport and am not sure I am understanding the concepts.
Say I'm an authenticated user with my token saved in local storage. Say I then navigate to a /user page, which will display data about my user. Normally, I would check if the user is logged in, and if they are not, they would get redirected to a login page. But in this case, since I can't send the authentication token from a page request, I have to load my /user page, then the page makes a request for user data, and if the data is not found, I redirect them to the login page via javascript.
Am I correct in how I would handle this? It seems like a bad user experience, having to wait and redirect twice. Is there a way around this? Is JWT just not what I'm looking for my implementation?
If you want to render the page server side, you should set the JWT as a cookie instead of using local storage. You would be able to catch, verify and use it when a user request a page.
But I have to say that modern web applications use client side rendering. So there's no need to store the JWT as a cookie. When requesting a page, you will recieve only the static assets and you will get data by queryng an API that could response with 401 (Invalid or Expired Or Missing Token).
It seems you were using server side rendering before. Now you want to use JWT and you have read somewhere that a common practice is to store it in LocalStorage (that's true). Now you are dealing with a server side rendered application architecture while tryng to mix client side rndered applications concepts.
You are not doing huge errors, but you should consider to fully render your application server or client( I suggest ) side. For the second option, google "Build single page application"
I'm working on a project based on Phalcon which consists in two different stand-alone subprojects: a php + angular frontend and a php REST API.
I protected the API with OAuth2, using PhpLeague OAuth2 Server. The API server is the OAuth2's authorization server AND resource server.
This is the actual flow:
The user can browse the public endpoints of the frontend, and when hits a private page, gets redirected to the login page;
The login page has username and password, POSTs them to the frontend server;
The frontend server calls a public method on the API server, which is expecting a Password Credential Grant: it validates the credentials and sends back an access token and a refresh token;
The frontend server caches both the access and refresh token in session and uses it for some API calls: the first of those is the '/users/me', which gets info about the current user and its ACL on the frontend sections;
The frontend server sends the page to the browser, which loads its javascript files.
Now, OAuth2 states that access tokens should be short-lived and refresh-token should be long-lived: in the frontend server logic, the API calls which receives a 401 (caused by the expired access token) are retried by sending first the refresh token to obtain a new access token via a Refresh Token Grant. If this second call is rejected, I assume the user is no more logged in (refresh token expired / revoked).
The pages are using Angular to perform data and ux/ui management. My question is:
should the Angular code call directly the API server?
Actually the first thing my javascript code does is to get a config object from the frontend server, which contains the access token too, and uses it to make the calls to the API server. The problem with this is that i should rewrite again the "refresh token logic" in javascript (after it expires, i get 401s), and by what I have read on the subject i understood that it is better to not make the refresh token visible to the client (as it can generate new access tokens).
So i was thinking about a "two step approach", where every javascript API call goes to an endpoint on the frontend server which relays it to the API server, but this is obviously slower (JS -> FRONTEND -> API and API -> FRONTEND -> JS).
What is the correct approach? It's not very clear to me if the frontend should be considered as two clients (php + js) which should work separately or not, as I imagine that an hypothetical iOS app would be making calls 100% against the API server.
I have used the same approach in my own projects. The problem that we have is that the client is not secure. In order to generate / refresh a token, you need to pass secure information to the authorization server.
I have done the same as you basically, let the back-end handle the tokens and their temporary storage. You cannot and should not trust the client with important information which lets you generate tokens. In terms of delays, I wouldn't worry about it too much since you're not going to be doing that much extra work, you won't even notice the delays. I have a system like this built and used by hundreds of thousands of users with absolutely no issues.
Now, you have said a few things in here which make me wonder what you are doing.
OAuth2 is not a user authentication system, it's an application authentication system. You don't pass a user and their password and generate a token for them, you pass a ClientID and ClientSecret and they generate a token for you. Then you have an endpoint which gives you the user details for this user, you pass your userid or username and get the details of that user.
A token expired does not mean your user is logged out. Those are two completely different things. How are you going to expire a token for example, when your user wants to log out? You can't, your token will still be valid until it expires after the set amount of time has passed.
A token can be used for let's say half an hour, but your user may use the website for 1 hour. So before you hit any API endpoint, you could check ... has this token expired yet? if yes then you can go and refresh it and keep working without having to bother your user with a new login screen.
The whole point of an OAuth2 system is to make sure that only authorised clients can access it. A client is not a user, it's an application. You can have a website for example and you only want users of that website to access your API.
You can have endpoints like ValidateUser for example, where you take a username and a password and return a yes or no and then you log your user in based on that.
Irrespective of language/framework, second approach is secure and better than first one because to get access token by providing refresh token to Authorization server, it still requires Client ID and Secret which should never be passed to Browser for security reasons.
In first approach, to make a direct call it will not work if your Authz Server is hosted on different domain than your frontend server because of Same Origin policy of browsers. Even if they are on same domain, still you are exposing Client ID and Secret which will compromise your frontend server
I'm hacking together a script to automate the submission of tickets to our helpdesk system. So far it's a very simple, but working system. I have a page with a form that auto-submits via JavaScript with form value based on the URL requested.
This works great when you access the page from your browser. Assuming you're already authenticated to the ticket system page, the auto-submitted form happily sends its form data and you are directed to the ticket list where you see the newly auto-submitted ticket. Unfortunately of course, the ticket system is an HTTPS secured site, so if you're not logged in you're directed to the login page and the auto-submission fails.
The idea however is to run this auto-submission on a schedule, or kick it off remotely, where the initiator won't necessarily be human and won't be following the form submission to babysit it with delicious authentication cookies.
So, being a newbie in this area, my options seem to be A) dive in and get real messy by listening for the auto-submission response, determine whether the login page is being returned and submit some credentials via JS (not a huge deal as this automation would run solely on a secured server), then resubmit the form... or B) somehow do this the proper way by authenticating beforehand. But that's where my knowledge ends.
I've read through this similar question, but am still coming up short. Is this proper automation only possible if the server in question supports some form of auth token API? Is there not a more direct way to connect and request/submit data to an HTTPS site? I've been glossing over some introductions to cURL, but have not yet dove in.
NB: I don't have direct access to the ticket database, code, nor to the web server processes/accounts running it. I probably can run processes on the same machine, which is why I'm not real concerned with the security of auto-submitting credentials, but that's probably it.
Firstly, whether your ticket system directs you to a login screen if you're not already authenticated has nothing to do with HTTPS - this will be either a username/password <form> that then sets a cookie, or it will be a WWW-Authenticate header. Each of these can be used whether you are using HTTPS or plain HTTP.
Whichever method it uses, if you're planning on doing this in a web browser, chances are you won't be able to because CORS (cross-origin resource sharing) will probably not have been set up to allow it.
If however you're doing this from a script such as Node.js, Python, PHP or anything else that can make arbitrary HTTP(S) requests, you might want to look at a flow like this:
Request the index page of the ticket system
Detect whether it gave you a login screen
If so, fetch any necessary data from the login screen (e.g. a nonce) and make a POST request as if you filled in the username/password yourself
Check that authentication was successful (based on the POST response)
Keep the cookie returned by your POST request and use it to submit the ticket.
For the simpler case where the system uses a WWW-Authenticate header it would be like this:
Request the index page of the ticket system
Detect the WWW-Authenticate header in the HTTP 401 response received
Send an Authorization header with an appropriate value
Check that authentication was successful (based on getting an HTTP 200 instead of a HTTP 401)
Send the same Authorization header again while submitting the ticket.
Using WWW-Authenticate is described at Wikipedia for basic and digest authentication.
I have a PHP application which has some jQuery and Ajax features in it. I would like to know, how is it possible to regenerate the Session Token - which I'm sending to validate the Ajax request - upon each Ajax request (without loading the page)?
I have more elements on the page which are running multiple Ajax queries, however at this moment they all get the same token. So if someone has the tokey, they can submit a forged request from another form I guess.
Generating token on client side makes no sense. You can't trust anything coming from client side, as you don't know if it's your client software which sends the request, or a malicious one.
You must create as many tokens as you have ajax possible requests, and return a new token with each response.
You should generate a CSRF token on server side for each user or each session. You can store it in your database, or in your session. You should send that token to your client, and wait it back with the ajax requests. It will work until your site is not XSS vulnerable...
Btw the first step to secure your application is using the HTTPS protocol...
I'm developing an API where a website owner submits their website url to a database, when the user uses the API the javascript hostname gets sent to our database and gets checked against the string they submitted when registering. Is it possible for a malicious user to spoof their hostname? If so, are there safer practices?
Anyone can send an arbitrarily constructed HTTP request; the referer headers or the properties of window.location cannot be trusted (even if the user cannot change the contents of window.location in their browser -- at least not without causing a navigation -- the user can always observe what requests get generated as a result of that value, and then send an HTTP request with that altered).
If that will be an issue, then you will probably want to use digital signatures along with the domain to ensure that the domain has not been altered (i.e., changing the domain without changing the signing token will render the request invalid, and generating a signing token from the domain is not obvious and requires some server-side backend mechanism that you provide to the customers of your API).