Hello!

© 2024 Kishan Kumar. All rights reserved.

How DPoP Works: A Guide to Proof of Possession for Web Tokens

The primary aim of DPoP is to prevent unauthorized or illegitimate parties from using leaked or stolen access tokens, by binding a token to a public key upon issuance and requiring that the client proves possession of the corresponding private key when using the token.

Sept 19, 2023

Hero

Web authentication is a crucial aspect of any web application that involves user data and interactions. However, web authentication is also vulnerable to various attacks, such as replay attacks, phishing attacks, or token theft. These attacks can compromise the security and privacy of both the users and the web applications.

To prevent these attacks, a new technology called DPoP (Demonstrated Proof of Possession) has been proposed. DPoP is a way of binding web tokens to the client that requests them, so that only the legitimate client can use them. DPoP can enhance the security and privacy of web authentication by preventing token replay, token leakage, or token impersonation.

In this article, you will learn how DPoP works, how to implement it in your web applications, and what benefits it can bring to your security and privacy. You will also see some examples of DPoP in action and some challenges and limitations of DPoP. We’ll try to answer the following questions:

  • What is DPoP?
  • How does DPoP work?
  • How to implement DPoP in your web applications?
  • What are the benefits of DPoP?
  • What are the challenges and limitations of DPoP?

Why need a DPoP Token?

Let’s start it by asking what are the drawbacks of the current authentication/authorization flow? If you need to learn how a simple authentication/authorization system works, you can refer to this article.

How Authentication Works: A Step-by-Step Explanation of the Process Behind Signing Up and Logging In

I recently wanted to build a project where I was required to have a feature to authenticate users.

In this article, we'll investigate why a simple authentication system might not work.

Let’s take an example to understand it. When a user wants to access a resource such as cute dog videos from the server (Resource Server), they have to provide a token or something that tells the server that this user is an authenticated user and is authorized to access the videos.

The way you get yourself authenticated is by providing your email and password and registering yourself with the server (Authorization Server). The server then sends you a token that you can use to communicate with it afterward.

The token you receive is a secret code that only the server can understand. You just have to send it back when the server asks for it. This way, you can avoid typing your email and password every time.

But what if the token that the server gave you is leaked? What if you mistakenly sent the token to one of your friends who now uses your token to watch dog videos?

It's a problem, isn't it? How will the server know whether the token is sent by you or your friend? All it knows is that it provided the token to the person who authenticated themselves with them by their password and email, and since only that person knows the password, it must be coming from them.

So, even though it was your friend who was using your token, the server thought it was you all the time. Poor server.

Can we protect this, somehow? Yes, there are multiple ways, and the first is to never share your token with anyone. Keep the token short-lived, such as 2 hrs, after which the token will no longer be deemed valid. The user has to authenticate themselves again with the server, and the server will provide them with the new token.

It will however irritate the user because they have to provide the credentials again and again, and they might not even come to your website again. So it's a tradeoff between the user experience and the security.

But let's not lose hope; another way to mitigate the misusage of the leaked token is to use the DPoP token. As the name implies, it gives the server additional information, telling them that they are the rightful owner of the token; that is why it is called Demonstrating Proof of Possession. Possession of what? Private Key!

The process involves some cryptographic jargon, so let's get away with that first.

DPoP involves Asymmetric cryptography.

Asymmetric cryptography involves public and private keys. These are nothing but random strings that are somehow related to each other by a mathematical function, however you cannot infer the private keys from public keys, not in thousand years.

As the name suggests, the private key must always be kept confidential; you don't reveal it, no matter what. Whereas the public key is like your bank account number, one can know it, but that doesn't mean they have access to your account. But, If they know your private key, they surely can.

How Asymmetric Cryptography Secures Your Data and Communication?

Let's say we both are secret agents, and I want to convey to you some information on where to meet. I sent you a message: Meet me at Bellandur around 2:00 PM.

But, here's a catch: other people (man in the middle) can intercept this message and alter it. Let's say someone changes the message toMeet me at Koramangala around 1:00 PM.

How will you know that the message has not been altered?

We can't! without the help of cryptography.

Let's introduce the two keys we discussed and see if they can help us somehow.

For this, I will use real key pairs to demonstrate the process. PS: I used Blockchain Demo: Public / Private Keys & Signing(andersbrownworth.com) to generate the key and sign the message. I used the random private key that they provided and its corresponding public key.

It doesn't matter actually which algo we use to generate it.

The Private Key

139827841952488031370243161951218995303290824043171910974415860000537508026761

The Public Key

1042c6f260e108ff036904f5ad974f11fa1ea8aca1f324675ea44c82b5b7d68dd228c84ea0
2d95ba8f4c2078207e4f8e4e2650bf538a405e436cc9d93f52bfdb12cf

Once the keys are generated, you first sign the message, which is Meet me at Bellandur around 2:00 PM with your private key. This will give you a signature.

The Signature

1304402207d0cf38da791274f96fdd66d0f349c264291810334c16e00440d7234ffbc198702
2201fee48eefc6512c6a1c5891ece44ed3dc525a733d10c6319a35dd8ec7c4cbba2

This will result in the complete info that I can now send to you, knowing fully well that nobody can alter it without you knowing it.

1Message: 
2Meet me at Bellandur around 2:00 PM
3
4Public Key: 
5042c6f260e108ff036904f5ad974f11fa1ea8aca1f324675ea44c82b5b7d68dd228c84ea
60d95ba8f4c2078207e4f8e4e2650bf538a405e436cc9d93f52bfdb12cf
7
8Signature:
9304402207d0cf38da791274f96fdd66d0f349c264291810334c16e00440d7234ffbc1987
1002201fee48eefc6512c6a1c5891ece44ed3dc525a733d10c6319a35dd8ec7c4cbba2

After receiving the info, you want to verify if it was me who actually sent this to you. For this, you'll take the public key that I sent, the message, and the signature and apply some magical mathematical function, and it will produce a yes or a no.

If the answer is yes, then the signature is valid, and the message has not been altered and is intact. If it is not, someone might have changed it, so we better cancel the plan.

To go into what mathematical function to apply is not the scope of the article, but rest assured, you can verify the signature and come up with a 100% surety of whether the message has been altered or not.

Again, you can use the abovementioned website to play with the tools.

Now, having this knowledge, we can proceed with the basics of DPoP.

For this context, assume there are three actors:

  1. The Client
  2. The Authorization Server (or AS) (the one who issues token)
  3. The Resource Server (or RS) (the one where you can watch the dog videos)

Alright, earlier, without DPoP, these are the steps you would take to watch the dog videos:

The Usual Way

  1. Login / Sign up with the Authorization Server by submitting your email and password.
  2. If you are a first-time user, you'll be thrown a hurdle, such as opening up your email and verifying the email, or in case of a phone number, you might be asked to provide the OTP.
  3. If you are already a registered user, the server (Authorization Server) will check the credentials you passed with the one in the database. Once it verifies its authenticity, you'll be authenticated and will be provided a bearer token.
  4. It is named bearer because anyone who possesses or bears the token can use it to access the protected resource without having to prove their identity because they already did it.
  5. Now, you can ask the Resource Server to give the dog videos by providing your bearer token.
  6. The Resource Server will check that you have got the bearer token and it is valid and not expired. It will then send you loads of Dog videos.

But if someone gets a hold of your token, they can ask the Resource Server for the resources without having to prove anything since a bearer token means they already have been authenticated.

This is where DPoP comes into the picture. But things change a lot.

The DPoP Way

  1. You first generate a key pair (public/private) key.
  2. You then create a JWT token. This is also called DPoP Proof JWT, and it is sent to the authorization server to get an access token. More on that later.
  3. The JWT Token that you create consists of three parts:
  • JWT Header
  • JWT Payload
  • JWT Signature

JWT Header

The header contains the crucial information, such as:

  1. The type of algorithm used to generate the key pairs (ES256).
  2. What kind of JWT is it? It is dpop+jwt.
  3. The public key itself is in the form of JWK. A JWK is a JSON data structure that represents a cryptographic key. It has the following attributes:
    • kty (key type): this parameter identifies the cryptographic algorithm family used within the key, such as EC (Elliptic Curve).
    • x, y the coordinate on the elliptic curve. (Out of scope for this article)
    • crv: the curve used with the key. (Out of scope).
1{
2    "typ":"dpop+jwt",
3    "alg":"ES256",
4    "jwk": {
5        "kty":"EC",
6        "x":"l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs",
7        "y":"9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA",
8        "crv":"P-256"
9    }
10}

JWT Payload

The payload contains the following information:

  1. jti claim: This is a unique identifier.
  2. htm claim: The HTTP method used.
  3. htu claim: The URL that you are sending your request to. In our case, we are sending the request to the authorization server.
  4. iat claim: Contains the timestamp when you issued the JWT token.
1{
2    "jti":"-MwC4Ehc6acd2lT1",
3    "htm":"POST",
4    "htu":"https://your.authorization.server/dpop/token",
5    "iat":1695035425
6}

JWT Signature

The signature is the last part of the JWT, and it is used to verify the integrity and authenticity of the JWT. It is signed using the private key of the client.

12-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg4PtFLbdLXiOSsX0x7NVY-
2FNyJK70nfbV37xRZT3Lg
The signature is then base64url encoded and appended to the JWT, separated by another dot.

The final DPoP proof JWT looks like this:

1eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6IkVDI
2iwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCRn
3MiLCJ5IjoiOVZFNGpmX09rX286NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1J
4EQSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHR
5tIjoiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2Vu
6IiwiaWF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqR
7MUvwnQg4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg
.   .   .

Our next step is to build the request to be sent to the Authorization Server. We have so far completed the JWT Token creation. Here is an example of what a request might look like:

1POST /token HTTP/1.1
2Host: your.authorization.server.com
3Content-Type: application/x-www-form-urlencoded
4DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\\
5 VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\\
6 nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\\
7 QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\\
8 oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\\
9 WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg\\
10 4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg
11
12grant_type=authorization_code\\
13&client_id=s6BhdRkqt\\
14&code=SplxlOBeZQQYbYS6WxSbIA
15&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\\
16&code_verifier=bEaL42izcC-o-xBk0K2vuJ6U-y1p9r_wW2dFWIWgjz-

The Authorization Server

When the authorization server receives the request, it looks for the DPoP header field sent by the client. It extracts the public key, payload, and header and uses the public key to verify the signature. If the verification is successful, it means the client who sent this request is the owner of the private key, and this public key belongs to them. In the same way, we ensured that the message was valid if the signature was verified in the case of our two agents.

After verifying, the Authorization Server issues a token of type DPoP. This means that the authorization server returns an access token (notice it is not called a bearer token) and, optionally, a refresh token that is bound to the public key of the client.

The token type is indicated by a "typ" parameter in the token response, which has the value "DPoP". For example, a token response may look like this:

1{
2   "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleS0xIn0.eyJzdWIiOiJib2IiLCJhdWQiOiJodHRwczovL3Jlc291cmNlLmV4YW1wbGUuY29tIiwiaXNzIjoiaHR0cHM6Ly9hdXRob3JpemF0aW9uLXNlcnZlci5leGFtcGxlLmNvbSIsImV4cCI6MTYyMjMwMjQwMCwiaWF0IjoxNjIyMzAxODAwLCJqdGkiOiJhYmNkLTEyMyIsImNuZiI6eyJqa3QiOiJIM0ZBbkVnTmVEbkZiTFdIaDNjUjNCNjN3STJVMGhtMFpUdUlWXzhJOEVVIn19.UMg7r2fQ8B7tC8sQkE8vqf7eO9xhFbHr4fQnqKsQwqg",
3   "token_type": "DPoP",
4   "expires_in": 3600
5}

The access token generated contains the following payload:

1{
2  "sub": "bob",
3  "aud": "https://resource.example.com",
4  "iss": "https://your.authorization.server.com",
5  "exp": 1622302400,
6  "iat": 1622301800,
7  "jti": "abcd-123",
8  "cnf": {
9    "jkt": "H3FAnEgNeDnFbLWHh3cR3B63wI2U0hm0ZTuIV_8I8EU"
10  }
11}

Please note there is a claim called cnf. This is the hash of our public key sent to the Authorization Server.

The cnf claim is a way of linking a token to a key. Here, we have linked our access token with the public key sent by the client.

The thumbprint is computed using the SHA-256 algorithm defined by RFC 7638. For example, if the public key in the DPoP proof JWT is:

1{
2  "kty": "RSA",
3  "n": "o5Fiw7GSdTDrO61ivks7KM2M7bLar4HF9DWLcIRDGcQqNu0aRMkWLD4QEBtqkyV8Uu30WZ4g8sZxgSGLVoSH9JGc270vWqtA0fYx7AhFi1JPHM-v3Kz3PtLHCIXTRFi-Cj-uDNn31RMduMVevtjmuPz99_qvQU4lDGhQsyAjONNEjYQ5wJp_iYVYPXXRpP3rGg2avoTrsvtFzEABecmIKWGh556M7qSFwdboIUKG-Q6DdBYD9aq3tm0A8JiFATA3RONVF8dSIPl1dfUkwRsosZI2Fr-OT51x6J5f0Kz8J6DUj_UHr0ecwtn25sLZHEN-fCxZ1LeEK-ZeUgIrxZLagw",
4  "e": "AQAB",
5  "kid": "HjFAbEgNeDnFbLWHh3cR3B63wI2U0xm0ZTuIV_8I8EU"
6}

Then, the thumbprint will be:

1H3FAnEgNeDnFbLWHh3cR3B63wI2U0xm0ZTuIV_8I8EU

And the cnf claim in the access token is:

1"cnf": { "jkt": "H3FAnEgNeDnFbLWHh3cR3B63wI2U0xm0ZTuIV_8I8EU" }

Once we have the access token, we can request the dog videos from the Resource Server (or RS).

Here's how:

  • You first create a JWT token similar to what we created before sending it to the Authorization Server. But this time, the payload will be different; htu will be of the Resource Server instead of the Authorization Server. Also, the htm will depend on what kind of resource you are trying to access; since you are asking for dog videos, most probably, it will be GET.
  • 1{
    2 "jti": "-NMwJ4Ehc6acd2lT1",
    3 "htm": "GET",
    4 "htu": "https://your.resource.server.com/get/videos/12342",
    5 "iat": 1695060322
    6}
  • The header of the JWT token will contain the public key that we generated the first time.
  • 1{
    2    "typ":"dpop+jwt",
    3    "alg":"ES256",
    4    "jwk": {
    5        "kty":"EC",
    6        "x":"l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs",
    7        "y":"9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA",
    8        "crv":"P-256"
    9    }
    10}
  • After forming the token, sign it with your private key to generate a signature.
  • 1z9tyS3pDAgdHgzAz9kV6gMsjXme3KqvEjZm-FbXIGe3JfojvZvgYEWHQ72Munq2az8U
    2XokzrJ2ZDIsYaAEKOzA
  • The final DPoP Proof token will look something like this
  • 1eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiItTk13SjRFaGM2YWNkMmx
    2UMSIsImh0bSI6IkdFVCIsImh0dSI6Imh0dHBzOi8vZG9jc3RvcmUudHJhZWZpay5wbGF
    30LnBob25lcGUuY29tL2dldC92aWRlb3MvMTIzNDIiLCJpYXQiOjE2OTUwNjAzMjJ9.z9
    4tyS3pDAgdHgzAz9kV6gMsjXme3KqvEjZm-FbXIGe3JfojvZvgYEWHQ72Munq2az8UXok
    5zrJ2ZDIsYaAEKOzA
  • Now, all we need is to create a Request.
  • 1curl -v -X GET \\
    2  --header 'Accept: application/json' \\
    3  --header 'Content-Type: application/json' \\
    4  --header 'Authorization: DPoP eyJraWQiOiJRVX.....wt7oSakPDUg' \\
    5  --header 'DPoP: eyJ0eXAiOiJkcG9w.....H8-u9gaK2-oIj8ipg' \\
    6  "https://resource.server.com/get/videos/12342"

Note: we are sending both the access token we got from the Authorization Server and the one we created ourselves.

The access token is sent in the Authorization Header, and our Proof is sent in the DPoP header.

.   .   .

Resource Server: Validate the access token and DPoP header.

Once the Resource server receives your request, it validates the headers sent by you.

  1. First, it verifies the signature; if it is invalid, it drops the request; otherwise, it checks for the access token to see whether it contains the cnf claim.
  2. After this, it compares the access token's jkt with the DPoP header's public key.

Once that is confirmed, It returns you the Dog Videos.

.   .   .

Conclusion

DPoP is a promising technology that can enhance the security and privacy of web authentication. By binding web tokens to the client that requests them, DPoP can prevent various attacks that exploit web tokens. DPoP can also enable more granular and flexible access control for web resources.

However, DPoP is not a silver bullet for web authentication. It still has some challenges and limitations, such as compatibility issues, performance overhead, or key management. Therefore, DPoP should be used with caution and in combination with other security measures.

If you want to learn more about DPoP or try it out yourself, you can check out these references:

.   .   .

The 0xkishan Newsletter

Subscribe to the newsletter to learn more about the decentralized web, AI and technology.

© 2024 Kishan Kumar. All rights reserved.