goodid

GoodID Connect JS library


Keywords
goodid, login, authentication, passwordless
License
GPL-3.0
Install
bower install goodid

Documentation

GoodID

GoodID Connect

GoodID Connect is a helper JavaScript library to easily implement and use the GoodID service. If you're new to GoodID or you want to find out more about it, visit the service's webpage: https://goodid.net

If you want to try the product first to see how the process works, then head to our interactive developer demo site at http://developer.demo.goodid.net You can download our full integration manual there.

Installation

There are several options to download, install and start using GoodID Connect.

Install with Bower

GoodID Connect is a registered package on Bower. Install it with the following command:

$ bower install goodid

The -S parameter adds the library to the bower.json dependencies section.

This will install it under the bower components directory, bower_components is the default name of this dir.

Install with npm

NPM

GoodID Connect is available from the npm registry as well. You can install it with the command:

$ npm install goodid

If you add the --save switch, it will save it under your dependencies section of your package.json.

This will add the package goodid under your node_modules directory. The main file for this is the uncompressed version, however there is also a minified version with the name connect.min.

Include from CDN

GoodID Connect is available from the following locations:

//cdn.jsdelivr.net/goodid/latest/connect.min.js

CDN is kindly provided by jsDelivr. Check out their version aliasing doc for more options on how to include the library.

goodid.net

The library is also available directly from goodid.net:

http://connect.goodid.net/connect.min.js

For the time being this URL only supports HTTP. HTTPS version is coming soon. Note, that at the moment, this is NOT a CDN.

Clone git repo

If none of the above solutions work for you, or you just want to place this somewhere custom, you can clone this repo with the command:

$ git clone https://github.com/idandtrust/goodid.git

This way you can just git pull to update the lib.

Alternatively, if you want go the extra-manual route, you can just download the lib as a zipped archive from GitHub here and place it whereever you like.

Right, but which one to choose?

Since GoodID is still in beta phase, this API is more or less prone to change. For the time being, you should stick to the CDN version available at jsDelivr. This will always provide you the latest and greatest that GoodID has to offer. We understand that you have your concerns downloading from an external location and would host the script locally instead. However JsDelivr is a fast and reliable service, so we can easliy recommend it.

Usage

GoodID Connect is fully AMD and CommonJS-compatible. Alternatively, you can use its public API in the global JS scope.

AMD

You can use GoodID Connect with any AMD loader. The following example uses RequireJS:

index.html:

<script data-main="main" src="path/to/require.js"></script>

main.js:

requirejs.config({
  paths: {
    goodid: 'path/to/goodid/connect' // or connect.min for the minified version
  }
});
requirejs(['app']);

Here you need to replace path/to/goodid/connect with the actual location, be it a local or CDN-served file.

app.js:

define(function(require) {
  var goodid = require('goodid');

  goodid.init({
    client_id: '[your client_id here]',
    onlogin: onLogin
  });

  function onLogin(e) {
    if (goodid.isLoginSuccessful()) {
      goodid.getClaims(function(claims) { /* ... */ });
    } else {
      var error = goodid.getErrors();
    }
  }

  return goodid;
});

CommonJS

You can also use the library with a CommonJS wrapper. Here is an example for that:

var goodid = require('./path/to/goodid/connect'); // or connect.min for the minified version

module.exports = function() {
  goodid.init({
    client_id: '[your client_id here]',
    onlogin: onLogin
  });

  function onLogin(e) {
    if (goodid.isLoginSuccessful()) {
      goodid.getClaims(function(claims) { /* ... */ });
    } else {
      var error = goodid.getErrors();
    }
  }
}

Replace path/to/goodid/connect with your preferred module file location. See the installation guide for GoodID Connect above.

You can use Browserify, Webpack or some other bundler to use these modules in your browser.

Global object

If you use neither AMD, nor CommonJS, then GoodID Connect exposes a global variable on the window object, called GoodID. Insert the following code anywhere within your HTML body:

<script>
'use strict';

function initGoodID() {
  GoodID.init({
    client_id: '[your client_id here]',
    onlogin: onLogin
  });
}

function onLogin(e) {
  if (goodid.isLoginSuccessful()) {
    goodid.getClaims(function(claims) { /* ... */ });
  } else {
    var error = goodid.getErrors();
  }
}

(function(d, t, i) {
    var s, b;
    if (d.getElementById(i)) {return;}
    s = d.createElement(t); s.id = i;
    s.src = 'path/to/goodid/connect.min.js';
    s.onload = s.onreadystatechange = initGoodID;
    b = d.getElementsByTagName(t)[0]; b.parentNode.insertBefore(s, b);
})(document, 'script', 'goodid-sdk');
</script>

You will need to replace path/to/goodid/connect.min.js with your preferred location. For this setup option, we suggest using the one provided by our CDN-hosted version that's available on this location: //cdn.jsdelivr.net/goodid/latest/connect.min.js. See more installation options in the section above.

GoodID login button

GoodID works by opening a popup window that shows your users the GoodID authentication screen. To open this popup window, you can manually call the signIn() method of the API, or use the custom <goodid:login> HTML tag provided by GoodID Connect.

Manual method

You can use the signIn() method like this: (this example uses jQuery)

<button id="goodid-login">Sign in with GoodID</button>
<script>
'use strict';

var goodid;
/* init GoodID here */

$('#goodid-login').click(goodid.signIn);
</script>

Automatic sign-in button

There are two choices here:

  • Use the HTML-compliant tag: <div class="goodid-login-button"></div>
  • Use the XML custom tag: <goodid:login>

A basic example with the HTML <div> tag goes like this:

<div class="goodid-login-button" data-onlogin="goodidLogin"></div>

When GoodID Connect loads up, all of these tags will be replaced by the actual button.

Specific attributes

The following attributes can be used with the button tags:

HTML param XML param Type Description
data-onlogin onlogin string Enter a methods's name in the initialization's context to be called when a login event (successful or failed) happens.
data-scope scope string A list of scopes to be requested. Can also be defined during the GoodID initialization. You can read more about scopes in the integration docs.

Public API

The GoodID Connect API exposes the following methods:

init(config)

returns: string

parameters:

  • config An object that lets you configure your GoodID implementation. See the possible configuration properties below.

This method initializes GoodID Connect.

set(parameter, value) / set(object)

returns: this

parameters:

  • parameter The name of the config parameter that you want to set
  • value The value of the parameter. The type of this parameter is dependent on the param you want to set.
  • object Give an object when you want to set multiple config parameters.

You can set the value of one or more configuration parameters.

signIn()

returns: false

This is an event handler method that you call when you want to open the GoodID popup. For example you can assign this method to a click event of a button, then the GoodID popup window will open when clicking that button.

This method returns false, so it will prevent the default event (and stop event propagation, if applied by jQuery) on the target element.

getParameters()

This method will return all the parameters and its values in a JSON object that you got back after a login event. Parses the params after the hashmark.

getAccessToken()

returns: string

When an access token is requested to access the userinfo endpoint, you can get its value after a successful sign-in by calling this method. Returns null when no access token can be returned.

getIdToken(callback)

parameters:

  • callback A callable method with the parameters <err, idToken> that will be called after the ID token is parsed.

The err parameter of the callback will contain the error that occured when the parsing failed, and the idToken will contain the parsed ID token in the following format:

{
  "header": { "alg": "RS256", "typ": "JWT"},
  "payload": {"sub": ...},
  "signature": "[the ID token's signature]"
}

The possible contents of the payload object can be found in the OpenID Connect specification

The callback method has the signature of a NodeJS callback (a "nodeback") so it can be easliy promisified.

getClaims(callback)

parameters:

  • callback Callback method. See definition and parameters at getIdToken()

This method will fetch the user claims that are included in the ID Token. This method will initially do a getIdToken() call, so if you just want the user claims in the ID Token, call this method instead. The callback has the signature <err, claims> The claims is a JSON object that contains the user claims from within the ID token.

getClaimsFromUserinfo(callback)

parameters:

  • callback A callback method that is executed after the XHR call of the UserInfo endpoint returns either successfully or fails. Signature: <err, claims> where the err param is an object of type Error, and claims is a JSON that contains the returned claims without the sub claim.

When an access token was requested, an XHR request will be fired on the UserInfo endpoint to get these claims. The callback will be called after the XHR call returns.

getError()

returns: object

On a failed or a denied sign-in, this method will return the error and description, like this:

{
  "error": "[error code]",
  "description": "[textual representation of the error]"
}

getLoginStatus()

returns: string

This method returns a string representing the current login status. You can use this for example in the method called by the onlogin configuration parameter.

Return values:

  • success When the sign-in was successful
  • denied When the sign-in was denied or failed
  • nologin When no previous login attempt was found in the current session

isLoginSuccessful()

returns: boolean

Returns true when the login was successful, false otherwise.

Configuration parameters

Since GoodID is an OpenID Connect-compliant service, most of these parameters refer to parameters sent to the authorization endpoint of the provider. For further explanation and use-cases, please refer to the OIDC specs.

Parameters

client_id

Required

type: string

Your client ID, which you receive when you become a client of GoodID. You can sign up to GoodID on this page.

redirect_uri

type: string

This is the URI on your site where the popup will redirect to with the ID token (on success) or the error (on failure) in the fragment part of the URL. By default, this will be the same page where the user clicks the GoodID sign-in button.

scope

type: array or string

The claim scopes you want. Possible scopes are: profile, email, address, phone, billto, pcard and openid. The expected format is a space-separated string of one or more of these scopes.

claims

type: object

Specify an object as the value of this parameter. For the exact format and claims that can be added, please refer to the integration document.

access_token

type: boolean

Enter true, if you want to request an access token, false, if you don't. If you want to request claims in the userinfo, then you need to have an access token, otherwise the popup will throw an error.

state

type: string

The state string is an opaque value that is used to maintain state between the request and the callback. This is usually done to mitigate XSRF attacks. Its value will be returned verbatim within the redirect URL's fragment.

nonce

type: string

This parameter can be used to send a random string that will be returned unmodified in the ID token's nonce claim. This can be used to mitigate replay attacks.

onlogin

type: function

A callback function that will be invoked when a sign-in event (successful or otherwise) happens. Receives the event object as parameter.

acr

type: integer

You can specify the security level of the mobile app that you demand from your users when they authenticate with GoodID. The following values are defined:

  • 1 This value means that a PIN will be requested once after the first login attempt. Stores it in the app's software env. This is the default.
  • 2 Level 2 will always require to enter the user's PIN after each login attempt. PIN is still stored in the software storage space.
  • 3 Level 3 is the same as level 2 with the addition that the PIN is stored in the phone hardware.

generateKey

type: boolean

The ID Token and UserInfo endpoints both return a JWE object. This means that it is both signed and encrypred. This is how GoodID realizes end-to-end security; the data is signed, then encrypted on the app, and the web is just a mediator in this process. In order to achieve this, GoodID needs two key pairs: one to sign/verify and one to encrypt/decrypt. Later on, you will be able to provide your own, but till then (or if you choose not to upload any keys) GoodID Connect can generate these for you. This is what this parameter does: it defaults to true, so when you don't specify this, two keypairs will be generated. This is totally transparent to you: the lib does everything that's needed to get your claims back plain text on your page. If you elect to handle everything by yourself (and key upload is available on GoodID ;) ) then just simply turn this config off, so Connect will stop generating keys.

Default configuration

{
  "client_id": null,
  "redirect_uri": "[current domain + pathname]",
  "scope": "openid",
  "claims": null,
  "access_token": true,
  "state": null,
  "nonce": null,
  "onlogin": null,
  "acr": 1,
  "generateKey": true
}

Acknowledgments

  • This library uses code from toddmotto's atomic.js library (GitHub, License)
  • Uses the Object.assign polyfill from MDN (Page)
  • Uses the CustomEvent polyfill from MDN (Page)