OAuth API

OAuth API: Walkthrough

This walkthrough sets up a basic website that implements the Square OAuth flow. Use it to build a seller-facing web page with a link to the Square authorization page and a callback page that handles the authorization redirect. These pages let a seller authorize your application and give it an access token for making calls on the seller's behalf.

Overview Permalink Get a link to this section

Implementing the Square OAuth flow for your application is a four-step process:

  1. Set up your application in the Developer Dashboard.

  2. Add a link to the Square authorization page from your seller-facing page with your application ID and the permissions the seller should grant to your application.

  3. In the callback page, get the authorization code and use it to get an OAuth token. 4. Maintain access using the refresh token. An OAuth access token expires after 30 days.

Follow this walkthrough to set up a website that implements the Square OAuth flow. Test your website by using a Sandbox seller account to complete the flow from the view of a seller. The walkthrough shows you how a seller views your application in the Seller Dashboard.

Before you start, note the following:

  • The walkthrough uses a PHP web server project. After finishing this walkthrough, you can explore similar GitHub examples in other languages. For more information, see connect-api-examples.

  • The Square Sandbox is a testing environment. The Sandbox does not work with production Square accounts. It lets you see how OAuth works in the developer Default Test Account that contains the application and how a seller account interacts with the OAuth process, without impacting your production environment.

Get ready Permalink Get a link to this section

To prepare for this walkthrough:

  • Create an application.

  • Set up Sandbox accounts.

  • Download the example project.

Create an application Permalink Get a link to this section

You may use an existing application, but for this walkthrough, create a new one.

  1. Go to the Developer Dashboard.

  2. Choose Create your first application. If you have one or more existing applications, click the + (plus sign) in the empty application card.

  3. In the Application Name box, type My Example App.

  4. Choose Save.

Create a seller Sandbox account Permalink Get a link to this section

Your Square developer account comes with a "Default Test Account" sandbox account. To simulate third-party application development, you need to create a second sandbox account to act as a seller account.

Create a sandbox account as a seller test account:

  1. Open the Developer Dashboard.

  2. In the Sandbox Test Accounts section, choose Add.

  3. In the Account Name box, specify Seller Test Account.

  4. In the Country box, choose any country.

  5. Clear the Automatically create authorizations for all my current apps check box.

  6. Choose Create.

The Developer Dashboard should look like the following:

DevDashboard Seller Test Accounts

Download the project template Permalink Get a link to this section

For this exercise, start with a predefined project as your web server.

  1. Download the connect-api-examples project using one of these options:

    • Download the ZIP file and unzip the content to a local directory.

    • Clone the GitHub repository to a local directory.
      The connect-api-examples repository contains the OAuth PHP project used for this walkthrough. It also has the OAuth project implemented in other languages and examples of other API use cases.

    Note

    Although the code is different for the other OAuth SDK samples, the same high-level workflow and concepts described in this topic apply to them.

  2. Open a command line.

  3. In the project directory, change to the connect-examples/oauth/php/ subdirectory.

  4. Review the directory which has the following files:

    • request_token.php is a web page with a link to the Square authorization page so a seller account can authorize your application.

    • callback.php is the target that the authorization page redirects to and where your application gets an OAuth token.

    • messages.php contains helper functions to give easy access to tokens and display error messages.

  5. In the directory, create the .env file and fill in the credentials and IDs for your application, following the format shown in the .env.example file.

  6. Install the Square PHP SDK in your project directory. Follow the installation instructions.

  7. Run the following command to start the server:

    php -S localhost:8000
    
  1. Verify that the PHP server is running. Open a browser window and enter http://localhost:8000/request_token.php. You should see the following:

    oauth : walkthrough : Figure 2

Now you are ready to build a basic web application that implements the Square OAuth flow.

Step 1: Set up your application Permalink Get a link to this section

To implement the Square OAuth flow, do these Developer Dashboard tasks:

  • Get the application ID, also known as the client ID.

  • Get the application secret, also known as the client secret.

  • Set the redirect URL for the callback endpoint where your application receives the authorization code.

The application ID is a query parameter for the Square authorization page. The Square authorization page sends the authorization code to the callback endpoint at your application redirect URL. Your callback uses the application ID, application secret, and the authorization code to call the ObtainToken endpoint to get an OAuth access token.

Get your credentials and set the redirect URL:

  1. Open the Developer Dashboard.

  2. Choose Open on the card for the My Example App application.

  3. At the top of the page, set the dashboard mode to the environment that you want to work with by choosing Sandbox or Production.

  4. Choose OAuth in the left navigation pane.

  5. In the Sandbox Redirect URL box, enter the URL for the callback you implement to complete the OAuth flow:

     http://localhost:8000/callback.php
    

    This walkthrough uses localhost in the Square Sandbox. An actual web server implementation must use HTTPS.

  1. In the Sandbox Application ID box, copy the application ID.

  2. In the Sandbox Application Secret box, choose Show, and then copy the application secret.

  3. Choose Save.

  4. In your project directory, create a copy of the .env.example file and name it .env

  5. In the newly created .env file, replace the your-environment with either sandbox or production

  6. Replace the your-application-id and your-application-secret placeholders with the Sandbox or Production application ID and application secret, respectively.

  7. Save the file.

OAuth Sandbox credentials have a sandbox prefix. The base URL for calling Sandbox endpoints is https://connect.squareupsandbox.com. When you configure for production, use production credentials and https://connect.squareup.com as the base URL.

Warning

Never check your credentials/access_token into your version control system. The .env file is included in the project .gitignore to help prevent uploading confidential information.

You should avoid putting the application secret in your source code. Instead, encrypt the secret and use an environment variable to reference the secret in your application.

Step 2: Link to the Square authorization page Permalink Get a link to this section

A seller initiates the OAuth flow by choosing a link to open the Square authorization page. The link sends the seller to the Square authorization page where the seller's identity is verified using Square sign-in and so the seller can grant the permissions to your application. The link URL looks like the following:

https://connect.squareupsandbox.com/oauth2/authorize?client_id={APPLICATION_ID}&scope=MERCHANT_PROFILE_READ+PAYMENTS_WRITE_ADDITIONAL_RECIPIENTS+PAYMENTS_WRITE+PAYMENTS_READ

The {APPLICATION_ID} placeholder value for the client_id parameter is the Sandbox application ID that you collected in step 1. The scope is the set of permissions that you want the seller to grant to your application. The permissions in the list are separated by a URL-encoded space (%20 or +).

The following shows the scope set for this walkthrough:

  • MERCHANT_PROFILE_READ enables calls to the List Merchants and Retrieve Merchant endpoints.

  • PAYMENTS_WRITE and PAYMENTS_READ let you create, cancel, and retrieve payments using the Payments API.

  • PAYMENTS_WRITE_ADDITIONAL_RECIPIENTS lets you add an application fee to a payment.

request_token.php contains the link to the Square authorization page. It URL-encodes the list of space-delimited permissions and creates the link using the Sandbox base URL, authorization page path, Sandbox application ID, and the encoded permissions.

<?php
require 'vendor/autoload.php';
require_once('messages.php');
 
use Dotenv\Dotenv;
 
$dotenv = Dotenv::create(__DIR__);
$dotenv->load();
 
// Specify the permissions and url encode the spaced separated list.
$permissions = urlencode(
                 "ITEMS_READ " .
                 "MERCHANT_PROFILE_READ " .
                 "PAYMENTS_WRITE_ADDITIONAL_RECIPIENTS " .
                 "PAYMENTS_WRITE " .
                 "PAYMENTS_READ"
              );
 
// Set the Auth_State cookie with a random md5 string to protect against cross-site request forgery.
// Auth_State will expire in 60 seconds (1 mins) after the page is loaded.
$state = md5(time());
setcookie("Auth_State", $state, time() + 60);
 
$application_id = getenv('SQ_APPLICATION_ID');   
$environment =  getenv('SQ_ENVIRONMENT');
 
if ($environment == "sandbox") {
 $base_url = "https://connect.squareupsandbox.com";
} else if ($environment == "production") {
 $base_url = "https://connect.squareup.com";
} else {
 displayError("Unsupported SQ_ENVIRONMENT", "Set the SQ_ENVIRONMENT variable in .env file to 'sandbox' or 'production'.");
}
 
// Display the OAuth link.
echo '<p><a href="' . $base_url . "/oauth2/authorize" .
    '?client_id=' . $application_id .
    '&scope=' . $permissions .
    '&state=' . $state .
    '">Authorize this application</a></p>';
?>

Session state management Permalink Get a link to this section

The md5 function generates a random string that is stored in the session cookie and passed in the state parameter. The state parameter is returned by the Square authorization page. The callback compares the state value with the string stored in session cookie and rejects if they do not match. The state parameter helps protect against cross-site request forgery (CSRF).

The session parameter is omitted because Sandbox only supports a default setting of true. For production, this value should be false. For more information about using the session parameter in production, see session parameter guidelines in OAuth API Best Practices.

Step 3: Exchange the authorization code for an OAuth token Permalink Get a link to this section

After the seller allows (or denies) your application the requested permissions, the Square authorization page redirects to the URL that you set on the OAuth page. The POST request on your callback page includes a query string with an authorization code or a denial error.

3.1 Handle the authorization callback Permalink Get a link to this section

The following code block parses the query string. If there is an authorization code, the obtainOAuthToken function is called to exchange the authorization code for OAuth tokens.

The code block performs three functions:

State validation Permalink Get a link to this section

To ensure that the response is for the request made in this session, the first if statement checks the state parameter against the value stored in the cookie. If the values do not match, the displayStateError function is called to display a message indicating that the state check failed and this block is exited.

Check for authorization code Permalink Get a link to this section

If the state check succeeds, the block checks for the response_type parameter. If the response_type parameter value is code, an authorization code is returned in the code parameter.

Get an access token Permalink Get a link to this section

The block gets the authorization code and passes it to the obtainOAuthToken function, which returns the OAuth access token and refresh token. For this walkthrough, those tokens are displayed on the web page so you can get them easily. In production, you should never display the tokens. Instead, you should encrypt them and store them securely. For more information, see OAuth API Best Practices.

If there is no response_type parameter set, error states are handled (including the case where the seller chooses Deny) and an error message is displayed.

// Handle the response.
try {
   // Verify the state to protect against cross-site request forgery.
   if ($_COOKIE["Auth_State"] !== $_GET['state']) {
     displayStateError();
     return;
   }

   // When the response_type is "code", the seller clicked Allow
   // and the authorization page returned the auth tokens.
   if ("code" === $_GET["response_type"]) {
     // Get the authorization code and use it to call the obtainOAuthToken wrapper function.
     $authorizationCode = $_GET['code'];
     list($accessToken, $refreshToken, $expiresAt, $merchantId) = obtainOAuthToken($authorizationCode);
     // Because we want to keep things simple and we're using Sandbox,
     // we call a function that writes the tokens to the page so we can easily copy and use them directly.
     // In production, you should never write tokens to the page. You should encrypt the tokens and handle them securely.
     writeTokensOnSuccess($accessToken, $refreshToken, $expiresAt, $merchantId);
   }
   elseif ($_GET['error']) {
     // Check to see if the seller clicked the Deny button and handle it as a special case.
     if(("access_denied" === $_GET["error"]) && ("user_denied" === $_GET["error_description"])) {
       displayError("Authorization denied", "You chose to deny access to the app.");
     }
     // Display the error and description for all other errors.
     else {
       displayError($_GET["error"], $_GET["error_description"]);
     }
   }
   else {
     // No recognizable parameters were returned.
     displayError("Unknown parameters", "Expected parameters were not returned");
   }
} catch (Exception $e) {
 // If the obtainToken call fails, you'll fall through to here.
 displayError("Exception", $e->getMessage());
}

3.2 Exchange the authorization code for a token Permalink Get a link to this section

The obtainOAuthToken function looks like the following:

<?php
require 'vendor/autoload.php';
require_once('messages.php');
 
use Square\Exceptions\ApiException;
use Square\SquareClient;
use Square\Environment;
use Square\Models\ObtainTokenRequest;
use Dotenv\Dotenv;
 
$dotenv = Dotenv::create(__DIR__);
$dotenv->load();
 
// The obtainOAuthToken function shows you how to obtain a OAuth access token
// with the OAuth API with the authorization code returned to OAuth callback.
function obtainOAuthToken($authorizationCode) {
 // Initialize Square PHP SDK OAuth API client.
 $environment = getenv('SQ_ENVIRONMENT') == "sandbox" ? Environment::SANDBOX : Environment::PRODUCTION;
 $apiClient = new SquareClient([
   'environment' => $environment
 ]);
 $oauthApi = $apiClient->getOAuthApi();
 
 // Initialize the request parameters for the obtainToken request.
 $body_grantType = 'authorization_code';
 $body = new ObtainTokenRequest(
   getenv('SQ_APPLICATION_ID'),
   getenv('SQ_APPLICATION_SECRET'),
   $body_grantType
 );
 $body->setCode($authorizationCode);
 
 // Call obtainToken endpoint to get the OAuth tokens.
 try {
     $response = $oauthApi->obtainToken($body);
 
     if ($response->isError()) {
       $code = $response->getErrors()[0]->getCode();
       $category = $response->getErrors()[0]->getCategory();
       $detail = $response->getErrors()[0]->getDetail();
 
       throw new Exception("Error Processing Request: obtainToken failed!\n" . $code . "\n" . $category . "\n" . $detail, 1);
     }
 } catch (ApiException $e) {
     error_log($e->getMessage());
     error_log($e->getHttpResponse()->getRawBody());
     throw new Exception("Error Processing Request: obtainToken failed!\n" . $e->getMessage() . "\n" . $e->getHttpResponse()->getRawBody(), 1);
 }
 
 // Extract the tokens from the response.
 $accessToken = $response->getResult()->getAccessToken();
 $refreshToken = $response->getResult()->getRefreshToken();
 $expiresAt = $response->getResult()->getExpiresAt();
 $merchantId = $response->getResult()->getMerchantId();
 
 // Return the tokens along with the expiry date/time and merchant ID.
 return array($accessToken, $refreshToken, $expiresAt, $merchantId);
}

The obtainOAuthToken function takes the authorization code and calls the ObtainToken endpoint to get the OAuth access token and refresh token. The ObtainToken endpoint takes your application ID, your application secret, a grant_type of authorization_code, and the authorization code.

3.3 Test your authorization flow Permalink Get a link to this section

You test the two flows that are possible based on a seller's actions on the Square authorization page: deny or allow authorization for your application.

  1. Open the Developer Dashboard.

  2. In the Sandbox Test Accounts section, find the seller test account you created, and then choose Open.

    The Sandbox Seller Dashboard for the seller account opens in a new tab. The Seller Dashboard is what the seller uses to manage their Square account. In the Sandbox, the seller needs to be signed in to see the Square authorization page. Sign in to a seller test account by launching the Seller Dashboard. In production, you can also control whether you force the seller to sign in explicitly by setting the session parameter to false (recommended). For more information, see OAuth API Best Practices.

  1. In the left pane, choose Apps.

    OAuth : Walkthrough : figure 3

    The Apps page is where your application is displayed after your application completes the OAuth flow for a seller. No applications are shown in the list because the seller test account has not yet authorized any applications.

  1. Save all the files you have worked on in the OAuth walkthrough.

  2. Start the PHP server, if it is not running:

    php -S localhost:8000
    
  1. Open a browser window and open request_token.php on localhost by entering http://localhost:8000/request_token.php in the address bar.

  2. Choose the Authorize this application link. The Square authorization page loads and looks like the following:

    OAuth : How it works : fig 1

    Note that permissions you requested in the authorization URL are listed on the page. You can test the Deny and Allow flows in the next steps.

  1. Choose Deny. The authorization page sends the browser to the page specified by your application Redirect URL. The URL looks like the following:

    http://localhost:8000/sandbox_callback.php?error=access_denied&error_description=user_denied

    The URL has two query parameters. The error value of access_denied indicates that authorization was denied. The error_description indicates that the reason for the denial was that the seller chose Deny. The callback.php page reads the query parameters, handles this error case, and displays error details that say You chose to deny access to the application.

  1. In the browser address bar, go to http://localhost:8000/refresh_token.php, refresh the page to reset the state in the cookie, choose Authorize this application, and then choose Allow. The authorization page redirects to your application's callback page with a URL that looks like the following:

    http://localhost:8000/callback.php?code=sandbox-sq0cgb-xJPZ8rwCk7KfapZz815Grw&response_type=code
    

    The URL has two query parameters. The response_type parameter tells you what is being returned. You should check response_type to ensure that its value is code. The code parameter is the authorization code that you exchange for an OAuth access token. The callback.php page reads the query parameters, uses the authorization code to get OAuth tokens, and displays Authorization succeeded.

    The page looks something like the following:

oauth : walkthrough : Figure 5

Because you are testing in the Sandbox, the example writes the access and refresh tokens to the page to make it easy for you to use the tokens.

Important

In production, you should not write the tokens in clear text and you certainly should not display them on a web page. Encrypt the tokens and store them securely in a database or other type of storage solution.

  1. Copy the OAuth access token and refresh token from the callback page. Use the OAuth tokens to call the CreatePayment and ObtainToken endpoints and to get a new access token using the refresh token in the next steps.

  2. See what an authorized application looks like for the seller. Open the Developer Dashboard, find the seller test account you created in the Sandbox Test Accounts section, choose Open, and then choose Apps in the left pane.

OAuth : Walkthrough : figure 6

In the Sandbox, the application ID is displayed as the name (in production, the application name is displayed). The seller can revoke access to your application by choosing the X in the Square account access section.

  1. Choose the application link to see the authorized permissions for this application.

OAUTH walkthroiugh step 3.3 - 11b

You have received an OAuth token from a Sandbox seller account and have seen the process from both the developer and seller perspectives. Now use your token to call Square APIs.

3.4 Use your token to call a Square API on behalf of the seller Permalink Get a link to this section

After you get your token, use the OAuth access token to call the Square API endpoints that your application has permissions for. To keep this simple, use API Explorer to call the CreatePayment endpoint to take a $100.00 payment with a $5 application fee going to your Square developer account and $95 going to the seller.

  1. Go to Square API Explorer. oauth : walkthrough : Figure 6.6

  2. Make sure Sandbox is selected, paste the access token that you obtained in the OAuth process into the Access token box, and then choose Save.

    API Explorer uses this access token to make calls on behalf of the seller.

  1. Set the following parameters in the body:

    1. For amount_money, choose Add, enter 10000 for the amount, and then set the currency to your selected country when you created your Square account.

      Note that money is represented in the lowest denomination for a currency, which for USD is cents. So the amount of 10000 is $100.00.

    2. For idempotency_key, choose Generate to create a unique value to ensure that this payment is only made once. For more information, see Idempotency.

    3. For source_id, choose cnon:card-nonce-ok. This simulates a card payment token that represents a credit card that can be used for payment. For more information about card tokens, see Online Payment Options.

    4. For app_fee_money, choose Add, enter 500 for amount, and then set the currency to your Square account country. oauth : walkthrough : Figure 8

  2. Choose Run Request. The Response box displays a 200 response code and returns details about the payment in the body of the response. The payment has an id value that you can use to identify this particular payment when calling ListPayments or you can get it directly using GetPayment. oauth : walkthrough : Figure 9

    You have successfully taken a payment using the Square API on behalf of a seller. Look at Seller Dashboard to see what it looks like from the seller's point of view.

  1. Open the Developer Dashboard, find the seller test account you created earlier in the Sandbox Test Accounts section, and then choose Open.

  2. In the Sandbox Seller Dashboard, choose Transactions in the left pane, and then choose the most recent transaction. The transaction details appear in a pane on the right.

    oauth : walkthrough : Figure 10

You see the $100 payment that was completed and the $5 application fee that your application collected and credited to your Sandbox developer account.

In the Other row, you see the $5.00 application fee from the CreatePayment call.

Refresh an expiring OAuth access token Permalink Get a link to this section

As previously discussed, an OAuth access token expires in 30 days. If you want your application to continue to call on behalf of a seller, refresh the access token. To do this, your application calls ObtainToken, passing the refresh token instead of an authorization code.

Use API Explorer Permalink Get a link to this section

You can do this with API Explorer.

  1. Go to the ObtainToken page in API Explorer.

  2. Set the following parameters in the body:

    1. client_id to the application ID for your application.

    2. client_secret to the application secret.

    3. grant_type to refresh_token.

    4. refresh_token to the refresh token you got from your original call to ObtainToken.

    oauth : walkthrough : Figure 10.5

  3. Choose Run Request. The 200 response looks like the following:

oauth : walkthrough : Figure 11

The access_token value is your new OAuth token. The refresh token never expires so you can use that same refresh token to get an OAuth access token whenever you need a new one.

Use the OAuth API Permalink Get a link to this section

In your production application, you can use the ObtainToken to refresh the access token associated with the refresh token used in the call.

Set the following parameters in the method call: 1. client_id to the application ID for your application. 2. client_secret to the application secret. 3. grant_type to refresh_token. 4. refresh_token to the refresh token that was paired with the access token to be refreshed.

The following example calls ObtainToken with a refresh token:

Obtain Token
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
curl https://connect.squareupsandbox.com/oauth2/token \
  -X POST \
  -H 'Square-Version: 2021-05-13' \
  -H 'Content-Type: application/json' \
  -d '{
    "refresh_token": "{REFRESH_TOKEN}",
    "client_id": "{APPLICATION_ID}",
    "client_secret": "sandbox-sq0csb-APPLICATION_SECRET_EXAMPLE",
    "grant_type": "refresh_token"
  }'

The response includes a new access token and a new refresh token. Be sure to replace the expiring access token and the old refresh token in your secure token cache:

{
  "access_token": "{OAUTH_ACCESS_TOKEN}",
  "token_type": "bearer",
  "expires_at": "2020-06-06T02:17:22Z",
  "merchant_id": "{MERCHANT_ID}",
  "refresh_token": "{OAUTH_REFRESH_TOKEN}"
}

You can also reduce the permission scope of an expiring access token. To learn about scope reduction, see Get Right-Sized Permissions with Down-Scoped OAuth Tokens.