I'd like to use Facebook Login/Connect to authenticate users on my website. The system consists of two things: 1) client side use of the FB JS SDK to auth the user and to set a (fbsr_) cookie, 2) retrieve this cookie on the server side and make a request against FB backend to get their email, that I'll use as an ID. (I'll use G+ login etc as well so email looks like a good common denominator.)
I pretty much copied what's here: https://developers.facebook.com/docs/facebook-login/login-flow-for-web/
The problem is, every time I refresh the page, I see that a new fbsr_${my_app_id} cookie is created. After 10 reloads in a row, I end up with 10 cookies that have the same name (and same domain) and different content. In other words, it looks like FB.init() always creates a new cookie and doesn't re-use the previous one (which becomes invalid). My observation is based on what I see in the "Cookies" window of Firefox in this case.
Am I doing something wrong? What can I do so the FB API reuses the previous cookie and doesn't create a myriad of cookies with the same name on my domain?
Thanks!
Related
Basically my question is similar to this one:
How to secure php scripts?
with one slight difference, the other side is Shopify.
Background info:
Shopify user bought some credits (Audible style), and wants to know how many he has available. He logs in into his account, and it says there that he has X credits.
That number comes from AJAX call to my server (I have full control), where there is a simple php script which checks the value in db (which is updated using webhooks from Shopify, each of which needs to be verified so they are secure, I think).
The script uses customers ID for a look up, and that value needs to be passed to the script somehow, and that allows someone external to just keep running it until he has all IDs and corresponding credits values.
So, my questions is, how do I stop that? How do I ensure that only authenticated users can check it, and only for their IDs.
There is plenty of info on Shopify docs about securing the connections the other way, i.e. to make sure only correct scripts have access to the Shopify db, but nothing about my problem.
As far as I know I only I only have access to JS on Shopify, which creates the problem, because everything I send to my server is visible to all.
Thanks
EDIT: I just read up on CSRF. I can easily implement checks for origin and headers, but these can be faked, right?
EDIT 2: I got around this problem by using metafields. So, instead of storing all that info on my server's db, I just use Customer Metafields to store the available credits. Webhooks are secure so that's brilliant. It still doesn't solve a problem with the next stage though. Customers will still need to be able to use their credits and get digital products, which are generated by my server. So I still need to verify the requests.
EDIT 3: Comment by #deceze and answer by #Jilu got me thinking. Yes, you are correct, I need to do that, but I don't have access to back-end on Shopify, so I cannot create session. However, what I could do (if I figure out how in js) is hash it. PHP login scripts operate on password_hash. That way you do not store a password in the db. Password get's verified again hash (or whatever you call) in the db, and it's either true or false. If true, you are logged in. So I could try to generate a token using a specific string (make it very long) and user id. Send it with the request, and using password_verify or what not, check it against the users. The one that pops positive is logged in user who requested the information. That is assuming I can hide the string in the Shopify...
Step1: Do a session login system.
Step2: Before the Ajax, generate a random token in your form or request page, put it into a input display none, send it with POST.
Verify each time if the token is set and is the same that you got.
You have now verified if the user is really logged in with session.
And you checked that he is from the right page.
You create a token out of shared secret (both Shopify and server have it), and client ID.
On Shopify:
{% assign my_secret_string = "ShopifyIsAwesome!" | hmac_sha256: "secret_key" %}
My encoded string is: {{ my_secret_string }}
On server:
We gonna be checking received hash value against values in our db, so we need to hash local client IDs using the same algo and key (that probably should be done on receiving the Customer Creation webhook).
Hash IDs using: http://php.net/manual/en/function.hash-hmac.php
$hashed_id = hash_hmac('sha256', '$client_id', 'secret_key');
Compare hash using: http://php.net/manual/en/function.hash-equals.php
$check = hash_equals($hashed_id, $received_id);
Then all that's requires is to loop through the db until you find a match. There may be quicker ways of doing it.
I have options to save/share/write on a page, which cannot be done unless they are signed in. Redirecting on click, to sign in page and bringing back can be done using cookies &/or passing URL query parameters (do let me know if there is a better way.
But, what about when the user goes through other pages?
like: trying to save --> sign in page --> forgot password page -->
I am not allowed to use flyouts. Please let me know the best way..
You should more completly learn technologies you are using.
Most convient way for all "keep-user-on-site" scenarios is COOKIE.
COOKIE is the only thing (and they are created for it) that live and send TO and FROM server on every page of SITE.
Cookies use DOMAIN based resolution so u can use single cookie not just for all pages of single domain, but for whole domain family.
But "forgot password" is not case of "keep-user-on-site". It's oppsite to this case. It's "we-know-that-it-is-not-user-for-now" - in this situation you always should prefer to use some temporal hashes in URLs that could be treated by your server as trusted.
Never mix them (cookies for long-live and urls for 'not-users'). When "we-know-that-it-is-not-user-for-now" pages are shown - all cookies, session headers and so on should be killed. At other if someone lost password, ask for new key on E-mail and then reset password - it could not cause LOGON operation and enter on site. You should redirect to logon page.
I have an application URL which generates xyz named cookie for me if the user is logged in, in browser. I want to hit the URL programatically(using Java/JSP) to look if the user is logged in or not.
Now every time when I hit the url from my Java code it doesn't find that cookie (xyz) as it creates new session on every request. This is probably because I am hitting the url from my code. Now how can I come up with this situation so that my application will create cookie in browser and my code will look for that cookie.
The cookie is stored client-side by the browser of the user, so if you call the URL server-side it won't sent the cookie back with the response.
The way you are trying to know that user is logged in or not, can not be achieved through your approach.
Possible workaround for our case is :
Implement the HttpSessionAttributeListener and override the method attributeAdded and attributeRemoved method of it.
When ever session is getting created for logged in user, you would be saving the userName attribute is session most probably. Once the userName attribute is getting saved, attributeAdded method of your listner will get called and you can see the name of user there, once user is logged out, attributeRemoved method will get called by trigger of session invalidate method and your listener will get the notification . You can see the name of user who has logged out.
See below example for detail explanation.
http://www.roseindia.net/servlets/SessionAttributeListenerExample.shtml
After a user fills in my "new" user form on "example-one.com", the "create" controller creates the record in the db. Then it does a redirect_to to an external site "payment-checkout.com". I have setup the Google Analytics code on both sites.
Google provides two functions _link and _linkByPost for use to use in any links or forms that go to your external domains. The problem is the user is being redirected by the controller action outside of the view and I cant use those two javascript functions to pass on the relevent G.A. info - what do i do?
Can anyone help?
The way _link works is by passing the Google Analytics cookies from your first domain via a query string to your second domain. The second domain, if configured correctly, will accept those URL parameters and apply them as cookie values for the purposes of tracking.
So, it shouldn't be difficult for you to apply your own version of the _link function.
Specifically, the _link function passes the following cookies:
__utma, __utmb, __utmc, __utmx, __utmz, __utmv and __utmk
Into a query string as such: ?__utma=87278922.614105561.1288923931.1294376393.1298325957.6&__utmb=87278922.1.10.1298325957&__utmc=87278922&__utmx=-&__utmz=87278922.1288923931.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)&__utmv=-&__utmk=72493274
So, all you need to do to replicate the _link function is, before you apply the server side redirect, grab the cookie values, and apply them as a query string on the URL you're redirecting to.
Now, that's not the only thing you'll need to do to get this working. The Google Analytics configuration on the payment site will need to be configured with _setAllowLinker set to true, as well as potentially disabling the domain hash and setting a particular domain name for the tracking cookies; it depends on your configuration. You can find out more about that in Google Analytics Cross Domain Tracking Guide.
#yc's approach looks like the best bet but if that doesn't work, I would suggest having your controller redirect the user to a "temp" page on your site itself and show some text like "Checking out....Please wait..." and using Javascript trigger the call to the "_link" function to redirect the user to the "payment-checkout.com" (again using Javascript).
I assume you're also tracking the page the user returns to and want to measure how many users you lose in the process in between?
My knowledge of the Google Analytics API is fairly limited, so maybe there's a better solution, but you could consider rendering a page containing the GA code and triggering the _link() function from there?
It might also be possible to perform an AJAX call on submitting the form (maybe using remote_form_for) and handling the GA redirect in an RJS-response:
page << "_gaq.push(['_link', 'http://example.com/test.html']);"
However, I'm not sure how well that would fit into your application.
If JavaScript is disabled what's a way of linking to the previous document in the session history?
Can PHP be used to simply link to the REFERRER or is there a better alternative?
Edit: Further to this, can previous post variables be retained?
You're really mixing the idea of previous document in client session history vs. server session history.
Since Javascript is client-side, executing a history.back() renders the control to the browser, which then decides which page was last in the history (keeping in mind that the last page may not be a page within your domain). When you're using server-side PHP, the HTTP header referrer is whatever the browser supplied to you. If your server-side URI wasn't called as a result of an explicit click on a link, form GET/POST, etc. , your script probably won't get a referrer header value.
If you only want to capture the referrer within your site's domain, you can start maintaining a breadcrumb trail server-side (in the user's session). eg: $_SESSION['breadcrumbs'] = array( 'page1', 'page2', ... )
POST variables can be persisted in the SESSION too though I've never seen a good reason to do so. If you're trying to return an error message for a form and expect to get back the POST, you shouldn't be saving the state of the original POST.