Skip to main content

Authorization Overview - V2

Note

These are instructions for connecting to the APIs using V2 Authentication. For V1 API Clients, please see Authorization Overview (V1)

Introduction

Authentication allows your application to securely access merchant data via the APIs.

Merchants need to authorize your API client to access their data using the OAuth2 authorization code grant flow.

At a glance

The basic steps of the Authorization flow are:

  1. Authorization Request: Provide the user with an authorization URL. The user clicks on the link, logs in, and consents to access. A code is returned to the redirect URI.

  2. Token Exchange: Capture the code and use it to send a request to the /token endpoint. Store the access_token and refresh_token and their expiry times.

  3. Token Refresh: When the access token is close to expiring, send a request to the /token endpoint with the latest refresh_token. Store the new access_token and new refresh_token and their expiry times.

Token expiry times should be monitored and managed dynamically

info

This article provides a general overview of the authorization flow. For a step-by-step walkthrough, see our Authentication Tutorial.

For information on obtaining an API Client, see Accessing the APIs.

The Authorization Flow

Obtaining an access token using the OAuth2 authorization code grant flow consists of the following steps:

1. Authorization Request

An authorization request is made when a Lightspeed Restaurant POS user clicks on a URL provided by the integrator.

The Authorization URL

Below are the URLs that should be used during the authorization process.

  • The trial environment is used for development and testing of your application
  • The production environment is used to connect your app to live merchant accounts.
important note

API Clients are bound to the server they were issued for. This means that if you have a client for the trial environment, it will not work on the production environment. Likewise, if you have a production client, it will not work on the trial environment.

EnvironmentAuthorization URL
Trialhttps://auth.lsk-demo.app/realms/k-series/protocol/openid-connect/auth
Productionhttps://auth.lsk-prod.app/realms/k-series/protocol/openid-connect/auth

The following query parameters must be passed in the Authorization URL:

  • response_type (required) - Must be code for the authorization code grant.
  • client_id (required) - The unique identifier for the OAuth client.
  • scope (required) - The access scopes being requested, space delimited (URL encoded).
  • redirect_uri (required) - The URL that the user will be redirected to after authenticating and authorizing the integration.
  • state (optional) - A unique string supplied by the external client that is persisted throughout the process to track the request.

Example Authorization URL

To connect to a merchant account on production, copy the following URL and replace the query parameter values with your own client ID, redirect URI, and scope(s). A state parameter can also be included, if desired.

https://auth.lsk-prod.app/realms/k-series/protocol/openid-connect/auth?response_type=code&client_id=DocumentationDemo-5745-4d30-8f1a-bd64511a62ed&redirect_uri=https://localhost&scope=financial-api%20orders-api&state=abcd123-efgh456

  • This URL should be supplied to the Lightspeed merchant.
  • When the user clicks on this URL, they will be prompted to login to their Lightspeed account.
  • Upon successful login, the user must provide consent for the OAuth client to access their data:

Consent Page

2. Token Request

Once the user authorizes the application, a temporary authorization code is passed to your redirect URI as a query parameter. If the state parameter was supplied, it will also be included.

Example Redirect with Authorization Code:

https://your-redirect-uri/?session_state=26a01a6c-9603-4596-a48d-86bbcaa54ef8&iss=https%3A%2F%2Fauth.lsk-demo.app%2Frealms%2Fk-series&code=185a6985-b01a-4833-b289-fad154ea2039.26a01a6c-9603-4596-a48d-86bbcaa54ef8.0bb5b13a-f6a0-4da3-9915-f7633ded915f

The authorization code should be captured from the query parameter in the URL.

The code should then be exchanged for an access and refresh token pair by sending a POST request to the Token URL.

EnvironmentToken URL
Trialhttps://auth.lsk-demo.app/realms/k-series/protocol/openid-connect/token
Productionhttps://auth.lsk-prod.app/realms/k-series/protocol/openid-connect/token

The client ID and client secret must be base64 encoded and passed as the authorization header in the following format client_id:client_secret.

For example:

DocumentationDemo-5745-4d30-8f1a-bd64511a62ed:fake-client-secret

becomes:

RG9jdW1lbnRhdGlvbkRlbW8tNTc0NS00ZDMwLThmMWEtYmQ2NDUxMWE2MmVkOmZha2UtY2xpZW50LXNlY3JldA==

The following values must be passed in the request body as a form-data payload.

  • grant_type=authorization_code
  • code: the code returned to redirect URI.
  • redirect_uri: the redirect URI for the client.

Sample Request:

curl --location --request POST 'https://auth.lsk-demo.app/realms/k-series/protocol/openid-connect/token' \
--header 'Authorization: Basic RG9jdW1lbnRhdGlvbkRlbW8tNTc0NS00ZDMwLThmMWEtYmQ2NDUxMWE2MmVkOmZha2UtY2xpZW50LXNlY3JldA==' \
--form 'grant_type="authorization_code"' \
--form 'code="185a6985-b01a-4833-b289-fad154ea2039.26a01a6c-9603-4596-a48d-86bbcaa54ef8.0bb5b13a-f6a0-4da3-9915-f7633ded915f"' \ (replace with the code returned to redirect URI)
--form 'redirect_uri="https://localhost"' (replace with the redirect URI for the client)

Sample Response:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlZk51UFNodDNvUDVDNTM1X0tWYjVhX1B3aHJ6VmNSa25lbUY0ZFNTOTdNIn0.eyJleHAiOjE3NTMzOTEyMzAs...NvbSJ9.u85UrQxvE8tcJqOZIZRlXqtdtw6vTKevsbM3hj5Z_qhi7Z-2d-gr2DXNnNeobRikvaCRt3tPyQhjxBnlJA0mamW5hrAEV1-tEoRF6C59FuAOcVNnj3ZD7NN7_BHlBsAfRaUNU2q0nbnWxRTJItukRsiCOX6ogjBZjI3wF-6xdLdE4UVPMotuR4lcuPIyjJd6sVbg_OJvyGuHCibuDuGBMO7NhuRMQW9OSBT5FpAU_27p98RorB82EHG0tRWlCFvR_VKFvUbi6ESEqKrf97elnrve3pgvHNY8WkuQ8NF2rSsdMsu_-nCdG6w84K9m5RRY6ZFH2DMHQHlftA1Fzx9hGg",
"expires_in": 1500,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlMTM1NDA1OS0wYmFjLTQwYzUtOWVkZi1hODhmZjI1ZjVjZWEifQ.eyJleHAiOjE3NTMzOTE1MzAsImlhdCI6MT...Jhc2ljIHByb2ZpbGUifQ.gBHNDXCvDmksgTp5fsw5Mg1Wso91JgdG_0C6bIv6isc4HIRPGY8pfXW016QWBeutJG8Ea-PKucJqxj1I_GoOSw",
"token_type": "Bearer",
"not-before-policy": 0,
"session_state": "26a01a6c-9603-4596-a48d-86bbcaa54ef8",
"scope": "financial-api email profile"
}

3. Refreshing the Token

Refresh tokens can be exchanged for a new access and refresh token pair by sending a POST request to the /token endpoint. The client ID and client secret must be base64 encoded and passed as the authorization header in the following format client_id:client_secret.

The values must be passed in the request body as an x-www-form-encoded payload. The endpoint will return a new access token and a new refresh token.

Sample Request:

curl \
--header 'Authorization: Basic c29tZV9jbGllbnRfaWQ6c29tZV9jbGllbnRfc2VjcmV0MQ==' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=138fc571-68b0-426d-82d3-b6386421788c' \
--request POST 'https://auth.lsk-demo.app/realms/k-series/protocol/openid-connect/token'

Sample Response:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlZk51UFNodDNvUDVDNTM1X0tWYjVhX1B3aHJ6VmNSa25lbUY0ZFNTOTdNIn0.eyJleHAiOjE3NTMzOTEyMzAs...NvbSJ9.u85UrQxvE8tcJqOZIZRlXqtdtw6vTKevsbM3hj5Z_qhi7Z-2d-gr2DXNnNeobRikvaCRt3tPyQhjxBnlJA0mamW5hrAEV1-tEoRF6C59FuAOcVNnj3ZD7NN7_BHlBsAfRaUNU2q0nbnWxRTJItukRsiCOX6ogjBZjI3wF-6xdLdE4UVPMotuR4lcuPIyjJd6sVbg_OJvyGuHCibuDuGBMO7NhuRMQW9OSBT5FpAU_27p98RorB82EHG0tRWlCFvR_VKFvUbi6ESEqKrf97elnrve3pgvHNY8WkuQ8NF2rSsdMsu_-nCdG6w84K9m5RRY6ZFH2DMHQHlftA1Fzx9hGg",
"expires_in": 1500,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlMTM1NDA1OS0wYmFjLTQwYzUtOWVkZi1hODhmZjI1ZjVjZWEifQ.eyJleHAiOjE3NTMzOTE1MzAsImlhdCI6MT...Jhc2ljIHByb2ZpbGUifQ.gBHNDXCvDmksgTp5fsw5Mg1Wso91JgdG_0C6bIv6isc4HIRPGY8pfXW016QWBeutJG8Ea-PKucJqxj1I_GoOSw",
"token_type": "Bearer",
"not-before-policy": 0,
"session_state": "26a01a6c-9603-4596-a48d-86bbcaa54ef8",
"scope": "financial-api email profile"
}

Token Lifecycle Best Practices

Maintaining Access

  • Refresh the access_token before it expires, using the latest refresh_token.

  • Each refresh returns a new refresh_token. Always update your stored token.

  • Monitor refresh_token lifetime and ensure the access_token is refreshed before the refresh token expires.

Handling Expiry Times

  • Never hardcode expiry values as they may change due to security updates.

  • Always check the token response for expires_in (access token lifetime) and refresh_expires_in (refresh token lifetime)

  • Dynamically schedule refreshes based on these values.

Further Details