Today I want to talk about using JWT to enable a client prove possession of a key.
(Proof of key possession is commonly abbreviated as POP.)
In which cases is it interesting for a client to be able to prove possession of a key to a third party? Mike Jones has articulated a few in this paper. A good example is when you would like to allow a client to generate a public/private key pair that could be used as the basis for message-level (or application-level) security, signing or encryption. (Message or app-level as opposed to transport-level, which is covered by TLS.)
A keypair is a good basis for message or app-level signing or encryption. The client uses its private key to sign a thing, and then a receiver can use the corresponding public key to verify the signed thing. But the question is, how can the receiver be assured that it is this particular client that owns the key?
There are a number of different ways to do this.
Mike Jones and John Bradley have authored IETF RFC 7800 to describe how to do it, with JWT. The title of this RFC is: "Proof of Possession Key Semantics for JSON Web Tokens." If you are like me, you have a hard time parsing that phrase. I don't know why they didn't use a simpler phrase, like "Using JWT to prove possession of a key".
Let's explore that memo and see how we might use Apigee Edge to implement the flow described within it.
RFC 7800 identifies three parties in the POP token flow:
The presenter is... typically the client. It contacts the issuer and asks for a POP token, and presumably authenticates to that issuer in that request. Later the presenter presents that token to the recipient.
The Issuer issues the POP token to the presenter; the token is signed with his own key.
The recipient verifies the POP token.
Because the recipient verifies the token, which is signed by the issuer, the recipient can be assured that the issuer has verified the presenter's identity.
If you're familiar with JWT, you may be aware that they are most often used as Bearer tokens. That means: when ANY client presents a JWT signed by the issuer, the recipient assumes that the "sub" claim (subject) identifies the holder (or Bearer). There are some attacks in which that assumption is false. Suppose Bob is the presenter, and he wants to present a JWT to Alice, the recipient . Since Alice treats the JWT as a Bearer token, any party presenting the token is assumed to be Bob.
If a malicious third party ("Mallory") has hijacked the JWT, then Mallory can present that JWT to Alice, and Alice will believe that Mallory is Bob.
A POP Token exchange is designed to circumvent that problem. The issuer, when it generates the initial JWT, wraps within it, a claim referring to a public key. RFC 7800 specifies the "cnf" claim for this purpose.
When the presenter (Bob) then presents that JWT to the recipient (Alice), the presenter can also send a nonce signed with the private key corresponding to the public key asserted in the JWT.
Then, to verify that Bob (presenter) possesses the key, Alice (the recipient) checks
Attached please find an example showing how this might work.
I have a proxy with 2 endpoints: one for the issuer and one for the recipient.
It isn't necessary that Apigee Edge act as both issuer and recipient, but it could.
This is just an example to illustrate the mechanics. There's a README that describes how to use it.