The sample server

The sample mid-tier server is a Node.js application. It is designed to work with the sample app, and also to serve as a model for developing your own mid-tier server.

The sample apps distributed with the SDK are configured to work with an instance of the sample server, called the “test server,” that is hosted by PayPal. Thus you need not set up and run the sample server in order to use the sample apps. You will need to set up and customize the sample server when you are ready to start testing your own app, though.

The sample server delivered with the SDK uses the same pre-defined Sandbox merchant as the sample apps, a client ID and a Secret. See the Authenticating SDK operation section for more information about authentication. The merchant (named teashop) is specified in ./sample-server/herokuserver/server.js. The client ID and Secret in are in ./sample-server/heroku-server/config.js. You can replace all of these values with your own.

For background about what a mid-tier server does and how it works, review Developing a mid-tier server. Also review the code comments in these files:

  • ./sample-server/heroku-server/config.js
  • ./sample-server/heroku-server/server.js
  • ./sample-server/heroku-server/lib/oauth.js

Setting up the sample server

The sample server is located in the SDK distribution files at ./sample-server/heroku-server/.

The sample server is easily deployed on the Heroku web app hosting site, and is easily modified to run elsewhere. Run the sample server on a shared resource; one instance of it can serve multiple developers.

To prepare the sample server for use on a local development system or server:

  1. Install Node.Js.
  2. Start a terminal window, navigate to the ./sample-server folder, and run npm install.
  3. Run server.js. Log messages appear in the terminal window. The server advertises itself using Bonjour/zeroconf. The Log In with PayPal return URL is not automated, but was configured when you installed the Node.js.

Functionality of the sample server

The sample server implements both of the basic designs described in Developing a mid-tier server. To proxy all SDK operations to the server (the default), set exports.CENTRAL_SERVER_MODE to true. To proxy only operations used to obtain access tokens, set it to false.

The sample server implements four URIs:

  • /login: A dummy version of user authentication. Returns a ticket that can be used in place of a password to reassure you that the person you're getting future requests from is the person who entered their password in your app.
  • /goPayPal: Validates the ticket and returns a URL that your app can open in a browser to start the Log In with PayPal flow. This method specifies the OAuth scopes you're interested in, which must include the PayPal Here scope (defined as https://uri.paypal.com/services/paypalhere).
  • /goApp: The endpoint where PayPal returns the user after the user completes authentication. This endpoint inspects the result of authentication and redirects back to your app.

First, the sample server sends a request to PayPal to the refresh token for an access token:

request.post(
    {
        url:config.PAYPAL_ACCESS_BASEURL +
        "auth/protocol/openidconnect/v1/tokenservice",
        auth:{ user:config.PAYPAL_APP_ID,
        pass:config.PAYPAL_SECRET, sendImmediately:true},
        form:{ grant_type:"authorization_code", code:req.query.code }
    },
    function (error, response, body) {}
);

The server encrypts the access token received from PayPal using the ticket, so if someone hijacks the URL handler of your app, the data is not usable; it is not the data sent by the Log In with PayPal flow. The server returns a URL to your app that allows the app to generate a refresh token when necessary. This URL is to the /refresh/username/token handler, and includes the refresh token issued by PayPal, encrypted with an account-specific server Secret. The refresh token is never stored on the server, and is not stored in a directly usable form on the client either. This minimizes the value of centralized data onyour server, and allows you to cut off refresh tokens in cases of compromised tokens.

  • /refresh/username/token: Decrypts the refresh token and passes it to the token service to get a new access token.

When you are ready to set up a server with your own client ID instead of the predefined client ID that the distributed samples use, set the return URL to point to your server. If you are testing on a real device, this URL generally needs to work on that device and on your simulator, meaning it must have a live DNS entry on the internet.

The merchant username and password are stored in a database defined at ./sample_server/heroku_server/users.db. (This is an nStore database; nStore is a database for Node.js applications.) The access and refresh tokens are stored in the same database when they become available.

For additional information, see Developing a mid-tier server and the source code comments in ./sample_server/heroku_server/server.js.

About the encrypted access token

The first time you run the sample app, the test server sends it an encrypted access token and a refresh URL (a URL on the test server that can be used to refresh the token).

The test server encrypts the access token with a seed value (called a "ticket"). The ticket is created when the user logs into the server for authentication for the first time. This technique for acquiring a seed for encrypting the access token is suitable for use in live mid-tier servers, but other techniques are possible.

The sample server distributed with the SDK handles the access token the same way as the test server.

The /sample-server/heroku-server/server.js file has a default test merchant named teashop, whose address is a confirmed address in the teashop PayPal account. When you begin developing an app, your code can retrieve merchant data (including the confirmed address) for an order (invoice) with the PayPalHereSDK class activeMerchant method. For more information, see the PayPalHereSDK class in the PayPal Here SDK reference documentation.