Skip to content

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.
  • 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. Expiration is limited and checked by Tapkey. A typical value for exp is iat + 1 hour.

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.eyJzdWIiOiJ1c2VySWQiLCJpc3MiOiJ5b3VyLWlzc3VlciIsImF1ZCI6InlvdXItYXVkaWVuY2UiLCJpYXQiOjE1MTYyMzkwMDAsImV4cCI6MTUxNjI0MjYwMH0.FhCCOcu11_ImeQc7aBsbMxnTtZPyDz-LTt9pww_G72gnb-fVWOZtpippywScGhrNwRqhIe5leI3a9en5O2ciff0kP09T_17rbERjI51Rb4Khst12HdnGTFyAlIygASf2o7eYTpHDfK7lVe8XxNMKIBtk_NZ9nQEoWyQWtCuaoqmh-w6Hyg1Rfw6NPWmpITl8lK7lAJj5ZIKj5rOCLBWL7VBNw0PDS3n-8pp16oCnUVSx-fuUpEJkwvCiuGPypE3elrkVxO6nSVy05foAJVJu84OcAh-aXS7GT8EgbdO5sXxS7andxG15yw9A17FxdKkqRlgQWXOcreYvqbZlRb1bnFSqRV9I3Wox7indFsEt-qmSgOTnYugaIYoPQ7fkg-kDywbYZOZsP3zOXeRXomGP81kJfO8DNDZGZBNf0_rLBq72NLSSlBtXthdMg4XetnOM11inNsMOxvR1LzAx57-7aTqQKOXC94EynQqVaIYEUG9NPNc5X0QcisVq3IiYZEurlz9RCaxHmqlf5T05lWWUipZFa9LVhAi1CIKYnQt-q0Mwi3EaQtjneM53cQL5VJjyRiXB27grXueLRDozx96RCg5LBMCrXkiN2qUy6skt9UcEIDwKWtbrhGyUMqncDnpCcn4C7H0eflMr10ys0aX7GRdIqaaj-OvPtR6vmwsW5J0

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-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvG4Z9QnHr46TcaOmemli
YZEigc/c6K8T+bNECaywq2urCE3LguHiO1Lu68JbSlUo09pZOhXPo1SPoINgboU3
Uk1eoXs7z9aX8/2Jp1elEx4szbNUnTsNy0H/Xbv/t89WEFU7t7RNzAojJlO8bXcB
XjMg7sdIGslV/0MCC5XrvMuD86M00YYRX1/Oy9np7Cno3nDo7I3yDflMWS6Ivu1d
twismYtAGz1gk+1PIur6HzkZAJQoKHkt6P/6VXTI7/9E5UWXLXqa3IVXV7jIkDMl
n+epbER06B/JRLWxt/FE6WznPEftKHHNtTP4bFkSKcyjZJYt88ZIfMRPgS7w5P/n
h96CdVdHr3/R4DOa8SV6TVsDhqXuw6inK8ju41jvZSuGTge08eaF+YgLDMCAPZhg
xqo9UBFQogygtZhbF4KDnsl4Z6QUaQHtEbLij8RoB+VPVo+3yXAIoFaYgsu8gsp4
sarniH0xTT5n6xHvU5xIB/zDhHxDZR9Ni0y20pzBCSCua8Ni0DGAuL346uoix7bI
AM0/5htdPL2KZqE58zO9Y6vSdFBdhBqX7jGJcv+OGBxjbUsl15bQfR0u4DzaRNBd
qZ1hhX4VRZwEWoB6nGN06XB9JfKLahPXOBEYAYmCK4TWzuBf36zet6FxrBBFg1v/
Ald6srpzhom56ydnyVpu8FUCAwEAAQ==
-----END PUBLIC KEY-----