User Tokens ----------- In order to make :doc:`Access API <../access/index>` requests, merchants can use an ``lptoken`` (a token identifying a LaterPay user). Merchants are advised to store this token for use in subsequent :doc:`Access API <../access/index>` requests after they have obtained the token for a user. .. note:: On a website, the easiest way to store an ``lptoken`` for a user is to store it in a tamper-proof cookie or in a user session (data tied to a user identified by the merchant's website). When storing the ``lptoken`` in a cookie it is advised that the cookie fulfills these requirements: - It should be digitally signed so you can detect attempts by the user to change its value. - It should be tied to user's session, IP address, user-id or other secondary attribute of a user on your website. This way you can prevent users from *sharing* their tokens, thereby pretending to be the same LaterPay user. Invalid tokens ~~~~~~~~~~~~~~ Tokens can become invalid in a number of cases. For example when a user logs in or out, or if the token expired. In this case, the :doc:`/access<../access/access>` API call will return the following JSON response: .. code:: {"status": "invalid_token"} In this case, merchant should delete their stored token and behave exactly as if they didn't have any token. In a case when a token was obtained for a user who was logged out of LaterPay and then that user has logged in, then the response from :doc:`/access <../access/access>` to a call using this token will reflect the logged in user's access status and will contain an additional ``new_token`` field. Merchant should replace their existing token for that user with the value of that field for later use. This saves the merchant from having to obtain the token for the logged in user again. .. _receiving_user_tokens: Receiving User Tokens ~~~~~~~~~~~~~~~~~~~~~ You can ask LaterPay to return user tokens to you by - using :doc:`/gettoken ` - using :doc:`Manual Identification URL <../identification/manual_ident_dialog>` - passing ``return_lptoken`` parameter to - :doc:`/dialog/add ` - :doc:`/dialog/buy ` LaterPay will do so in a signed URL. The URL is signed using the same :ref:`signature algorithms ` and the same secret key used for communicating with LaterPay. It's really important that you verify the signature on a returned token, otherwise users will be able to inject random data into the conversation between you and LaterPay. Three url parameters will be added by LaterPay to url provided by the service consumer: - ``lptoken`` - the identifier which allows LaterPay and service consumer to refer to the same user, browser or device which is currently visiting the service consumer's website. - ``ts`` - token creation time as number of seconds from unix epoch. - ``hmac`` - signature created using the same :ref:`signature algorithms ` and shared secret used by service consumer to communicate with LaterPay API. If above parameters appear in original ``redir`` url, they'll be removed and replaced by ones provided by LaterPay so that the resulting url will contain only one of each of these parameters. Other url parameters present in original url will appear in the url along with the LaterPay provided parameters. If the original url contains a url ``#fragment``, it will be appended to the resulting url. The signature (``hmac`` parameter's value) will be based on: - LaterPay provided parameters: ``lptoken`` and ``ts`` - Parameters from original url. - Base url based on the original url - ``URL`` as described in :ref:`signing section `. - ``GET`` as HTTP method The url ``#fragment`` if present, does not play any role in creation of the signature. An example interaction with :doc:`/gettoken ` assuming merchant's id is ``merchantsIdFake`` and merchant's shared secret is ``merchantsSecretFake`` looks like this: #. Merchant creates a :doc:`/gettoken ` url (with ``redir`` parameter ``http://merchants-site/hello?id=3#fragment``). Resulting url looks like this: .. code:: https://api.sandbox.laterpaytest.net/gettoken?ts=1416485196&cp=merchantsIdFake&redir=http%3A%2F%2Fmerchants-site%2Fhello%3Fid%3D3%23fragment&hmac=8b5dc5ad76b324054a77de5573956250ec8e65244c313aa0718a90ad #. Merchant redirects the user to the above url, user is identified, and a new ``lptoken`` is created. Let's assume the value of the new ``lptoken`` is .. code:: t|mfMMwuQItvQlQHE7QNlrwKFcHF8Ap72koSVsPi7uk6pTI2ALIIDMBM9fZ6mXxL9y13ThU3/Ec3FobqHknk5UZA==|1416487845|0992b01cb678734f6f1dd808fb82fd8e214d6a992c0303b1076529f3 #. User is redirected to: .. code:: http://merchants-site/hello?id=3&ts=1416485196&lptoken=t%7CmfMMwuQItvQlQHE7QNlrwKFcHF8Ap72koSVsPi7uk6pTI2ALIIDMBM9fZ6mXxL9y13ThU3%2FEc3FobqHknk5UZA%3D%3D%7C1416487845%7C0992b01cb678734f6f1dd808fb82fd8e214d6a992c0303b1076529f3&hmac=62fef6bfbe917459e26a6a0b730252985ae6aa7d2f59503da0ea8e56#fragment .. note:: After receiving a request containing an ``lptoken`` parameter and validating and saving it for later use for a user, it is a good practice to redirect the user to the original target of the request but without ``lptoken``, ``ts`` and ``hmac`` parameters. In our example above, user would be redirected to ``http://merchants-site/hello?id=3#fragment``. That way, users can safely share or bookmark the original link (without LaterPay provided parameters). Common Mistakes ~~~~~~~~~~~~~~~ A common "mistake" is to check for a user token *before* doing URL path matching, and redirecting to :doc:`/gettoken ` regardless of whether or not the path would "resolve". This violates the Principle of Least Astonishment, because suddenly ``GET /this/is/totally/bogus`` gets responses of 302 (to :doc:`/gettoken `) rather than 404. So for example in `Django `_ you would probably *not* want to check and redirect in a `Django Middleware's process_request `_ because that would be called before the URL matching. Instead you might use `class-based views `_, the code for which will be hit *after* URL matching, so only for "valid" URLs.