Sept 19, 2023
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:
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.
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.
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.
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.
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.
139827841952488031370243161951218995303290824043171910974415860000537508026761
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.
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:
Alright, earlier, without DPoP, these are the steps you would take to watch the 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 header contains the crucial information, such as:
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}
The payload contains the following information:
1{
2 "jti":"-MwC4Ehc6acd2lT1",
3 "htm":"POST",
4 "htu":"https://your.authorization.server/dpop/token",
5 "iat":1695035425
6}
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 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-
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:
1{
2 "jti": "-NMwJ4Ehc6acd2lT1",
3 "htm": "GET",
4 "htu": "https://your.resource.server.com/get/videos/12342",
5 "iat": 1695060322
6}
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}
1z9tyS3pDAgdHgzAz9kV6gMsjXme3KqvEjZm-FbXIGe3JfojvZvgYEWHQ72Munq2az8U
2XokzrJ2ZDIsYaAEKOzA
1eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiItTk13SjRFaGM2YWNkMmx
2UMSIsImh0bSI6IkdFVCIsImh0dSI6Imh0dHBzOi8vZG9jc3RvcmUudHJhZWZpay5wbGF
30LnBob25lcGUuY29tL2dldC92aWRlb3MvMTIzNDIiLCJpYXQiOjE2OTUwNjAzMjJ9.z9
4tyS3pDAgdHgzAz9kV6gMsjXme3KqvEjZm-FbXIGe3JfojvZvgYEWHQ72Munq2az8UXok
5zrJ2ZDIsYaAEKOzA
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.
Once the Resource server receives your request, it validates the headers sent by you.
Once that is confirmed, It returns you the Dog Videos.
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:
Subscribe to the newsletter to learn more about the decentralized web, AI and technology.
Please be respectful!