Skip to content

Commit fa999c7

Browse files
authored
Merge pull request #9 from internetee/add-pkce
Added PKCE info
2 parents fde79ff + 4bc5a71 commit fa999c7

File tree

1 file changed

+77
-1
lines changed

1 file changed

+77
-1
lines changed

source/index.html.md

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,8 @@ Optional query parameters:
360360

361361
- `ui_locales` - selection of the user interface language. The following languages are supported: `et`, `en`, `ru`
362362
- `nonce` - unique parameter which helps to prevent replay attacks based on the protocol
363+
- `code_challenge_method` - required for [PKCE](#pkce-proof-key-for-code-exchange)/public clients, must be `S256`
364+
- `code_challenge` - required for [PKCE](#pkce-proof-key-for-code-exchange)/public clients, base64url-encoded SHA-256 hash of `code_verifier`
363365

364366
An example of an authentication request:
365367

@@ -371,6 +373,19 @@ GET https://auth.eeid.ee/hydra-public/oauth2/auth?client_id=oidc-b8ab3705-c25f-4
371373
&state=f3b2c3e7f4cf0bed3a783ed6ece617e3
372374
```
373375

376+
<br>
377+
Example for [PKCE](#pkce-proof-key-for-code-exchange)/public client:
378+
379+
```shell
380+
GET https://auth.eeid.ee/hydra-public/oauth2/auth?client_id=oidc-b8ab3705-c25f-4271-b87d-ecf190aa4982-11
381+
&redirect_uri=https%3A%2F%2Feservice.institution.ee%2Fcallback
382+
&response_type=code
383+
&scope=openid
384+
&state=f3b2c3e7f4cf0bed3a783ed6ece617e3
385+
&code_challenge_method=S256
386+
&code_challenge=R8Kf3up4QxQhM9E7Q4P1H0IrbIee8f4Y2m5kY2C4QGA
387+
```
388+
374389
### Redirect request
375390

376391
The redirect request is a HTTP GET request which is used to redirect the user back to the return address entered upon registration of the client application in [eeID manager](https://eeid.ee). In the redirect request an authorization code is sent to the client application, based on which the client application will request the access token in order to get personal identification code, name and other attributes of the authenticated person. The security code state received in the authentication request is mirrored back. Read more about forming and verifying state from [Protection against false request attacks](#protection).
@@ -420,7 +435,14 @@ code=71ed5797c3d957817d31&
420435
redirect_uri=https%3A%2F%2Feservice.institution.ee%2Fcallback
421436
```
422437
<br>
423-
The client secret code must be provided in the identity token request. For this purpose, the request must include the `Authorization` request header with the value formed of the word Basic, a space and a string `<client_id>:<client_secret>` encoded in the Base64 format. The body of the HTTP POST request must be presented in a serialised [format](https://openid.net/specs/openid-connect-core-1_0.html#FormSerialization) based on the OpenID Connect protocol. The body of the request must include the `code` received from the authentication service.
438+
There are two supported client authentication modes for token request:
439+
440+
1. **Confidential client** (`token_endpoint_auth_method=client_secret_basic`):
441+
include `Authorization: Basic base64(<client_id>:<client_secret>)`.
442+
2. **Public PKCE client** (`token_endpoint_auth_method=none`):
443+
do not send client secret, send `client_id` and `code_verifier` in request body.
444+
445+
The body of the HTTP POST request must be presented in a serialised [format](https://openid.net/specs/openid-connect-core-1_0.html#FormSerialization) based on the OpenID Connect protocol. The body of the request must include the `code` received from the authentication service.
424446

425447
The body of the request must include the following parameters:
426448

@@ -429,6 +451,25 @@ Element | Description
429451
`grant_type` | The `authorization_code` value required based on the protocol
430452
`code` | The authorization code received from the authentication service
431453
`redirect_uri`| The redirect URL sent in the authorisation request
454+
`client_id` | Required for public PKCE clients
455+
`code_verifier` | Required for public PKCE clients. Must match the `code_challenge` sent in the auth request
456+
457+
PKCE/public client token request example:
458+
459+
```shell
460+
POST https://auth.eeid.ee/hydra-public/oauth2/token
461+
Content-Type: application/x-www-form-urlencoded
462+
```
463+
464+
```shell
465+
grant_type=authorization_code&
466+
client_id=oidc-b8ab3705-c25f-4271-b87d-ecf190aa4982-11&
467+
code=71ed5797c3d957817d31&
468+
redirect_uri=https%3A%2F%2Feservice.institution.ee%2Fcallback&
469+
code_verifier=Z1YvSmg2a3R0R0l0Y1VxV1A4N3hGQ09mR2xPZTlQd3Y5bnN4WDBqYl91QkN4VQ
470+
```
471+
472+
PKCE requirement follows OAuth2 Authorization Code + PKCE best practices. For flow details and rationale, see Ory documentation: [OAuth2 authorization code flow](https://www.ory.com/docs/oauth2-oidc/authorization-code-flow).
432473

433474
The server verifies that the identity token is requested by the right application and issues the identity token included in the response body. The response body uses JSON format consisting four elements:
434475

@@ -550,6 +591,41 @@ about the error are returned:
550591
}
551592
```
552593

594+
## PKCE (Proof Key for Code Exchange)
595+
596+
[PKCE](https://datatracker.ietf.org/doc/html/rfc7636) is a security extension for OAuth2 Authorization Code flow. It protects public clients (for example SPA, mobile app, desktop app) from authorization code interception attacks.
597+
598+
In PKCE flow, the client:
599+
600+
1. Generates a random `code_verifier`
601+
2. Calculates `code_challenge` from that verifier using SHA-256 (`S256`)
602+
3. Sends `code_challenge` in authorization request (`/oauth2/auth`)
603+
4. Sends original `code_verifier` in token request (`/oauth2/token`)
604+
605+
The authorization server validates that `code_verifier` matches the original `code_challenge`. If it does not match, token issuance fails.
606+
607+
### Which mode to choose in eeID Manager
608+
609+
- Use `token_endpoint_auth_method=none` for public PKCE clients.
610+
- Use `token_endpoint_auth_method=client_secret_basic` for confidential server-side clients that can safely store a client secret.
611+
612+
### Minimal PKCE checklist
613+
614+
- Authorization request must include:
615+
- `code_challenge_method=S256`
616+
- `code_challenge=<base64url(sha256(code_verifier))>`
617+
- Token request must include:
618+
- `grant_type=authorization_code`
619+
- `client_id`
620+
- `code`
621+
- `redirect_uri`
622+
- `code_verifier`
623+
- For PKCE/public clients, do not send client secret.
624+
625+
### Why this matters
626+
627+
Without PKCE, a stolen authorization code can be exchanged for tokens by an attacker. PKCE binds the code exchange to the same client that initiated the login flow.
628+
553629
## Protection
554630

555631
The client application must implement protective measures against false request attacks (cross-site request forgery, CSRF).

0 commit comments

Comments
 (0)