CoreID

Introduction to Assently CoreID

The Assently CoreID Client is a javascript plugin that allows your users to securely authenticate with electronic identification (eID) without any of the hassle. CoreID Client works in both your app and your website.

Let us worry about integrations, security, browser support and maintenance while you focus on creating value for your users.

Contact us at info@assently.com to get started.

How does it work?

Add our javascript to your website/app, generate a token, configure with a few lines of code and you're good to go!

CoreID securely communicates with our servers which handle the integrations with the different eID providers.

Check out our quick start guide to see how to get started with CoreID.

Languages

The client is localized in the following languages:

  • English
  • Finnish
  • Norwegian
  • Swedish

Security

All traffic is encrypted via SSL/TLS.

Information is sent via JSON web tokens encrypted with HS256.

Messages are decoded and verified with shared secrets.

Getting started

Follow our guide to get started in authentication or use this guide for signing !

Technical details

The client is 100% JavaScript and uses XMLHttpRequests and embeds via an iframe.

Test

The test client will target the test environment of our API and the providers (if applicable).

Make sure to use your test account secrets.

Please refer to each providers documentation on how to test authentication with a specific provider.

<script src="https://coreid-test.assently.com/embed/coreid.js"></script>

Production

Only real persons or subjects can authenticate.

Make sure to use your production secrets.

<script src="https://coreid.assently.com/embed/coreid.js"></script>

Message formats

We use JWT (JSON Web Tokens) for secure communication between our server and your clients.

If you want to use SAML please contact us at info@assently.com for more information

Client API and configuration

Functions

init({ config [object], token [string], callback [function] })

Initializes the CoreID client, must be called before start().

var config = {};
var myCallback = function(data) {};

coreid_client.init({
  config,
  'YOUR TOKEN HERE',
  myCallback
});

start()

Shows the CoreID client to the user.

coreid_client.start();

close()

Hides the CoreID client from the user.

coreid_client.close();

Configuration

token - String, undefined

The secret sauce!

See the this section for information on how to generate your auth token.

token: '😎✌️🏽'

callback - Function, undefined

This function will be invoked by the client at the end of transactions, both for success and fail or in case of an error.

// a basic example
callback: function(data) {
  if (data.success === true) {
    // sweet! let's validate and keep this token for whatever
    $.post('api/token/validate', data.token, handleSuccess, handleError);
  } else if (data.type === 'failed') {
    console.log('authentication failed', data.errorMessage);
  } else if (data.type === 'cancelled') {
    console.log('user closed the app');
  } else if (data.type === 'error') {
    console.log('an error occurred', data.errorMessage);
  }
}

The callback recieves an object parameter that can have the following properties

// A successful transaction object would look like this
{
  success: true,          // always exists if authentication succeeded
  token: '#####',         // JWT that contains identity token, validate this!
  provider: 'se-bankid',  // provider that user authenticated with
  type: 'authenticated',  // transaction type
  transactionId: '####'   // is present for most of the providers, use this as a reference when contacting Assently Support
}

// An unsuccessful transaction object
{
  type: 'failed',         // if authentication failed
  provider: 'se-bankid',  // provider used
  errorMessage: ''        // information about the possible error
}

// User closed or cancelled CoreID client,
// can happen after authentication is successful
{
  type: 'cancelled',
  errorMessage: 'USER_UI_CANCEL
}

// An error occurred, which usually indicates
// a wrong configuration
{
  type: 'error',
  errorMessage: '' // details about the error,
  success: false
}

config.allowedEids - String[], ['*']

This option allows you to define which eID providers you want to enable.

The default value ['*'] will enable all providers.

[
  '*',                // All
  'fi-mv',            // Finnish Mobiilivarmenne
  'fi-tupas',         // Finnish Tupas
  'fi-vrk',           // Finnish VRK
  'no-bankid',        // Norwegian bankID
  'no-bankid-mobile', // Norwegian bankID mobile
  'se-bankid',        // Swedish bankID
  'se-telia-osif'     // Swedish Telia
  'dk-nemid'          // Danish NemID
]

Note that you need to have at least the same eIDs in your token since token parameters define authorization to the CoreID API.

config.location - String, undefined

This option configures the default country view when starting the client.

Overriden by config.provider.

If undefined the user will first be presented with a view to select country.

'se' // default view will display the Swedish providers
'fi' // ... Finnish providers
'no' // ... Norwegian providers

config.mode - String, undefined

Sets the mode. Depending on the mode only to that mode available eIDs will be shown to the user.

'auth' // Authentication mode
'sign' // Signing mode

config.provider - String, undefined

Sets the default view to the specific provider, overrides default view set by the location option.

'fi-mv'            // Finnish Mobiilivarmenne
'fi-tupas'         // Finnish Tupas
'fi-vrk'           // Finnish VRK
'no-bankid'        // Norwegian bankID
'no-bankid-mobile' // Norwegian bankID mobile
'se-bankid'        // Swedish bankID
'se-telia-osif'    // Swedish Telia
'dk-nemid'         // Danish NemID

config.providerSettings - Object, undefined

This object allows for provider-specific settings, note that not all providers have this option.

Available configurations:

{
  'se-bankid': {
    // if set to false the client will not try to open the native bankID app.
    // there is an event emitted with all the info you need,
    // see separate section
    autoStart: true, // default
    // customize the 'redirect'-parameter to bankID app
    // see bankID's documentation for more information
    redirectUrl: 'someURI'
  },
  'fi-tupas': {
    // if set, will sort Tupas banks alphabetically, in ascending or descending order
    // if not set, will retain it's original order
    sort: 'asc', // or 'desc'
    // use include to specify exactly which banks you want to be available
    // 'include' will make sure the client only ever lists your selected banks
    // for a list of banks and their IDs, see below
    include: [''],
    // use exclude to specify banks to be excluded
    // this option will be ignored if include-option is specified
    exclude: [''],
  }
}

Tupas banks:

[
  { Id: "08ACDDE6-2C38-418B-ACC7-67CEF0FD24A8", BankName: "Nordea"},
  { Id: "5A57F571-C625-46D8-A721-7F23CBF0A9AE", BankName: "Danske Bank"},
  { Id: "916194F1-A31A-4DBD-B481-EDDD1F5A311D", BankName: "Handelsbanken"},
  { Id: "4885E8D2-C6AC-4732-A3FF-132C4CA9977B", BankName: "Aktia Tunnistus"},
  { Id: "6C583D7B-1C6F-4CBC-9BE9-FA9C26CDD4F1", BankName: "S-pankki"},
  { Id: "2625E44A-3E08-4323-8B4E-D4E0AD1C2615", BankName: "POP"},
  { Id: "1BD11C49-65BF-4DA3-B609-60414EBD8F1F", BankName: "OP"}
]

config.showTitle - Boolean, true

showTitle: true

Setting to show the title inside the frame. Defaults to true.

config.sign - Object, undefined

The sign object is mandatory in sign mode. All properties are required!

{
  title: 'Your title',    // The title
  data: 'Your document',  // The data you want to sign
  type: 'text'            // The format of data, the only allowed value is text, but more types will be added in the future

Events

The client also emits some events via PostMessage that developers can subscribe to.

All events are of type MessageEvent and are dispatched at the target window, subscribe like so:

window.addEventListener('message', function(e) {
  // check e.data.type
});

None of these events are required to be handled by the developer, they are provided for your convenience.

bankId-startClient

MessageEvent {
  data: {
    type: 'bankId-startClient', // event type
    autoStartToken: 'TOKEN',    // needed to start the app correctly
    transactionId:  'guid'      // Assently generated transaction id
  }
}

This event fires when the Swedish BankID app is to be opened.

Contains data to allow developers to start the Swedish BankID app by their own accord.

More about the JWT Auth Token

JWT Basics

Take a couple of minutes and read a little bit at https://jwt.io/introduction/.

JWT Libraries

Find a library at https://jwt.io/#libraries or google a library that supports your platform.

Create the JWT

Use the library to define your claims, specify that you want to use HMAC SHA256 and sign it with the auth secret provided by Assently.

Claims

There are 7 claims that are required, e.g.:

{
  "jti": "3bfae357-c056-4567-b15d-ca657fbdg866",
  "iss": "acme",
  "aud": [
    "se-bankid",
    "fi-mv"
  ],
  "iat": 1467217112,
  "exp": 1467218912,
  "hst": "https://acme.com",
  // Custom display names must be registered with Assently beforehand
  // Valid displaynames are
  // "Assently" for production
  // "test av mobilt bankid" for test
  "dnm": "Acme"
}

Descriptions for each claim can be found below.

"jti"

Name
JWT id

Description
A unique token identifier

Format
Guid 4

Example
"3bfae357-c056-4567-b15d-ca657fbdg866"

Mandatory
Yes

"iss"

Name
Issuer

Description
The customer account name (as issued by Assently)

Example
"acme"

Mandatory
Yes

"aud"

Name
Audience

Description
Should contain the e-ID providers you want your users to choose from.

Note: Make sure the e-ID:s in the token at a minimum includes the "allowedEids" configuration in the client.

Available EIDs:

  • all - All available EIDs
  • se - All Swedish EIDs
  • se-bankid - Swedish BankID
  • se-telia-osif - Swedish Telia
  • fi - All Finnish EIDs
  • fi-mv - Finnish Mobiilivarmenne
  • no - All Norwegian EIDs
  • no-bankid - Norwegian BankID

If using multiple e-IDs, the "aud" value is an array of strings. If using a single e-ID the "aud" value can be a single string value.

Example
["se_bankid", "fi-mv"]

Mandatory
Yes

"iat"

Name
Issued at

Description
Identifies the time at which the JWT was issued.

Format
Unix timestamp

Example
1467217112

Mandatory
Yes

"exp"

Name
Expiration time

Description
Identifies the expiration time on or after which the JWT is not accepted for processing.

Format
Unix timestamp

Example
1467218912

Mandatory
Yes

"hst"

The host that is using the service.

Name
Embed host

Description
The URL of the host including scheme (and if differs from default, port).

Format
URL

Example
"https://www.acme.com"

Mandatory
Yes

"dnm"

Name
Display name

Description
The text (usually company name) to be displayed on the end user's display during authentication.

Note that a custom display name must be registered with Assently in advance. If no display name is registered, "Assently" will be used as default.

In test environment with se-bankid the display name must be specified "Test av Mobilt BankId".

Example
"Acme"

Mandatory
Only for se-bankid and fi-mv

More about the JWT Identity Token

When a user has successfully authenticated you will recieve a JWT in the callback.

1. Verify the signature of the token

To be sure nothing has been tampered with, you must verify the signature of the token with a shared secret.

HMACSHA256(
  base64(header) + '.' + base64(payload),
  secret
)
2. Validate the claims of the token

If any of these claims are invalid you must reject the JWT.

iss
Should match the hostname of the embed script path.


aud
Should match your issuer name provided by Assently


exp
Must be in the future.

3. Done!

The JWT payload contains claims regarding who the authenticated subject is.

How you use this information is up to you.

"sub"

Identifier of the subject

Name
Subject

Description
Can be a national id number, birthdate or phone number.

Example
"19800101"

Mandatory
Yes


"sub.national_id"

The subjects national id number.

Name
National Id

Description
The format can vary depending on EID Provider.

Example
"198001011234"

Mandatory
No


"sub.family_name"

Name
Family name

Description
Last name, surname, or family name of the subjet

Example
"Miller"

Mandatory
No


"sub.given_name"

Given name of the subject.

Name
Given name

Description
Some providers also include middle name(s).

Example
"Frank"

Mandatory
No

"sub.full_name"

Full name of the subject

Name
Full name

Description
Includes first name(s) and last name(s).

Example
"Frank Miller"

Mandatory
No

"provider"

Name
Provider

Description
The name of the e-ID provider that was used to conduct the authentication.

Example
"se-bankid"

Mandatory
Yes

"provider.data"

Name
Provider data

Description
All personal information related to the subject as received from the e-ID provider. This is usually an x.509 certificate that we send along in its raw form encoded as a base64 string

Format
base64 encoded string

Mandatory
Yes

"jti"

Name
JWT id

Description
The unique identifier of the token.

Example
"66619e7a-e34b-4f76-85df-71634328d3g1"

Mandatory
Yes

"iss"

Name
Issuer

Description
The token issuer.

Example
"coreid-test.assently.com"
"coreid.assently.com"

Mandatory
Yes

"aud"

The intended receiver of the token.

Name
Audience

Description
Contains your customer account name.

Example
"some-company-name"

Mandatory
Yes

"iat"

Name
Issued at

Description
Identifies the time at which the JWT was issued.

Format
Unix timestamp

Example
1466429950

Mandatory
Yes

"exp"

Name
Expiration Time

Description
Identifies the expiration time on or after which the JWT is not accepted for processing.

Format
Unix timestamp

Example
1466433550

Mandatory
Yes

"auth_jti"

The JWT id from the auth token used in the same session.

Name
Auth Token JWT id

Description
This claim can be used for comparison with the "jti" claim in the auth token.
A match verifies that the identity received is related to the original request.

Example
"3bfae357-c056-4567-b15d-ca657fbdg866"

Mandatory
Yes

Supported eID Providers

eID Provider Country Authentication Signing
Telia Sweden yes no
BankID Sweden yes no
Tupas Finland yes no
Mobiilivarmenne Finland yes no
VRK Finland yes no
BankID Norway yes text only
BankID Mobile Norway yes text only*
NemID Denmark yes no

* Due to limitations in SIM Toolkit on mobile phones BankID Server has to filter and prepare the “text to sign” before sending it to the mobile phone. The following ASCII input characters are accepted; [0-9] [a-z] [æ] [ø] [å] [A-Z] [Æ] [Ø] [Å] [CR] [LF] [#] [$] [%-&] [(-?] [@] [¡] [£] [¤] [¥] [§] [¿] [Ä] [Ç] [É] [Ñ] [Ö] [Ü] [ß] [à] [ä] [è] [é] [ì] [ñ] [ò] [ö] [ù]. The maximum length for signing data is approx 38 characters.

Working with the eID Providers in different Environments

Test Environment

CoreID test environment connects with the different EID provider's test services. You have the option to use to this environment if you want to try out one or more EID provider using test certificates. Since each EID provider have different ways of authenticating users (software, mobile etc) they way to get a hold of test certificates are also very provider specific.

Swedish BankID (Svenskt BankID)

To test Swedish BankID you need to download a test certificate at

Certificates are available both for mobile and computer use. Instructions on how to install the BankID software and the test certificate are found at

Note that the claim "dnm" (Display Name) in the Auth Token has to be set to "Test av Mobilt BankId" in the test environment.

Swedish Telia

Telia uses a software called NetId that can be downloaded here:

Get test certificates at:

NetId only works in Firefox in Windows.

Snippets

More snippets coming soon. For now, C# is all you get.

C# Code snippets

Auth Token Creation

This C# snippet use System.IdentityModel.Tokens.Jwt library.

public class AuthTokenService
    {
        /// <param name="displayName">Display name is required for Swedish BankId and Finnish Mobiilivarmenne and should be added to token as a "dnm" claim.</param>
        /// <param name="embedHost">The URI of the host. Required claim, should be added as "hst"</param>
        /// <param name="accountId">Customer accountid at Assently</param>
        /// <param name="secret">The secret that is used to sign the JWT. Provided by Assently</param>
        /// <returns>Encoded JWT string</returns>
        public string CreateToken(string displayName, string embedHost, string accountId, string secret)
        {
            // The time at which the token was issued.
            var issuedAt = (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;

            var claims = new List<Claim>()
            {
                new Claim("dnm", displayName),
                 // "jti" (Jwt Id) is a mandatory token identifier. Should be a GUID4.
                new Claim("jti", Guid.NewGuid().ToString()),
                new Claim("hst", embedHost),
                new Claim("iat", issuedAt.ToString()),


                // It is possible to add each implementation as a separate claim
                new Claim("aud", EidAccess.SwedishBankId),
                new Claim("aud", EidAccess.FinnishMobiilivarmenne),
                new Claim("aud", EidAccess.NorwegianBankId),
                // Or add all swedish
                new Claim("aud", EidAccess.AllSwedish),
                // Or all
                new Claim("aud", EidAccess.All)

            };
            // Expiration time for the token, this is how long the token can be used to start an authentication session.
            var expires = DateTime.UtcNow.Add(TimeSpan.FromMinutes(30));

            var jwt = new JwtSecurityToken(
                issuer: accountId,
                claims: claims,
                expires: expires,
                signingCredentials:
                    new SigningCredentials(
                        new InMemorySymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)),
                        "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
                        "http://www.w3.org/2001/04/xmlenc#sha256"
                        )
               );

            var jwtHandler = new JwtSecurityTokenHandler();
            return jwtHandler.WriteToken(jwt);
        }
    }

Auth Token Validation

This C# snippet use System.IdentityModel.Tokens.Jwt library.

public class IdentityTokenService
    {
        public JwtSecurityToken ValidateToken(string token)
        {

            var configuration = ConfigurationManager.AppSettings;
            var tokenHandler = new JwtSecurityTokenHandler();
            var secret = configuration["IdentitySecret"];
            var keyBytes = Encoding.UTF8.GetBytes(secret);

            var tokenValidationParameters = new TokenValidationParameters()
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new InMemorySymmetricSecurityKey(keyBytes),


                ValidateIssuer = true,
                ValidIssuer = configuration["Issuer"],
                ValidAudience = configuration["AccountId"],
                ValidateAudience = true,
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero,
                LifetimeValidator = (before, expires, jwttoken, validationParameters) =>
                {
                    var now = DateTime.UtcNow.Add(validationParameters.ClockSkew);
                    if (before.HasValue && now < before.Value)
                    {
                        return false;
                    }
                    if (expires.HasValue && expires <= now)
                    {
                        return false;
                    }

                    return true;
                }
            };
            SecurityToken validatedToken;

           tokenHandler.ValidateToken(token, tokenValidationParameters, out validatedToken);

            return validatedToken as JwtSecurityToken;
        }

        public bool ValidateJwtId(HttpCookie cookie, JwtSecurityToken identityToken)
        {
            var authToken = new JwtSecurityToken(cookie.Value);
            var authJwtId = authToken.Claims.First(c => c.Type == "jti").Value;
            var identityTokenAuthJwtId = identityToken.Claims.First(c => c.Type == "auth_jti").Value;
            if (authJwtId == identityTokenAuthJwtId)
            {
                return true;
            }
            return false;
        }
    }