Client Credentials - JWT

Get a new access token

📘

Europe (EU) and Canada (CA) Base URLs

EU - https://{talkdesk-account-name}.talkdeskid.eu/oauth/token

CA - https://{talkdesk-account-name}.talkdeskidca.com/oauth/token

👍

Access and Registration

Authentication

Client Authentication

The requests made to the token service must be authenticated using a signed JWT assertion (as per the private_key_jwt mechanism of OpenID Connect):

require 'jwt'
require 'securerandom'

key = '<client_private_key>'

pem_key = key.scan(/.{1,64}/).tap do |lines|
  lines.unshift "-----BEGIN PRIVATE KEY-----"
  lines.push "-----END PRIVATE KEY-----"
end.join("\n")

private_key = OpenSSL::PKey::EC.new pem_key

payload = 
  {
    "jti": SecureRandom.uuid,
    "iss": "<client_id>",
    "sub": "<client_id>",
    "aud": "https://<account_name>.talkdeskid.com/oauth/token",
    "iat": Time.now.to_i,
    "exp": Time.now.to_i + 5*60
  }

token = JWT.encode payload, private_key, '<client_key_algorithm>', {"kid": "<client_key_id>"}
package com.talkdesk.example;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

public class GenerateClientAssertion {

    public static void main(String... args) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
        String key = "<client_private_key>";

        // Replace EC with ECDSA if BouncyCastle is enabled
        PrivateKey privateKey = KeyFactory.getInstance("EC")
                .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(key)));

        String token = Jwts.builder()
                .setHeaderParam("kid", "<client_key_id>")
                .setId(UUID.randomUUID().toString())
                .setIssuer("<client_id>")
                .setSubject("<client_id>")
                .setAudience("https://<account>.talkdeskid.com/oauth/token")
                .setIssuedAt(new Date())
                .setExpiration(Date.from(Instant.now().plusSeconds(300)))
                .signWith(SignatureAlgorithm.<client_key_algorithm>, privateKey)
                .compact();
    }

}
# Requires the 'PyJWT' and 'cryptography' packages to be installed

import uuid
import jwt
from datetime import datetime, timedelta

# Client Private Key
CLIENT_PRIVATE_KEY = "<client_private_key>"

CLIENT_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" + CLIENT_PRIVATE_KEY + "\n-----END PRIVATE KEY-----"

# JWT Headers
headers = {"kid": "<client_key_id>"}

# JWT Payload
payload = {"iss": "<client_id>",\
    "sub": "<client_id>",\
    "aud": "https://<account_name>.talkdeskid.com/oauth/token",\
    "jti": str(uuid.uuid4()),\
    "exp": datetime.utcnow() + \
    timedelta(seconds=300),\
    "iat": datetime.utcnow()}

# Signed JWT 
jwt_token = jwt.encode(payload, CLIENT_PRIVATE_KEY, algorithm = "<client_key_algorithm>", headers = headers)
(require 
  '[clj-time.core :as time]
  '[buddy.sign.jwt :as jwt]
  '[buddy.core.keys :as keys])

(def token 
  (jwt/sign
    {:jti (str (java.util.UUID/randomUUID))
     :iss "<CLIENT_ID>" 
     :sub "<CLIENT_ID>" 
     :aud "https://taiga.talkdeskid.com/oauth/token" 
     :exp (time/plus (time/now) (time/minutes 5)) 
     :iat (time/now)}
    (keys/private-key "<CLIENT_PRIVATE_KEY_FILE>")
    {:alg :es256
     :kid "<CLIENT_KEY_ID>"}))
// Requires the 'jsonwebtoken' and 'uuid' packages to be installed
var jwt = require('jsonwebtoken');
var uuid = require('uuid/v4');

var private_key = '<client_private_key>'
private_key = "-----BEGIN PRIVATE KEY-----\n" + private_key + "\n-----END PRIVATE KEY-----"

var header = {
  kid: '<client_key_id>'
}

var payload = {
  iss: '<client_id>',
  sub: '<client_id>',
  aud: 'https://<account_name>.talkdeskid.com/oauth/token',
  jti: uuid(),
  exp: Math.floor(Date.now() / 1000) + 300,
  iat: Math.floor(Date.now() / 1000)
}

token = jwt.sign(payload, private_key, {header: header, algorithm: '<client_key_algorith>'})

❗️

Signed JWT - Expiration

You will get an invalid_client error message if your signed JWT has expired.

In the example above, the signed JWT expires after five minutes. If you wish to have a signed JWT with a longer expiration date, you can change it via the exp and/or setExpiration variables.

Body Response - Schema

200 (the access token - and optional refresh token - generated, along with some additional properties about the authorization)

ParameterTypeDescriptionRequired
access_tokenstringThe access token.yes
token_typestringThe type of token to be specified in the authorization header. Default: Bearer.yes
expires_inintegerDuration of time (seconds) the access token is granted for.yes
scopestringA space-separated list of scopes (URL encoded) the client requested access to. If the "scope" parameter is not provided in the request body parameter, the returned value will be the list of scopes the client granted.yes
refresh_tokenstringThe refresh token used to obtain another access token. Required only when using "authorization_code" and "refresh_token" grant types.no
sidstringThe session ID of the user authenticated during the authorization code flow. Required only when using "authorization_code" and "refresh_token" grant types.no
id_tokenstringThe ID token (OpenID Connect functionality to return information about the authentication performed during the authorization code flow). Required only when using "authorization_code" grant type and if "openid" scope was included in the "scope" parameter provided in the "/oauth/authorize" request query parameter.no

400 (bad request), 401 (unauthorized)

ParameterTypeDescriptionRequired
errorstringn/ayes
error_descriptionstringn/ayes

🚧

Troubleshooting

If you have questions or technical issues, please open a ticket using this form.

Access Token Request

Language
URL
Click Try It! to start a request and see the response here!