There is a .NET Framework-based Windows desktop application which communicates with a PHP-based backend web site. I am experiencing permanent signature validation failures when trying to validate the tokens provided by the .NET application to the PHP web site (openssl_verify
returns 0
).
.NET Framework application uses a Microsoft Authentication Library (MSAL) to authenticate a user against an Azure Active Directory (AAD). The library returns a token as a string. The application sends this token as part of its request to the PHP-based server.
var result = await Application.AcquireTokenAsync(scopes).ConfigureAwait(false);
var token = result.AccessToken;
headers.Add("X-Auth-AAD-Token", token);
The PHP-based server web site receives the token provided by the .NET application. It than tries to verify the token and use it when requesting user data from an Azure Active Directory. The PHP web site uses Networg/oauth2-azure library which is a provider of the generic thephpleage/oauth2-client library which then uses a firebase/php-jwt library to handle JWT tokens.
The PHP application instantiates an Azure
provider and calls
$provider->validateAccessToken($token);
where $token
is the string received from the .NET application. This method calls
$keys = $this->getJwtVerificationKeys();
(array)JWT::decode($accessToken, $keys, ['RS256'])
where $keys
are an array of public keys retrieved from the https://login.windows.net/common/discovery/keys
endpoint.
The JWT::decode
then split the token to a header, payload and a signature, decode them, choose the right public key and verify the signature:
public static function decode($jwt, $key, array $allowed_algs = array())
$tks = explode('.', $jwt);
list($headb64, $bodyb64, $cryptob64) = $tks;
$header = static::jsonDecode(static::urlsafeB64Decode($headb64))
$sig = static::urlsafeB64Decode($cryptob64);
$key = $key[$header->kid];
static::verify("$headb64.$bodyb64", $sig, $key, $header->alg);
where jsonDecode
calls
$obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
and urlsafeB64Decode
looks like
public static function urlsafeB64Decode($input)
$remainder = strlen($input) % 4;
if ($remainder) {
$padlen = 4 - $remainder;
$input .= str_repeat('=', $padlen);
}
return base64_decode(strtr($input, '-_', '+/'));
The verify
method then tries to verify the signature by calling openssl_verify
.
private static function verify($msg, $signature, $key, $alg)
list($function, $algorithm) = static::$supported_algs[$alg]; // list('openssl', 'SHA256')
openssl_verify($msg, $signature, $key, $algorithm);
The openssl_verify function returns 0
which means that the signature verification failed (not match).
What am I doing wrong? How to fix it?
Edit: I am not supposed to verify the signature unless the token is issued for "me". As the token I checked is scoped to a Graph API, only the Graph API is supposed to verify it. After I changed the scope of the token requested to the web application, the signature verifies as expected.