Identity Providers

Identity providers can be used to connect existing, external sources of user identities with Tapkey.

Creating a Key Pair

In order to create a new key pair, run

$ openssl genpkey -algorithm rsa -pkeyopt rsa_keygen_bits:4096 -out ip_key -pass stdin -aes256

which will prompt for a pass phrase to secure the key. Instead of stdin, any of the options documented in the Pass Phrase Options section in openssl(1) can be used. For the rest of this guide, strongpassphrase is used as an example pass phrase. Substitute with your own pass phrase.

Info

It is possible to choose an RSA key size of 2048, however, we recommend using 4096 bits. It is not possible to choose an RKA key size < 2048 or > 4096 at the moment.

To extract the public key in a format that can be used with Tapkey, run

$ openssl rsa -in ip_key -pubout

which will print the public key in the following format:

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAv75dbVe+X84JfM0AwziA
   ...
bN26sbHb5Ekh8yHroawdK5cCAwEAAQ==
-----END PUBLIC KEY-----

Registering a New Identity Provider

Registration of identity providers is described in the OAuth Client and Identity Provider Registration section.

Creating JWT Tokens

The following snippet outlines the creation of JWT tokens that can be used with the Token Exchange grant type. The issued tokens must at least contain the following fields:

  • aud: The audience of the identity provider as specified during registration.
  • iss: The issuer of the identity provider as specified during registration.
  • sub: An identifier representing the subject that this JWT token is issued for.
  • iat: Issued at timestamp.
  • exp: Expiration timestamp. A typical value for exp is iat + 1 hour.
  • http://tapkey.net/oauth/token_exchange/client_id: The ID of your OAuth client registered with Tapkey for the Token Exchange grant type.

Additionally, the token must be signed using the RSA256 algorithm.

Maximum token lifetime

The token expiration (exp) is checked during the token exchange by Tapkey. The token's lifetime must not exceed 25 hours at the moment of token exchange. In case the token expiration check fails, the token exchange request is rejected with 400 Bad Request.

const fs = require('fs');
const jwt = require('jsonwebtoken');

const key = fs.readFileSync('ip_key');
const token = jwt.sign({
    "http://tapkey.net/oauth/token_exchange/client_id": "123abcd"
}, { key: key, passphrase: 'strongpassphrase' }, {
    algorithm: 'RS256',
    audience: 'your-audience',
    expiresIn: '1h',
    issuer: 'your-issuer',
    subject: 'userId'
});

console.log(token);
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.security.Keys
import io.jsonwebtoken.SignatureAlgorithm
import java.util.*

fun main() {
    // Load your private key instead of this line
    val keyPair = Keys.keyPairFor(SignatureAlgorithm.RS256)

    val expiration = Calendar.getInstance()
    expiration.roll(Calendar.HOUR, 1)

    val jws = Jwts.builder()
        .setSubject("userId")
        .setAudience("your-audience")
        .setIssuer("your-issuer")
        .setIssuedAt(Date())
        .setExpiration(expiration.time)
        .addClaims(
            hashMapOf("http://tapkey.net/oauth/token_exchange/client_id" to "123abcd") as Map<String, Any>?
        )
        .signWith(keyPair.private, SignatureAlgorithm.RS256)
        .compact()

    println(jws)
}
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.security.Keys
import io.jsonwebtoken.SignatureAlgorithm
import java.util.*

// Load your private key instead of this line
private final KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.RS256);

Calendar expiration = Calendar.getInstance();
expiration.roll(Calendar.HOUR, 1);

String jws = Jwts.builder()

    .setSubject("userId")
    .setAudience("your-audience")
    .setIssuer("your-issuer")
    .setIssuedAt(Date())
    .setExpiration(expiration.getTime())
    .addClaims(new HashMap<String, Object>() {{
        put("http://tapkey.net/oauth/token_exchange/client_id", "123abcd");
    }})
    .signWith(keyPair.getPrivate(), SignatureAlgorithm.RS256)
    .compact();

System.out.println(jws);

Example

Tip

To debug JWT tokens you may use jwt.io. It provides functionality to decode JWT tokens and validate their signature or even change token details. jwt.io is affiliated with Auth0, open-source (MIT) and does not record tokens.

The listing below contains an exemplary JWT token issued by an identity provider that can be used with the Token Exchange grant type.

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJpc3MiOiJ5b3VyLWlzc3VlciIsImF1ZCI6InlvdXItYXVkaWVuY2UiLCJodHRwOi8vdGFwa2V5Lm5ldC9vYXV0aC90b2tlbl9leGNoYW5nZS9jbGllbnRfaWQiOiIxMjNhYmMiLCJpYXQiOjE1MTYyMzkwMDAsImV4cCI6MTUxNjI0MjYwMH0.lktBCBobTinSkpUutshjgJPHikH8KFlo-UafT7NJKCpQvoVgK5AU-1oGx2IgGmh-RfmeK4YaCNz0q8WjVg0qSAI1KlClbKV0sVPyJ3UWh3lqQQtaGjeKdWZ5nLqtbjFL4rQnXbFynuzyOyCWWGyvuXlcQpsnDnme-URP7yPZ8chd8OQwF5DYfpWTEoZUcycdhW5zcJN-LZBEKLv8e0XI8Hqovo5UkPq2NVPuwp2eF8r14jcgs0P_-CbQOn3s_SfcW5v2Z_IyHcgmPRC2xmFkORq1IsVWOCbgd81hS6tgm3HZVl91-XO_MuKkyoTlN6CdEIzcHMjBHDGZa9zPC_ZixdksHXW2InvEDvPxmqNlWFUOWLMTpfeaIZ-i3qzIto60Lk3QKrtJQst0bPF0IlHPM8ni6369wIZ8dQKW8s0xviJWBvRvO_P1VP9K5_uiYf7iySXpIpctFH8jjGMT5He95fZ309ldK1bTG9YCVtV8f0FpnwYo7NZucMC7oemayUtLdMa_A6JbX6yoHUVrHLXWDoDXJmvde7-h0r6tJUClGShypsn2rS8hrmBt7TGco2tA5We5IELnuy-zEgj5qD679i3HrBJQUenxrMYHiPTijZ-xUZ9AkZRe1ZUYhxU3Q4-5q6YNWoiGAC1FNe3KZEgfeI3DtkNupT-n0HdXTRCnjmo

The JWT above consists of a header

{
  "alg": "RS256",
  "typ": "JWT"
}

and a payload section

{
  "sub": "userId",
  "iss": "your-issuer",
  "aud": "your-audience",
  "http://tapkey.net/oauth/token_exchange/client_id": "123abc",
  "iat": 1516239000,
  "exp": 1516242600
}

and has a signature that can be verified with the following public key:

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxWj/WgqR5UKY+j0yTIbI
wCAbPR7gyKLs01K9t1Ne4mpzwQmYbzaHExc6asSbYZZWK0682FYbgcgl7bYpD9Tv
8MchGtB7UG2t4veTX7/tiStbCWjyjZeFJJEUo5xB6FJ70RntK5dZ1x/ghmWVuOwG
A/gpnjY/4tsP/5uvuhNRFTq+6QCIUk41VfuNURfzQaNRskKKwaplq1Ixr57WlfpE
FZ8QCZJunb5Kx9+9kguq9fgGTBJJl6EHR38ZnPtcHFsjJpLNpuNyhKMgsyPHLUMw
IuJdrYEDeBwz2UFsdlv5LyXgYYiB4GWzsmd3GHngvprdEH3+qVECCVUl/sE5G91Y
i8yosqCG/fMXUxgh4Cd0qtjSSspMivI2pazKXg2V8kZa8zdkk/U6tDQod6Yx8QJA
i4b1JpkM084XjPp744CNUCgkXaMHXsxt2j8iNXzeOwjI8UmM7E2AHi7yW4hQ1RqS
TG7gRq/DNJO3SmOOXH0mylKoEj3V6Zux9N6O70wdh+r6jRRLMt7Onp4c+Yn8qo8U
6cYnoERNOjcpeTt95G0/nTTD37bWz0UQ5+APdyTfkqvv6ZXfUcH23l1dtd3L9/v7
DWQPxixayegv/fLRRoSITNFxiyFsrJO7XGzNekbGcUrLwlL7uppR/6PAbHCimr//
/b8ZiU8ZE/RPvifLOYryNpkCAwEAAQ==
-----END PUBLIC KEY-----

Working With Users

Users of external identity providers must be registered with Tapkey using the

PUT/Owners/{ownerAccountId}/IdentityProviders/{ipId}/Users

operation before they can interact with Tapkey.

To create a new user, the user's external ID (identity provider user ID) as well as the identity provider's ID will be passed to Tapkey. Tapkey will issue an internal ID for that user (Tapkey user ID). The combination of identity provider ID and identity provider user ID can be used to create a contact for the external user via the

PUT/Owners/{ownerAccountId}/Contacts/

operation.

To list all users of an identity provider that are registered with Tapkey, or to retrieve single users by wither Tapkey user ID or identity provider user ID, the

GET/Owners/{ownerAccountId}/IdentityProviders/{ipId}/Users

operations can be used.