Skip to content


Target audience: Developers, Stakeholders


Please note: We do not recommend that you implement SSO using this system. This system will be obsolete in the future. Please implement Single Sign-On using Single Sign-On v2 (SSO2), read more here.


This section describes the Payway Javascript API for web clients.

The main purpose of the JS-API is to provide a simple way for web applications to integrate with Payway with backend-implementation.

The JS-API is a client library in javascript that lets you:

  • Initiate Payway login
  • Know if there is a session in Payway to achieve SSO
  • Get basic information about the session and the user
  • Validate user access server-side


When using the JS API you will be performing CORS requests. Hence the API-user must allow incoming requests from your domain.

To whitelist your domain(s) you simply need to configure them for said API-user. This is done in the PAP API-user configuration section.

The Origin header is set automatically during CORS requests by the browser.

Whitelist origin domain in PAP

Typical flow


  • User not logged in user arrives at your app
  • You do a Tulo.session call
  • Using the active flag the app concludes that the user is not logged in
  • The app presents the login button
  • The user clicks the login button and you Initiate the login
  • A Payway login is performed and a Payway session is established
  • The user's browser is returned to your redirect URI where you capture the state parameter
  • The user arrives at the page where he clicked the log in button
  • The app verifies if the user has access to the article in the backend

Script location

Environment Url



= jQuery 1.5.1 required for CORS requests


>= jQuery 2.2.*


Tested using jQuery 2.2.4


To use the JS-API you must initialize it on every page where you need to interact with the session. You do this with the Tulo.init method.


Parameter Type Values Required Explanation
Origin Header Required Origin header. This is set automatically during CORS requests by the browser
env String stage or prod Required
client_id String your client id Required
redirect_uri String your redirect uri Required
organisation String your Payway instance's id Required
fields Comma separated String products(current package and product-codes), first_name Optional this parameters let's you specify which data to be sent back

Example init:

* client_id, redirect_uri and organisation will be delivered by Adeprimo
Tulo.init('__client_id__', '__redirect_uri__', '__organisation__', {env:'prod', fields: 'first_name,products'});

The Session call

To interact with the session, use the Tulo.session method. This will make a call to Payway's backend and return data about the session.

Default values returned

Field Description
active Status of the session (true/false).
id Account id.
sid Session id.
contact_email E-mail of the account
display_name The full name of the account.


// if the user is logged in show the full name else show login
Tulo.session(function (data) {
    if (data && {
        alert('Hi ' + data.display_name);

The session data is returned in a JWT token and written to a cookie named T_ID on your application's domain. Since the browser sends the cookies to your server you may use the T_ID cookie to perform operations where you need to verify the validity of the data on the backend. You should not trust any of the data in the client as it has not been verified.

Initiate login

You may initiate a Payway login by calling the Tulo.login method. The method accepts one argument: The page where you would like to send the user after the login is done. This is usually the page that the user is on when he clicks the login in the first place.

On your redirect uri page, you should capture the state parameter and send the user there. You should also run Tulo.session to make sure that the JWT-cookie(T_ID) is refreshed before sending the user to the final page. This way your backend will be able to use the fresh T_ID cookie.

Example code redirect uri page

Tulo.init('__client_id__', '__redirect_uri__', '__organisation__',
        {env:'stage', fields: 'alias,contact_email,organisation,products,customer_number,first_name,last_name,mobile_number'});
Tulo.session(function(data) {
    if ( {
        // redirect to the page in the state
        window.location = getParameterByName('state');

Using JS-API for SSO

By performing the Session call on every page you may know if the user has a Payway-session or not. This can be used to implement SSO functionality without backend integration.


// if the user is logged in show the full name else show login
Tulo.session(function (data) {
    if (data && {
        //the user has a session, you should considered it logged in
    } else {
        //no active session was recognized by Payway, you should considered the user as NOT logged in
        //.eg. show login button

Single sign out

Similarly to perform a single sign out you may make the Tulo.logout(return_page). This will redirect the user to Payway's backend where the session is destroyed. This means that all other applications using the JS-API will get a non-active response in their Tulo.session calls. After the session is destroyed the user is returned to the return page you specified.

Verifying the validity of the data on the backend

When you need to know that the data is correct and has not been tampered with e.g. checking if the user has read access to an article, you should verify the data on the backend. You verify the data using the signature field and your client id and client secret. When the signature has been validated you should also verify that the CLAIMS of the session are correct. JWT is used to represent the claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed or MACed using JSON Web Signature (JWS) and/or encrypted using JSON Web Encryption (JWE).


Field Description
iat (Issued At) The time of issuing the JWT.
nbf (Not Before) The time before the JWT should not be approved.
exp (Expiration Time) The time after the JWT should not be approved.
iss (Issuer) The entity which has created the JWT: "Tulo".
aud(Audience) The entity which is the intended recipient of the JWT. Set to your REDIRECT_URI.
prn (Principal) The subject of this JWT. Email-address of the current session.

Ruby example:

require 'jwt'
require 'json'

client = {
      :client_id => '52753620400e063f79000001',
      :secret => '94b3edb3f5931123489729613b6f5f07e0ff2c109c62627fe594de289b3a6d73',
      :redirect_uri => 'http://localhost:9292/forward',
      :organisation_id => 'org'
cookie = request.cookie('T_ID')
payload = JSON.parse(cookie)
now =

    signature = payload['signature']
    data = JWT.decode(signature, client[:secret])
    if data['nbf'] && now > data['nbf'] && now <= data['exp'] && data['iss'] == 'Tulo' && data['session']['active'] && data['aud'] == client[:redirect_uri]
        puts "Validated OK!"
        puts "Prodceeding to validate article access using #{data.inspect}"
    rescue JWT::DecodeError => e
        puts 'JWT is invalid, abort!'
        puts e

If you have not validated the data you cannot trust it.

Session data example on valid session:

  "active": true,
  "sid": "9CfygGMZLpL7ygXArR0ucJ-oelEQlJXq_r6_JEgtTOCPwDSZQEmiNm3fST_6Vxs6jYd5YzmvQ6HiXDfdwBjNboxplMtHNGC9yNsWTYbJyKY=,f5JkF_mYkAdZrmJom4jVGA==",
  "id": "554e2b9201c6a33e4c000036",
  "contact_email": "",
  "display_name": "Magnus Rosenquist",
  "organisation": "adeprimo",
  "products": ["adeprimo_digital"],
  "first_name": "Magnus",
  "last_name": "Rosenquist",
  "mobile_number": "0767715817"

Example when Payway could not identify session:

  "iat": 1352797577,
  "session": {
    "active": false
  "signature": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjEzNTI3OTc1NzcsInNlc3Npb24iOnsiYWN0aXZlIjpmYWxzZX19.skL5OB5s695-oFH8B9YdXL-UtKdTCXPZu7kB7u5esZM"

If there is no support for cross-domain cookies on the JSONP call as is the case with the Safari Intelligent tracking prevention, the solution does not work. The same would happen if the user has disabled cross-domain cookies.



As of Safari 11, Safari now defaults to blocking third-party cookies. More details about the Safari Intelligent tracking prevention change can be found at the webkit website. This section describes how to implement the ITP workaround on your websites that use Payway JS-API.

ITP Versions

Affected browser

  • Safari 11
  • Safari 12+

What is the problem?

For users browsing with Safari 11 or later are now affected by the new cookie partition rules, the call to /session at from your sites will not be able to send cookies.

Therefore Payway cannot identify the user and will, therefore, respond with session response where the user seems to be logged out (active==false) even though the user is still logged into Payway.

When running on Safari 11 or a later version that implements some version of ITP, the JS-API cannot rely on cookies, we propose a token solution as a fallback.

How does the fallback work?

  • When the user comes to the integrating site and presses login (Tulo.login), the user is redirected to to login.
  • When the user is redirected back to the redirect uri (landing page) on the integrating site, a "js_api_token" is returned as a query parameter.
    • You should capture this token by running the fallback-script.
  • On each "Tulo.init" you will supply the "js_api_token" using the fallback-script.
    • This way the token will be sent with each call to /session. The user is then identified using the "js_api_token" when no cookie is available.
  • The token is only available for a browser session.
    • When the user closes the browser and opens it again, it will seem to the implementing application as the user is not logged in (active==false in T_ID cookie).
    • The user is still logged in Payway (if he/she has selected "remember me").
    • When the user clicks login (Tulo.login) he/she will be redirected to and returned to your "redirect_uri" with a new "js_api_token" without having to enter any credentials.

You should let the user press the login button himself.


In stage, use instead.

Capture js_api_token on redirect uri (landing page)

<script src=""></script>
Safari11Fallback.setFallbackToken(); // capture js_api_token from query string and store it in a cookie T_SFT on your domain. Only do this on the redirect uri (landing page)
Tulo.init(...., js_api_token: Safari11Fallback.getFallbackToken()}); //you must init the Tulo script to use the js_api_token when calling /session

On other pages using Tulo.session

<script src=""></script>
Tulo.init(...., js_api_token: Safari11Fallback.getFallbackToken()}); //on all pages where you use Tulo.session you must init the Tulo script with the js_api_token