Hi guys I need some advice please.
Our payment gateway sends back some data when an order is succesfully posted that is included in the url string.
The only problem is users are refreshing the page and sending through a bunch of cfmail commands each time they refresh the thank you page!
Which is better for our security, to setup a redirect to our home page shortly after this page is loaded, to setup a way to stop the user loading the page more than once or to strip out the order info so the user can't click refresh?
Below is a sample url that the payment gateway generates upon a succesful transaction.
http://www.ourwebsitename.com/ConfirmationPage.cfm?cartinfo=^XXXX^1&orderinfo=Customer^Name^Billing Name^Billing^Line^1^Town^Postcode^websitename^Order^Amount^&responsesitesecurity=SECUREHASHCODE&thisorderid=OURORDERID
What are people thoughts on securing this page?
The way I've addressed this in the past is to do the following
On any page that the user is shown, try not to have any of the logic that actually does anything. Display logic only on display pages
At the end of the checkout process, send the email, and then use <cflocation> to redirect to the confirmation page
Add some check-bit to the session or whatever you use to keep track of the user to flag that the email has already been sent
If you REALLY don't want users resending the email twice, use a <cflock> and confirm that the flag mentioned in #3 hasn't been flagged inside the <cflock> (to make sure it hasn't been sent by the process that locked it)
This should help reduce / remove the impact of the user refreshing. When I've had this in the past it's been due to people placing logic on the output pages that should really have been on one of the pages that the user doesn't get shown (due to them silently redirecting)
I suggest that you add a confirmation_email_sent-column to your order table in the database, and then set this flag the first time you send the email. If the users refreshes the page, you will notice that this flag is already set, and can then skip sending the email. If there are other side effects than the e-mail-sending, then these should probably be mitigated in the same way.
Related
We keep playing this cat and mouse game with Robinhood.com. I have a trading app which used to trade stocks with Robinhood, but they keep changing the unsupported unofficial API to make it difficult for traders to use. I know that many people are doing the same thing and I want to reach out to them to see if there is a new answer. The latest problem is when I try to get a Bearer token using the URL https://api.robinhood.com/oauth2/token/ the API returns the following JSON: {"detail":"This version of Robinhood is no longer supported. Please update your app or use Robinhood for Web to log in to your account."}. This started happening on 4/26/2019.
Has anyone found a work around for this, yet, or have they finally beaten us into submission?
A more complete solution (not need browser):
Use requests.session.
Obtain the login page by making a GET request to "https://robinhood.com/login".
At this point the session's cookies will contain 'device_id'.
Obtain this device_id and use it in making the oauth2 token request to "https://api.robinhood.com/oauth2/token/" also add in the data request "challenge_type" (either "sms" or "email").
This request will fail with a 400 error code. Robinhood will send an SMS message or Email with a temporary (5 minute) code.
Also at this point use the 400 response's body to get "id" from "challenge" inside of the JSON object.
Confirm the challenge by making a POST request to "https://api.robinhood.com/challenge/CHALLENGEID/respond/" where CHALLENGEID is the same id mentioned in the first failed /oauth2/token/ POST request.
Make the same POST request to "https://api.robinhood.com/oauth2/token/" and include in the header "X-ROBINHOOD-CHALLENGE-RESPONSE-ID" with the value CHALLENGEID.
You can reuse a device_id with user/pass after this even after logging out.
Be cautious with storing device_id as it is the result of user/pass login and successful SMS/email 2FA.
Just got it working. At the risk of them seeing this post and changing it more, here we go:
First, you're going to want to log into your RH account in a web browser
View Source on the page, and look for clientId - it should be a big hex number separated by dashes
Add that number to your POST requests to /oauth2/token under the field device_token
There's probably another way to retrieve the device token, and I'm not even sure it's unique, but that way should work.
Good to be back here after a very long time.
Not sure if anyone is still looking for answers to this, but I have a very simple solution.
At Robinhood's login screen, enter your username/email and your password, press F12 on your keyboard to bring up the console panel and switch to the "Network" tab then wait for the page to load completely. (During this time you will see a list of items being loaded rapidly depending on the connection speed.)
At this time you can keep clearing the list by clicking on the button highlighted in the below image.
Click on button highlighted repeatedly until the list is empty
Now, log into your Robinhood account. At this point your console should display a list similar to the one shown below.
Look for the name "token/", most likely it will be the second one you get all the information you need. And this information will be under the Headers then Request Payload
I was able to find this with past knowledge and experience of web scraping for fun. And also, I needed to know this as well, since I recently started doing trades via Robinhood.
Hope this help you curious ones out there.
For my Robinhood account I am using Google Authenticator for my 2FA. What I have so far is that I send the original call that I was sending before to https://api.robinhood.com/oauth2/token/. This is giving me a response of:
{"mfa_required":true,"mfa_type":"app"}
I then repeat my oauth token request, but this time providing the value from Google Authenticator (so my GUI has to prompt me to fill it in) with this payload in the request to https://api.robinhood.com/oauth2/token/:
{"grant_type":"password","scope":"internal","client_id":"c82SH0WZOsabOXGP2sxqcj34FxkvfnWRZBKlBjFS","expires_in":86400,"device_token":"***","username":"***","password":"****","mfa_code":"***"}
and then I am getting an access token in reply
We have a site that uses a "one-time" login process for password resets which are not initiated by the user themselves. (for instance, a password reset that is initiated by an admin or another employee) A URL is sent to the user via email which can then be used to reset their password. The URL can only be visited one time. (there's more to this for security-sake but I'll keep it simple) Recently, some users have complained that when they visit the link, it has already expired. The end result is that they can't reset their passwords using this feature. We discovered that the users in question have a spam filter or "link checker" in their environment that they do not have access to. This device visits the one-time link before the user is able to, to make sure its safe.
I'm trying to solve this issue and was wondering if there's a way I can detect these type of devices on the web server when the request is made? When the spam filter visits the link, is there something in the http request that would stand apart from a regular browser? Maybe they all use a specific custom HTTP header? Or maybe there's a regex I could use on the user agent? I haven't been able to catch one of these yet, so I'm not sure what the request looks like coming from a spam filter.
Anyone know of a way to detect spam filters of any vendor by looking at the http requests? I know it's a long shot but maybe they all use a specific header for reasons such as this?
I got approval to modify the design to remove the one-time aspect of the URL. This solves the issue and saves me the headache. Thanks for the suggestion, #PeeHaa
i've got a site, which has a login system.
here's my scenario:
user is not logged in
fills in a form to submit data
before the create action, i check if the user is logged in.
if the user is not logged in, they are prompted to sign up and log in..
upon sign up / login the form is submitted and the form data saved without prompting the user to save it again.
In order to do this, I need to use a redirect_to, specify the controller and action, however, this requires a POST, and I don't believe you can post variables on a redirect.
any ideas of a work around, which would keep the current user flow?
Some options you might want to try:
Perform the user registration using AJAX, so you never have to leave the page and won't need a redirect
Store the form data to a 'temporary' user account, then update the account to 'real' with the user registration info. You may want to occasionally clean out old 'temporary user' data that never completed the registration.
Convert the form data to serialized form and pass it along with the redirect as a url parameter (only works for a guaranteed small amount of data)
Store the form data in the session (last resort, only use if your traffic will remain relatively low, as you may end up running into scalability issues)
(noob alert) Problem Statement: I have a chrome extension that takes that allows a user to bookmark a page by sending the details of bookmark to a server and storing the data under that user's profile.
This means I need to authenticate the user and then send the userID to the server every time
I send back bookmark.
Issues:
1)The bookmark is shown in the popup and then sent to the server, however if the user is not logged in(authenticated) the pop up should only show an interface that allows for user name pass not the book mark data, my issue, how would I achieve this? i know I have to use one pop file, but how would I have to separate interfaces?
2)What is the best method to authenticate the extention? and ensure that data are being sent from the extension only, i.e prevent attacks on the web service.
Can anyone help?
1) You can set popup page at any time with chrome.browserAction.setPopup.
So, the extension starts with the login form as the default popup under 'manifest.json'. After user login, set the browserAction popup to your main extension page.
2) Since the and user can edit anything on your extension code, you should prevent attacks or whatever from server-side i.e request tokens, request quota for ip and/or elapsed-time. And a simple authentication via POST under a SSL connection should be enough.
I am currently building an internal web application used in a factory/warehouse type location. The users will be sharing a single PC between several people, so we need to have a fairly short session timeout to stop people wandering off and leaving the application logged in where someone else can come to the PC and do something under the previous user's username.
The problem with this is a session can timeout while a user is currently entering information into a form, especially if they take a long time.
How would you deal with this in a user friendly manner?
Keep the server informed about the fact that the user is actively entering information.
For instance send a message to the server if the user presses the TAB key or clicks with a mouse on a field.
The final solution is up to you.
Use AJAX to regularly stash the contents of the partially filled-out form so they have not lost their work if they get booted by the system. Heck, once you're doing that, use AJAX to keep their session from timing out if they spend the time typing.
The best advice would probably be to ask the users to close the browser window once they're done. With the use of session-cookies, the session will automatically end when the browser is closed or otherwise on a 30 minute timeout (can be changed afaik).
Since there by default is no interaction between the browser and the server once a page is loaded, you would have to have a javascript contact the server in the background on forms-pages to refresh the session, but it seems a bit too much trouble for such a minor problem.
If the session timeout is so short that the user doesn't have the time to fill in a form, I would put an AJAX script that makes a http request to the server, every few minutes, to keep the session alive. I would do that only on pages that the user has to fill in something or has already started filling something.
Another solution would be to use a session timeout reminder script that popups a dialog to remind the user that the session is about to time out. The popup should display a "Logout" and a "Continue using application" that makes a ajax request to update the session time out.
Maybe that a keep-alive javascript process could be helpfull in this case. If the script capture some key triggers, it send a "I'm still typing" message to the server to keep the session alive.
have you considered breaking the form into smaller chunks?
Monitor the timeout and post a pop-up to notify the user that their current session will expire and present "OK" or "Cancel" buttons. OK to keep the session going (i.e. reset the counter to another 5 minutes or 10 minutes - whatever you need) -or- Cancel to allow the session to continue to countdown to zero and thus, ending.
That's one of lots of ways to handle it.
Using a JavaScript "thread" to keep the session open is, to me, a bad idea.
It's against the idea of session timeout which exists to free some resources if there's no user in front of the application.
I think you should adjust the session timeout with the more accurate time, in order to fill the form in an "typical normal use".
You may also be proactive by :
having a JavaScript alert displaying a non-intrusive warning (not a popup) to the user before the timeout expire, which say that the session will expire soon (and give an link to send an ajax request to reset the timeout and remove that warning - that will avoid the user to lost the form he is currently typing),
and also have a second JavaScript "thread", which, if the session has expired, redirect to the login page with a message saying that the session has now expired.
It think that's the best because it avoid the user to fill a complicated form for nothing, and handle the case when the user has gone away.
As an alternative for the technical solutions, you could make your application in such a way that everytime a particular job is done, for example filling in a form, you ask the user if he wants to continue doing another job or if he's done. Yould could have a startscreen with menu options and if the user chooses an option he first has to enter his credentials.
Or put a password field on the form. Depends on how many forms they have to fill in a session.
When the user posts the form and their session has timed out, you should make sure you save the form values somewhere and then ask the user to login again. Once they have re-authenticated you they can then re-submit the form (as none of their data will have been lost).
I had developed something requiring very long session. The user logged in on a page when he sit on the machine and after doing his work, logged out. Now he may use system for few minutes or for hours. To keep session alive till he logged out, I used timer with javascript, it went to server and updated an anthem label with current time on server.