I am working on integrating Telia’s OAuth service in a WordPress plugin and am stuck with an error during the token exchange process. Although the authentication process is completed successfully, I cannot exchange the authorization code for tokens due to a “Client assertion is invalid” error.
I’m using Firebase JWT library https://github.com/firebase/php-jwt
//Requiring jtw-php
require_once plugin_dir_path(__FILE__) . 'php-jwt-main/src/JWT.php';
require_once plugin_dir_path(__FILE__) . 'php-jwt-main/src/Key.php';
use FirebaseJWTJWT;
use FirebaseJWTKey;
// generating the JWT and send it to Telia's token endpoint
function exchange_code_for_tokens($authorization_code) {
error_log("Starting token exchange process.");
$jwt_payload = [
'iss' => CLIENT_ID,
'sub' => CLIENT_ID,
'aud' => "https://example.com/uas",
'iat' => time(),
'exp' => time() + 300,
'jti' => bin2hex(random_bytes(16))
];
error_log("JWT Payload: " . json_encode($jwt_payload));
$client_assertion = JWT::encode($jwt_payload, PRIVATE_KEY, 'RS256');
error_log("Client Assertion: " . $client_assertion);
$post_data = [
'grant_type' => 'authorization_code',
'client_id' => CLIENT_ID,
'client_assertion_type' => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
'client_assertion' => $client_assertion,
'code' => $authorization_code,
'redirect_uri' => REDIRECT_URI
];
$response = wp_remote_post(TOKEN_ENDPOINT, [
'body' => http_build_query($post_data),
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
]
]);
$body = wp_remote_retrieve_body($response);
$response_data = json_decode($body, true);
if (isset($response_data['error'])) {
error_log("Error retrieving tokens: " . $response_data['error_description']);
error_log("Full error response: " . json_encode($response_data));
return null;
} else {
error_log("Tokens retrieved successfully.");
return $response_data;
}
}
// handling the callback from Telia's auth service
add_action('init', function () {
if (isset($_GET['code'])) {
$authorization_code = sanitize_text_field($_GET['code']);
$tokens = exchange_code_for_tokens($authorization_code);
if ($tokens) {
error_log("Tokens retrieved successfully.");
} else {
error_log("Failed to retrieve tokens.");
}
}
});
The logs I’m getting after success Authentication
Client Assertion: xxxx
JWT Payload: {
"iss": "d1245979-f61b-7c1b-b31e-3332204160c3",
"sub": "d7986979-f89b-4c1b-b31e-9423404160c3",
"aud": "https://example.com/uas",
"iat": 1723117411,
"exp": 1723117711,
"jti": "d3d4a5927cc3f419386e57d13111c80f"
}
Error retrieving tokens: Client assertion is invalid
Full error response: {"error_description":"Client assertion is invalid","error":"invalid_client"}
Failed to retrieve tokens.
Here’s some general Information from Telia integration guide:
Token Request:
-
Token requests are made to the token endpoint.
-
Client authentication is performed using
private_key_jwt
. -
Include
client_assertion
parameter, which is a JWT signed with the RS256 algorithm using the client’s private key. -
Public key should not restrict key usage because Telia will encrypt the ID token with this key.
-
Modulus
n
of the public key should be base64url encoded.
Required Parameters:
-
grant_type
: Must beauthorization_code
. -
redirect_uri
: Same as used for the authorization request. -
code
: Authorization Code from the Authorization Response. -
client_id
: OAuth Client Identifier. -
client_assertion_type
:urn:ietf:params:oauth:client-assertion-type:jwt-bearer
-
client_assertion
: Contains a signed JWT.
JWT Claims in client_assertion
:
-
iss
: Client ID -
sub
: Client ID -
aud
:https://example.com/uas
-
exp
: Expiration time in UNIX epoch time (seconds since 1/1/1970), must not be more than 60 minutes into the future. -
jti
: JWT ID, used to enforce one-time use of JWTs.
jwt.io keys testing result “Signature Verified”
Contacting Telia
I ensured with Telia that the public key in their end is correct.
They asked to ensure I’m using the right private key to sign the request, which seems to be correct in my code.
I’ve ensured the client_assertion
matches the requirements and the public key for the RS256
signing is correctly set up on Telia’s server. Any ideas on what might be going wrong?