GoodData PGP Single Sign-On

This Single Sign-On (SSO) implementation is a custom proprietary implementation provided by GoodData. This implementation is based on the PGP keypair exchange. It allows your application to sign in an existing GoodData user. The authentication is done not by username and password but by generating a session-specific token using a pair of PGP keys.

Depending on your current situation and use case, the GoodData PGP SSO is sometimes easier to implement than SAML SSO.

This article assumes that you access your projects at https://secure.gooddata.com/.

If you are a white-labeled customer, replace secure.gooddata.com with your white-labeled domain in procedure steps or examples when needed.

Contents:

Implementation Process

A complete implementation requires actions on both sides, yours and GoodData’s.

  • GoodData deploy your public key and an SSO provider configuration.
  • You implement a login mechanism that uses the GoodData login resource.

The whole process usually takes few working days. Here are the basic steps:

  1. You send a request to GoodData Support to create an SSO provider.
    Include your public PGP key in the request. If you need to generate a new PGP key pair, see How to Generate a Public-Private Key Pair. Do not delete the PGP header and footer (BEGIN/END) from the public key that you are sending.

  2. GoodData deploys your SSO provider to the production environment. You receive a unique SSO parameter to use in user provisioning.
    This parameter is SSOProvider in the API for managing users.

    Only a domain administrator can create or modify a user with the ssoProvider parameter specified.

  3. You set up your SSO environment.

Example Use Case: Embedding GoodData

In the following example, you are embeding a dashboard into your application. To do so, you are doing the following:

  • Posting the PGP login request form parameters to the PGP login URL
  • Posting the result target to an iframe
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <!-- Prevent content caching --> 
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>
    <meta http-equiv="Pragma" content="no-cache"/>
    <meta http-equiv="Expires" content="0"/>
    <title>Example GoodData PGP SSO Login</title>
</head>
<body>
<form id="helperForm" target="embeddedGoodDataIframe" method="post" action="https://secure.gooddata.com/gdc/account/customerlogin">
    <input id="targetUrl" type="hidden" name="targetUrl" value=""/>
    <input id="ssoProvider" type="hidden" name="ssoProvider" value=""/>
    <input id="encryptedClaims" type="hidden" name="encryptedClaims" value=""/>
</form>

<iframe name="embeddedGoodDataIframe"></iframe>
<script type="text/javascript">
    let targetUrl = "/dashboard.html";
    let ssoProvider = "sso-provider-name";
    let pgpMessage = "-----BEGIN PGP MESSAGE-----\n" +
    "\n" + "hQIOA3sav0dr/91SEAf+IzO38qQ9TBnUz2YRtHCgAX7sOwG8v/KdXNJa3TMC7Ed/\n" +
    "zoZDIzJnZHaAT+h356XX+f2lAFbJHqs1HUGoOMM1XwRShrC2tSiNdHTh14bZk3MS\n" +
    "PN52RyoNHEWa6A8d0Ptsx9vhMbPVfRVmOJHiRaKmxZMw5i4OUvj2nDgPXtzDGGDD\n" +
    ... "zW1FkFtZpE0bEHSrMEpKCKy68E4yRyFKo7CUIgmTn1EC59WMJ0a+ERt1YgRVn1fb\n" +
    "O8VPB/H6a4zyO8Q1/MnRfS++YlRHdzjT/f+cKstGrEjPAFYpW3GPkN0LI+xo/JQY\n" +
    "S/TpYhp3+Cghb0O9rusiTRnJ88dQ07aysqpB6Xs=\n" +
    "=DkmC\n" +
    "-----END PGP MESSAGE-----";
    document.getElementById('targetUrl').value = targetUrl;
    document.getElementById('ssoProvider').value = ssoProvider;
    document.getElementById('encryptedClaims').value = pgpMessage;
    document.getElementById('helperForm').submit();
</script>
</body>
</html>

Disable Caching

We recommend that you serve the page with HTTP headers which disable caching because it is more reliable than meta tags. For more information, see https://www.mnot.net/cache_docs/#META.

Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0

Post the PGP Login Request Form Parameters

No encoding is needed when posting the parameters.

  • API resource: https://secure.gooddata.com/gdc/account/customerlogin
  • Method: POST
  • Parameters:
    • targetUrl defines the URL of the dashboard, report or any other page that you want to embed. The URL is relative to the GoodData server starting with a slash (“/”).
    • ssoProvider corresponds to the ssoProvider parameter used in the API for managing users.
    • encryptedClaims must be dynamically generated based on the user who you want to authenticate (see Create Encrypted Claims).

For more information about the API call, see the API documentation for SSO PGP login.

Do not use the PGP SSO GET method. This method is no longer supported and stopped working on February 15, 2019 (see PGP SSO GET Method).

Create Encrypted Claims

You have to dynamically generate an encryptedClaims parameter.

Steps:

  1. Create a JSON file in the following format:

    {
      "email": "end.user@domain.com",
      "validity": 123456789,
      "notBefore": 11515111,
      "notOnOrAfter": 11515211
    }
    • email (mandatory) corresponds to the user account set up in GoodData with SSO permissions. This email is used for logging in through the SSO login resource.
      The email is case-sensitive: User@domain.com and user@domain.com are not the same.

    • validity (mandatory) is a date in the UTC timezone (UNIX timestamp format and INTEGER data type) when the generated token expires. It must be set from a minimum of +10 minutes from present up to a maximum of 36 hours from present.

    • notBefore (optional) is a UNIX timestamp (in seconds) that specifies the earliest instant in time when the login session begins being valid.

    • notOnOrAfter (optional) a UNIX timestamp (in seconds) that specifies the instant in time when the login session expires.

    Though the notBefore and notOnOrAfter parameters are optional, we strongly recommend that you use them because they minimize a potential abuse of a login session. These parameters ensure that a login session is valid within the specified period only (and it must not last longer than few minutes).

  2. Sign the JSON file using the private part of your key.
    Do not use the --clearsign option.

    gpg --armor -u pgpOwner.user@domain.com --output signed.txt --sign json.txt
  3. Encrypt the result using the GoodData public PGP key.

    gpg --armor --output enc.txt --encrypt --recipient security@gooddata.com signed.txt
  4. Use the encrypted message as the encryptedClaims parameter in the PGP login request (see Post the PGP Login Request Form Parameters).

Authentication Process

The following picture shows the whole authentication process:

PGP-based SSO Security

Supported Encryption Algorithms

Public keyRSA, RSA-E, RSA-S, ELG-E, DSA
Cipher3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH

SSO Session Duration

When an SSO session is initiated via login, the initiating application can define the length of the session token in the JSON.

This session duration is defined using the validity parameter. The validity parameter must be set as a UNIX time code that is a minimum of +10 minutes from present up to a maximum of 36 hours from present.

The header of the response to the login request contains a SuperSecured Token (SST), which defines how long the session can last regardless of whether a user is active or not. If the SSO user is still logged in to the GoodData platform at the moment when the SST expires, the GoodData application stops responding.

To renew the token, refresh the parent page. This lets you log in back to the GoodData platform, and starts a new GoodData session over SSO.

You must control your PGP key validity and update it before it expires.

Troubleshooting

Problem:

I cannot load a dashboard.

Reason:

The SSO handshake failed.

Solution:

This may be due to an improper SSO configuration or using a wrong SSO integration method. If you are not sure what is wrong, contact GoodData Support.