Single Sign-On (SSO)

Before you begin:

Single sign-on (SSO) allows ReviewPro user's to autheticate via a third-party site such a companies internal intranet. 

Users of this API should take care to protect the shared secret used to sign requests between the third-party trusted site doing the authentication and ReviewPro.  You should also ensure that proper security and coding practices are followed to avoid unauthorized access to your ReviewPro account. 

How it works:

SSO works by ReviewPro and the authenticating third-party entity e.g. corporate intranet-- sharing a secret key.  When the third-party wishes to authenticate a user, they make a post to ReviewPro sending the username, UMT timestamp in milliseconds and a signature generated by hashing the secret + username + timestamp.  When ReviewPro receives the request, we lookup the shared secret associated with that user’s account and attempt to generate the same hash.  If the hashes match, the user is authenticated.  ReviewPro also does a second check to make sure the user is coming from an authorized domain.  

Configuration:

Before you begin coding you will first need to configure your SSO Profile via our Backoffice API.

Use the "Create SSO Profile" endpoint to add new SSO Profile to your account including the following settings:

  • Name (optional): the name for your SSO Profile
  • Active (required): true if this profile is active (usually you want this field to be true for new profiles)
  • Remote Login URL (optional): the URL ReviewPro will redirect the user too if he/she is not logged in
  • Remote Logout URL (optional): the URL ReviewPro will redirect to when a user selects “logout” within the application e.g. redirect back to the corporate intranet site
  • Domain URL (optional): only users coming from this URL will be able to authenticate using SSO

After a successful creation, the response will contain a secret key you can use to login. Make sure to store the key safely, as we will only return the full key on creation.

The response will also contain a SSO Profile Id you can assign to your users via "Create/Update User" endpoint which accepts a field "ssoProfileId". Users associated with this id will be able to login using the mentioned secret key.

Import Note on the Timestamp

  • ReviewPro only allows a 30 second difference between the timestamp sent and the timestamp used to verify.  Any timestamp older than 30 seconds will result in an authentication denied
  • The clock of the client generating the timestamp must be synced using NTP.
  • The clock must be in “time from epoch” and not unix time.  If your system generates unix time by default, just multiple the value by 1000
  • The timestamp must be in UMT (GMT)

How to Sign the Request

  • The signature is based on the HMAC format.  Most modern programing languages have libraries for HMAC 
  • The hashing algorithm to be used is SHA512
  • The signature is the result of the function SHA512(shared secret + username + timestamp)
  • Convert the resulting signature to a hex value

Sending the Request

  • You will need to send the following parameters to ReviewPro in order to authenticate using SSO:
    • j_username, the username of the user (note the user must have been already created in the system)
    • j_timestamp, the timestamp
    • j_signature, the HMAC generated signature as described in the previous section
    • You must generate a POST request to https://delta.reviewpro.com/login

Sample implementation

The following Python example shows an implementation of SSO.  When a user clicks on the link ending in /loginsso, the backend populates the j_username,j_timestamp and j_signature parameters and pass these values to an html template to render the results html.  

@app.route('/loginsso')
@nocache
def loginsso():
    j_username = 'reviewpro@reviewpro.com'
    j_timestamp = str( int(round(time.time() * 1000)))
    hm = hmac.new(SHARED_SEC, "reviewpro@reviewpro.com%s" % j_timestamp, digestmod=hashlib.sha512)
    j_signature = hm.hexdigest()
    return flask.render_template("loginsso.html", j_username=j_username, j_timestamp=j_timestamp, j_signature=j_signature)

On the template side, we simply create a form, populate the j_* values, submit the form via the onload of the body:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>redirect</title>
</head>
<body onload="loginsso_form.submit()">
<form  name="loginsso_form" action="https://delta.reviewpro.com/login" method="post">
    <input type="hidden" name="j_username" value="{{ j_username  }}"/>
    <input type="hidden" name="j_timestamp" value="{{ j_timestamp  }}"/>
    <input type="hidden" name="j_signature" value="{{ j_signature  }}"/>
</form>
</body>
</html>

Important Considerations:

  • Remember that after you generate a signature you only have 30 seconds for your request to be received.  For this reason don’t generate a form with the values prefilled directly in your intranet or other page as by the time it’s sent it will most likely be expired.  Rather create an intermediate page, as in the example
  • Remember that the timestamp must be synced via UTP
  • The endpoint only accepts the POST http method
  • The order of the values in the signature are import
  • Use SHA512 for the hashing.