Learn how to build a Square OAuth API flow to authorize your application to access a Square account.
OAuth API

OAuth Walkthrough: Test Authorization with a Web Server

You can test your application or website to receive and manage OAuth tokens using the Square Sandbox. The Sandbox lets you test each of the three stages of OAuth (described in this topic) without using production seller accounts.

Use this walkthrough to:

  • Direct the seller to the Square authorization page. You can simulate getting authorization from a seller's Sandbox test account.

  • Receive and retain OAuth tokens. The Sandbox application receives the Sandbox test account authorization and obtains the OAuth access token and refresh token. The walkthrough application does not retain the OAuth tokens or store them securely. Retaining and securely storing OAuth tokens must be done in production.

  • Refresh and revoke OAuth tokens. OAuth tokens from Sandbox test accounts act just like production OAuth tokens. Therefore, you can test refreshing the authorization using the refresh token. You can also test revoking the authorization.

Implementing the Square OAuth using code flow is a three-step process:

  1. Create a URL link to the Square authorization page that includes your application ID and the permissions you want the seller to grant to your application. Give the seller the link.

  2. Create a URL to your application that you use as your redirect URL. The redirect URL points to the application that receives the authorization code when the seller approves your authorization request and uses it to get the OAuth tokens. When your application is in place at the redirect URL, add the redirect URL to your application using the Developer Dashboard.

  3. Get the access token and refresh token. Maintain access using the refresh token. An OAuth access token expires after 30 days.

Before you start, note the following:

  • You must have an application created using the Developer Dashboard. You use the application ID and OAuth secret during this walkthrough. If you do not have an application that you created using the Developer Dashboard, see Get Started.

  • This walkthrough uses a PHP web server project. You must download the project, the PHP Square SDK, and Composer. For complete installation instructions, see the project readme. After completing 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. The Sandbox lets you see how OAuth works with a developer test account and how a seller account interacts with the OAuth process, without impacting your production environment.

There are a few differences between using the OAuth process in Sandbox and in production. These include:

  • Using the Sandbox and a Sandbox test account, you can use localhost and HTTP. In production, you cannot use localhost and you must use HTTPS.

  • In production, the session parameter for the authorization page URL must be set to false.

  • In the Sandbox, the application ID has a prefix of "sandbox".

  • In the Sandbox, the application secret has a prefix of "sandbox".

  • Sandbox and production endpoints have different base URLs:

    • Sandbox: https://connect.squareupsandbox.com

    • Production: https://connect.squareup.com

  • Make sure you are using your production ID, secret, and base URL when in production.

  1. Sign in to the Developer Dashboard.

  2. Choose Open for an application. If you do not have an application set up, see Get Started.

  3. At the top of the page, set the dashboard mode to Sandbox.

  4. In the left navigation pane, choose OAuth.

  5. In the Application ID box, copy and save the application ID.

  6. In the Application Secret box, choose Show, and then copy and save the application secret.

  7. In the Redirect URL box, enter the URL that redirects the seller authorization to your application. For this walkthrough using the Sandbox, use this value: http://localhost:8000/callback.php

    Important

    For this walkthrough using the Sandbox, you can use HTTP for localhost. A production account must use an actual web server implementation and must connect using HTTPS.

  8. Choose Save.

For this walkthrough, you use code that creates a simple web server that responds to the seller authorization and gets the OAuth tokens. Do the following to set up the project. You can also follow the instructions in the README.md file. The connect-api-examples repository contains the OAuth PHP project used for this walkthrough. 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.

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

  2. Open a command line.

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

  4. Review the directory that 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. The Square authorization page sends the authorization code to the callback endpoint at your application's redirect URL. Your callback uses the application ID, application secret, and authorization code to call the ObtainToken endpoint to get the OAuth access tokens.

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

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

    Important

    If you are using an Apple Mac, file names beginning with "." are not visible by default. To view hidden files in Terminal, use the 'ls -a' command. To view hidden files in Finder, hold down Cmd + Shift + .(dot).

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

  7. Run the following command to start the server:

  8. Verify that the PHP server is running.

Your Square developer account comes with a default test account in the Sandbox. To simulate third-party application development, you need to create a second Sandbox account to act as a seller account.

In the Sandbox, the seller must be signed in to see the Square authorization page. Sign in to a seller test account by opening 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).

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, enter Seller Test Account.

  4. In the Country box, choose any country.

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

  6. Choose Create.

    The Developer Dashboard should look like the following:

    A screenshot showing what the Developer Dashboard should look like after creating a new Sandbox test account.

  7. Choose Open for the new seller account. This opens the Seller Dashboard for the account. Leave this page open in your browser.

  8. Open a new browser window and enter http://localhost:8000/request_token.php. You should see the following:

    A graphic showing the Authorize button.

    Important

    When testing in the Sandbox, you need to have a Seller Dashboard open so the request_token.php code can send the request to it. You are simulating what the seller does in a production environment when they receive the authorization request and approve it.

  9. Choose the Authorize button.

  10. The page shows the authorization request for the new account. Choose Allow.

  11. The page shows that the authorization succeeded. The callback.php code got the authorization code from the seller's authorization, submitted the OAuth API call ObtainToken, and received the access token and refresh token. The authorization returns the following parameters:

  • state is the CSRF token your application passed in the state parameter for the Square authorization page. Use this value to verify that this is a valid request.

  • response_type is code. This indicates that an authorization code was returned.

  • code is the authorization code. Use this value when you call ObtainToken to get the access token and refresh token for the seller account. The value you provide to the ObtainToken call must match this value exactly.

For more information about the values returned in the seller authorization, see Receive Seller Authorization and Manage Seller OAuth Tokens.

You have now completed the OAuth process by obtaining the access token and refresh token for the test seller. The next steps show you how to use the access token and refresh token.

After you get the seller OAuth tokens, use the 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 API Explorer.

  2. Make sure Sandbox is selected at the top of the page, 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.

  3. Set the following parameters in the body:

    • For amount_money, choose Add, enter 10000 for the amount, and then set the currency to the country you selected 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.

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

    • 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.

    • For app_fee_money, choose Add, enter 500 for amount, and then set the currency to your Square account country.

      A screenshot showing a CreatePayment request in API Explorer.

  4. 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.

    A screenshot showing the details of a response when a request is made using API Explorer.

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

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

  6. 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.

    A screenshot showing the details of a transaction in the Seller Dashboard.

    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.

When you have completed the previous step, you know that you can use the seller's OAuth access token to make API calls on their behalf. Your application should be able to refresh the access token before it expires in 30 days. To keep this simple, use API Explorer to call the ObtainToken endpoint to refresh the seller token.

  1. Go to Square API Explorer.

  2. Make sure Sandbox is selected at the top of the page, paste your application's access token into the Access token box, and then choose Save.

  3. Set the following parameters in the body:

    • For client_id, enter your application's Sandbox application ID.

    • For client_secret, enter the Sandbox application secret for your application.

    • For grant_type, enter refresh_token.

    • For refresh_token, enter the seller's OAuth refresh token.

  4. Choose Run Request. The Response box displays a 200 response code and returns information about the new access token. Use this new access token to call the Square APIs on the seller's behalf.

Your application should give the seller the ability to revoke the access token if they choose to. To keep this simple, use API Explorer to call the RevokeToken endpoint to revoke the seller token.

  1. Go to Square API Explorer.

  2. Make sure Sandbox is selected at the top of the page, paste your application's access token into the Access token box, and then choose Save.

  3. Set the following parameters in the body:

    • For client_secret, enter the Sandbox application secret for your application.

    • In Body, for access_token, enter the seller's OAuth access token.

    • For client_id, enter your application's Sandbox application ID.

  4. Choose Run Request. The Response box displays a 200 response code and returns "success":true.

The request_token.php code creates the URL link to the Square authorization page that you give to the seller so they can authorize your application. The code uses your developer application ID and secret and requests several permissions that are then incorporated into the URL. The permissions in the list are separated by a URL-encoded space (%20 or +).

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 the session cookie and rejects the request if they do not match. The state parameter helps protect against cross-site request forgery (CSRF).

The session parameter is omitted because the Sandbox only supports a default setting of true. For production, this value should be false.

The {APPLICATION_ID} placeholder value for the client_id parameter is the Sandbox application ID you got from the Developer Dashboard for your application.

The completed URL looks like the following. For a complete review of the parameters used in the URL, see Create the Redirect URL and Square Authorization Page URL.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
<?php
  session_start();
  if (empty($_SESSION['auth_state'])) {
    $_SESSION['auth_state'] = bin2hex(random_bytes(32));
  }
?>
<link rel="stylesheet" href="public/style.css" type="text/css">
<meta name="viewport" content="width=device-width">
<?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.
$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 '
<div class="wrapper">
  <a class="btn"
   href="' . $base_url . "/oauth2/authorize" .
     '?client_id=' . $application_id .
     '&scope=' . $permissions .
     '&state=' . $_SESSION['auth_state'] .'">
     <strong>Authorize</strong>
  </a>
</div>';
?>

The callback.php code parses the query string that is returned after the seller allows (or denies) your application the requested permissions the Square authorization page redirects to the redirect URL. This is the URL that you set on the OAuth page of your application in the Developer Dashboard. The POST request on your callback page includes a query string with an authorization code or a denial error.

The 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:

  • Validates the state parameter. 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.

  • Checks for authorization. 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.

  • Calls ObtainToken to get the access and refresh tokens. 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. For this walkthrough, these 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.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
<?php
  session_start();
?>
<link rel="stylesheet" href="public/style.css" type="text/css">
<?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 an 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);
}

// Handle the response.
try {
    // Verify the state to protect against cross-site request forgery.
    if ($_SESSION["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()); 
}

?>

If you need more assistance, contact Developer Support or ask for help in the Developer Forums.