Single sign on

Last updated: 2026-03-27

Imagine a world where one set of credentials gives you access to multiple applications. That is the convenience Single Sign-On (SSO) brings. It simplifies user experience, reduces password fatigue, and enhances security.

📘
  • What makes OAuth OpenID Connect special? OAuth OpenID Connect is the engine that powers SSO. It is an authentication standard built on OAuth 2.0. Unlike SAML, which uses XML, OAuth OpenID Connect uses JSON. This makes it lightweight and perfect for the web. It verifies user identity and gathers basic profile information in a secure and efficient manner.
  • Why are SSO and OAuth OpenID Connect the perfect pair? When you log into one application using SSO with OAuth OpenID Connect, you are authenticated across all connected applications. It is seamless, efficient, and the future of authentication.

Use cases

  • User login: Log in swiftly and securely with existing identity provider credentials.
  • Session tracker: Automatically manage session timeouts to enhance security and user experience.
  • User logout: Terminate a session.

User login

Authenticate swiftly and securely with a trusted identity provider. This provides a seamless login process without another set of credentials and uses the identity provider's authentication measures.

How it works

  1. User-browser interaction: Initiate authorisation. Redirect the user to the identity provider's page.
  2. Application-server interaction: Acquire access token. Request an access token after successful authorisation.
  3. Application-server interaction: Retrieve user information. Use the access token to fetch user information and decide to grant the user access.

1. Initiate authorisation

This step occurs in the user's browser.

  • Initiate authorisation: Redirect the user's browser to the identity provider's authorisation endpoint (/v2/authorize).
  • User login: The user enters their credentials and logs in on the identity provider's page.
  • Two-factor authentication (2FA): If enabled, the user completes the second factor (for example, entering a code sent to their mobile device).
  • Return to application: Post successful login and 2FA verification, the user's browser is redirected back to your application using the predefined redirect URL.

When integrating with the SSO application based on OpenID Connect, obtain explicit end-user consent before including Personally Identifiable Information (PII) such as name and preferred_username in the /sso/v2/userinfo response. This consent is integrated during the authorisation flow when scope=openid profile is requested. External applications should comply with this process to maintain user trust and data privacy.

Request parameters:

ParameterRequiredFormatComment
client_idYesANOAuth client ID, an attribute of an OAUTH_APP user on Smart Payments Platform.
redirect_uriYesANURL to redirect user after successful authorisation. Must be URL-encoded.
scopeYesANScope for accessing data. Use scope=openid for OpenID Connect, or scope=openid profile to request additional user profile information.
response_typeYesANType of OAuth2 workflow to execute. Use response_type=code for the authorisation code flow.
login_hintNoANOptional entity identifier to retrieve custom UI styles for the login prompt.
stateNoANOptional parameter to prevent CSRF. The same value sent by the redirect is returned to the client application.

Sample request:

curl -G https://sandbox-card.peachpayments.com/sso/v2/authorize \
 -d "client_id=8a8294185a03a29d015a04621dcd0351" \
 -d "redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" \
 -d "scope=openid" \
 -d "response_type=code" \
 -d "login_hint=8a8294174e735d0c014e78cf26461790" \
 -d "state=90377ea8-ad35-4ad2-9087-51cbce3f03a6"
public Dictionary<string, dynamic> Request() {
  Dictionary<string, dynamic> responseData;
  string data="client_id=8a8294185a03a29d015a04621dcd0351" +
    "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" +
    "&scope=openid" +
    "&response_type=code" +
    "&login_hint=8a8294174e735d0c014e78cf26461790" +
    "&state=90377ea8-ad35-4ad2-9087-51cbce3f03a6";
  string url = "https://sandbox-card.peachpayments.com/sso/v2/authorize?" + data;
  HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
  request.Method = "GET";
  using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
  {
      Stream dataStream = response.GetResponseStream();
      StreamReader reader = new StreamReader(dataStream);
      var s = new JavaScriptSerializer();
      responseData = s.Deserialize<Dictionary<string, dynamic>>(reader.ReadToEnd());
      reader.Close();
      dataStream.Close();
  }
  return responseData;
}

responseData = Request()["result"]["description"];
import groovy.json.JsonSlurper

public static String request() {
  def data = "client_id=8a8294185a03a29d015a04621dcd0351" +
  "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" +
  "&scope=openid" +
  "&response_type=code" +
  "&login_hint=8a8294174e735d0c014e78cf26461790" +
  "&state=90377ea8-ad35-4ad2-9087-51cbce3f03a6"
  def url = ("https://sandbox-card.peachpayments.com/sso/v2/authorize?" + data).toURL()
  def connection = url.openConnection()
  connection.setRequestMethod("GET")
  def json = new JsonSlurper().parseText(connection.inputStream.text)
  json
}
println request()
private String request() throws IOException {
  URL url = new URL("https://sandbox-card.peachpayments.com/sso/v2/authorize?client_id=8a8294185a03a29d015a04621dcd0351 +
&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on +
&scope=openid +
&response_type=code +
&login_hint=8a8294174e735d0c014e78cf26461790 +
&state=90377ea8-ad35-4ad2-9087-51cbce3f03a6");

  HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
  conn.setRequestMethod("GET");
  int responseCode = conn.getResponseCode();
  InputStream is;

  if (responseCode >= 400) is = conn.getErrorStream();
  else is = conn.getInputStream();

  return IOUtils.toString(is);
}
const https = require('https');
const querystring = require('querystring');

const request = async () => {
  var path='/sso/v2/authorize';
  path += '?client_id=8a8294185a03a29d015a04621dcd0351';
  path += '&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on';
  path += '&scope=openid';
  path += '&response_type=code';
  path += '&login_hint=8a8294174e735d0c014e78cf26461790';
  path += '&state=90377ea8-ad35-4ad2-9087-51cbce3f03a6';
  const options = {
    port: 443,
    host: 'sandbox-card.peachpayments.com',
    path: path,
    method: 'GET',
  };
  return new Promise((resolve, reject) => {
    const postRequest = https.request(options, function(res) {
      const buf = [];
      res.on('data', chunk => {
        buf.push(Buffer.from(chunk));
      });
      res.on('end', () => {
        const jsonString = Buffer.concat(buf).toString('utf8');
        try {
          resolve(JSON.parse(jsonString));
        } catch (error) {
          reject(error);
        }
      });
    });
    postRequest.on('error', reject);
    postRequest.end();
  });
};

request().then(console.log).catch(console.error);
function request() {
  $url = "https://sandbox-card.peachpayments.com/sso/v2/authorize";
  $url .= "?client_id=8a8294185a03a29d015a04621dcd0351";
  $url .= "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on";
  $url .= "&scope=openid";
  $url .= "&response_type=code";
  $url .= "&login_hint=8a8294174e735d0c014e78cf26461790";
  $url .= "&state=90377ea8-ad35-4ad2-9087-51cbce3f03a6";

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// this should be set to true in production
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $responseData = curl_exec($ch);
  if(curl_errno($ch)) {
    return curl_error($ch);
  }
  curl_close($ch);
  return $responseData;
}
$responseData = request();
try:
  from urllib.parse import urlencode
  from urllib.request import build_opener, Request, HTTPHandler
  from urllib.error import HTTPError, URLError
except ImportError:
  from urllib import urlencode
  from urllib2 import build_opener, Request, HTTPHandler, HTTPError, URLError
import json

def request():
  url = "https://sandbox-card.peachpayments.com/sso/v2/authorize"
  url += '?client_id=8a8294185a03a29d015a04621dcd0351'
  url += '&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on'
  url += '&scope=openid'
  url += '&response_type=code'
  url += '&login_hint=8a8294174e735d0c014e78cf26461790'
  url += '&state=90377ea8-ad35-4ad2-9087-51cbce3f03a6'
  try:
    opener = build_opener(HTTPHandler)
    request = Request(url, data=b'')
    request.get_method = lambda: 'GET'
    response = opener.open(request)
    return json.loads(response.read());
  except HTTPError as e:
    return json.loads(e.read());
  except URLError as e:
    return e.reason;

responseData = request();
print(responseData);
require 'net/https'
require 'uri'
require 'json'

def request()
  path = ("?client_id=8a8294185a03a29d015a04621dcd0351" +
    "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" +
    "&scope=openid" +
    "&response_type=code" +
    "&login_hint=8a8294174e735d0c014e78cf26461790" +
    "&state=90377ea8-ad35-4ad2-9087-51cbce3f03a6")
  uri = URI.parse('https://sandbox-card.peachpayments.com/sso/v2/authorize' + path)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  res = http.get(uri.request_uri)
  return JSON.parse(res.body)
end

puts request()
def initialPayment : String = {
  val url = "https://sandbox-card.peachpayments.com/sso/v2/authorize"
  url +="?client_id=8a8294185a03a29d015a04621dcd0351"
  url +="&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on"
  url +="&scope=openid"
  url +="&response_type=code"
  url +="&login_hint=8a8294174e735d0c014e78cf26461790"
  url +="&state=90377ea8-ad35-4ad2-9087-51cbce3f03a6"
  val conn = new URL(url).openConnection()

  conn match {
    case secureConn: HttpsURLConnection  => secureConn.setRequestMethod("GET")
    case _ => throw new ClassCastException
  }
  conn.connect()
  if (conn.getResponseCode() >= 400) {
    return IOUtils.toString(conn.getErrorStream())
  }
  else {
    return IOUtils.toString(conn.getInputStream())
  }
}
Public Function Request() As Dictionary(Of String, Object)
  Dim url As String = "https://sandbox-card.peachpayments.com/sso/v2/authorize" +
    "?client_id=8a8294185a03a29d015a04621dcd0351" +
    "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" +
    "&scope=openid" +
    "&response_type=code" +
    "&login_hint=8a8294174e735d0c014e78cf26461790" +
    "&state=90377ea8-ad35-4ad2-9087-51cbce3f03a6"

  Dim req As WebRequest = WebRequest.Create(url)
  req.Method = "GET"
  req.ContentType = "application/x-www-form-urlencoded"
  Dim res As WebResponse = req.GetResponse()
  Dim resStream = res.GetResponseStream()
  Dim reader As New StreamReader(resStream)
  Dim response As String = reader.ReadToEnd()
  reader.Close()
  resStream.Close()
  res.Close()
  Dim jss As New System.Web.Script.Serialization.JavaScriptSerializer()
  Dim dict As Dictionary(Of String, Object) = jss.Deserialize(Of Dictionary(Of String, Object))(response)

  Return dict
End Function

responseData = Request()("result")("description")

2. Acquire access token

This step is handled by your application's server.

Acquire access token: Make a request to the identity provider's token endpoint (/v2/token) and receive an access token.

Request header:

HeaderRequiredFormatComment
AuthorizationYesANFollows HTTP Basic authentication. Formatted as "Basic " + base64.encode(url_encode(client_id) + ":" + url_encode(client_secret)).
  • client_id: Unique OAuth contact identifier for your application, provided by the identity provider.
  • client_secret: Confidential key for your application, provided by the identity provider.

Request parameters:

ParameterRequiredFormatComment
codeYesANOne-time use code passed by authentication.
redirect_uriYesANRedirect URL from the first redirect.
scopeYesANToken scope. Use scope=openid for OpenID Connect, or scope=openid profile to request additional user profile information.
grant_typeYesANGrant type for the token request. Currently accepts authorization_code only.

Response parameters:

ParameterFormatComment
access_tokenAN256Key that permits an application to make further requests on behalf of a user.
refresh_tokenAN256Token used to obtain a new access token when the current access token expires.
scopeANDefines the scope of the access. Use scope=openid for OpenID Connect, or scope=openid profile for additional user profile information.
id_tokenAN256JSON Web Token (JWT) that contains claims about the authenticated user, such as identity and email. This token can be parsed to obtain user information directly.
token_typeANSpecifies the OAuth2 token type. Currently, it is Bearer.
expires_inNLifespan of the access token in seconds.

Sample request:

curl https://sandbox-card.peachpayments.com/sso/v2/token \
 -d "code=" \
 -d "redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" \
 -d "scope=openid" \
 -d "grant_type=authorization_code" \
 -H "Authorization: Basic OGE4Mjk0MTg1YTAzYTI5ZDAxNWEwNDYyMWRjZDAzNTE6Z2NrYWtLOGE="
public Dictionary<string, dynamic> Request() {
  Dictionary<string, dynamic> responseData;
  string url = "https://sandbox-card.peachpayments.com/sso/v2/token";
  string data = "code=" +
    "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" +
    "&scope=openid" +
    "&grant_type=authorization_code";
  string auth = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes("8a8294185a03a29d015a04621dcd0351:gckakK8a"));
  HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
  request.Method = "POST";
  request.Headers.Add("Authorization", auth);
  request.ContentType = "application/x-www-form-urlencoded";
  byte[] byteData = Encoding.UTF8.GetBytes(data);
  request.ContentLength = byteData.Length;
  using (Stream postStream = request.GetRequestStream())
  {
    postStream.Write(byteData, 0, byteData.Length);
  }
  using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
  {
    Stream dataStream = response.GetResponseStream();
    StreamReader reader = new StreamReader(dataStream);
    var s = new JavaScriptSerializer();
    responseData = s.Deserialize<Dictionary<string, dynamic>>(reader.ReadToEnd());
    reader.Close();
    dataStream.Close();
  }
  return responseData;
}

responseData = Request();
import groovy.json.JsonSlurper

public static String request() {
  def url = new URL("https://sandbox-card.peachpayments.com/sso/v2/token")
  def connection = url.openConnection()
  connection.setRequestMethod("POST")
  def auth = "Basic " + "8a8294185a03a29d015a04621dcd0351:gckakK8a".bytes.encodeBase64().toString()
  connection.setRequestProperty("Authorization", auth)
  connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
  def data = "code=" +
    "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" +
    "&scope=openid" +
    "&grant_type=authorization_code"
  connection.doOutput = true
  connection.outputStream << data
  def json = new JsonSlurper().parseText(connection.inputStream.text)
  json
}
println request()
private String request() throws IOException {
  URL url = new URL("https://sandbox-card.peachpayments.com/sso/v2/token");
  HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
  conn.setRequestMethod("POST");
  String auth = "Basic " + Base64.getEncoder().encodeToString(("8a8294185a03a29d015a04621dcd0351:gckakK8a").getBytes());
  conn.setRequestProperty("Authorization", auth);
  conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
  String data = "code=" +
    "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" +
    "&scope=openid" +
    "&grant_type=authorization_code";
  conn.setDoOutput(true);
  conn.getOutputStream().write(data.getBytes());
  int responseCode = conn.getResponseCode();
  InputStream is;
  if (responseCode >= 400) is = conn.getErrorStream();
  else is = conn.getInputStream();
  return IOUtils.toString(is);
}
const https = require('https');
const querystring = require('querystring');

const request = async () => {
  const data = querystring.stringify({
    code: '',
    redirect_uri: 'https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on',
    scope: 'openid',
    grant_type: 'authorization_code'
  });
  const auth = 'Basic ' + Buffer.from('8a8294185a03a29d015a04621dcd0351:gckakK8a').toString('base64');
  const options = {
    port: 443,
    host: 'sandbox-card.peachpayments.com',
    path: '/sso/v2/token',
    method: 'POST',
    headers: {
      'Authorization': auth,
      'Content-Type': 'application/x-www-form-urlencoded',
      'Content-Length': data.length
    }
  };
  return new Promise((resolve, reject) => {
    const postRequest = https.request(options, function(res) {
      const buf = [];
      res.on('data', chunk => {
        buf.push(Buffer.from(chunk));
      });
      res.on('end', () => {
        const jsonString = Buffer.concat(buf).toString('utf8');
        try {
          resolve(JSON.parse(jsonString));
        } catch (error) {
          reject(error);
        }
      });
    });
    postRequest.on('error', reject);
    postRequest.write(data);
    postRequest.end();
  });
};

request().then(console.log).catch(console.error);
function request() {
  $url = "https://sandbox-card.peachpayments.com/sso/v2/token";
  $data = "code=" .
    "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" .
    "&scope=openid" .
    "&grant_type=authorization_code";
  $auth = "Basic " . base64_encode("8a8294185a03a29d015a04621dcd0351:gckakK8a");

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: " . $auth));
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $responseData = curl_exec($ch);
  if(curl_errno($ch)) {
    return curl_error($ch);
  }
  curl_close($ch);
  return $responseData;
}
$responseData = request();
try:
  from urllib.parse import urlencode
  from urllib.request import build_opener, Request, HTTPHandler
  from urllib.error import HTTPError, URLError
  import base64
except ImportError:
  from urllib import urlencode
  from urllib2 import build_opener, Request, HTTPHandler, HTTPError, URLError
  import base64
import json

def request():
  url = "https://sandbox-card.peachpayments.com/sso/v2/token"
  data = urlencode({
    'code': '',
    'redirect_uri': 'https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on',
    'scope': 'openid',
    'grant_type': 'authorization_code'
  }).encode('utf-8')
  auth = "Basic " + base64.b64encode(b"8a8294185a03a29d015a04621dcd0351:gckakK8a").decode('utf-8')
  try:
    opener = build_opener(HTTPHandler)
    request = Request(url, data=data)
    request.add_header('Authorization', auth)
    request.add_header('Content-Type', 'application/x-www-form-urlencoded')
    response = opener.open(request)
    return json.loads(response.read());
  except HTTPError as e:
    return json.loads(e.read());
  except URLError as e:
    return e.reason;

responseData = request();
print(responseData);
require 'net/https'
require 'uri'
require 'json'
require 'base64'

def request()
  uri = URI.parse('https://sandbox-card.peachpayments.com/sso/v2/token')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  req = Net::HTTP::Post.new(uri.request_uri)
  data = "code=" +
    "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" +
    "&scope=openid" +
    "&grant_type=authorization_code"
  auth = "Basic " + Base64.strict_encode64("8a8294185a03a29d015a04621dcd0351:gckakK8a")
  req['Authorization'] = auth
  req['Content-Type'] = 'application/x-www-form-urlencoded'
  req.body = data
  res = http.request(req)
  return JSON.parse(res.body)
end

puts request()
def request : String = {
  val url = new URL("https://sandbox-card.peachpayments.com/sso/v2/token")
  val conn = url.openConnection().asInstanceOf[HttpsURLConnection]
  conn.setRequestMethod("POST")
  val auth = "Basic " + Base64.getEncoder.encodeToString(("8a8294185a03a29d015a04621dcd0351:gckakK8a").getBytes)
  conn.setRequestProperty("Authorization", auth)
  conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
  val data = "code=" +
    "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" +
    "&scope=openid" +
    "&grant_type=authorization_code"
  conn.setDoOutput(true)
  conn.getOutputStream.write(data.getBytes)
  if (conn.getResponseCode() >= 400) {
    return IOUtils.toString(conn.getErrorStream())
  }
  else {
    return IOUtils.toString(conn.getInputStream())
  }
}
Public Function Request() As Dictionary(Of String, Object)
  Dim url As String = "https://sandbox-card.peachpayments.com/sso/v2/token"
  Dim data As String = "code=" +
    "&redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on" +
    "&scope=openid" +
    "&grant_type=authorization_code"
  Dim auth As String = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes("8a8294185a03a29d015a04621dcd0351:gckakK8a"))

  Dim req As WebRequest = WebRequest.Create(url)
  req.Method = "POST"
  req.Headers.Add("Authorization", auth)
  req.ContentType = "application/x-www-form-urlencoded"
  Dim byteData As Byte() = Encoding.UTF8.GetBytes(data)
  req.ContentLength = byteData.Length
  Dim postStream As Stream = req.GetRequestStream()
  postStream.Write(byteData, 0, byteData.Length)
  postStream.Close()
  Dim res As WebResponse = req.GetResponse()
  Dim resStream = res.GetResponseStream()
  Dim reader As New StreamReader(resStream)
  Dim response As String = reader.ReadToEnd()
  reader.Close()
  resStream.Close()
  res.Close()
  Dim jss As New System.Web.Script.Serialization.JavaScriptSerializer()
  Dim dict As Dictionary(Of String, Object) = jss.Deserialize(Of Dictionary(Of String, Object))(response)

  Return dict
End Function

responseData = Request()

3. Retrieve user information

This step is also handled by your application's server.

  • Retrieve user information: Use the access token to query the identity provider's user information endpoint (/v2/userinfo).
  • User login confirmation: Based on the received information and your application's rules, decide whether to grant the user access.

Request header:

HeaderRequiredFormatComment
AuthorizationYesAN256Contains the bearer token for authorisation. It is formatted as "Bearer " + access_token.

Response parameters:

ParameterFormatComment
subAN32Unique key identifying the subject. Represents the contact identifier.
roleAN256User role. One of: Account Access, Accounting Global, Administrator, Analysis, Callcentre, Callcentre Restricted, Operator.
attached_toARRAYJSON array of objects, each representing an attachment level with: entityId, entityType, path, pathOfIds, and deprecated level.
nameAN35Contact name. Provided only when scope=openid profile.
preferred_usernameAN256Contact username (email address). Provided only when scope=openid profile.

Sample request:

curl -G https://sandbox-card.peachpayments.com/sso/v2/userinfo \
 -H "Authorization: Bearer <access-token>"
public Dictionary<string, dynamic> Request() {
  Dictionary<string, dynamic> responseData;
  string url = "https://sandbox-card.peachpayments.com/sso/v2/userinfo";
  HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
  request.Method = "GET";
  request.Headers.Add("Authorization", "Bearer <access-token>");
  using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
  {
    Stream dataStream = response.GetResponseStream();
    StreamReader reader = new StreamReader(dataStream);
    var s = new JavaScriptSerializer();
    responseData = s.Deserialize<Dictionary<string, dynamic>>(reader.ReadToEnd());
    reader.Close();
    dataStream.Close();
  }
  return responseData;
}

responseData = Request();
import groovy.json.JsonSlurper

public static String request() {
  def url = new URL("https://sandbox-card.peachpayments.com/sso/v2/userinfo")
  def connection = url.openConnection()
  connection.setRequestMethod("GET")
  connection.setRequestProperty("Authorization", "Bearer <access-token>")
  def json = new JsonSlurper().parseText(connection.inputStream.text)
  json
}
println request()
private String request() throws IOException {
  URL url = new URL("https://sandbox-card.peachpayments.com/sso/v2/userinfo");
  HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
  conn.setRequestMethod("GET");
  conn.setRequestProperty("Authorization", "Bearer <access-token>");
  int responseCode = conn.getResponseCode();
  InputStream is;
  if (responseCode >= 400) is = conn.getErrorStream();
  else is = conn.getInputStream();
  return IOUtils.toString(is);
}
const https = require('https');

const request = async () => {
  const options = {
    port: 443,
    host: 'sandbox-card.peachpayments.com',
    path: '/sso/v2/userinfo',
    method: 'GET',
    headers: {
      'Authorization': 'Bearer <access-token>'
    }
  };
  return new Promise((resolve, reject) => {
    const getRequest = https.request(options, function(res) {
      const buf = [];
      res.on('data', chunk => {
        buf.push(Buffer.from(chunk));
      });
      res.on('end', () => {
        const jsonString = Buffer.concat(buf).toString('utf8');
        try {
          resolve(JSON.parse(jsonString));
        } catch (error) {
          reject(error);
        }
      });
    });
    getRequest.on('error', reject);
    getRequest.end();
  });
};

request().then(console.log).catch(console.error);
function request() {
  $url = "https://sandbox-card.peachpayments.com/sso/v2/userinfo";

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
  curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer <access-token>"));
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $responseData = curl_exec($ch);
  if(curl_errno($ch)) {
    return curl_error($ch);
  }
  curl_close($ch);
  return $responseData;
}
$responseData = request();
try:
  from urllib.request import build_opener, Request, HTTPHandler
  from urllib.error import HTTPError, URLError
except ImportError:
  from urllib2 import build_opener, Request, HTTPHandler, HTTPError, URLError
import json

def request():
  url = "https://sandbox-card.peachpayments.com/sso/v2/userinfo"
  try:
    opener = build_opener(HTTPHandler)
    request = Request(url)
    request.add_header('Authorization', 'Bearer <access-token>')
    response = opener.open(request)
    return json.loads(response.read());
  except HTTPError as e:
    return json.loads(e.read());
  except URLError as e:
    return e.reason;

responseData = request();
print(responseData);
require 'net/https'
require 'uri'
require 'json'

def request()
  uri = URI.parse('https://sandbox-card.peachpayments.com/sso/v2/userinfo')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  req = Net::HTTP::Get.new(uri.request_uri)
  req['Authorization'] = 'Bearer <access-token>'
  res = http.request(req)
  return JSON.parse(res.body)
end

puts request()
def request : String = {
  val url = new URL("https://sandbox-card.peachpayments.com/sso/v2/userinfo")
  val conn = url.openConnection().asInstanceOf[HttpsURLConnection]
  conn.setRequestMethod("GET")
  conn.setRequestProperty("Authorization", "Bearer <access-token>")
  conn.connect()
  if (conn.getResponseCode() >= 400) {
    return IOUtils.toString(conn.getErrorStream())
  }
  else {
    return IOUtils.toString(conn.getInputStream())
  }
}
Public Function Request() As Dictionary(Of String, Object)
  Dim url As String = "https://sandbox-card.peachpayments.com/sso/v2/userinfo"

  Dim req As WebRequest = WebRequest.Create(url)
  req.Method = "GET"
  req.Headers.Add("Authorization", "Bearer <access-token>")
  Dim res As WebResponse = req.GetResponse()
  Dim resStream = res.GetResponseStream()
  Dim reader As New StreamReader(resStream)
  Dim response As String = reader.ReadToEnd()
  reader.Close()
  resStream.Close()
  res.Close()
  Dim jss As New System.Web.Script.Serialization.JavaScriptSerializer()
  Dim dict As Dictionary(Of String, Object) = jss.Deserialize(Of Dictionary(Of String, Object))(response)

  Return dict
End Function

responseData = Request()

Session tracker

Experience the power of real-time session tracking in Single Sign-On (SSO). The session tracker keeps you informed about the user's active status in the Authentication Manager and any logout actions from connected applications. Upon logout, your application receives an instant alert, enabling swift response. Post-action, your application is ready to initiate a new Login Workflow, ensuring a smooth transition for potential user re-login. Discover enhanced control and fluid user management with the session tracker in SSO.

The swift workflow is as follows:

  • User logs into your application via the Login Workflow.
  • User navigates to a different application, like the Smart Payments Platform.
  • User logs out, activating the Logout workflow on the visited application.
  • User accesses an internal page in your application. The Session Tracker JavaScript Snippet promptly alerts your application about the session change.
  • Your application swiftly terminates the local user session and readies a new Login Workflow.

How it works

  1. Responding to logout events: Listen to logout events.
  2. Verifying user login status (individual check): Perform individual checks to see if the user has remotely logged out.
  3. Verifying user login status (polling): Continually verifies at set intervals if the user has logged out.

1. Responding to logout events

Your application can receive notifications about changes in the user's remote session (on the Authentication Manager) by embedding a JavaScript Snippet on each page of your application. This allows your application to take action, such as terminating the local user session and initiating a new Login Workflow.

Please add the following JavaScript code to each page of your application that needs to respond to remote logout events:

Sample:

<script type="text/javascript">
(function(w, d, o, u, r, a, m)  {
  w[r] = w[r] ||
    function() {
      (w[r].q = w[r].q || []).push(arguments);
  };
  a = d.createElement(o),
  m = d.getElementsByTagName(o)[0];
  a.async = 1;
  a.src = u;
  m.parentNode.insertBefore(a, m);
})(window, document, 'script', 'https://sandbox-card.peachpayments.com/sso/sessionTracker/oasm.js', '_OASM');
 
//put your client id instead of {your_client_id}
_OASM('client_id', '{your_client_id}');
 
//callback for whenever the session status is different than expected
_OASM('on_change', function(){
  //remove user session locally
  //start a new Login Workflow
});
</script>

2. Verifying user login status (individual check)

After integrating the above script into your page, your application can perform individual checks to see if the user has remotely logged out. If the remote login status of the user is not as expected ('logged_in'), your application will be notified via the function defined by _OASM('on_change').

Sample:

_OASM('check', 'logged_in');

3. Verifying user login status (polling)

Your application can also set up a polling mechanism that continually verifies at set intervals if the user has logged out.

Sample:

// Set the interval (in milliseconds) at which your application should verify if the user has logged out.
_OASM('poll', {state:'logged_in', interval: 10000});

User logout

Terminate your session swiftly and securely.

How it works

  1. Terminate session: Redirect the user to the identity provider's page.

1. Terminate session

Redirect the user to the identity provider's page to initiate the authorisation process.

Sample request:

curl -G https://sandbox-card.peachpayments.com/sso/v2/logout \
 -d "post_logout_redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on"
public Dictionary<string, dynamic> Request() {
  Dictionary<string, dynamic> responseData;
  string data="post_logout_redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on";
  string url = "https://sandbox-card.peachpayments.com/sso/v2/logout?" + data;
  HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
  request.Method = "GET";
  using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
  {
      Stream dataStream = response.GetResponseStream();
      StreamReader reader = new StreamReader(dataStream);
      var s = new JavaScriptSerializer();
      responseData = s.Deserialize<Dictionary<string, dynamic>>(reader.ReadToEnd());
      reader.Close();
      dataStream.Close();
  }
  return responseData;
}

responseData = Request()["result"]["description"];
import groovy.json.JsonSlurper

public static String request() {
  def data = "post_logout_redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on"
  def url = ("https://sandbox-card.peachpayments.com/sso/v2/logout?" + data).toURL()
  def connection = url.openConnection()
  connection.setRequestMethod("GET")
  def json = new JsonSlurper().parseText(connection.inputStream.text)
  json
}
println request()
private String request() throws IOException {
  URL url = new URL("https://sandbox-card.peachpayments.com/sso/v2/logout?post_logout_redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on");

  HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
  conn.setRequestMethod("GET");
  int responseCode = conn.getResponseCode();
  InputStream is;

  if (responseCode >= 400) is = conn.getErrorStream();
  else is = conn.getInputStream();

  return IOUtils.toString(is);
}
const https = require('https');
const querystring = require('querystring');

const request = async () => {
  var path='/sso/v2/logout';
  path += '?post_logout_redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on';
  const options = {
    host: 'sandbox-card.peachpayments.com',
    port: 443,
    path: path,
    method: 'GET'
  };
  return new Promise((resolve, reject) => {
    const req = https.request(options, (res) => {
      let data = '';
      res.on('data', (chunk) => { data += chunk; });
      res.on('end', () => { resolve(data); });
    });
    req.on('error', (e) => { reject(e); });
    req.end();
  });
}

request().then(console.log).catch(console.error);
function request() {
  $data = "post_logout_redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on";
  $url = "https://sandbox-card.peachpayments.com/sso/v2/logout?" . $data;
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, array());
  $responseData = curl_exec($ch);
  curl_close($ch);
  return json_decode($responseData, true);
}
$responseData = request();
try:
  from urllib.parse import urlencode
  from urllib.request import urlopen
  data = urlencode({
    'post_logout_redirect_uri': 'https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on'
  }).encode('utf-8')
  request = urlopen('https://sandbox-card.peachpayments.com/sso/v2/logout?' + data.decode("utf-8"))
  responseData = request.read().decode("utf-8")
except Exception as e:
  responseData = str(e)
print(responseData);
require 'net/https'

def request
  data = "post_logout_redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on"
  uri = URI("https://sandbox-card.peachpayments.com/sso/v2/logout?" + data)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  request = Net::HTTP::Get.new(uri.request_uri)
  response = http.request(request)
  JSON.parse(response.body)
end
puts request()
def request : String = {
  val data = "post_logout_redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on"
  val url = new java.net.URL("https://sandbox-card.peachpayments.com/sso/v2/logout?" + data)
  val connection = url.openConnection().asInstanceOf[java.net.HttpURLConnection]
  connection.setRequestMethod("GET")
  val inputStream = connection.getInputStream
  val response = scala.io.Source.fromInputStream(inputStream).mkString
  inputStream.close
  response
}
println(request)
Public Function Request() As Dictionary(Of String, Object)
  Dim url As String = "https://sandbox-card.peachpayments.com/sso/v2/logout" +
    "?post_logout_redirect_uri=https://developer.peachpayments.com/docs/oppwa-guides-single-sign-on"
  Dim request As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
  request.Method = "GET"
  Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
  Dim dataStream As Stream = response.GetResponseStream()
  Dim reader As New StreamReader(dataStream)
  Dim responseFromServer As String = reader.ReadToEnd()
  reader.Close()
  dataStream.Close()
  response.Close()
  Dim s As New JavaScriptSerializer()
  Return s.Deserialize(Of Dictionary(Of String, Object))(responseFromServer)
End Function

responseData = Request()("result")("description")