From ae1d19b9bba89c06a636fdc48f22c5b0365ff7a5 Mon Sep 17 00:00:00 2001 From: Christoph Braun Date: Wed, 24 Jun 2026 12:24:06 +0200 Subject: [PATCH 1/2] update primer --- primer/index.bs | 29 +++++++++++++++++++---------- primer/primer-login.mmd | 17 +++++++++-------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/primer/index.bs b/primer/index.bs index 5e863e8..c104d8a 100644 --- a/primer/index.bs +++ b/primer/index.bs @@ -360,18 +360,27 @@ id, the [=code challenge=], the user's webid, their desired response types, and } ``` -

11. Send authorization code to redirect url

+

11. Send authorization code and `iss` parameter to redirect url

Once Alice successfully logs in, the OP redirects back to the application via the provided -redirect uri, including useful information with it: +redirect uri. The OP includes the authorization code as well as its own issuer identifier as the iss parameter to protect against mix-up attacks: ```http -302 redirect to: https://decentphotos.example/callback?code=m-OrTPHdRsm8W_e9P0J2Bt +302 redirect to: https://decentphotos.example/callback?code=m-OrTPHdRsm8W_e9P0J2Bt&iss=https%3A%2F%2Fsecureauth.example ``` -This redirect gives decentphotos the [=authorization code=] that it will exchange for requested tokens. +This redirect gives decentphotos the [=authorization code=] that it will exchange for requested tokens, along with the issuer identifier required for the next validation step. -

12. Generates a DPoP Client Key Pair

+

12. Validate `iss` Parameter

+ +Before proceeding to exchange the code for tokens, decentphotos must verify the `iss` parameter. +This ensures the application is receiving the code from the exact OP it intended to communicate with. + +The application checks that the `iss` value (`https://secureauth.example`) matches the issuer URL it resolved in Step 3. +If the `iss` parameter is missing or does not match the expected OP, decentphotos must reject the response, abort the authentication flow, and optionally display an error to Alice. +In our example, the issuer matches, so we may safely continue. + +

13. Generates a DPoP Client Key Pair

Solid-OIDC depends on [Demonstration of Proof-of-Possession (DPoP) tokens](https://tools.ietf.org/html/draft-ietf-oauth-dpop). @@ -410,7 +419,7 @@ The public key looks like: } ``` -

13. Generates a DPoP Header

+

14. Generates a DPoP Header

Now that we generated a private key for the client, we need to generate the DPoP header. To do so, we create a [JSON Web Token](https://jwt.io/introduction/) and sign it using the key we @@ -459,7 +468,7 @@ Token Body: that can optionally be used by the server to defend against replay attacks - `"iat": 1603306128`: The date the token was issued, in this case October 21, 2020 15:52:33 GMT. -

14. Token request with code and code verifier

+

15. Token request with code and code verifier

Now, we have everything we need to make an auth request. No need to redirect the web browser for this one. We only need to make an AJAX request to the `token` endpoint as defined in the @@ -495,7 +504,7 @@ Body: Once this request is completed decentphotos can remove the code verifier from session storage. -

15. Validate code verifier

+

16. Validate code verifier

The OP looks up the [=authorization code=] that was saved earlier in a keystore. It checks to see that the client id in the keystore corresponds to the client id from the request. If it does not, it must @@ -511,13 +520,13 @@ BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) == code_challenge If they do not correspond the OP must reject the request with a 400 HTTP status and `invalid_grant` error code. -

16. Validates DPoP Token Signature

+

17. Validates DPoP Token Signature

The OP extracts the client's public key from the DPoP header (at header.jwk). It confirms that the DPoP token has a valid signature. If not, the OP must reject the request with a 400 HTTP status and `invalid_dpop_proof` error code. -

17. Converts the DPoP public key to a JWK thumbprint

+

18. Converts the DPoP public key to a JWK thumbprint

Currently the DPoP token contains a JWK public key, but before we place it inside the access token, it needs to be converted into a [JWK thumbprint](https://tools.ietf.org/html/rfc7638). diff --git a/primer/primer-login.mmd b/primer/primer-login.mmd index 4ba4eee..2a011e9 100644 --- a/primer/primer-login.mmd +++ b/primer/primer-login.mmd @@ -17,13 +17,14 @@ sequenceDiagram note over OP: 8. Validates redirect url with Client ID Document note over OP: 9. Alice Logs In note over OP: 10. Generates an authorization code - OP->>Client: 11. Send authorization code to redirect url - note over Client: 12. Generates DPoP Client Key Pair - note over Client: 13. Generates a DPoP Header - Client->>OP: 14. Token request with code and code verifier - note over OP: 15. Validates code verifier - note over OP: 16. Validates DPoP Token signature - note over OP: 17. Converts the DPoP public key to a JWK thumbprint + OP->>Client: 11. Send authorization code and iss parameter to redirect url + note over Client: 12 Validates that the returned iss matches the expected OP issuer + note over Client: 13. Generates DPoP Client Key Pair + note over Client: 14. Generates a DPoP Header + Client->>OP: 15. Token request with code and code verifier + note over OP: 16. Validates code verifier + note over OP: 17. Validates DPoP Token signature + note over OP: 18. Converts the DPoP public key to a JWK thumbprint note over OP: 19. Generates id token note over OP: 20. Generates refresh token - OP->>Client: 21. Send tokens + OP->>Client: 21. Send tokens \ No newline at end of file From 470d4c45321c50392eca7cf665c68cc11291f754 Mon Sep 17 00:00:00 2001 From: Christoph Braun Date: Wed, 24 Jun 2026 12:26:21 +0200 Subject: [PATCH 2/2] update diagram --- sequence.mmd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sequence.mmd b/sequence.mmd index 97c0b36..0b93e74 100644 --- a/sequence.mmd +++ b/sequence.mmd @@ -14,7 +14,8 @@ sequenceDiagram OP->> ClientID: get Client ID document ClientID->> OP: ClientID document Note over OP: compare redirect_uri - OP ->> C: return Authorization Code + OP ->> C: return Authorization Code and iss parameter + Note over C: Validate iss matches expected OP C ->> OP: present Authorization Code and DPoP proof Note over OP: ⚙️ Client is authenticated ✅ OP ->> C: return DPoP bound OIDC ID Token