Table of Contents
Single Sign-On (SSO)
About Single Sign-On
FoxyCart's SSO allows customers who are already logged into your website to proceed through to checkout without needing to re-enter their username and password. This allows for far greater integration options, and can provide for a significantly improved checkout flow if you have customers who may already be logged into an external system. In order to prevent possible security issues, SSO checkouts still require the customer to enter the CSC when using a saved credit card.
Alternate Uses of SSO
Because of how FoxyCart's SSO functionality works it actually allows for a few interesting options in besides straight single sign-on:
- Checkout can be made entirely “private”, requiring authentication (through your own system) prior to allowing purchase. This could allow for members-only stores or other secure ordering or customer pre-screening opportunities.
- Prior to passing a customer on to the checkout the customer's cart could be retrieved (using the JSONP functionality) and validated to ensure they:
- aren't ordering more or less items than may be required;
- aren't getting a discount or price range they aren't authorized to get;
- have entered any additional information (referrer values, coupon codes, etc.);
- have registered through your system's own registration process;
- have been presented with cross-sell or up-sell opportunities.
- A functional site + FoxyCart setup, using the API to synchronize customer records with your own user database.
How It Works
The Basic Idea
The basic idea of SSO is as follows:
- User creates an account or logs into SITE.
- On any user creation or modification, the SITE synchs the user's information with FoxyCart's customer records, using the API.
- When the user attempts to load the SITE's FoxyCart checkout (ie. from clicking “checkout” on the cart, from a direct to checkout request, etc.), the checkout redirects the user back to the SSO endpoint as configured in your FoxyCart store settings.
- The SITE's endpoint checks the current user's authentication status (on the SITE). This is possible because the endpoint is (probably) on the same domain as the SITE (where the initial authentication and any cookie-based sessions reside), and thus can access whatever session information might be available (such as the
- Based on the SITE's shared-authentication endpoint, the script can:
- Redirect the user to the checkout, authenticated;
- Redirect the user to the checkout, not authenticated; or
- Take other action, such as redirect the user to a login or registration page, or deny checkout altogether.
Before we get to the details of an SSO implementation, it's important to understand what we consider “best practices” when it comes to SSO. The most important piece that people often miss is that users can be created from You → FoxyCart (via the API) and from FoxyCart → You (via the instant datafeed).
There are two related but unique user creation flows, then:
- The user adds products to the cart and proceeds through to the checkout all without your system knowing who the user is. When the user successfully completes the checkout, your system gets the instant datafeed and creates (or updates, if the user exists already) the user in your database.
- The user registers on your system first, logs in, then proceeds through to the FoxyCart checkout, already authenticated via SSO.
We strongly recommend allowing both options. Though there are situations where you may require a login prior to allowing a customer to add items to their cart (or even to see pricing), in most situations it will only hurt your sales if you require users to create an account prior to completing the checkout. Also, FoxyCart's checkout is arguably one of the most streamlined user registration forms around, and if the customer is going to be entering information you might as well just have them enter it in one place.
What Is Passed To The Endpoint, and When It Happens
Read the above overview first. Then take note of some of the details below.
- WHEN: On every
checkoutrequest submitted to FoxyCart, the checkout will redirect back to your shared-authentication endpoint unless a valid authentication token (
fc_auth_token) is passed in.
- WHAT: When the
checkoutredirects the user back to your shared-authentication endpoint two additional values are passed in as well, as
fcsid: The user's FoxyCart session id. This is necessary to maintain the session across domains, particularly important when a store is not using a custom subdomain and the user has third-party cookies disabled.
timestamp: The epoch time on the FoxyCart server. It is important to note that this value is basically provided just in case you want to confirm that times are synched properly. This value should not be used for anything but confirming that the
timestampyou hash and return (below) is indeed in the future as far as FoxyCart is concerned.
What Checkout Requires From The Endpoint
If shared-authentication is enabled, the checkout will not load unless a valid
fc_auth_token (and other supporting information) is passed in by your endpoint when it redirects the user. Here's what the checkout expects and requires.
fc_auth_token: The authentication token is a SHA-1 hash of the FoxyCart customer ID (available through the API), the expiration timestamp, and the store's FoxyCart API key. These values are separated by
|(the pipe symbol). Here's what it might look like in PHP:
$auth_token = sha1($customer_id . '|' . $timestamp . '|' . $foxycart_api_key);
or in Ruby:
- It is critically important to note that the
timestampvalue you hash must match the
timestampvalue you send in the clear (below). Again, the
timestampprovided to your endpoint must not be used when passed back to FoxyCart, as that timestamp will already be in the past.
fcsid: The FoxyCart session ID. This is necessary to prevent issues with users with 3rd party cookies disabled and stores that are not using a custom subdomain.
fc_customer_id: INTEGER. The customer ID, as determined and stored when the user is first created or synched using the API. NOTE: If a customer is not authenticated and you would like to allow them through to checkout, enter a customer ID of
timestamp: INTEGER, epoch time. The future time that this authentication token will expire. If a customer makes a checkout request with an expired authentication token, then FoxyCart will redirect them to the endpoint in order to generate a new token.
The completed redirect might look something like this (in PHP):
$redirect_complete = 'https://yourdomain.foxycart.com/checkout?fc_auth_token=' . $auth_token . '&fcsid=' . $fcsid . '&fc_customer_id=' . $customer_id . '×tamp=' . $timestamp; header('Location: ' . $redirect_complete);
What Happens on Error
- If the SHA-1 hash passed to FoxyCart does is invalid or doesn't match the supplied cleartext values, the user is redirected back to the store's URL (as configured in the store settings). The only way this should happen is if your SSO endpoint is configured incorrectly, or if a malicious user is attempting to manipulate the redirect URL.
- If the SSO timestamp has expired, the user will be redirected back to the shared-authentication endpoint. This may result in the user then being bounced immediately back to the checkout, which can be problematic as it will appear that there was an error on checkout.
- Set the timestamp/expiration far enough in the future (an hour or more, perhaps) to prevent issues.
setTimeout()to match your expiration setting alerting your user that their checkout session is about to expire to let your customers know that their session is about to (or has already) expired.
If you're convinced that FoxyCart is broken because you can't get SSO working, it's possible, but unlikely. Check a few common causes:
- What's your timestamp value? It must be in the future, but don't set a date in the year 24800 or something crazy. If it's in the past, that's your problem.
- The customer ID must match the FoxyCart customer ID, as retrieved in the XML datafeed or API. This isn't (usually) the ID of the customer in your database.
- The customer ID is for a non-guest customer record (the
is_anonymousbit should be 0). You cannot send the checkout a guest user, since guest users cannot be reused (by design).
- The URL should be pointing to
- The URL should be wellformed, and doesn't have any syntax errors like missing
- The hash you're sending (in the URL) is indeed what you get by manually hashing the pieces you're sending.
If you still can't get it working, please post in our forum and we'll be happy to help.
Best Practices: How To Approach a SSO Integration
One of the things we often hear is this workflow:
When the user goes to checkout I want them to be required to login or already be logged in. For new customers I want them to be redirected to the registration page on my site.
We generally recommend allowing a checkout as a guest (or if not enabling guest mode, at least allowing checkout through the FoxyCart-powered checkout page without first registering elsewhere). That allows for the most streamlined approach, and puts the least number of hurdles between your customer and a successful transaction. So if possible, you should allow checkout without first registering on your site. Once the order's done, you can create the user in your systems, so the end result is still a synchronized user. (Of course, you may have very legitimate reasons for requiring registration first, but if possible we recommend allowing an unauthenticated checkout.)
In any case, there are three main pieces to dig into:
- Creating and updating users from your system → FoxyCart.
- Creating and updating users from FoxyCart → your system.
- The SSO endpoint (FoxyCart → your system → FoxyCart).
#1 would generally be code in your system that attaches to specific events like
OnUserSave, or other events where users are created or modified. On those events, just do a quick FoxyCart API call to create/update the user as needed.
#2 would be an endpoint on your system that accepted and processed the instant XML datafeed in order to create or update the user on your system.
#3 would be another endpoint on your end to handle the Single Sign-On functionality.
These three pieces are the foundation for a fully synchronized userbase between FoxyCart and your system of choice. If you have any questions about this process, just ask.
Caveats and Gotchas
- Using pre-population to set customer values shouldn't be used with SSO, as SSO and pre-population kind of do similar things. Using both is possible depending on your SSO settings, but you'll want to do pretty thorough testing to ensure it behaves as desired.