NAV Navbar
Logo
Java .Net

Overview

Introduction

SAASPASS provides two-factor authentication authentication for developers to integrate into their apps and websites. By eliminating usernames and passwords, SAASPASS enhances convenience and strengthens security. SAASPASS uses an HTTP API to provide multi-factor authentication for any web, mobile web or mobile application. With HTTP calls, SAASPASS provides a simple and secure interface for developers to integrate.

Explore SAASPASS security with our simulator and sample (Java and .NET) applications. See how the integration can be customized to meet the needs of any application.

The SAASPASS Widgets Page allows developers to create an iFrame embeddable widget customizable for any application. Depending on how you want to use SAASPASS, the iFrame can populate an OTP login field, Instant login/Instant registration barcode, Proximity bluetooth, or any combination of the three.

SAASPASS Services

SAASPASS HTTP API, contains various services to perform application integration and account management functionality.

There are 2 scopes of services: application-scope (called for a specific application) and company-scope (called regardless of application, but for the company).

Application Integration Services

Application Integration Services are about user’s login/registration process with SAASPASS for specific application, so they have application-scope.

These services are:

Service definitions can be found on Application Integration Services section. Each request to these services needs to be authenticated properly. For authentication details, check Authentication section.

Account Management Services

Account Management Services are about managing your accounts remotely, without using the Admin Portal on SAASPASS. Depends on its functionality, a service might have ‘application-scope’ or company-scope.

Account Management Services are:

Service definitions can be found on Account Management Services section. Each request to these services needs to be authenticated properly. For authentication details, check the Authentication section.

Authentication

Token Generation

Introduction

Generate Application-Scope Token

public static string GetApplicationToken()
{
    string urlForToken = "https://www.saaspass.com/sd/rest/applications/" + apiKey + "/tokens?password=" + apiPassword;
    return GetToken(urlForToken);
}

public static string GetToken(string url)
{
    try
    {
        WebRequest request = WebRequest.Create(url);
        WebResponse response = request.GetResponse();
        StreamReader reader = new StreamReader(response.GetResponseStream());
        string tokenJsonString = reader.ReadToEnd();
        if (tokenJsonString != null)
        {
            JToken tokenJtoken = JObject.Parse(tokenJsonString);
            return (string)tokenJtoken.SelectToken("token");
        }
        else
        {
            return null;
        }
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    ErrMessage = reader.ReadToEnd();
                }
            }
        }
        return null;
    }
}
import org.springframework.web.client.RestTemplate;

class TokenGeneration {

    private static final String API_URL = "https://www.saaspass.com/sd/rest";

    public String getAppToken() {
        String url = "%s/applications/%s/tokens?password=%s";
        url = String.format(url, API_URL, APP_API_KEY, APP_PASSWORD);
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.getForObject(url, TokenResponse.class).token;
    }

    private class TokenResponse {
        private String token;
        public String getToken() { return token; }
    }

Generate Company-Scope Token

public static string GetCompanyToken()
{
    string urlForCompanyToken = "https://www.saaspass.com/sd/rest/" + companyKey + "/tokens?companysecret=" + companySecret;
    return GetToken(urlForCompanyToken);
}
    public String getCompanyToken() {
        String url = "%s/%s/tokens?companysecret=%s";
        url = String.format(url, API_URL, COMPANY_KEY, COMPANY_SECRET);
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.getForObject(url, TokenResponse.class).token;
    }
}

To make a request to the SAASPASS HTTP API you need to authenticate it first. The authentication process works by obtaining a proper token first and then providing this token within your actual request. Later, you can use this token for all requests to our API till it is expired. Once it is expired, you need to obtain a new token.

There are two types of tokens in our API: company-scope and application-scope. If the service you are calling has company-scope, you need to provide a token of type company-scope. If the service you are calling has application-scope, you need to provide a token of type application-scope. (These scopes are explained here in the OVERVIEW)

Note: You cannot use a company-scope token to authenticate the call/request to an application-scope service or vice versa.

Ip Filtering

Generate Application-scope Token

IMPORTANT NOTICE: Your API application key and password are important and very sensitive/private data. Please be very careful on how you handle them and who can see them. We recommend that only administrators and developers see these data.

To view your application’s API key and password, go to the Developers Page in the SAASPASS Admin Portal, and you will find it on the left side (API KEY & PASSWORD).

Application-scope Token

Service Name: Generate Token (application-scope)
URL: [GET] /applications/{application_api_key}/tokens
Description: Generates application-scope token to be used while calling application-specific services. (Find list of these services: OVERVIEW)
Scope: Your Application
Parameters: application_key as URL parameter:

Your application is represented with application_key as a parameter in the URL.
Password required
An Application password that you can see on the API KEY & PASSWORD section on the left menu of the developer site in the SAASPASS Admin Portal.
Example Request: https://www.saaspass.com/sd/rest/applications/00de4v5ocd9v338w/tokens?password=yourpassword
Where here the API KEY is ‘00de4v5ocd9v338w’ andthe password is ‘yourpassword’.
Response: If the provided credentials are correct you will get a JSON structure containing the token value. The returned token is valid for a limited time. Once the token expires, you need to re-authenticate. The JSON structure will look like so:
json{"token":"HJKSDHADUIOEJLDHKJHSDKLJHSDUIQOUWEY"}
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Token Validity:

Generate Company-scope Token

To view your company credentials, go to the Corporate Settings page in the SAASPASS Admin Portal.

Company-Scope Token

Service Name: Generate Token (company-scope)
URL: [GET] /{company_key}/tokens
Description: Generates company-scope token to be used while calling/requesting company-scope services. (Find list of these services: OVERVIEW)
Scope: Your Application
Parameters: company_key as URL parameter:

Your company is represented with company_key as a parameter in the URL. Find your key on your admin portal under Corporate Settings>Company Credentials.
Password required

An Application password that you can see on the API KEY & PASSWORD section on the left menu of the developer site in the SAASPASS Admin Portal.
Example Request: https://www.saaspass.com/sd/rest/u45z33dfm0xff129ko/tokens?companysecret=09jdu277dsxff1290zz9021ffx0mfd21z54
Where here the API KEY is ‘00de4v5ocd9v338w’ andthe password is ‘yourpassword’.
Response: Response: If the provided credentials are correct you will get a JSON structure containing the token value. The returned token is valid for limited time. Once the token expires, you need to re-authenticate. The JSON structure will look like so:

{
"token":"HJKSDHADUIOEJLDHKJHSDKLJHSDUIQOUWEY"
}

If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Token Validity:

Company Credentials

Company credentials are used for authenticating your company requests to SAASPASS HTTP API.

SAASPASS HTTP API provides a group of services which help you to manage your company accounts automatically. You can add, verify and delete a user account by calling SAASPASS API. Your requests will be proceed only if the call provides valid company credentials (company key and company secret).

Company Key

Unique identification value for your company in SAASPASS. This key is randomly generated when company credentials are first time generated by the admin.

It is used within the request calls to SAASPASS HTTP API for any of the company-scope services.

Company Secret

Value requested in the company-scope token generation. It can be regenerated any time. See Token Request section for more details.

Company IP Filtering

Even each request is authenticated via token that based on your company credentials, for more security, it is recommended to define IP Filtering on your company to ensure SAASPASS accepts requests from your servers only.

If you have IP Filtering, the client that you are calling services from must have matched IP address. Otherwise you will receive INVALID_IP error. For more detail about error, see RESPONSES & ERROR HANDLING

Edit Company IP Filtering by clicking on COMPANY CREDENTIALS button.

Company Credentials

Application Credentials

Application credentials are used for authenticating your application requests to SAASPASS HTTP API.

SAASPASS HTTP API provides a group of services which you integrate with your application. Your users will be authenticated to log in or register in to your application. Your requests will be proceed only if the call provides valid application credentials (application key and/or application secret).

Application Key

Unique identification value for your application in SAASPASS. This key is randomly generated when application is added to your company.

It is used within the request calls to SAASPASS HTTP API for any of the application-scope services.

Application Password

Value requested in the application-scope token generation. It can be regenerated any time. See Token Request section for more details.

Application Credentials

App Integration Services

One-Time Password

OTP Check Request

public static bool OTPCheck(string username, string otp, string apptoken)
{
    string urlForOtp = "https://www.saaspass.com/sd/rest/applications/" + apiKey + "/otpchecks?username=" + username + "&otp=" + otp + "&token=" + apptoken;
    return CheckResponse(urlForOtp);

}

public static bool CheckResponse(string url)
{
    try
    {
        WebRequest webRequest = WebRequest.Create(url);
        if (webRequest.GetResponse() != null)
        {
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.GetResponseStream() != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string jsonString = reader.ReadToEnd();
                    if (jsonString != null && !jsonString.Equals(""))
                    {
                        JToken tokenJtoken = JObject.Parse(jsonString);
                        ErrMessage = tokenJtoken.SelectToken("resultMessage") != null ? (string)tokenJtoken.SelectToken("resultMessage") : "";
                        ErrMessage += tokenJtoken.SelectToken("warning") != null ? " - " + (string)tokenJtoken.SelectToken("warning") : "";
                    }
                }
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    if (httpResponse.StatusCode.ToString()=="429")
                    {
                        ErrMessage = " X-Rate-Limit-Limit " + httpResponse.Headers["X-Rate-Limit-Limit"];
                        ErrMessage += " ### X-Rate-Limit-Remaining " + httpResponse.Headers["X-Rate-Limit-Remaining"];
                        ErrMessage += " ### X-Rate-Limit-Resets " + httpResponse.Headers["X-Rate-Limit-Resets"];
                    }
                    else
                        ErrMessage += reader.ReadToEnd();
                }
            }
        }
        return false;
    }
}
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

class OneTimePassword {

    private static final String API_URL = "https://www.saaspass.com/sd/rest";

    public boolean otpCheck(String username, String otp) {
        String url = "%s/applications/%s/otpchecks?username=%s&otp=%s&token=%s";
        url = String.format(url, API_URL, APP_API_KEY, username, otp, getAppToken());
        ResponseEntity<?> r = call(url, OtpCheckResponse.class);
        return r.getStatusCode() == OK;
    }

    private <T> ResponseEntity<?> call(String url, Class<T> responseType) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new ResponseErrorHandler());

        try {
            return ResponseEntity.ok(restTemplate.getForObject(url, responseType));
        } catch (ApiException e) {
            return ResponseEntity.status(e.getStatusCode()).body(e.getErrorResponse());
        }
    }

    private class OtpCheckResponse {
    }
}

Introduction

OTP Check services offers integration to log in by manual entry of user credentials.

SAASPASS mobile application offline generates dynamic one-time passwords. There is no need for an internet connection in order to generate a one-time password. This allows the user to log in to the application when the mobile application is offline so unavailable to use other online SAASPASS Services.

One-Time Password (Manual Login)

One-time password login service can be integrated in different ways:

To check One-time Password, application should proceed with a GET request to SAASPASS HTTP API.

OTP check request

Service Name: OTP Check
URL: [GET] /applications/{application_API_key}/otpchecks
Description: Checks if OTP is valid for the given username.
Scope: Your Application
Parameters: username: required

Username of account which trying to log in.
otp: required

The One-Time Password value to be checked.
token: required

Obtained token to call a service. This token should be application-scope.
Token Requirement: It requires application-scope token. Read Authentication section for more info
Example Request: https://www.saaspass.com/sd/rest/applications/00de4v5ocd9v338w/otpchecks?username=john@myemail.com&otp=568214&token=HDFAIOANASDCJBKLHUFUIQWEJKUHSASD
Response: If the call to this resource is successful you will get a 200 (OK) HTTP response.
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Working with static passwords (SAASPASS as a 2nd factor)

If SAASPASS will work as a 2nd factor together with static password; we highly recommend to check user static credentials (username + password) before calling the SAASPASS HTTP API as the easiest integration way.

In case the application will check static credentials after SAASPASS validation; you have to select “Static Password for user account is required” from “Application Settings”.

By checking this option, SAASPASS is aware that application has to check static password after OTP check API call. On mobile app, under user account details page, user finds an input where to store his static password. In this way, application is able to integrate other online services like Scan Barcode or Proximity. For example, user will be able to scan the barcode and SAASPASS will send the static password within the login response without the need of user typing it.

One-Time Password Settings

A manual login form for an application can be reached by anyone. This means anyone may send a random login request with random values for username and passwords.

SAASPASS may be called and username may not be found within the user accounts assinged to that application from the SAASPASS administration portal.

Administrator decides how SAASPASS should respond to such requests. SAASPASS can directly block the login request or return a detailed error to the application; which will handle the login request by itself. This setting is offered depending on the username type. From ‘Application Settings’ decide what to do for:

For SECURITY reasons, SAASPASS always recommends (and offer by default) to reject any login request if the account is not active on SAASPASS and assigned to the application.

Scan Barcode

Scan Barcode Login (Instant Login)

///This block of code should be in Example.aspx, which page in the barcode.
protected void Page_Load(object sender, EventArgs e)
{
    try
    {
        Session["appToken"] = GetApplicationToken();
        if (Session["appToken"] != null && !Session["appToken"].Equals(""))
        {
            string session = HttpContext.Current.Session.SessionID;
            barcodeImageGrid.ImageUrl = GetBarcodeImage(Session["appToken"].ToString(), session,"IL");
            ClientAdapter.Instance.Join(session);
            Session["session"] = session;
       }
        else
        {
            Response.Write("Session Expired!");
        }
    }
    catch (Exception){}
}       

///This block of code should be in InstantExample.aspx, which page's url is Instant Post URL .
protected void Page_Load(object sender, EventArgs e)
{
    Message message = new Message();
    message.reqSession = Request.Headers["session"];
    message.reqTracker = Request.Headers["tracker"];
    message.reqUsername = Request.Headers["username"];

    if (!TrackerIdValidation(message.reqUsername, message.reqTracker, GetApplicationToken()))
        return;
    else
    {
        if (!string.IsNullOrWhiteSpace(message.reqSession) && !string.IsNullOrEmpty(message.reqTracker) && !string.IsNullOrEmpty(message.reqUsername))
        {
            Session["username"] = message.reqUsername;
            ClientAdapter.Instance.SendMessage(message);
        }
    }
}

public static string GetBarcodeImage(string apptoken, string session, string type)
{
    string urlForBarcode = domain + "/rest/applications/" + apiKey + "/barcodes?type=" + type + "&session=" + session + "&token=" + apptoken;

    try
    {
        WebRequest reqForBarcode = WebRequest.Create(urlForBarcode);
        WebResponse resForBarcode = reqForBarcode.GetResponse();
        StreamReader readBarcode = new StreamReader(resForBarcode.GetResponseStream());
        string barcodeJsonString = readBarcode.ReadToEnd();

        if (!barcodeJsonString.Equals(""))
        {
            JToken barcodeJtoken = JObject.Parse(barcodeJsonString);
            if (barcodeJtoken.SelectToken("bluetoothcode") != null)
                return "saaspass://bluepass?" + (string)barcodeJtoken.SelectToken("bluetoothcode");
            else
                return "data:image/png;base64," + (string)barcodeJtoken.SelectToken("barcodeimage");
        }
        else
            return null;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    ErrMessage = reader.ReadToEnd();
                }
            }
        }
        return null;
    }
}
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

class ScanBarcode {

    private static final String API_URL = "https://www.saaspass.com/sd/rest";

    public String barcodes(BarcodeType type, String session) {

        String url = "%s/applications/%s/barcodes?type=%s&session=%s&token=%s";
        url = String.format(url, API_URL, APP_API_KEY, type, session, getAppToken());

        ResponseEntity<?> r = call(url, BarcodeResponse.class);
        if (r.getStatusCode() != OK) return null;

        BarcodeResponse body = (BarcodeResponse) r.getBody();

        if (body.barcodeimage != null)
            return "data:image/png;base64," + body.barcodeimage;

        if (body.bluetoothcode != null)
            return "saaspass://bluepass?" + body.bluetoothcode;

        return null;
    }

    private <T> ResponseEntity<?> call(String url, Class<T> responseType) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new ResponseErrorHandler());

        try {
            return ResponseEntity.ok(restTemplate.getForObject(url, responseType));
        } catch (ApiException e) {
            return ResponseEntity.status(e.getStatusCode()).body(e.getErrorResponse());
        }
    }

    private enum BarcodeType {
        IL, IR, BT, ILIR, ILBT
    }

    private class BarcodeResponse {
        private String barcodeimage;
        private String bluetoothcode;

        public String getBarcodeimage() { return barcodeimage; }
        public String getBluetoothcode() { return bluetoothcode; }
    }
}
class InstantLogin {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    @RequestMapping(value = "/instant-login", method = POST)
    private ResponseEntity<?> instantLogin(@RequestHeader String username,
                                           @RequestHeader String session,
                                           @RequestHeader String tracker) {

        HttpStatus status = Tracker.validate(tracker, username);
        if (status != OK) return ResponseEntity.status(status).body(null);

        simpMessagingTemplate.convertAndSend("/topic/instant-login/" + session, username);
        return ResponseEntity.ok(null);
    }
}


// Include this Javascript Code in your login page
const socket = new SockJS(`${BACKEND_URL}/socket`);
const stompClient = Stomp.over(socket);

stompClient.connect({}, () => {
    stompClient.subscribe(
        `/topic/instant-login/${getSession()}`,
        () => window.location = '/'
    );
});

Introduction

Scan Barcode allows users to login to services and websites that produce a SAASPASS readable encrypted barcode. By scanning a barcode, users login instantly to services or devices that support this format.

Scan Barcode is a simple and quick way to authenticate users to websites, applications and desktop computers with multi-factor authentication.

Scan Barcode Login (Instant Login)

The general process of Scan Barcode is as follows:

  1. Select Scan Barcode as a service from Application Settings. Submit the Instant Login Post URL.

  2. On the login page of your application , embed a session-specific barcode generated by SAASPASS and identified with a session ID. To get this barcode send a REST HTTP GET request to applications/{application_API_key}/barcodes. Check Get barcode request for full details.

  3. When a user scans your application’s Instant Login barcode with its SAASPASS Mobile App, a login request is sent from the user device to SAASPASS servers for authentication. If the authentication is successful SAASPASS will send a POST request to the Login Post URL with session, username and tracker data in the request headers.

  4. In order to be sure that the POST request received on the Instant Login Post URL is really from SAASPASS, check the received tracker value. For that, send a request to applications/{application_API_key}/trackers/{received_tracker_value}. Check TrackerID Validation section for full details.

  5. Once the tracker has been validated, with session and username data, your application should make a reverse AJAX call to the user with the session and log him in. Check Reverse Ajax Implementation section for full details.

Get Barcode Request

Service Name: Scan Barcode Login
URL: [GET] /applications/{application_API_key}/barcodes
Description: It generates a barcode for your application to be displayed on the login page.
Scope: Your Application
Parameters: session: required

The Session ID for the session that should be logged in.
token: required

The pre-obtained token to call a service. This token should be application-scope and not expired.
type: required

Specifies the type of barcode to get and use. In order to generate an Instant Login barcode, set this parameter to “IL”.
Token Requirement: It requires an application-scope token. Read the Authentication section for more info
Example Request: https://www.saaspass.com/sd/rest/applications/00de4v5ocd9v338w/barcodes?session=09EEEF760B0F77B6DB7F7124DC712704\&token=HDFAIOANASDCJBKLHUFUIQWEJKUHSASD&type=IL
Response: If the call to this resource is successful you will get a 200 (OK) HTTP response and a JSON structure containing an encoded barcode. Response that SAASPASS returns has detailed information within below JSON structure:
{
"barcodeimage":"iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAIAAAD2HxkiAAAJLklEQVR42u3dUXKcyhJFUc1/0n5TuHrkzirBOp8dihYUucrBAds//0TkaH4sgQiEIhCKCIQiEIoIhCIQigiEIhCKCIQiEIoIhCIQigiEIhCKCIQiEIoIhCIQigiEIhCKCIQiEIoIhCIQigiEIhCKyOUIf4I8OYbi86lzr9d2an2eHM9vv/+3P/NfftepO…."
}
barcodeimage (String): Contains Base64 encoded value of the .png barcode..
To integrate the barcode with your application, add an image HTML tag with the “barcodeimage” value like this:

<img id="barcodeImageGrid" src="data:image/png;base64,iVBORw0KGgoAAAANSUhE...."/>
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Proximity

Proximity Login (Instant Login)

string bluetoothImageBT =GetBarcodeImage(Session["appToken"].ToString(), HttpContext.Current.Session.SessionID, "BT");
ltlProximity.Text = "<iframe name='we' id='12'  frameborder='no' scrolling='auto' height='200px' width='100%' src='"+ bluetoothImage + "' style='left:0; background-color:#B8B8B8;visibility: hidden;'></iframe>";

string bluetoothImageILBT =GetBarcodeImage(Session["appToken"].ToString(), HttpContext.Current.Session.SessionID, "ILBT");
ltlProximity2.Text = "<iframe name='we' id='13'  frameborder='no' scrolling='auto' height='200px' width='100%' src='"+ bluetoothImage + "' style='left:0; background-color:#B8B8B8;visibility: hidden;'></iframe>";


public static string GetBarcodeImage(string apptoken, string session, string type)
{
    string urlForBarcode = domain + "/rest/applications/" + apiKey + "/barcodes?type=" + type + "&session=" + session + "&token=" + apptoken;

    try
    {
        WebRequest reqForBarcode = WebRequest.Create(urlForBarcode);
        WebResponse resForBarcode = reqForBarcode.GetResponse();
        StreamReader readBarcode = new StreamReader(resForBarcode.GetResponseStream());
        string barcodeJsonString = readBarcode.ReadToEnd();

        if (!barcodeJsonString.Equals(""))
        {
            JToken barcodeJtoken = JObject.Parse(barcodeJsonString);
            if (barcodeJtoken.SelectToken("bluetoothcode") != null)
                return "saaspass://bluepass?" + (string)barcodeJtoken.SelectToken("bluetoothcode");
            else
                return "data:image/png;base64," + (string)barcodeJtoken.SelectToken("barcodeimage");
        }
        else
            return null;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    ErrMessage = reader.ReadToEnd();
                }
            }
        }
        return null;
    }
}
String bluetoothcode = ScanBarcode.barcodes(BarcodeType.BT, session);



<!-- include this snippet in your login page -->
<iframe src="${bluetoothcode}"
        style="display: none;">
</iframe>

Introduction

Proximity combines multi-factor authentication with location-based iBeacon Bluetooth Low Energy (BLE) technology to let users authenticate via their mobile device’s proximity to their computer. Proximity authenticates users to websites and applications with this service integrated.

Users can pair, unpair and manage devices with their SAASPASS mobile app. Proximity-based authentication uses the Bluetooth low-energy format so SAASPASS Proximity is extremely battery efficient.

Proximity works on Bluetooth-capable devices. Most Apple devices (iPhone 4S onwards) and the latest Apple Macs support BLE and the list of supported platforms is increasing every day. Most of the latest Android devices support Proximty as well.

Proximity Login (Instant Login)

The general process of Proximity is as follows:

  1. Select Proximity as a service from Application Settings. Submit the Instant Login Post URL.

  2. On the login page of your application , embed a session-specific Proximity code generated by SAASPASS and identified with a session ID. To get this code send a REST HTTP GET request to applications/{application_API_key}/barcodes. Check Get barcode request for full details.

  3. When a user’s device bluetooth senses the proximity code embedded in your application, a login request is sent from the user device to SAASPASS servers for authentication. If the authentication is successful SAASPASS will send a POST request to the Login Post URL with session, username and tracker data in the request headers.

  4. In order to be sure that the POST request received on the Instant Login Post URL is really from SAASPASS, check the received tracker value. For that, send a request to applications/{application_API_key}/trackers/{received_tracker_value}. Check TrackerID Validation section for full details.

  5. Once the tracker has been validated, with s ession and username data, your application should make a reverse AJAX call to the user with the session and log him in. Check Reverse Ajax Implementation section for full details.

Get Barcode Request

Service Name: Proximity Login
URL: [GET] /applications/{application_API_key}/barcodes
Description: It generates a Proximity code for your application to be displayed on the login page.
Scope: Your Application
Parameters: session: required

The Session ID for the session that should be logged in.
token: required

The pre-obtained token to call a service. This token should be application-scope and not expired.
type: required

Specifies the type of barcode to get and use. In order to generate a Proximity Login code, set this parameter to “BL”.
Token Requirement: This API call allows for the possibility of a combined response (for Scan Barcode login and Proximity bluetooth code at once). To get this response, set this parameter to “ILBT”.
It requires an application-scope token. Read the Authentication section for more info
Example Request: Proximity bluetooth barcode ‘BT’:
https://www.saaspass.com/sd/rest/applications/00de4v5ocd9v338w/barcodes?session=09EEEF760B0F77B6DB7F7124DC712704&token=HDFAIOANASDCJBKLHUFUIQWEJKUHSASD&type=BT
Instant Login + Proximity Bluetooth barcode ‘ILBT’
https://www.saaspass.com/sd/rest/applications/00de4v5ocd9v338w/barcodes?session=09EEEF760B0F77B6DB7F7124DC712704&token=HDFAIOANASDCJBKLHUFUIQWEJKUHSASD&type=ILBT
Response: If the call to this resource is successful you will get a 200 (OK) HTTP response and a JSON structure containing a Proximity barcode. Response that SAASPASS returns has detailed information within below JSON structure:
{
"bluetoothcode":"iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAIAAAD2HxkiAAAJyUlEQVR42u3aUbLbOAxFQe9/05ktzCvhgLTc+HQlCkWimdIlP/+UUkfrYwqUglApCJVSECoFoVIKQqUgVEpBqBSESikIlYJQKQWhUhAqpSBUCkKlFI..."
}
bluetoothcode (String): Contains Base64 encoded value of the Proximity barcode..
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Push Login

Push Login

        public static bool PushLogin(string username, string session, string appToken)
        {
            string urlForPushLogin = domain + "/rest/applications/" + apiKey + "/push?username=" + username + "&session=" +session+ "&token=" + appToken;
            return CheckResponse(urlForPushLogin);
        }


        protected void pushLoginButton_Click(object sender, EventArgs e)
        {
            if (!username.Text.Equals(""))
            {
                try
                {
                    if (Session["appToken"] == null)
                    {
                        Session["appToken"] = AppMethods.GetApplicationToken();
                    }
                    else
                    {
                        string session = HttpContext.Current.Session.SessionID;
                        bool pushLogin = AppMethods.PushLogin(username.Text, Session["session"].ToString(), Session["appToken"].ToString());
                        if (pushLogin)
                        {
                            Session["username"] = username.Text.ToString();
                            ClientAdapter.Instance.Join(session);
                            Session["session"] = session;
                        }
                    }

                }
                catch (Exception) { }
            }
        }


public static bool CheckResponse(string url)
{
    try
    {
        WebRequest webRequest = WebRequest.Create(url);
        if (webRequest.GetResponse() != null)
        {
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.GetResponseStream() != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string jsonString = reader.ReadToEnd();
                    if (jsonString != null && !jsonString.Equals(""))
                    {
                        JToken tokenJtoken = JObject.Parse(jsonString);
                        ErrMessage = tokenJtoken.SelectToken("resultMessage") != null ? (string)tokenJtoken.SelectToken("resultMessage") : "";
                        ErrMessage += tokenJtoken.SelectToken("warning") != null ? " - " + (string)tokenJtoken.SelectToken("warning") : "";
                    }
                }
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    if (httpResponse.StatusCode.ToString()=="429")
                    {
                        ErrMessage = " X-Rate-Limit-Limit " + httpResponse.Headers["X-Rate-Limit-Limit"];
                        ErrMessage += " ### X-Rate-Limit-Remaining " + httpResponse.Headers["X-Rate-Limit-Remaining"];
                        ErrMessage += " ### X-Rate-Limit-Resets " + httpResponse.Headers["X-Rate-Limit-Resets"];
                    }
                    else
                        ErrMessage += reader.ReadToEnd();
                }
            }
        }
        return false;
    }
}
```csharp




##Single Sign-On

> Get SSO Login Request

```csharp
string tracker = Request.QueryString["tracker"];
string username = Request.QueryString["account"];
if (username!=null && !username.Equals(""))
{
    if (TrackerIdValidation(username, tracker, GetApplicationToken()))
    {
        Session["username"] = username;
        Response.Redirect("/Default.aspx");

    }
    else
    {
        Response.Write("tracker data or account information cannot get.");
    }
}


public static bool TrackerIdValidation(string username, string trackers, string appToken)
{
    string urlForTracker = "https://www.saaspass.com/sd/rest/applications/" + apiKey + "/trackers/" + trackers + "?token=" + appToken + "&account=" + username;
    return CheckResponse(urlForTracker);
}


public static bool CheckResponse(string url)
{
    try
    {
        WebRequest webRequest = WebRequest.Create(url);
        if (webRequest.GetResponse() != null)
        {
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.GetResponseStream() != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string jsonString = reader.ReadToEnd();
                    if (jsonString != null && !jsonString.Equals(""))
                    {
                        JToken tokenJtoken = JObject.Parse(jsonString);
                        ErrMessage = tokenJtoken.SelectToken("resultMessage") != null ? (string)tokenJtoken.SelectToken("resultMessage") : "";
                        ErrMessage += tokenJtoken.SelectToken("warning") != null ? " - " + (string)tokenJtoken.SelectToken("warning") : "";
                    }
                }
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    if (httpResponse.StatusCode.ToString()=="429")
                    {
                        ErrMessage = " X-Rate-Limit-Limit " + httpResponse.Headers["X-Rate-Limit-Limit"];
                        ErrMessage += " ### X-Rate-Limit-Remaining " + httpResponse.Headers["X-Rate-Limit-Remaining"];
                        ErrMessage += " ### X-Rate-Limit-Resets " + httpResponse.Headers["X-Rate-Limit-Resets"];
                    }
                    else
                        ErrMessage += reader.ReadToEnd();
                }
            }
        }
        return false;
    }
}
class SingleSignOn {

    @RequestMapping(value = "/sso", method = GET)
    private ResponseEntity<?> sso(TrackerRequest request) {

        HttpStatus status = Tracker.validate(request.getTracker(), request.getAccount());

        if (status != OK) {
            // ... redirect to error page ...
            return r;
        }

        // ... sign the `account` in, and redirect ...

        return ResponseEntity.ok();
    }

    private class TrackerRequest {
        private String tracker;
        private String account;
        // ... getters and setters ...
    }
}

Introduction

SAASPASS Single Sign-on (SSO) provides two-factor authentication for multiple applications at once. SAASPASS Single Sign-on internally stores and translates multiple authentication processes on behalf of a user for a simple and seamless login.

SAASPASS Single Sign-On is great for users because it minimizes the need to memorize passwords and eliminates time spent entering login credentials. SAASPASS SSO is more secure because passwords are less likely to be written down or shared and is always activated with the easiest to use two-step verification.

SAASPASS Single Sign-On is great for enterprises because it reduces costly password reset and IT help desk time waste related to authentication. Since employees typically use multiple applications at work, SSO creates a one-step launch for many computers. You can also log in from the mobile device and tablets using SSO with two-factor authentication using On Device Login.

Single Sign-On (SSO)

The general process of Single Sign-on is as follows:

  1. Select Single Sign-on as a service from Application Settings. Submit the SSO GET URL.

  2. SSO GET URL receives a GET request from SAASPASS containing a tracker value and a user account for a user logging in to your application. At this point, the user has already been successfully authenticated by SAASPASS.

  3. In order to be sure that the GET request received is really from SAASPASS, check the received tracker value. For that, send a request to applications/{application_API_key}/trackers/{received_tracker_value}. Check TrackerID Validation section for full details.

Get SSO Login request

Service Name: Single Sign-on
Description: It sends a login request to application for a user account already authenticated by SAASPASS.
Scope: Your Application
Parameters: account:
User account for which the tracker was issued.
tracker:
Obtained token to call a service. This token should be application-scope.
Token Requirement: This API call allows for the possibility of a combined response (for Scan Barcode login and Proximity bluetooth code at once). To get this response, set this parameter to “ILBT”.
It requires an application-scope token. Read the Authentication section for more info
Example GET Request: https://myapplication.com/sso?tracker=b4097ed670833a83&account=john.s@myapplication.com

Instant Registration

Instant Registration


///This block of code should be in ExampleRegistration.aspx, which page in the barcode.
protected void getRegistrationBarcode_Click(object sender, EventArgs e)
{
    if (Session["appToken"] != null && !Session["appToken"].Equals(""))
    {
        registerBarcode.ImageUrl = null;
        string session = HttpContext.Current.Session.SessionID;
        registerBarcode.ImageUrl = AppMethods.GetBarcodeImage(Session["appToken"].ToString(), session, "IR");
        ClientAdapter.Instance.Join(session);
        Session["sessionIR"] = session;
    }
    else
    {
        Response.Write("Session Expired!");
        Response.Redirect("/Login.aspx");
    }
}

protected void getRegistrationAndLoginBarcode_Click(object sender, EventArgs e)
{
    if (Session["appToken"] != null && !Session["appToken"].Equals(""))
    {
        registerBarcode.ImageUrl = null;
        string session = HttpContext.Current.Session.SessionID;
        registerBarcode.ImageUrl = AppMethods.GetBarcodeImage(Session["appToken"].ToString(), session, "ILIR");
        ClientAdapter.Instance.Join(session);
        Session["sessionIR"] = session;
    }
    else
    {
        Response.Write("Session Expired!");
        Response.Redirect("/Login.aspx");
    }
}


///This block of code should be in ExampleInstantRegistration.aspx, which page's url is Instant Post URL .
public static string GetBarcodeImage(string apptoken, string session, string type)
{
    string urlForBarcode = domain + "/rest/applications/" + apiKey + "/barcodes?type=" + type + "&session=" + session + "&token=" + apptoken;

    try
    {
        WebRequest reqForBarcode = WebRequest.Create(urlForBarcode);
        WebResponse resForBarcode = reqForBarcode.GetResponse();
        StreamReader readBarcode = new StreamReader(resForBarcode.GetResponseStream());
        string barcodeJsonString = readBarcode.ReadToEnd();

        if (!barcodeJsonString.Equals(""))
        {
            JToken barcodeJtoken = JObject.Parse(barcodeJsonString);
            if (barcodeJtoken.SelectToken("bluetoothcode") != null)
                return "saaspass://bluepass?" + (string)barcodeJtoken.SelectToken("bluetoothcode");
            else
                return "data:image/png;base64," + (string)barcodeJtoken.SelectToken("barcodeimage");
        }
        else
            return null;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    ErrMessage = reader.ReadToEnd();
                }
            }
        }
        return null;
    }
}
class InstantRegister {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    @RequestMapping(value = "/instant-registration", method = POST)
    private ResponseEntity<?> instantRegister(@RequestHeader String username,
                                              @RequestHeader String session,
                                              @RequestHeader String tracker) {

        HttpStatus status = Tracker.validate(tracker, username);
        if (status != OK) return ResponseEntity.status(status).body(null);

        simpMessagingTemplate.convertAndSend("/topic/instant-registration/" + session, username);
        return ResponseEntity.ok(null);
    }
}

// Include this Javascript Code in your login page
const socket = new SockJS(`${BACKEND_URL}/socket`);
const stompClient = Stomp.over(socket);

stompClient.connect({}, () => {
    stompClient.subscribe(
        `/topic/instant-registration/${getSession()}`,
        () => window.location = '/'
    );
});

The general process of Instant Registration is as follows:

  1. Select Instant Registration as a service from Application Settings. Submit the Instant Registration Post URL.

  2. On the login page of your application , embed a session-specific barcode generated by SAASPASS and identified with a session ID. To get this barcode send a REST HTTP GET request to applications/{application_API_key}/barcodes. Check [Get barcode request] for full details.

  3. When a user scans your application’s Instant Registration barcode with its SAASPASS Mobile App, a login request is sent from the user device to SAASPASS servers for authentication and registration. If they are successful SAASPASS will send a POST request to the Instant Registration Post URL with session, username and tracker data in the request headers.

  4. In order to be sure that the POST request received on the Instant Registration Post URL is really from SAASPASS, check the received tracker value. For that, send a request to applications/{application_API_key}/trackers/{received_tracker_value}. Check TrackerID Validation section for full details.

  5. Once the tracker has been validated, with session and username data, your application should make a reverse AJAX call to the user with the session, register and log him in (if your app log the users in right after registration). Check Reverse Ajax Implementation section for full details.

Get barcode request

Service Name: Instant Registration
URL: [GET] /applications/{application_API_key}/barcodes
Description: It generates a barcode for your application to be displayed on the registration/login page.
Scope: Your Application
Parameters: session: required

The Session ID for the session that should be logged in.
token: required

Obtained token to call a service. This token should be application-scope.
type: required

Specifies the type of barcode to get and use. In order to generate an Instant Registration barcode, set this parameter to “IR”.

This API call allows for the possibility of a combined response (for Scan Barcode login and Instant Registration at once). To get this response, set this paramter to “ILIR”.
Token Requirement: It requires application-scope token. Read Authentication section for more info
Example Request: Instant Regisatration barcode ‘IR’:

https://www.saaspass.com/sd/rest/applications/00de4v5ocd9v338w/barcodes?session=09EEEF760B0F77B6DB7F7124DC712704&token=HDFAIOANASDCJBKLHUFUIQWEJKUHSASD&type=IR

Instant Login + Instant Registration barcode ‘ILIR’

https://www.saaspass.com/sd/rest/applications/00de4v5ocd9v338w/barcodes?session=09EEEF760B0F77B6DB7F7124DC712704&token=HDFAIOANASDCJBKLHUFUIQWEJKUHSASD&type=ILIR
Response: If the call to this resource is successful you will get a 200 (OK) HTTP response and a JSON structure containing a Registration barcode. Response that SAASPASS returns has detailed information within below JSON structure:
{
"barcodeimage":"L+RyFZroMiQim/Sc+C4XuHU8DnabV1XxYhK1INk+4TEaPoJfFXiz54bspo5cu2iespNNRK4c9owkmwL5abgt3gI6w6d651NGMLmuXoduQia/OvARrPgXPONC77Vc/vWdannUybJtPzEfl1z3C8mYVpARm4JX..."
}

barcodeimage (String): Contains Base64 encoded value of the Registration barcode.
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Mobile Application Login

Introduction

Mobile application login integration allows users of your native mobile apps to log in using SAASPASS mobile app as a user authentication key.

With this service integrated, the user is able to log in to the custom mobile application by 2 different ways:

If custom application works with a backend server, current manual login form can still be kept and remain fully functional.

Requirements and Recommendations

For a correct functionality of this service you will need:

Mobile Application Login Flow

1) Custom Mobile App Calls SAASPASS Mobile App.

On click ‘Login with SAASPASS’, Custom mobile app calls SAASPASS mobile application:

2) SAASPASS Mobile App Finds User Account.

SAASPASS recognizes the application requesting for login. It checks if that SAASPASS ID has user accounts for that application:

SAASPASS mobile app sends login credentials to be checked by SAASPASS Server.

NOTE: If user logs in by ‘Open in Mobile App’; login process starts from this point.

3) SAASPASS Server Checks Credentials

If Login credentials are valid:

If Login credentials or any other parameter are not valid:

4) SAASPASS Mobile App Returns Response To Custom Mobile App

The same response got from SAASPASS Server is sent to Custom mobile app.

5) Custom Mobile App Handles Login Response

If ERROR is returned custom mobile app interface should inform the user.

If Username and TrackerID is returned:

Flow With Login Form

If the manual login form is kept together with the new SAASPASS mobile login integration; One-Time Password service must be integrated.

iOS SDK

Introduction

SAASPASS SDK allows to set up the communication between the custom mobile app and the SAASPASS mobile app.

This communication is part of the user authentication process. At the end point, the custom mobile app will receive the login response through the SDK.

Steps for Integration in iOS.

Terminology


iOS SDK

SAASPASS SDK VERSION: 1.0.0

SDK RELEASE DATE: 2015/12/06

Download iOS SDK Download iOS Sample App


Import SAASPASS SDK To Xcode Project

The SDK automatically loads its framework and resource dependencies.


‘Login with Saaspass’ - Integration

1) GET THE APPLICATION KEY


2) CONFIGURE THE .plist FOR YOUR PROJECT

Schema:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <array>
            <key> CFBundleURLSchemes</key>
            <string>saaspasssdk-appKey-urlSchemeSuffix</string>
        </array>
    </dict>
</array>

Parameters:

appKey required Application key given for your Custom application.
urlSchemeSuffix optional (Suffix) String that is appended to the base URL scheme used for SaasPass login.(Optional)



3) ADD API KEY AND SUFFIXES TO THE .plist

Example:

<key>CFBundleURLTypes</key>
<array>
<dict>
<array>
<key> CFBundleURLSchemes</key>
<string>saaspasssdk-123456789-testVersion</string>
</array>
</dict>
</array>




4) EXTRA CONFIGURATION FOR IOS9

In iOS 9 you have to whitelist any URL schemes your App wants to query in Info.plist under the LSApplicationQueriesSchemes key (an array of strings).

Add the following to your application’s .plist:

<key>LSApplicationQueriesSchemes</key>
<array>
<string>saaspass-auth</string>
</array>

5) CONNECT APPLICATION DELEGATE

To post process the results from SaasPass Login (or any action that requires switching over to the native SAASPASS app) you need to conenct your AppDelegate to the SPSDKManager.

In your AppDelegate.m add:

// AppDelegate.m
#import <SaasPassSDK/SaasPassSDK.h>

-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

return [[SPSDKManager sharedInstance] application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; 
}




6) ADD ‘LOGIN WITH SAASPASS’ BUTTON CODE

To add a SaasPass-branded login button to your app add the following code snippet to a view controller.

// Add this to the header file, e.g. in ViewController.h
#import <SaasPassSDK/SaasPassSDK.h>

// Add this delegate into your view controller
@interface ViewController : UIViewController <SPSDKLoginButtonDelegate>

// Add this to the header of your file, e.g. in ViewController.m
// after #import "ViewController.h"
// Add this to the body

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Add a SAASPASS-branded login button to your app 
SPSDKLoginButton *loginButton = [[SPSDKLoginButton alloc] init];
// Set delegate for SPSDKLoginButton 
loginButton.delegate = self;
// Optional: Place the button in the center of your view.
loginButton.center = self.view.center;
[self.view addSubview:loginButton];

}
@end

7) ADD ‘LOGIN WITH SAASPASS’ BUTTON FROM INTERFACE BUILDER

1) Add new UIButton in the Interface Builder and set its type as ‘Custom’. 2) In ‘Show the attributes inspector’, under ‘Button’ section, select ‘Custom’ as Type.

3) In ‘Show Identity Inspector’, under ‘Custom Class’ section, select ‘SPSDKLoginButton’ as Class.

4) In ‘Show the Connections Inspector’, set the delegate for the SPSDKLoginButton. (You can also set delegate programmatically after adding SPSDKLoginButton as IBOutlet to your ViewController)

8) HANDLE RECEIVED RESPONSE

Add this method for handling responses or some error in the SPSDKLoginButton delegate:

//Method for received results from login action

-(void) loginButton:(SPSDKLoginButton *)loginButton

didCompleteWithResult:(SPSDKLoginResult *)result withError:(NSError*)error

{
if (error) {
//Process error
} else if (result.isCanceled) {
//Cancelled
}else {
//Logged in
}
}

‘Open In Mobile App’ - Integration

Once your login is integrated with SAASPASS; your users have a second way to log in to the custom mobile application.

They can open SAASPASS mobile app and tap on the ‘Open in mobile app’ button displayed in the user account of your application:

Once SAASPASS checks the user credentials, the custom mobile app will get the information of the account to be logged in.


INTEGRATION

Make sure you have completed steps 1 to 5 on ‘Login With SAASPASS’ - Integration section. Later proceed with these extra steps

6) CONNECT APPLICATION DELEGATE AS SPSDKMANAGER DELEGATE

To handle ‘Open In Mobile App’ requests you need to set your AppDelegate as SPSDKManagerDelegate

// Add this delegate into your Application Delegate
@interface AppDelegate : UIResponder <UIApplicationDelegate, SPSDKManagerDelegate>
// Add this on your applicationDidFinishLaunchingWithOptions method
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Set delegate method for SPSDKManager
[SPSDKManager sharedInstance].delegate = self;
}

7) HANDLE RECEIVED LOGIN REQUESTS

Add this method for handling ‘Open In Mobile App’ requests in your AppDelegate (SPSDKManagerDelegate)

//Method for handling 'Open In Mobile App' requests
-(void) didLoginRequestReceivedWithResult:(SPSDKLoginResult *)result
withError:(NSError*)error
{
if (error) {
//Process error
} else {
//Log user in
}
}

Android SDK

Introduction

SAASPASS SDK allows to set up the communication between the custom mobile app and the SAASPASS mobile app.

This communication is part of the user authentication process. At the end point, the custom mobile app will receive the login response through the SDK.

Steps for Integration in Android.

Terminology


Android SDK

SAASPASS SDK VERSION: 1.0.0

SDK RELEASE DATE: 2015/12/06

Download Android SDK

Download Android Sample App


Android Studio Set Up

1) Take the downloaded package and place it in the libs folder.


2) In gradle.build file add the following code:

repositories{ 
    flatDir { 
        dirs 'libs' 
    } 
} 


3) Under dependencies add:

compile(name:'saaspassSDK', ext:'aar')


4) Sync your project and the SDK is ready to use.


‘Login with Saaspass’ - Integration

1) Get the application key


2) Open the androidmanifest.xml

<activity android:name="com.example.custom.MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="saaspasssdk-applicationKey" />
</intent-filter>
</activity>

If Activity is a LAUNCHER activity, add two intent filters instead:

<activity android:name="com.example.custom.MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="saaspasssdk-applicationKey" />
</intent-filter>
</activity>

Enter the Application Key got in step 1 instead of applicationKey

3) Create an activity

Define the ‘Login With SAASPASS’ button in the Layout:

<com.saaspass.widget.SaasPassLoginButton"
android:id="@+id/btnlogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"/>


Add imports:

import com.saaspass.controller.SaasPassInitializer; 
import com.saaspass.interfaces.SaasPassCallback; 
import com.saaspass.login.LoginResult; 
import com.saaspass.widget.SaasPassLoginButton;


In Activity class declare the widgets you defined in the activity’s layout as fields of this class:

private SaasPassLoginButton loginButton;


The SDK needs to be initialized. Define the instance in Activity class:

private SaasPassInitializer saasPassInitializer;

In onCreate() using findViewById initialize the widget:

saasPassInitializer = new SaasPassInitializer(this); 
loginButton = (SaasPassLoginButton) findViewById(R.id.btnlogin); 
loginButton.setOnClickListener(this); 

In onCreate() method after initializing SaasPassInitializer put the following code:

loginButton = (SaasPassLoginButton) findViewById(R.id.btnlogin);
loginButton.setOnClickListener(this);
saasPassInitializer.login(this, new SaasPassCallback <LoginResult>() {
@Override
public void onLoadFinishCallback(LoginResult result) {
username = result.getUsername();
trackerId = result.getTrackerId();
//after getting username and trackerId handle the login process 
}
@Override
public void onCancel() {
Toast.makeText(getApplicationContext(), "Action Canceled!",Toast.LENGTH_SHORT).show();
}
@Override
public void onError(String error) {
Toast.makeText(getApplicationContext(), error, Toast.LENGTH_SHORT).show();
}
});

In onClick() method for login button create and register callback like follow:

saasPassInitializer.initCallback(this, appKey);

‘Open In Mobile App’ - Integration

Once your login is integrated with SAASPASS; your users have a second way to log in to the custom mobile application.

They can open SAASPASS mobile app and tap on the ‘Open in mobile app’ button displayed in the user account of your application:




How To Get A Hashkey

On OS X :

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

On Windows :

keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64

For development purposes, you may use different hashkeys working on debugging mode. Add them under application settings ‘Hashkey’ separated by ‘;;’. If you create a new debug hashkey, submit the password field empty. Only enter the password for the release hashkey generation. Don’t forget to add the release hashkey on SAASPASS.

To get a Hashkey open Command Prompt(cmd) and execute the following cmd commands:

Account Management

Add Account

Add Account

public static bool AddAccount(string username, string grouplist, string accountowner, string companytoken)
{
    string urlForAddAcount = "https://www.saaspass.com/sd/rest/" + companyKey + "/addaccount?username=" + username + "&grouplist=" + grouplist + "&accountowner=" + accountowner + "&token=" + companytoken;
    return CheckResponse(urlForAddAcount);
}

public static bool CheckResponse(string url)
{
    try
    {
        WebRequest webRequest = WebRequest.Create(url);
        if (webRequest.GetResponse() != null)
        {
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.GetResponseStream() != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string jsonString = reader.ReadToEnd();
                    if (jsonString != null && !jsonString.Equals(""))
                    {
                        JToken tokenJtoken = JObject.Parse(jsonString);
                        ErrMessage = tokenJtoken.SelectToken("resultMessage") != null ? (string)tokenJtoken.SelectToken("resultMessage") : "";
                        ErrMessage += tokenJtoken.SelectToken("warning") != null ? " - " + (string)tokenJtoken.SelectToken("warning") : "";
                    }
                }
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    if (httpResponse.StatusCode.ToString()=="429")
                    {
                        ErrMessage = " X-Rate-Limit-Limit " + httpResponse.Headers["X-Rate-Limit-Limit"];
                        ErrMessage += " ### X-Rate-Limit-Remaining " + httpResponse.Headers["X-Rate-Limit-Remaining"];
                        ErrMessage += " ### X-Rate-Limit-Resets " + httpResponse.Headers["X-Rate-Limit-Resets"];
                    }
                    else
                        ErrMessage += reader.ReadToEnd();
                }
            }
        }
        return false;
    }
}
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class AddAccount {

    private static final String API_URL = "https://www.saaspass.com/sd/rest";

    public SpResponse addaccount(String username, String accountowner, List<String> groups) {
        String grouplist = String.join(",", groups);
        String url = "%s/%s/addaccount?username=%s&accountowner=%s&grouplist=%s&token=%s";
        url = String.format(url, API_URL, COMPANY_KEY, username, accountowner, grouplist, getCompanyToken());
        ResponseEntity<?> r = call(url, SpResponse.class);
        return r.getStatusCode() == OK ? (SpResponse) r.getBody() : null;
    }

    private <T> ResponseEntity<?> call(String url, Class<T> responseType) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new ResponseErrorHandler());

        try {
            return ResponseEntity.ok(restTemplate.getForObject(url, responseType));
        } catch (ApiException e) {
            return ResponseEntity.status(e.getStatusCode()).body(e.getErrorResponse());
        }
    }
}

public class SpResponse {

    private String resultMessage;
    private boolean isVerified;
    private boolean isPendingOnEmail;
    private boolean isAccountOwnerBlocked;
    private String warning;

    public String getResultMessage() { return resultMessage; }
    public boolean getIsVerified() { return isVerified; }
    public boolean getIsPendingOnEmail() { return isPendingOnEmail; }
    public boolean getIsAccountOwnerBlocked() { return isAccountOwnerBlocked; }
    public String getWarning() { return warning; }
}

Add Account Request

Service Name: Add Account
URL: [GET] /{company_key}/addaccount
Description: It adds new user account to your company.
Scope: Your Company
Parameters: company_key as URL variable:

Your company is represented with company_key in the URL. Find your key on your admin portal under Corporate Settings>Company Credentials.
token: required

The pre-obtained token to call a service. This token should be company-scope and not expired.
username: required

Username of account that you want to add. It can be a simple username, email or mobile number.
accountowner: optional

If you want to verify the new account you are adding, you can provide verification data with this parameter.

If you have direct information about the SAASPASS user that you want to verify the account for, provide his/her SAASPASS ID or his/her verified email or his/her verified Active Directory account or his/her verified phone number as ‘accountowner’.

If as ‘accountowner’, you provide an email that is not verified yet, SAASPASS will send a verification link to this email and when user verifies this link with her/his SAASPASS credentials, the account will be verified for that user. Not verified email can be provided only if ‘username’ refers to a simple username account or an Active Directory account (not email or phone number account)
grouplist: optional

If you want to add the new account to specific group(s) (any custom group or application dedicated group), you can provide the name of these groups within this parameter. Group names should be comma separated.

If you don’t provide any group in this parameter, a new account will be created but it will not be added to any specific group (just to ‘Everyone’).
Token Requirement: It requires company-scope token. Read the Authentication section for more info
Example Request: https://www.saaspass.com/sd/rest/u45aaaa1290z/addaccount?username=jane.doe\&grouplist=groupA%2CgroupB&accountowner=979538547\&token=6JCHH1CROH019TCSG0HSEPW7CXTLUV606A0E07EP5NXWF5D29RJL3MW3
Response: If the call to this resource is successful you will get a 200 (OK) HTTP response. Successful code means new account is created in your company. But it may not be successfully verified. Response that SAASPASS returns has detailed information within below JSON structure:
{
"resultMessage":"Successful","isVerified":true,"isPendingOnEmail":false,"isAccountOwnerBlocked":false,"warning":null
}

resultMessage (String): Contains message about result. It is “Successful” if operation is successful without any warning. It is “Successful with warning” if there is a warning message.

isVerified (Boolean): ‘true’ if added account is verified for a user also. ‘false’ if it is not verified yet.

isPendingOnEmail (Boolean): ‘true’ if account is not verified but it is pending on email verification.

isAccountOwnerBlocked (Boolean): ‘true’ if the owner of account is blocked from logging in to the applications since it is waiting your approval of recovery operation that user did. You can approve her/his recovery and unblock from admin portal.

warning (String): Contains warning message if there is a warning about added account.
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Details

Successful call will result in adding a new account to your company with given username.

Rate Limit

You can call this service 100 times in any 10 minutes. If you exceed the rate limit, response will result in “Too many requests”. For more on this topic see our RESPONSES & ERROR HANDLING

Verify Account

Verify Account

public static bool VerifyAccount(string username, bool isadaccount, string accountowner, string companytoken)
{
    string urlForVerifyAcount = "https://www.saaspass.com/sd/rest/" + companyKey + "/verifyaccount?username=" + username + "&isadaccount=" + isadaccount + "&accountowner=" + accountowner + "&token=" + companytoken;
    return CheckResponse(urlForVerifyAcount);
}

public static bool CheckResponse(string url)
{
    try
    {
        WebRequest webRequest = WebRequest.Create(url);
        if (webRequest.GetResponse() != null)
        {
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.GetResponseStream() != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string jsonString = reader.ReadToEnd();
                    if (jsonString != null && !jsonString.Equals(""))
                    {
                        JToken tokenJtoken = JObject.Parse(jsonString);
                        ErrMessage = tokenJtoken.SelectToken("resultMessage") != null ? (string)tokenJtoken.SelectToken("resultMessage") : "";
                        ErrMessage += tokenJtoken.SelectToken("warning") != null ? " - " + (string)tokenJtoken.SelectToken("warning") : "";
                    }
                }
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    if (httpResponse.StatusCode.ToString()=="429")
                    {
                        ErrMessage = " X-Rate-Limit-Limit " + httpResponse.Headers["X-Rate-Limit-Limit"];
                        ErrMessage += " ### X-Rate-Limit-Remaining " + httpResponse.Headers["X-Rate-Limit-Remaining"];
                        ErrMessage += " ### X-Rate-Limit-Resets " + httpResponse.Headers["X-Rate-Limit-Resets"];
                    }
                    else
                        ErrMessage += reader.ReadToEnd();
                }
            }
        }
        return false;
    }
}

import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class VerifyAccount {

    private static final String API_URL = "https://www.saaspass.com/sd/rest";

    public SpResponse verifyaccount(String username, String accountowner, boolean isadaccount) {
        String url = "%s/%s/verifyaccount?username=%s&accountowner=%s&isadaccount=%s&token=%s";
        url = String.format(url, API_URL, COMPANY_KEY, username, accountowner, isadaccount, getCompanyToken());
        ResponseEntity<?> r = call(url, SpResponse.class);
        return r.getStatusCode() == OK ? (SpResponse) r.getBody() : null;
    }

    private <T> ResponseEntity<?> call(String url, Class<T> responseType) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new ResponseErrorHandler());

        try {
            return ResponseEntity.ok(restTemplate.getForObject(url, responseType));
        } catch (ApiException e) {
            return ResponseEntity.status(e.getStatusCode()).body(e.getErrorResponse());
        }
    }
}

Verify Account Request

Service Name: Verify Account
URL: [GET] /{company_key}/verifyaccount
Description: Verifies existing account in your company.
Scope: Your Company
Parameters: company_key as URL variable:

Your company is represented with company_key in the URL. Find your key on your admin portal under Corporate Settings>Company Credentials.
token: required

The pre-obtained token to call a service. This token should be company-scope and not expired.
username: required

Username of account that you want to add. It can be a simple username, email or mobile number.
accountowner: required

If you want to verify the new account you are adding, you can provide verification data with this parameter.

If you have direct information about the SAASPASS user that you want to verify the account for, provide his/her SAASPASS ID or his/her verified email or his/her verified Active Directory account or his/her verified phone number as ‘accountowner’.

If as ‘accountowner’, you provide an email that is not verified yet, SAASPASS will send a verification link to this email and when user verifies this link with her/his SAASPASS credentials, the account will be verified for that user. Not verified email can be provided only if ‘username’ refers to a simple username account or an Active Directory account (not email or mobile number account)
isadaccount: optional

If the account you are trying to verify is an Active Directory account, this parameter must be ‘true’. Otherwise it is ‘false’ by default.
Token Requirement: It requires company-scope token. Read Authentication section for more info
Example Request: https://www.saaspass.com/sd/rest/u45aaaa1290z/verifyaccount?username=jane.doe@mydomain.com\&isadaccount=false\&accountowner=979538547&token=6JCHH1CROH019TCSG0HSEPW7CXTLUV606A0E07EP5NXWF5D29RJL3MW3
Response: If the call to this resource is successful you will get a 200 (OK) HTTP response. Successful code means the account you provided is verified in your company or it is pending on email verification. But it may not be successfully verified. Response that SAASPASS returns has detailed information within below JSON structure:
{
"resultMessage":"Successful","isVerified":true,"isPendingOnEmail":false,"isAccountOwnerBlocked":false,"warning":null
}

resultMessage (String): Contains message about result. It is “Successful” if operation is successful without any warning. It is “Successful with warning” if there is a warning message.

isVerified (Boolean): ‘true’ if added account is verified for a user also. ‘false’ if it is not verified yet.

isPendingOnEmail (Boolean): ‘true’ if account is not verified but it is pending on email verification.

isAccountOwnerBlocked (Boolean): ‘true’ if the owner of account is blocked from logging in to the applications since it is waiting your approval of recovery operation that user did. You can approve her/his recovery and unblock from admin portal.

warning (String): Contains warning message if there is a warning about added account.
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Details

Successful call will result in verifying existing account in your company or setting it as pending on email verification. If the account you provided was already pending on an email, but you provided a different email in the ‘accountowner’ parameter, existing verification email will be invalidated and account will be pending on new email.

Rate Limit

You can call this service 100 times in any 10 minutes. If you exceed the rate limit, response will result in “Too many requests”. For more on this topic see our RESPONSES & ERROR HANDLING

Remove Account

Remove Account

public static bool RemoveAccount(string username, string companyToken)
{
    string urlForRemoveAcount = "https://www.saaspass.com/sd/rest/" + companyKey + "/removeaccount?username=" + username + "&token=" + companyToken;
    return CheckResponse(urlForRemoveAcount);
}

public static bool CheckResponse(string url)
{
    try
    {
        WebRequest webRequest = WebRequest.Create(url);
        if (webRequest.GetResponse() != null)
        {
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.GetResponseStream() != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string jsonString = reader.ReadToEnd();
                    if (jsonString != null && !jsonString.Equals(""))
                    {
                        JToken tokenJtoken = JObject.Parse(jsonString);
                        ErrMessage = tokenJtoken.SelectToken("resultMessage") != null ? (string)tokenJtoken.SelectToken("resultMessage") : "";
                        ErrMessage += tokenJtoken.SelectToken("warning") != null ? " - " + (string)tokenJtoken.SelectToken("warning") : "";
                    }
                }
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    if (httpResponse.StatusCode.ToString()=="429")
                    {
                        ErrMessage = " X-Rate-Limit-Limit " + httpResponse.Headers["X-Rate-Limit-Limit"];
                        ErrMessage += " ### X-Rate-Limit-Remaining " + httpResponse.Headers["X-Rate-Limit-Remaining"];
                        ErrMessage += " ### X-Rate-Limit-Resets " + httpResponse.Headers["X-Rate-Limit-Resets"];
                    }
                    else
                        ErrMessage += reader.ReadToEnd();
                }
            }
        }
        return false;
    }
}
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class RemoveAccount {

    private static final String API_URL = "https://www.saaspass.com/sd/rest";

    public SpResponse removeaccount(String username) {
        String url = "%s/%s/removeaccount?username=%s&token=%s";
        url = String.format(url, API_URL, COMPANY_KEY, username, getCompanyToken());
        ResponseEntity<?> r = call(url, SpResponse.class);
        return r.getStatusCode() == OK ? (SpResponse) r.getBody() : null;
    }

    private <T> ResponseEntity<?> call(String url, Class<T> responseType) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new ResponseErrorHandler());

        try {
            return ResponseEntity.ok(restTemplate.getForObject(url, responseType));
        } catch (ApiException e) {
            return ResponseEntity.status(e.getStatusCode()).body(e.getErrorResponse());
        }
    }
}

Remove Account Request

Service Name: Remove Account
URL: [GET] /{company_key}/removeaccount
Description: Removes existing account from your company.
Scope: Your Company
Parameters: company_key as URL variable:

Your company is represented with company_key in the URL. Find your key on your admin portal under Corporate Settings>Company Credentials.
token: required

Obtained token to call a service. This token should be company-scope.
username: required

Username of account that you want to remove. It can be a simple username, email, Active Directory account or phone number. This account must refer to an existing account in your company.
Token Requirement: It requires company-scope token. Read the Authentication section for more info
Example Request: https://www.saaspass.com/sd/rest/u45aaaa1290z/removeaccount?username=jane.doe@mydomain.com&token=6JCHH1CROH019TCSG0HSEPW7CXTLUV606A0E07EP5NXWF5D29RJL3MW3
Response: If the call to this resource is successful you will get a 200 (OK) HTTP response. Successful code means the account you provided is successfully deleted from your company. Response that SAASPASS returns has detailed information within below JSON structure:
{
"resultMessage":"Successful","isVerified":true,"isPendingOnEmail":false,"isAccountOwnerBlocked":false,"warning":null
}

resultMessage (String): Contains message about result. It is “Successful” if operation is successful without any warning. It is “Successful with warning” if there is a warning message.

isVerified (Boolean): ‘true’ if added account is verified for a user also. ‘false’ if it is not verified yet.

isPendingOnEmail (Boolean): ‘true’ if account is not verified but it is pending on email verification.

isAccountOwnerBlocked (Boolean): ‘true’ if the owner of account is blocked from logging in to the applications since it is waiting your approval of recovery operation that user did. You can approve her/his recovery and unblock from admin portal.

warning (String): Contains warning message if there is a warning about added account.
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Details

If the ‘username’ you provided refers to multiple accounts, call will fail. Be sure that ‘username’ refers to one account in your company.

Rate Limit

You can call this service 100 times in any 10 minutes. If you exceed the rate limit, response will result in “Too many requests”. For more on this topic see our RESPONSES & ERROR HANDLING

Register Account By Admin

Register Account By Admin

public static bool RegistrationByAdmin(string username, bool isadaccount, string accountowner, string apptoken)
{
    string urlForRegistrationByAdmin = "https://www.saaspass.com/sd/rest/applications/" + apiKey + "/registerbyadmin?username=" + username + "&isadaccount=" + isadaccount + "&accountowner=" + accountowner + "&token=" + apptoken;
    return CheckResponse(urlForRegistrationByAdmin);
}

public static bool CheckResponse(string url)
{
    try
    {
        WebRequest webRequest = WebRequest.Create(url);
        if (webRequest.GetResponse() != null)
        {
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.GetResponseStream() != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string jsonString = reader.ReadToEnd();
                    if (jsonString != null && !jsonString.Equals(""))
                    {
                        JToken tokenJtoken = JObject.Parse(jsonString);
                        ErrMessage = tokenJtoken.SelectToken("resultMessage") != null ? (string)tokenJtoken.SelectToken("resultMessage") : "";
                        ErrMessage += tokenJtoken.SelectToken("warning") != null ? " - " + (string)tokenJtoken.SelectToken("warning") : "";
                    }
                }
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    if (httpResponse.StatusCode.ToString()=="429")
                    {
                        ErrMessage = " X-Rate-Limit-Limit " + httpResponse.Headers["X-Rate-Limit-Limit"];
                        ErrMessage += " ### X-Rate-Limit-Remaining " + httpResponse.Headers["X-Rate-Limit-Remaining"];
                        ErrMessage += " ### X-Rate-Limit-Resets " + httpResponse.Headers["X-Rate-Limit-Resets"];
                    }
                    else
                        ErrMessage += reader.ReadToEnd();
                }
            }
        }
        return false;
    }
}
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class RegisterByAdmin {

    private static final String API_URL = "https://www.saaspass.com/sd/rest";

    public SpResponse registerbyadmin(String username, String accountowner, boolean isadaccount) {
        String url = "%s/applications/%s/registerbyadmin?username=%s&accountowner=%s&isadaccount=%s&token=%s";
        url = String.format(url, API_URL, APP_API_KEY, username, accountowner, isadaccount, getAppToken());
        ResponseEntity<?> r = call(url, SpResponse.class);
        return r.getStatusCode() == OK ? (SpResponse) r.getBody() : null;
    }

    private <T> ResponseEntity<?> call(String url, Class<T> responseType) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new ResponseErrorHandler());

        try {
            return ResponseEntity.ok(restTemplate.getForObject(url, responseType));
        } catch (ApiException e) {
            return ResponseEntity.status(e.getStatusCode()).body(e.getErrorResponse());
        }
    }
}

Register Account By Admin Request

Service Name: Register Account by Admin
URL: [GET] /applications/{application_api_key}/registerbyadmin
Description: Registers an account to your application. If the ‘username’ you provide refers to an existing account in your company, service registers this account. Otherwise it creates new account.
Scope: Your Company
Parameters: application_key as URL variable:

Your application is represented with application_key in the URL. Find your key in your admin portal under your application.
token: required

Obtained token to call a service. This token should be application-scope.
username: required

Username of account that you want to register to the application. It can be simple username, email, Active Directory account or mobile number.
accountowner: optional

If you want to verify the new account you are adding, you can provide a verification data with this parameter.

If you have a direct information about the SAASPASS user that you want to verify the account for, provide his SAASPASS ID or his verified email or his verified Active Directory account or his verified phone number as ‘accountowner’.

If as ‘accountowner’, you provide an email that is not verified yet, SAASPASS will send verification link to this email and when user verifies this link with her/his SAASPASS credentials, the account will be verified for that user. But not verified email can be provided only if ‘username’ refers to a simple username account or an Active Directory account (not email or mobile number account)
isadaccount: optional

If the account you are trying to register is Active Directory account, this parameter must be ‘true’. Otherwise it is ‘false’ by default.
Token Requirement: It requires application-scope token. Read Authentication section for more info
Example Request: https://www.saaspass.com/sd/rest/applications/CPAYR1SL7VN51WQA/registerbyadmin?username=jane.doe&isadaccount=false&accountowner=779034663&token=0PIY25S32US3WYP9ZGUFCZBAYTEMIFSF8THRMWPC59NHD0BPCSXKSSODZSCNCLPY
Response: If the call to this resource is successful you will get a 200 (OK) HTTP response. Successful code means account is registered to the application successfully and it is added to related Application Group. But it may not be successfully verified yet. Response that SAASPASS returns has detailed information within below JSON structure:


{
"resultMessage":"Successful","isVerified":true,"isPendingOnEmail":false,"isAccountOwnerBlocked":false,"warning":null
}

resultMessage (String): Contains message about result. It is “Successful” if operation is successful without any warning. It is “Successful with warning” if there is a warning message.

isVerified (Boolean): ‘true’ if added account is verified for a user also. ‘false’ if it is not verified yet.

isPendingOnEmail (Boolean): ‘true’ if account is not verified but it is pending on email verification.

isAccountOwnerBlocked (Boolean): ‘true’ if the owner of account is blocked from logging in to the applications since it is waiting your approval of recovery operation that user did. You can approve her/his recovery and unblock from admin portal.

warning (String): Contains warning message if there is a warning about added account.
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Details

Rate Limit

You can call this service 100 times in any 10 minutes. If you exceed the rate limit, response will result in “Too many requests”. For more on this topic see our RESPONSES & ERROR HANDLING

Register Account By User

Register Account By User

public static bool RegistrationByUser(string username, bool isadaccount, string saaspassid, string otp, string apptoken)
{
    string urlForRegistrationByUser = "https://www.saaspass.com/sd/rest/applications/" + apiKey + "/registerbyuser?username=" + username + "&isadaccount=" + isadaccount + "&saaspassid=" + saaspassid + "&otp=" + otp + "&token=" + apptoken;
    return CheckResponse(urlForRegistrationByUser);
}

public static bool CheckResponse(string url)
{
    try
    {
        WebRequest webRequest = WebRequest.Create(url);
        if (webRequest.GetResponse() != null)
        {
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.GetResponseStream() != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string jsonString = reader.ReadToEnd();
                    if (jsonString != null && !jsonString.Equals(""))
                    {
                        JToken tokenJtoken = JObject.Parse(jsonString);
                        ErrMessage = tokenJtoken.SelectToken("resultMessage") != null ? (string)tokenJtoken.SelectToken("resultMessage") : "";
                        ErrMessage += tokenJtoken.SelectToken("warning") != null ? " - " + (string)tokenJtoken.SelectToken("warning") : "";
                    }
                }
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    if (httpResponse.StatusCode.ToString()=="429")
                    {
                        ErrMessage = " X-Rate-Limit-Limit " + httpResponse.Headers["X-Rate-Limit-Limit"];
                        ErrMessage += " ### X-Rate-Limit-Remaining " + httpResponse.Headers["X-Rate-Limit-Remaining"];
                        ErrMessage += " ### X-Rate-Limit-Resets " + httpResponse.Headers["X-Rate-Limit-Resets"];
                    }
                    else
                        ErrMessage += reader.ReadToEnd();
                }
            }
        }
        return false;
    }
}
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class RegisterByUser {

    private static final String API_URL = "https://www.saaspass.com/sd/rest";

    public SpResponse registerbyuser(String username, String saaspassid, String otp, boolean isadaccount) {
        String url = "%s/applications/%s/registerbyuser?username=%s&saaspassid=%s&otp=%s&isadaccount=%s&token=%s";
        url = <String class=""></String>format(url, API_URL, APP_API_KEY, username, saaspassid, otp, isadaccount, getAppToken());
        ResponseEntity<?> r = call(url, SpResponse.class);
        return r.getStatusCode() == OK ? (SpResponse) r.getBody() : null;
    }

    private <T> ResponseEntity<?> call(String url, Class<T> responseType) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new ResponseErrorHandler());

        try {
            return ResponseEntity.ok(restTemplate.getForObject(url, responseType));
        } catch (ApiException e) {
            return ResponseEntity.status(e.getStatusCode()).body(e.getErrorResponse());
        }
    }
}

Register Account By User Request

Service Name: Register Account by User
URL: [GET] /applications/{application_api_key}/registerbyuser
Description: Registers an account to your application and verifies it for user that is provided. If the ‘username’ you provide refers to an existing account in your company, service registers this account. Otherwise it creates new account.
Scope: Your Company
Parameters: application_key as URL variable:

Your application is represented with application_key in the URL. Find your key in your admin portal under your application.
username: required

Username of account that you want to register to the application. It can be simple username, email, Active Directory account or mobile number.
token: required

Obtained token to call a service. This token should be application-scope.
isadaccount: optional

If the account you are trying to register is Active Directory account, this parameter must be ‘true’. Otherwise it is ‘false’ by default.
saaspassid: required

SAASPASS ID of user that account will be verified for.
otp: required

One-time password that is generated by user via user’s SAASPASS
Token Requirement: It requires application-scope token. Read Authentication section for more info
Example Request: https://www.saaspass.com/sd/rest/applications/CPAYR1SL7VN51WQA/registerbyuser?username=xterser%40addomain.co\&isadaccount=true&saaspassid=079034663\&otp=12151\&token=0PIY25S32US3WYP9ZGUFCZBAYTEMIFSF8THRMWPC59NHD0BPCSXKSSODZSCNCLPY
Response: If the call to this resource is successful you will get a 200 (OK) HTTP response. Successful code means account is registered to the application successfully and it is added to related Application Group. But it may not be successfully verified yet. Response that SAASPASS returns has detailed information within below JSON structure:


{
"resultMessage":"Successful","isVerified":true,"isPendingOnEmail":false,"isAccountOwnerBlocked":false,"warning":null
}

resultMessage (String): Contains message about result. It is “Successful” if operation is successful without any warning. It is “Successful with warning” if there is a warning message.

isVerified (Boolean): ‘true’ if added account is verified for a user also. ‘false’ if it is not verified yet.

isPendingOnEmail (Boolean): ‘true’ if account is not verified but it is pending on email verification.

isAccountOwnerBlocked (Boolean): ‘true’ if the owner of account is blocked from logging in to the applications since it is waiting your approval of recovery operation that user did. You can approve her/his recovery and unblock from admin portal.

warning (String): Contains warning message if there is a warning about added account.
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Details

Rate Limit

You can call this service 100 times in any 10 minutes. If you exceed the rate limit, response will result in “Too many requests”. For more on this topic see our RESPONSES & ERROR HANDLING

Unregister Account

Unregister Account

public static bool UnRegistration(string username, string apptoken)
{
    string urlForRegistration = "https://www.saaspass.com/sd/rest/applications/" + apiKey + "/unregister?username=" + username + "&token=" + apptoken;
    return CheckResponse(urlForRegistration);
}

public static bool CheckResponse(string url)
{
    try
    {
        WebRequest webRequest = WebRequest.Create(url);
        if (webRequest.GetResponse() != null)
        {
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.GetResponseStream() != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string jsonString = reader.ReadToEnd();
                    if (jsonString != null && !jsonString.Equals(""))
                    {
                        JToken tokenJtoken = JObject.Parse(jsonString);
                        ErrMessage = tokenJtoken.SelectToken("resultMessage") != null ? (string)tokenJtoken.SelectToken("resultMessage") : "";
                        ErrMessage += tokenJtoken.SelectToken("warning") != null ? " - " + (string)tokenJtoken.SelectToken("warning") : "";
                    }
                }
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    if (httpResponse.StatusCode.ToString()=="429")
                    {
                        ErrMessage = " X-Rate-Limit-Limit " + httpResponse.Headers["X-Rate-Limit-Limit"];
                        ErrMessage += " ### X-Rate-Limit-Remaining " + httpResponse.Headers["X-Rate-Limit-Remaining"];
                        ErrMessage += " ### X-Rate-Limit-Resets " + httpResponse.Headers["X-Rate-Limit-Resets"];
                    }
                    else
                        ErrMessage += reader.ReadToEnd();
                }
            }
        }
        return false;
    }
}
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class Unregister {

    private static final String API_URL = "https://www.saaspass.com/sd/rest";

    public SpResponse unregister(String username) {
        String url = "%s/applications/%s/unregister?username=%s&token=%s";
        url = String.format(url, API_URL, APP_API_KEY, username, getAppToken());
        ResponseEntity<?> r = call(url, SpResponse.class);
        return r.getStatusCode() == OK ? (SpResponse) r.getBody() : null;
    }

    private <T> ResponseEntity<?> call(String url, Class<T> responseType) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new ResponseErrorHandler());

        try {
            return ResponseEntity.ok(restTemplate.getForObject(url, responseType));
        } catch (ApiException e) {
            return ResponseEntity.status(e.getStatusCode()).body(e.getErrorResponse());
        }
    }
}

Unregister Account

Service Name: Unregister Accountr
URL: [GET] /applications/{application_api_key}/unregister
Description: Removes given account from the application. (Account stays in your company)account. Otherwise it creates new account.
Scope: Your Application
Parameters: application_key as URL variable:**

Your application is represented with application_key in the URL. Find your key in your admin portal under your application.
token: required

Obtained token to call a service. This token should be application-scope.
username: required

Username of account that you want to unregister from the application. It can be simple username, email, Active Directory account or mobile number.
Token Requirement: It requires application-scope token. Read Authentication section for more info
Example Request: https://www.saaspass.com/sd/rest/applications/CPAYR1SL7VN51WQA/unregister?username=jane.doe%40emaild.com&token=0PIY25S32US3WYP9ZGUFCZBAYTEMIFSF8THRMWPC59NHD0BPCSXKSSODZSCNCLPY
Response: If the call to this resource is successful you will get a 200 (OK) HTTP response. Successful code means account is removed from Application Group of given application. But if account is under some other group that is also assigned to same application, successful response will have warning about it. Response that SAASPASS returns has detailed information within below JSON struct:


{
"resultMessage":"Successful","isVerified":true,"isPendingOnEmail":false,"isAccountOwnerBlocked":false,"warning":null
}

resultMessage (String): Contains message about result. It is “Successful” if operation is successful without any warning. It is “Successful with warning” if there is a warning message.

isVerified (Boolean): ‘true’ if added account is verified for a user also. ‘false’ if it is not verified yet.

isPendingOnEmail (Boolean): ‘true’ if account is not verified but it is pending on email verification.

isAccountOwnerBlocked (Boolean): ‘true’ if the owner of account is blocked from logging in to the applications since it is waiting your approval of recovery operation that user did. You can approve her/his recovery and unblock from admin portal.

warning (String): Contains warning message if there is a warning about added account.
If the call to this resource is unsuccessful, you will get a non-200 HTTP status code relative to the type of error. For more on this topic see our RESPONSES & ERROR HANDLING

Details

Rate Limit

You can call this service 100 times in any 10 minutes. If you exceed the rate limit, response will result in “Too many requests”. For more on this topic see our RESPONSES & ERROR HANDLING

Tracker Id Validation

For security reasons SAASPASS offers to the custom backend server a way to validate any trackerID received after a login request.

TrackerID request

TrackerID request

public static bool TrackerIdValidation(string username, string trackers, string appToken)
{
    string urlForTracker = "https://www.saaspass.com/sd/rest/applications/" + apiKey + "/trackers/" + trackers + "?token=" + appToken + "&account=" + username;
    return CheckResponse(urlForTracker);
}

public static bool CheckResponse(string url)
{
    try
    {
        WebRequest webRequest = WebRequest.Create(url);
        if (webRequest.GetResponse() != null)
        {
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.GetResponseStream() != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string jsonString = reader.ReadToEnd();
                    if (jsonString != null && !jsonString.Equals(""))
                    {
                        JToken tokenJtoken = JObject.Parse(jsonString);
                        ErrMessage = tokenJtoken.SelectToken("resultMessage") != null ? (string)tokenJtoken.SelectToken("resultMessage") : "";
                        ErrMessage += tokenJtoken.SelectToken("warning") != null ? " - " + (string)tokenJtoken.SelectToken("warning") : "";
                    }
                }
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    catch (WebException e)
    {
        using (WebResponse response = e.Response)
        {
            HttpWebResponse httpResponse = (HttpWebResponse)response;
            if (httpResponse != null)
            {
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    if (httpResponse.StatusCode.ToString()=="429")
                    {
                        ErrMessage = " X-Rate-Limit-Limit " + httpResponse.Headers["X-Rate-Limit-Limit"];
                        ErrMessage += " ### X-Rate-Limit-Remaining " + httpResponse.Headers["X-Rate-Limit-Remaining"];
                        ErrMessage += " ### X-Rate-Limit-Resets " + httpResponse.Headers["X-Rate-Limit-Resets"];
                    }
                    else
                        ErrMessage += reader.ReadToEnd();
                }
            }
        }
        return false;
    }
}
public class Tracker {

    private static final String API_URL = "https://www.saaspass.com/sd/rest";

    public HttpStatus validate(String tracker, String account) {
        String url = "%s/applications/%s/trackers/%s?account=%s%token=%s";
        url = String.format(url, API_URL, APP_API_KEY, tracker, account, getAppToken());
        ResponseEntity<?> r = call(url, TrackerResponse.class);
        return r.getStatusCode();
    }

    private <T> ResponseEntity<?> call(String url, Class<T> responseType) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new ResponseErrorHandler());

        try {
            return ResponseEntity.ok(restTemplate.getForObject(url, responseType));
        } catch (ApiException e) {
            return ResponseEntity.status(e.getStatusCode()).body(e.getErrorResponse());
        }
    }

    private class TrackerResponse {
    }
}
Service Name: TrackerID Validation
URL: applications/{application_API_key}/trackers/{tracker_value}?token={token\\_value}&account={account\\_value}
Description: It validates if the POST request received by application is coming from SAASPASS.
Scope: Application Scope
Parameters: application key: required

Application key given for your Custom application.
token: required

Obtained token to call a service. This token should be application-scope.
account: required

User account for which the tracker was issued.
Token Requirement: It requires application-scope token. Read Authentication section for more info
Example Request: https://www.saaspass.com/sd/rest/applications/00de4v5ocd9v338w/trackers/b4097ed670833a83?token=HDFAIOANASDCJBKLHUFUIQWEJKUHSASD&account=john.s@yourdomain.com
Response: If TrackerID is valid a 200 (OK) status HTTP response is sent and the user can be logged in.

If TrackerID is not valid a non-200 HTTP status code is sent. Check them out in Responses & Error Handling section.

Error Cases

HTTP Statuses

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.DefaultResponseErrorHandler;
import java.io.IOException;

class ResponseErrorHandler extends DefaultResponseErrorHandler {

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        try {
            ErrorResponse errorResponse = new ObjectMapper().readValue(response.getBody(), ErrorResponse.class);
            throw new ApiException(response.getStatusCode(), errorResponse);
        } catch (JsonParseException e) {
            String message = response.getRawStatusCode() + " - " + response.getStatusText();
            throw new ApiException(response.getStatusCode(), new ErrorResponse(message));
        }
    }
}

class ApiException extends RuntimeException {

    private HttpStatus statusCode;
    private ErrorResponse errorResponse;

    ApiException(HttpStatus statusCode, ErrorResponse errorResponse) {
        this.statusCode = statusCode;
        this.errorResponse = errorResponse;
    }

    HttpStatus getStatusCode() { return statusCode; }
    ErrorResponse getErrorResponse() { return errorResponse; }
}

public class ErrorResponse {

    private RestErrorEnum name;
    private String message;
    private String informationlink;

    public ErrorResponse() {}
    public ErrorResponse(String message) { this.message = message; }

    public RestErrorEnum getName() { return name; }
    public String getMessage() { return message; }
    public String getInformationlink() { return informationlink; }
}
Error Code Error Message
200 OK
201 Resource created
400 Bad request
401 Unauthorized
403 Forbidden
404 Resource not found
429 Too Many Requests
500 SAASPASS server error

Rate Limit Headers

Response Headers Definition
X-Rate-Limit-Limit Maximum rate limit of the called service in a time window
X-Rate-Limit-Resets Time info that next window will open (unix epoch - Long)
X-Rate-Limit-Remaining Number of request remains in current window

Error Codes

enum RestErrorEnum {

    CONNECTION_PROBLEMS("Connection problems."),
    INVALID_RESOURCE_ID("Invalid resource ID specified."),
    EMPTY_OR_NULL_VALUE("Empty or null parameter value."),
    MAX_LENGTH_EXCEEDED("Maximum parameter length exceeded."),
    INVALID_PARAMETER_VALUE("Invalid parameter value."),
    APPLICATION_NOT_FOUND("Application not found."),
    SAASPASS_SERVER_ERROR("SAASPASS internal server error. Please try again."),
    TRACKER_NOT_FOUND("The specified tracker was not found."),
    INVALID_OTP("The provided OTP is invalid."),
    NO_DEVICE_FOUND("No active device found for user."),
    INVALID_IP("Action not allowed from this IP address."),
    APPLICATION_NOT_ACTIVE("Application is not active."),
    TRACKER_EXPIRED("Tracker has expired."),
    INVALID_CREDENTIALS("Invalid authentication credentials."),
    EXPIRED_TOKEN("The provided token has expired. Please re-authenticate."),
    ACTION_FORBIDDEN_FOR_APPLICATION("Action forbidden for this application."),
    USER_NOT_ASSIGNED_TO_APPLICATION("User not assigned to application"),
    USER_NOT_ASSIGNED_TO_COMPANY("User not assigned to company."),
    INVALID_RDP_SESSION("Invalid RDP session."),
    EXPIRED_RDP_SESSION("Expired RDP session."),
    INVALID_REQUEST("Invalid JSON request body");

    private String message;

    RestErrorEnum(final String message) {
        this.message = message;
    }
}

SAASPASS RESTful API uses some of the standard HTTP status codes alongside a JSON response description.

JSON Structure in the response body:


{
"name": "{ERROR NAME}",
"message": "{Error description}",
"informationlink": "{Link to error documentation}"
}

> Generic Errors

Error Code Error Message When It May Occur
INVALID_REQUEST Invalid JSON request body Invalid JSON request body
INVALID_RESOURCE_ID Invalid resource ID When the provided resource identificator does not exist.
EMPTY_OR_NULL_VALUE Empty or null parameter value sent in request. When a requested parameter has no value or an empty value, either as a URL parameter or a JSON field.
MAX_LENGTH_EXCEEDED Maximum parameter length exceeded. When a requested parameter value has exceeded the maximum length, either as a URL parameter or a JSON field.
INVALID_PARAMETER_VALUE Invalid parameter value. When a requested parameter has an invalid value. Most commonly, the value is not in its predefined format.
SAASPASS_SERVER_ERROR SAASPASS internal server error. Try the action again. If the problem persists, please inform our administrators.
TOO_MANY_REQUEST Rate Limit exceeded for this service. Wait till time window resets When same service calls reached to its rate limit in current time window (see Rate Limit section).

> Credential Errors

Error Code Error Message When It May Occur
INVALID_CREDENTIALS Invalid authentication credentials. When the credentials sent during service call are incorrect. When you receive this error it means that either your credential parameters (company credentials or application credentials are invalid or that your application has been deleted by your administrator. See detailed info on Authentication
INVALID_OTP The provided OTP is invalid. When the provided OTP value is invalid or expired.
NO_DEVICE_FOUND No active device found for user. When there is no active device found for the specified user, or the user itself is not active
TRACKER_NOT_FOUND The specified tracker was not found When the specified parameters in the request do not match any of our tracker records.
INCORRECT_CREDENTIALS Incorrect credentials. If problem continues, check time/time zone of your mobile device When calling Register Account By User service and user’s SAASPASS credentials are not valid.

> Token Errors

Error Code Error Message When It May Occur
EXPIRED_TOKEN The provided token is expired. Please re-authenticate When the provided token has expired. You should generate new token and call the service with it. Token generation and expiration policy are different for company-scope and application-scope services. For more information about tokens, see Authentication
INVALID_TOKEN The provided token has expired. Please re-authenticate. When the provided token value is incorrect. You should generate new token and call the service with it. For more information about tokens, read Authentication API page. Token generation and expiration policy are different for company-scope and application-scope services. For more information about tokens, see Authentication

> Application Errors

Error Code Error Message When It May Occur
APPLICATION_NOT_FOUND Application not found. When an Application was not found due to one or more incorrect parameters.
APPLICATION_NOT_ACTIVE Application is not active. When the specified application is not active.
ACTION_FORBIDDEN_FOR_APPLICATION Action forbidden for this application. When the application doing the REST call does not have rights to perform the call.
INVALID_IP Action not allowed from this IP address. When the IP address of client that is calling a service does not match the setup IP filter for your application or your company. If the called service has application-scope (i.e OtpCheck, RegisterAccount by Admin…), check IP filtering setup in your application configuration. If the service has company-scope (i.e Add Account, Remove Account…), check IP filtering setup in your company’s corporate settings. See IP Filtering info on Authentication

> One-Time Password Login Specific Errors

Error Code Error Message When It May Occur
LOGINFAIL_ACCOUNT_NOTASSIGNED_OR_NOTVERIFIED User account is not assigned to the application or it is not verified The user account sent in the request is not assigned to the application or not verified under SAASPASS portal by the admin.
LOGINFAIL_OTP_MANDATORY_FOR_ACCOUNT OTP is mandatory for account that is assigned to application and verified When the user account sent in the request is verifed and assigned to the application under SAASPASS portal by the admin must provide valid One-Time Password. In this case, OTP value is empty.
LOGINFAIL_UNVERIFIED_ASSIGNED_ACCOUNT_NOT_ALLOWED Login with an unverified/assigned account is not allowed for the application When administrator does not allow the login for NOT verified accounts which are assigned to the application in SAASPASS Portal. This setting can be changed from “Application Settings” on SAASPASS Portal.
LOGINFAIL_UNASSIGNED_ACCOUNT_NOT_ALLOWED Login with an unverified account that is not assigned to the application is not allowed When administrator does not allow the login for NOT verified accounts which are NOT assigned to the application in SAASPASS Portal. This setting can be changed from “Application Settings” on SAASPASS Portal.
LOGINFAIL_NONEXIST_ACCOUNT_NOT_ALLOWED Login with non-existing account is not allowed for the application When administrator does not allow the login for accounts which are NOT added to the company in SAASPASS Portal. This setting can be changed from “Application Settings” on SAASPASS Portal.
LOGINFAIL_ACCOUNT_BLOCKED User account is blocked from login to applications The user account requesting for login is blocked. Blocked accounts are not allowed to log into SAASPASS protected applications. Administrator is able to unblock the account from SAASPASS Portal.
LOGINFAIL_NOTASSIGNED_ALLOWED_IF_ACTIVE Login with not-assigned account is allowed for application only if account is active When administrator allow the login for accounts which are NOT assigned to the application if account is added and active in SAASPASS Portal. This setting can be changed from “Application Settings” on SAASPASS Portal.

> Account Management Errors

Error Code Error Message When It May Occur
ACCOUNT_ALREADY_EXISTS Account already exists When calling Adding Account service and the account already exists in your company.
ACCOUNT_IS_VERIFIED_FOR_ANOTHER_USER Account is already verified and the owner is different than the verification data refers When calling an account management service with already verified account and given ‘accountowner’ does not refer to the owner of this account.
VERIFICATION_DATA_IS_INVALID Verification data is invalid When calling an account management service with ‘accountowner’ parameter but value of parameter is invalid or it is SAASPASS ID that cannot be found.
PENDING_ACCOUNT_NOT_FOUND Pending account not found When calling Verify Account service but a pending account with given ‘username’ not found in your company to verify.
NOT_ALLOWED_TO_VERIFY_ACCOUNT This type of account is not allowed to be verified manually When calling Register Account By User service and user’s SAASPASS credentials are not valid.
NOT_ALLOWED_TO_VERIFY_VIA_EMAIL This type of account is not allowed to be verified via verification email When calling an account management service with ‘accountowner’ parameter that is email address but the account type is also email address. If email address belongs to your domain, ‘accountowner’ parameter should refer to a SAASPASS user directly or it should be empty.
ACTION_NOT_SUCCESSFUL Action is not successful. Check your parameters or developers page When calling an account management service results in fail due to some reason. You should check your request and parameters.
NOT_ALLOWED_ADDING_TO_GROUP Provided group is managed automatically. Adding account manually is not allowed When calling an account management service with ‘grouplist’ parameter that contains a group which is not allowed to add account manually. Account can be added to custom groups or Application Group.
GROUP_NOT_FOUND Group not found When calling an account management service with ‘grouplist’ parameter that contains a group which cannot be found in your company.
NOT_ALLOWED_TO_DELETE_AD_ACCOUNT AD type account cannot be deleted manually When calling Remove Account service but the type of given account is Active Directory Account. AD accounts can be deleted from Active Directory and synced with AD agent to SAASPASS.
NOT_ALLOWED_TO_CREATE_AD_ACCOUNT AD type account cannot be created manually When calling Add Account, Register Account By Admin, Register Account By User services and given account type is Active Directory account. AD accounts can be created from Active Directory and synced with AD agent to SAASPASS.
USER_NOT_ASSIGNED_TO_APPLICATION User not assigned to application. When the username for which you are requesting OTP check is not assigned to SAASPASS as a user of your application. When you receive this message you can either block his login
USER_NOT_ASSIGNED_TO_COMPANY User not assigned to company. When the username for which you are requesting OTP check is not assigned to SAASPASS as a user of your company.
ACCOUNT_NOT_FOUND Account not found When calling an account management service that ‘username’ does not refer to an existing account in your company while it was required to be.
NO_UNIQUE_ACCOUNT_FOUND No unique account found for given username When calling an account management service that is not referring to unique account in your company. This generally can happen if ‘username’ parameter refers to multiple simple username account. If there are more than 1 account with same username and you want to use the verified one, you should provide owner of this account with ‘accountowner’ parameter.

SAASPASS Connect

Integration

This section explains how you can add SAASPASS Connect button to your application web page and implement the authentication flow.

Authentication flow is implemented with OpenID Connect (and Oauth2.0) protocol. As developer, you will find required information in brief here about client implementation of OpenID Connect but for more details about protocol, you can refer to OpenID Connect Basic Client Implementer’s Guide: http://openid.net/specs/openid-connect-basic-1_0.html

Note: The operation after successful authentication in your application side is up to your needs. For example you will get the email of the authenticated user after SAASPASS sends you a successful authentication response. And if you defined a proper scope to get the full user profile from SAASPASS, you MAY get the username that user defined on the profile (if user provided the username on profile). So you can decide to either use email or this username to be the account name of the user in your application. Also it is up to you to check if this account name exists in your database. So you can allow users that already exist in your system only (registered before) or you can just create a new user right after successful authentication.

Add SAASPASS Connect button to your login page:

String clientId = "{your_client_id}";
String redirectUri = "{your_redirect_url}";
String scopes = "{your_scope_list}";
String state = UUID.randomUUID().toString();
//Add to session since you will validate this later on server side
session.setAttribute("state", state);

<a href="https://www.saaspass.com/sd/oauth/authorize?response_type=code&client_id=<%=clientId%>&redirect_uri=<%=redirectUri%>&scope=<%=scopes%>&state=<%=state%>">
    <img src="assets/login_with-saaspass.png" alt="Sign in with SAASPASS"/a>
</a>

Coming Soon...

Send authentication request to SAASPASS:

//On your servlet handler, get parameters that is sent to your callback URL
doGet(HttpServletRequest request, HttpServletResponse response) {
    String authorizationCode = request.getParameter("code");
    String stateValue = request.getParameter("state");
    //validate state value here. It should match with the one you generated for button
    String your_state_code = (String)request.getSession().getAttribute("state");
    If(!stateValue.equals(your_state_code) {
             //ERROR
    }
}
Coming Soon...

Parameter Value Details
response_type code This parameter-value pair initiates Basic Flow that is asking a temporary code from SAASPASS that will be used to obtain tokens
client_id code This parameter-value pair initiates Basic Flow that is asking a temporary code from SAASPASS that will be used to obtain tokens
redirect_uri code This parameter-value pair initiates Basic Flow that is asking a temporary code from SAASPASS that will be used to obtain tokens
scope {SCOPE_LIST}
e.g. openid email address
‘scope’ defines the list of user information that your application wants to retrieve from SAASPASS about authenticated user. Replace {SCOPE_LIST} with list of scopes that you request. Scopes should be space separated.

openid: This is mandatory scope to be provided to proceed with openid connect protocol.

email: This is mandatory scope to be provided. It lets user’s email to be returned inside ID Token that you will see in that section.

phone: (optional) Add this scope to get verified phone number of user if provided.

profile: (optional) Add this scope to get more profile information of user. This will include info like name, family name, full name, gender, birth date and updated time.

address: (optional) Add this scope to get address information of user. This will include info like street address, city, country and postal code of user.
state {STATE}
e.g. 1xx9xx9f8bfxx1
This state can be used to protect your flow against cross-site request forgery like attacks. You can generate a random string and replace with {STATE} in the URL pattern. State will be returned back in the response as well so that you can validate it by comparing with the one you generated and sent in the request

Get Access Token and ID Token:

PARAMETER VALUE
Content-type application/x-www-form-urlencoded
Accept application/json



PARAMETER VALUE DETAILS
access_token This is access token. Access token can be used to get more information about authenticated user. Check ‘Getting User Information’ section saaspass_connect.integration.parameter3a.details
token_type It is type of token which is ‘bearer’ for this response saaspass_connect.integration.parameter3b.details
expires_in Expiration time of access token in seconds saaspass_connect.integration.parameter3c.details
scope Contains scope(s) that was provided during request saaspass_connect.integration.parameter3d.details

An example response body is:

{
"access_token": "901f6bfc-9cd2-4d40-8509-c3616ca80707",
"token_type": "bearer",
"expires_in": 86399,
"scope": "openid email",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE",
"email": "useremail@emdomain.com"
}




PARAMETER VALUE
access_token This is access token. Access token can be used to get more information about authenticated user. Check ‘Getting User Information’ section
token_type It is type of token which is ‘bearer’ for this response
expires_in Expiration time of access token in seconds
scope Contains scope(s) that was provided during request
email This is email of users that they chose for authentication with your application within a SAASPASS Profile. This email is already verified by SAASPASS and you can use this as username of user for this authentication
id_token This is JSON Web Token that includes authenticated user’s identity and it is signed by SAASPASS. Check ‘Handling ID Token’ for details



//Here it is used Apache Http components. It is up to you how to handle Http request-responses here.
URI uri = new URIBuilder().setScheme("https")
            .setHost("www.saaspass.com")
            .setPath("/sd/oauth/token")
            .setParameter("grant_type", "authorization_code")
            .setParameter("code", "{your_authorization_code}")
            .setParameter("redirect_uri", "{your_callback_url}")
            .setParameter("client_id", "{your_client_id}")
            .setParameter("client_secret", "{your_client_secret}")
            .build();
HttpPost postRequest = new HttpPost(uri);
postRequest.setHeader("Content-type", "application/x-www-form-urlencoded");
postRequest.setHeader("Accept", "application/json");

HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(postRequest);

//read response as you want, get as String

JsonParser parser = new JsonParser();    //used 'gson' as json library
JsonObject responseJson = (JsonObject)parser.parse(result.toString());
String token = responseJson.get("access_token").getAsString();
String idToken = responseJson.get("id_token").getAsString();
//read other attributes
Coming Soon...

Handle ID Token:

Token is Base64 encoded value. Example value:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE
String[] idTokenParts = idToken.split("\\.");
String idTokenHeader = base64UrlDecode(idTokenParts[0]);
String idTokenDataAsJsonStr = base64UrlDecode(idTokenParts[1]);   //Using any base64 decoding library
byte[] idTokenSignature = base64UrlDecodeToBytes(idTokenParts[2]);
Coming Soon...



> Part-1: Headers

JsonParser parser = new JsonParser();
JsonObject headersJson = (JsonObject)parser.parse(idTokenHeader);
String keyId = headersJson.get("kid").getAsString();
String algorithm = headersJson.get("alg").getAsString();
Coming Soon...

PARAMETER VALUE
alg This identifies the algorithm that was used for signing
kid It is identifier for the key that was used for signing



> Part-2: ID Token Claims

This is 2nd part of ID Token and contains main data. See attribute details below. You MAY want to validate some attributes against their expected value.

JsonObject idTokenData = (JsonObject)parser.parse(idTokenDataAsJsonStr);

//if you want to validate issuer
String issuer = idTokenData.get("iss").getAsString();
if(!issuer.equals("http://www.saaspass.com")) {
    //ERROR
}

//if you want to validate client id
String clientId = idTokenData.get("aud").getAsString();
if(!clientId.equals("{your_client_id}")) {
    //ERROR
}

//This is unique identifier of user's SAASPASS profile
String userProfileId = idTokenData.get("sub").getAsString();

//User's verified email that can be used as username
String userEmail = idTokenData.get("email").getAsString();

//Id token expiration time
Long expirationTime = idTokenData.get("exp").getAsLong();
Coming Soon...

PARAMETER VALUE
iss Identifier of issuer. This should be ‘http://www.saaspass.com’ for the ID Tokens that come from SAASPASS
sub Unique identifier of user’s profile that was chosen by user during authentication. Note that SAASPASS users may have multiple profiles that can have different email or same email
aud Contains {CLIENT_KEY} that you provided on SAASPASS Connect configuration
exp Expiration time of ID Token in Unix time. This ID Token should be ignored if expiration time passed current time
iat Time when ID Token was issued. It is in Unix time
jti Unique identifier of the ID Token
email Email of authenticated user. It can be used as username of user for your application
saaspass_id This is unique identifier of user’s SAASPASS account. It is up to your need to use it in your system



> Part-3: Signature

- Before using ID Token, you should decide if you want to validate the signature of token. - Validating signature will prove that the user information is provided by SAASPASS. You don’t really need to validate signature in this flow since authentication flow was executed between your application server and SAASPASS. But if you are getting this ID Token through some 3rd party application or another layer of your authentication process, it is recommended to validate ID Token). - Signature is represented by Base64 decoded of 3rd part of ID Token. Token is signed using private key that is specific to your SAASPASS Connect that you configured on SAASPASS Admin Portal. So to validate signature, you can use public key that is given to you on DEVELOPERS tab under that SAASPASS Connect.

//Using boucnycastle to read public key
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;

import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

//...

validateIdTokenSignature() {
    byte[] idTokenData = (idTokenParts[0] + "." + idTokenParts[1]).getBytes(StandardCharsets.UTF_8);
    String publicKeyAsStr = "{your_public_key}";
    PublicKey publicKey = getAsPublicKey(publicKeyAsStr);

    boolean isValidSignature = isValidSignature(idTokenData, idTokenSignature, publicKey);
    If(!isValidSignature) {
        //ERROR
    }
}

boolean isValidSignature(byte[] data, byte[] signature, PublicKey pubKey) throws GeneralSecurityException {
        Signature sig = Signature.getInstance("SHA256withRSA");
        sig.initVerify(pubKey);
        sig.update(data);

        return sig.verify(signature);
 }

PublicKey getAsPublicKey(final String publicKeyAsString) {
        final KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
        final byte[] keyContentAsByte = getKeyContentAsByte(publicKeyAsString);
        final X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyContentAsByte);
        return factory.generatePublic(pubKeySpec);
 }

byte[] getKeyContentAsByte(final String keyAsString) {
        final StringReader reader = new StringReader(keyAsString);
        final PemReader pemReader = new PemReader(reader);
        PemObject pemObject = null;
        try {
            pemObject = pemReader.readPemObject();
        } finally {
            pemReader.close();
        }
        return pemObject.getContent();
 }

Coming Soon...

Get User Information:

URI uri = new URIBuilder().setScheme("https")
        .setHost("www.saaspass.com")
        .setPath("/sd/oauth/userinfo")
        .build();
HttpGet getRequest = new HttpGet(uri);
getRequest.setHeader("Authorization", "Bearer "+accessToken);  //access token that you received before
getRequest.setHeader("Accept", "application/jwt");

HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(getRequest);

//... read response as you want, get as String

String[] jwtResponseParts = result.toString().split("\\.");
String userInfoAsJsonStr = base64UrlDecode(jwtResponseParts[1]);
JsonParser parser = new JsonParser();
JsonObject userInfoData = (JsonObject)parser.parse(userInfoAsJsonStr);
String profileId = userInfoData.get("sub").getAsString();
String country = userInfoData.get("address").getAsJsonObject().get("country").getAsString();
//...other attributes
Coming Soon...



PARAMETER VALUE DETAILS
“Authorization” “Bearer ” + access_token access_token is the Access Token that you received in token response
“Accept” “application/jwt” Response will be in JWT format. This header is optional, see response details.
PARAMETER REQUIRED SCOPEDETAILS
sub N.A Unique identifier of user’s profile that was chosen by user during authentication. Note that SAASPASS users may have multiple profiles that can have different email or same email
given_name profile First name of user
family_name profile Family name of user
name profile Full name of user. Consists of given name and family name
preferred_username profile This is username that user may define in the profile. It is your decision to use this or email as account name of user in your application
gender profile Gender of user. (values: Male, Female, Unknown)
birthdate profile Birth date of user in yyyy-MM-dd format
updated_at profile Last update time of the user profile in ‘long’ type (millisecond)
email email Verified email of user
email_verified email It will come ‘true’ since email of user is already verified by SAASPASS
phone_number phone Verified phone number of user
phone_number_verified phone It will come ‘true’ since phone number of user is already verified by SAASPASS
address address This contains address information of user. Fields below are inside address section of response:
street_address: address of user
locality: City of user
country: Country of user
postal_code: Postal code of user

Example response data for user info:


{
  "sub": "248289761001",
  "given_name": "Jane",
  "family_name": "Doe",
  "name": "Jane Doe",
  "preferred_username": "j.doe",
  "gender": "Female",
  "birthdate": "1980-12-19",
  "updated_at": 1482497922045,  "email": "janedoe@example.com",
  "email_verified": true,
  "phone_number": "+1092911232",
  "phone_number_verified": true,
  "address": {
    "street_address": "100 main st",
    "locality": "Seattle",
    "country": "US",
    "postal_code": "98104"
  }
}


SAASPASS Connect Demo

Sample Application is currently offered for Java.

SAASPASS Connect Sample Application

Integration Tools

Sample App

SAASPASS offers a sample project of an application with the different SAASPASS services integrated.

Download the project and import it into your workspace. Check how an application should call SAASPASS HTTP API for manual login, how to handle Instant Login, Instant Registration of how to call for new account registrations.

Sample Application is currently offered for Java and .NET

Java Sample Application .Net Sample Application

Download Android Sample App Download iOS Sample App

Reverse Ajax Implementation

Reverse Ajax

///This block of code should be in Example.aspx for receive message from server
 <!-- Receive messages -->
    <asp:ScriptManager ID="ScriptManager1" runat="server" AsyncPostBackTimeout="2147483647">
        <Services>
            <asp:ServiceReference Path="~/Dispatcher.asmx" />
        </Services>
    </asp:ScriptManager>
    <script type="text/javascript">
        function waitEvent() {
            CustomApplication.Dispatcher.WaitMessage("<%= Session["session"] %>",
            function (response) {
                displayMessage(response);
                setTimeout(waitEvent, 0);
            },
            function () {
                setTimeout(waitEvent, 0);
            });
        }
        function displayMessage(message) {
            if (message != null) {
                window.location.href = "/Default.aspx?username=" + message;
            }
        }
    </script>


///This block of code should be in Example.aspx.cs
 protected void Page_PreRender(object sender, EventArgs e)
{
    if (Session["session"] != null)
    {
        ClientScript.RegisterStartupScript(this.GetType(), "ActivateWaitingLoop", "waitEvent();", true);
    }
}

///This block of code should be in Dispatcher.asmx.cs service for getting messages
using System.Web.Services;
namespace CustomApplication
{
    /// This web service contains methods that help dispatching events to the client.
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    [System.Web.Script.Services.ScriptService]
    public class Dispatcher : System.Web.Services.WebService
    {
        /// Dispatch the new message event.
        /// <param name="userName">The loged in user name</param> <returns>the message content</returns>
        [WebMethod]
        public string WaitMessage(string session)
        {
            return ClientAdapter.Instance.GetMessage(session);
        }
    }
}

///This block of code should be in ClientAdapter.cs
using System.Collections.Generic;
namespace CustomApplication
{
    /// This class is used to send events/messages to multiple clients.
    public class ClientAdapter
    {
        /// The recipient list.
        private Dictionary<string, Client> recipients = new Dictionary<string, Client>();
        /// Send a message to a particular recipient.
        public void SendMessage(Message message)
        {
            if (recipients.ContainsKey(message.reqSession))
            {
                Client client = recipients[message.reqSession];
                client.EnqueueMessage(message);
            }
        }
        /// Called by a individual recipient to wait and receive a message. <returns>The message content</returns>
        public string GetMessage(string session)
        {
            string username = string.Empty;
            if (recipients.ContainsKey(session))
            {
                Client client = recipients[session];
                username = client.DequeueMessage().reqUsername;
                string a = username;
            }
            return username;
        }
        /// Join a user to the recipient list.
        public void Join(string session)
        {
            recipients[session] = new Client();
        }
        public static ClientAdapter Instance = new ClientAdapter();
        private ClientAdapter() { }
    }
}

///This block of code should be in Client.cs
using System.Collections.Generic;
using System.Threading;
namespace CustomApplication
{
    public class Client
    {
        private ManualResetEvent messageEvent = new ManualResetEvent(false);
        private Queue<Message> messageQueue = new Queue<Message>();

        /// This method is called by a sender to send a message to this client.
        public void EnqueueMessage(Message message)
        {
            lock (messageQueue)
            {
                messageQueue.Enqueue(message);

                // Set a new message event.
                messageEvent.Set();
            }
        }
        /// This method is called by the client to receive messages from the message queue.
        /// If no message, it will wait until a new message is inserted. <returns>the unread message</returns>
        public Message DequeueMessage()
        {
            // Wait until a new message.
            messageEvent.WaitOne();
            lock (messageQueue)
            {
                if (messageQueue.Count == 1)
                {
                    messageEvent.Reset();
                }
                return messageQueue.Dequeue();
            }
        }
    }
}

///This block of code should be in Message.cs
namespace CustomApplication
{
    public class Message
    {
        public string reqSession { get; set; }
        public string reqTracker { get; set; }
        public string reqUsername { get; set; }
    }
}

Some of the SAASPASS services are triggered directly from the SAASPASS mobile application by the user interaction. This ends up with SAASPASS server sending a login response to a web application which didn’t request anything.

In order to let the user log in automatically to its session, developer should integrate the Reverse Ajax to let the browser session to take an action for the request received from SAASPASS Servers.

SAASPASS Services requiring Reverse Ajax implementation are:

For more information about Reverse Ajax: https://en.wikipedia.org/wiki/Comet_(programming)

iOS SDK

Introduction

SAASPASS SDK allows to set up the communication between the custom mobile app and the SAASPASS mobile app.

This communication is part of the user authentication process. At the end point, the custom mobile app will receive the login response through the SDK.

Steps for Integration in iOS.

Terminology


iOS SDK

SAASPASS SDK VERSION: 1.0.0

SDK RELEASE DATE: 2015/12/06

Download iOS SDK Download iOS Sample App Download iOS Swift Sample App


Import SAASPASS SDK To Xcode Project(Objective-c)

The SDK automatically loads its framework and resource dependencies.


‘Login with Saaspass’ - Integration

1) GET THE APPLICATION KEY


2) CONFIGURE THE .plist FOR YOUR PROJECT

Schema:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <array>
            <key> CFBundleURLSchemes</key>
            <string>saaspasssdk-appKey-urlSchemeSuffix</string>
        </array>
    </dict>
</array>

Parameters:

appKey required Application key given for your Custom application.
urlSchemeSuffix optional (Suffix) String that is appended to the base URL scheme used for SaasPass login.(Optional)



3) ADD API KEY AND SUFFIXES TO THE .plist

Example:

<key>CFBundleURLTypes</key>
<array>
<dict>
<array>
<key> CFBundleURLSchemes</key>
<string>saaspasssdk-123456789-testVersion</string>
</array>
</dict>
</array>




4) EXTRA CONFIGURATION FOR IOS9

In iOS 9 you have to whitelist any URL schemes your App wants to query in Info.plist under the LSApplicationQueriesSchemes key (an array of strings).

Add the following to your application’s .plist:

<key>LSApplicationQueriesSchemes</key>
<array>
<string>saaspass-auth</string>
</array>

5) CONNECT APPLICATION DELEGATE

To post process the results from SaasPass Login (or any action that requires switching over to the native SAASPASS app) you need to conenct your AppDelegate to the SPSDKManager.

In your AppDelegate.m add:

// AppDelegate.m
#import <SaasPassSDK/SaasPassSDK.h>

-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

return [[SPSDKManager sharedInstance] application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; 
}




6) ADD ‘LOGIN WITH SAASPASS’ BUTTON CODE

To add a SaasPass-branded login button to your app add the following code snippet to a view controller.

// Add this to the header file, e.g. in ViewController.h
#import <SaasPassSDK/SaasPassSDK.h>

// Add this delegate into your view controller
@interface ViewController : UIViewController <SPSDKLoginButtonDelegate>

// Add this to the header of your file, e.g. in ViewController.m
// after #import "ViewController.h"
// Add this to the body

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Add a SAASPASS-branded login button to your app 
SPSDKLoginButton *loginButton = [[SPSDKLoginButton alloc] init];
// Set delegate for SPSDKLoginButton 
loginButton.delegate = self;
// Optional: Place the button in the center of your view.
loginButton.center = self.view.center;
[self.view addSubview:loginButton];

}
@end

7) ADD ‘LOGIN WITH SAASPASS’ BUTTON FROM INTERFACE BUILDER

1) Add new UIButton in the Interface Builder and set its type as ‘Custom’. 2) In ‘Show the attributes inspector’, under ‘Button’ section, select ‘Custom’ as Type.

3) In ‘Show Identity Inspector’, under ‘Custom Class’ section, select ‘SPSDKLoginButton’ as Class.

4) In ‘Show the Connections Inspector’, set the delegate for the SPSDKLoginButton. (You can also set delegate programmatically after adding SPSDKLoginButton as IBOutlet to your ViewController)

8) HANDLE RECEIVED RESPONSE

Add this method for handling responses or some error in the SPSDKLoginButton delegate:

//Method for received results from login action

-(void) loginButton:(SPSDKLoginButton *)loginButton

didCompleteWithResult:(SPSDKLoginResult *)result withError:(NSError*)error

{
if (error) {
//Process error
} else if (result.isCanceled) {
//Cancelled
}else {
//Logged in
}
}

‘Open In Mobile App’ - Integration

Once your login is integrated with SAASPASS; your users have a second way to log in to the custom mobile application.

They can open SAASPASS mobile app and tap on the ‘Open in mobile app’ button displayed in the user account of your application:

Once SAASPASS checks the user credentials, the custom mobile app will get the information of the account to be logged in.


Integration

Make sure you have completed steps 1 to 5 on ‘Login With SAASPASS’ - Integration section. Later proceed with these extra steps

6) CONNECT APPLICATION DELEGATE AS SPSDKMANAGER DELEGATE

To handle ‘Open In Mobile App’ requests you need to set your AppDelegate as SPSDKManagerDelegate

// Add this delegate into your Application Delegate
@interface AppDelegate : UIResponder <UIApplicationDelegate, SPSDKManagerDelegate>
// Add this on your applicationDidFinishLaunchingWithOptions method
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Set delegate method for SPSDKManager
[SPSDKManager sharedInstance].delegate = self;
}

7) HANDLE RECEIVED LOGIN REQUESTS

Add this method for handling ‘Open In Mobile App’ requests in your AppDelegate (SPSDKManagerDelegate)

//Method for handling 'Open In Mobile App' requests
-(void) didLoginRequestReceivedWithResult:(SPSDKLoginResult *)result
withError:(NSError*)error
{
if (error) {
//Process error
} else {
//Log user in
}
}

Import SAASPASS SDK To Xcode Project(Swift)

Add bridging header to use the SDK in your Swift Project

‘Login With SAASPASS’ - Integration

Add ‘login with saaspass’ button code

// AppDelegate

func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {    
        return sharedInstance.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
    }

Add ‘login with saaspass’ button from interface builder

// Make AppDelegate a delegate of SPSDKManagerDelegate
// Code:
class LoginViewController: UIViewController, SPSDKLoginButtonDelegate {}

// Add this to the body
override func viewDidLoad() {
        super.viewDidLoad()

//        Add a SaasPass-branded login button to your app
//        let loginButton = SPSDKLoginButton.init(frame: CGRect.init(x: 60, y: 440, width: 200, height: 50))
//        Optional: Place the button in the center of your view.
//        loginButton.center = self.view.center
//        self.view.addSubview(loginButton)
    }


Handle received response

// Code:
func loginButton(_ loginButton: SPSDKLoginButton!, didCompleteWith result: SPSDKLoginResult!, withError error: Error?) {
        if error != nil {
            // Process error
        } else if (result.isCanceled) {
            // Cancelled
        } else {
            // Logged in
        }
    }

Swift integration

Connect application delegate as spsdkmanager delegate

// Code:
    // Add this delegate into your Application Delegate
class AppDelegate: UIResponder, UIApplicationDelegate, SPSDKManagerDelegate {}

    // Add this on your applicaton(,didFinishLaunchingWithOptions)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        sharedInstance.delegate = self
        return true
    }

Handle received login requests

// Code: 
func performLogin(result: SPSDKLoginResult) {
        // Logged in
        let controller = self.window?.rootViewController?.storyboard?.instantiateViewController(withIdentifier: "SuccessfulLoginViewController")
        self.window?.rootViewController?.present(controller!, animated: true, completion: nil)
        AppDelegate.loggedIn = true
    }

    func didLoginRequestReceived(with result: SPSDKLoginResult!, withError error: Error!) {
        if (AppDelegate.loggedIn) {
            if ((result) != nil) {
                self.performLogin(result: result)
            }
        }
    }

Android SDK

Introduction

SAASPASS SDK allows to set up the communication between the custom mobile app and the SAASPASS mobile app.

This communication is part of the user authentication process. At the end point, the custom mobile app will receive the login response through the SDK.

Steps for Integration in Android.

Terminology


Android SDK

SAASPASS SDK VERSION: 1.0.0

SDK RELEASE DATE: 2015/12/06

Download Android SDK

Download Android Sample App


Android Studio Set Up

1) Take the downloaded package and place it in the libs folder.


2) In gradle.build file add the following code:

repositories{ 
    flatDir { 
        dirs 'libs' 
    } 
} 


3) Under dependencies add:

compile(name:'saaspassSDK', ext:'aar')


4) Sync your project and the SDK is ready to use.


‘Login with Saaspass’ - Integration

1) Get the application key


2) Open the androidmanifest.xml

<activity android:name="com.example.custom.MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="saaspasssdk-applicationKey" />
</intent-filter>
</activity>

If Activity is a LAUNCHER activity, add two intent filters instead:

<activity android:name="com.example.custom.MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="saaspasssdk-applicationKey" />
</intent-filter>
</activity>

Enter the Application Key got in step 1 instead of applicationKey

3) Create an activity

Define the ‘Login With SAASPASS’ button in the Layout:

<com.saaspass.widget.SaasPassLoginButton"
android:id="@+id/btnlogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"/>


Add imports:

import com.saaspass.controller.SaasPassInitializer; 
import com.saaspass.interfaces.SaasPassCallback; 
import com.saaspass.login.LoginResult; 
import com.saaspass.widget.SaasPassLoginButton;


In Activity class declare the widgets you defined in the activity’s layout as fields of this class:

private SaasPassLoginButton loginButton;


The SDK needs to be initialized. Define the instance in Activity class:

private SaasPassInitializer saasPassInitializer;

In onCreate() using findViewById initialize the widget:

saasPassInitializer = new SaasPassInitializer(this); 
loginButton = (SaasPassLoginButton) findViewById(R.id.btnlogin); 
loginButton.setOnClickListener(this); 

In onCreate() method after initializing SaasPassInitializer put the following code:

loginButton = (SaasPassLoginButton) findViewById(R.id.btnlogin);
loginButton.setOnClickListener(this);
saasPassInitializer.login(this, new SaasPassCallback <LoginResult>() {
@Override
public void onLoadFinishCallback(LoginResult result) {
username = result.getUsername();
trackerId = result.getTrackerId();
//after getting username and trackerId handle the login process 
}
@Override
public void onCancel() {
Toast.makeText(getApplicationContext(), "Action Canceled!",Toast.LENGTH_SHORT).show();
}
@Override
public void onError(String error) {
Toast.makeText(getApplicationContext(), error, Toast.LENGTH_SHORT).show();
}
});

In onClick() method for login button create and register callback like follow:

saasPassInitializer.initCallback(this, appKey);

‘Open In Mobile App’ - Integration

Once your login is integrated with SAASPASS; your users have a second way to log in to the custom mobile application.

They can open SAASPASS mobile app and tap on the ‘Open in mobile app’ button displayed in the user account of your application:




How To Get A Hashkey

On OS X :

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

On Windows :

keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64

For development purposes, you may use different hashkeys working on debugging mode. Add them under application settings ‘Hashkey’ separated by ‘;;’. If you create a new debug hashkey, submit the password field empty. Only enter the password for the release hashkey generation. Don’t forget to add the release hashkey on SAASPASS.

To get a Hashkey open Command Prompt(cmd) and execute the following cmd commands:

Javascript SDK

Instructions

Integrate your JavaScript Web App with SAASPASS

Integration Steps

<iframe  src="https://www.saaspass.com/sd/widget/?appKey=LAJC2CYB5SZNCDPW"
            onload="saaspassWidgetLoaded(this)" id="widgetId"></iframe>





function saaspassWidgetLoaded(iframe) {
    var username = getUrlParam('username');
           if (username) {
                    iframe.contentWindow.postMessage({username: username}, iframe.src);
           }
}





SaaspassJwtClaims loggedInUserClaims = SaaspassJwtValidator.validateJwtAndReturnClaims(jwt, yourAppSecret);

* SaaspassJwtValidator.java is a util class provided in sample project that takes JWT and App Password to validate JWT and returns user claims with SaaspassJwtClaims object.





String successPage = "/success.html";

String contextPath = request.getContextPath();

String usernameParam = "?username="+loggedInUserClaims.getUsername();

response.sendRedirect(contextPath + successPage+usernameParam);

* This uses username of authenticated user and redirects user to ‘success.html’ in the project which welcomes user with his username.