Today I Learned

hashrocket A Hashrocket project

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' }
See More #ruby TILs
Looking for help? Each developer at Hashrocket has years of experience working with Ruby applications of all types and sizes. We're an active presence at Ruby conferences, have written some of the most popular gems, and have worked on many of the web's Ruby on Rails success stories. Contact us today to talk about your Ruby project.