Azure key discovery provides modulus and exponent
To verify a JWT coming from Azure, you must provide the ruby JWT
package a public key. That public key must be OpenSSL::PKey::RSA
value.
The Azure key discovery url provides this public key definition:
{
"keys": [
{
"kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk",
"nbf": 1493763266,
"use": "sig",
"kty": "RSA",
"e": "AQAB",
"n": "tVKUtcx_n9rt5afY_2WFNvU6PlFMggCatsZ3l4RjKxH0jgdLq6CScb0P3ZGXYbPzXvmmLiWZizpb-h0qup5jznOvOr-Dhw9908584BSgC83YacjWNqEK3urxhyE2jWjwRm2N95WGgb5mzE5XmZIvkvyXnn7X8dvgFPF5QwIngGsDG8LyHuJWlaDhr_EPLMW4wHvH0zZCuRMARIJmmqiMy3VD4ftq4nS5s8vJL0pVSrkuNojtokp84AtkADCDU_BUhrc2sIgfnvZ03koCQRoZmWiHu86SuJZYkDFstVTVSR0hiXudFlfQ2rOhPlpObmku68lXw-7V-P7jwrQRFfQVXw"
}
]
}
First, I tried using the n
value to create a ruby public key:
> OpenSSL::PKey::RSA.new(key['n'])
OpenSSL::PKey::RSAError: Neither PUB key nor PRIV key: nested asn1 error
So n
is not the public key? WTF is n
. Via the wikipedia page for RSA.
Alice transmits her public key (n, e) to Bob via a reliable, but not necessarily secret, route
n
is the modulus. e
is the exponent (in this case AQAB
), but the ruby library requires a pem. We must convert the modulus and exponent to a pem. Luckily there is a gem for that:
gem install rsa-pem-from-mod-exp
Convert to a pem then to a pubkey:
require 'rsa_pem'
pem = RsaPem.from(key['n'], key['e'])
public_key = OpenSSL::PKey::RSA.new(pem)
And verify your token
decoded_token = JWT.decode token, public_key, true, { :algorithm => 'RS256' }
Tweet