22

My JSON Web Token (JWT):

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6InU0T2ZORlBId0VCb3NIanRyYXVPYlY4NExuWSIsImtpZCI6InU0T2ZORlBId0VCb3NIanRyYXVPYlY4NExuWSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tLyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE1NjM0MDY2NjQsIm5iZiI6MTU2MzQwNjY2NCwiZXhwIjoxNTYzNDEwNTY0LCJhaW8iOiI0MkZnWUJCdGZ6U3I3YnIvcDR0cWVxZGwvMndOQmdBPSIsImFwcGlkIjoiZjFmNmQ1NWUtY2YyYy00MjJkLWIxODYtODQ4NjI0ZGI5NWU4IiwiYXBwaWRhY3IiOiIyIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6ImRmOWRmZjhkLWJjYjUtNGIxNy04Y2VjLTRiZTFhMDFmOTIxMiIsInN1YiI6ImRmOWRmZjhkLWJjYjUtNGIxNy04Y2VjLTRiZTFhMDFmOTIxMiIsInRpZCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsInV0aSI6ImhpMDEtOFlSdUVtTExjeE05TDN6QUEiLCJ2ZXIiOiIxLjAifQ.kwfGrWiQwqhJpZfryW9D1hHDC2AC6tUT16OXkmlIeyxTMqY0gdO0U3KClYczDzMs6kpXc5sQOBaTrBQgERnfKf1nqrHoDmHzaKmY20LKByMopH9uhcPF3lkDNW--dfruNHywF6DZ4cLtgSWcZOBs_BAwQqy1i5Hja7WNf5InyhyscXjUdntIz9rK599IzvD8MwkgYViMEXATNNh2CvEqRp-AZxVjCP_cI6h9Lx3j8__9xRIoWIwnv_rqHGcPpg6hJMfUJMtlLjJaBo0h0veCCZj-fUORidN7EPHNSw9IJF29-nGhw6rmkcD7F8q6WpK8dUfiYGk_QxOCRTw9gpkKKA

When I paste this token into jwt.io, it automatically fills in a public key and says the signature on the token has been verified. How does it know the public key?

identigral
  • 3,920
  • 16
  • 31
squidword
  • 437
  • 3
  • 11

1 Answers1

36

From JWT Best Current Practices (RFC 8725) :

The means of determining the keys owned by an issuer is application- specific. As one example, OpenID Connect issuer values are https URLs that reference a JSON metadata document that contains a jwks_uri value that is an https URL from which the issuer's keys are retrieved as a JWK Set (RFC 7517). This same mechanism is used by ietf-oauth-discovery. Other applications may use different means of binding keys to issuers.

The OpenID Connect (OIDC) provider metadata location is documented in OIDC Discovery specification

OpenID Providers supporting Discovery MUST make a JSON document available at the path formed by concatenating the string /.well-known/openid-configuration to the Issuer. The syntax and semantics of .well-known are defined in RFC 5785 and apply to the Issuer value when it contains no path component.

The payload of your token is

{
  "aud": "https://management.azure.com/",
  "iss": "https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/",
  "iat": 1563406664,
  "nbf": 1563406664,
  "exp": 1563410564,
  "aio": "42FgYBBtfzSr7br/p4tqeqdl/2wNBgA=",
  "appid": "f1f6d55e-cf2c-422d-b186-848624db95e8",
  "appidacr": "2",
  "idp": "https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/",
  "oid": "df9dff8d-bcb5-4b17-8cec-4be1a01f9212",
  "sub": "df9dff8d-bcb5-4b17-8cec-4be1a01f9212",
  "tid": "72f988bf-86f1-41af-91ab-2d7cd011db47",
  "uti": "hi01-8YRuEmLLcxM9L3zAA",
  "ver": "1.0"
}

The Issuer is represented by the iss claim. If you take the value of iss, append /.well-known/openid-configuration to it and pop the resulting URL into your browser, you'll see the OIDC Provider metadata. One of the keys in this metadata document is jwks_uri which points to another document with a JSON Web Key Set. The latter is a set of JSON Web Keys (JWKs). A JWK is a JSON representation of a crypto key. To identify the desired JWK in the set, the claims x5t (SHA-1 thumbprint of a X.509 certificate) and/or kid (key id / alias / name) from the token in question are used.

jwt.io successfully cheats on the very first step of this whole sequence by pulling OIDC metadata based on iss claim. If the JWT was issued by a service that did not speak OpenID Connect and/or did not implement all of these related specifications, jwt.io wouldn't have found the key to validate the signature.

Community
  • 1
  • 1
identigral
  • 3,920
  • 16
  • 31
  • Thank you! I'm trying to implement something in C++ to validate certain JWT tokens and this helps. – squidword Jul 18 '19 at 03:49
  • The last line of the answer has the important info: "If the JWT was issued by a service that did not speak OpenID Connect and/or did not implement all of these related specifications (OIDC specs), jwt.io wouldn't have found the key to validate the signature." – Prateek Kumar Dalbehera Jan 14 '20 at 09:51