Skip to content

Commit c73370b

Browse files
feature : PKCE module and its sample
1 parent 104d015 commit c73370b

File tree

5 files changed

+33
-22
lines changed

5 files changed

+33
-22
lines changed

README.md

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -246,21 +246,15 @@ public class CommonDataSourceConfiguration {
246246
2. Check the login page at the "resources/templates/login.hml"
247247
3. Ensure the callback URL (http://localhost:8081/callback1) is properly set in the ``oauth2_registered_client`` table in the database.
248248
- How to use
249-
1. Open the web browser by connecting to ``http://localhost:8370/oauth2/authorize?response_type=code&client_id=client_customer&state=xxx&scope=read&redirect_uri=http%3A%2F%2Flocalhost%3A8081%2Fcallback1``, using the values from the ``oauth2_registered_client`` 2. Now you Login with ``[email protected] / 1234 ``
249+
1. Open the web browser by connecting to ``http://localhost:8370/oauth2/authorize?response_type=code&client_id=client_customer&state=xxx&scope=read&redirect_uri=http%3A%2F%2Flocalhost%3A8081%2Fcallback1&code_challenge=HVoKJYs8JruAxs7hKcG4oLpJXCP-z1jJQtXpQte6GyA&code_challenge_method=S256``, using the values from the ``oauth2_registered_client``
250+
- PKCE (``code_challege, code_challege_METHOD``) is optional.
251+
- PKCE adds a Code Verifier and a Code Challenge to the flow, enhancing the Authorization Code Grant Flow by preventing the issuance of an Access Token if the Authorization Code is compromised.
250252
2. Login with ``[email protected] / 1234 ``
251253
3. You will be redirected to
252254
``https://localhost:8081/callback1?code=215e9539-1dcb-4843-b1ea-b2d7be0a3c44&state=xxx``
253-
4. You can login with this API payload
254-
```http request
255-
POST /oauth2/token HTTP/1.1
256-
Host: localhost:8370
257-
Accept: application/json
258-
Content-Type: application/x-www-form-urlencoded
259-
App-Token: aaa # You can achieve the separated and shared session using App-Token
260-
Authorization: ••••••
261-
Content-Length: 57
262-
grant_type=code&code=ef5aaaaf-ebae-4677-aac5-abf8e8412f1e
263-
```
255+
4. You can login with the API in the Postman
256+
- ![img4.png](reference/docs/img.png)
257+
- ``code_verifier`` sample : EAp91aanXdoMcoOc2Il55H3UDDIV909k9olEEcl6L24J6_9X
264258

265259
## Running this App with Docker
266260
* Use the following module for Blue-Green deployment:

client/src/main/resources/templates/login.html

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ <h1 class="h3 mb-3 fw-normal">Please sign in</h1>
6262
client_id: urlParams.get('client_id'),
6363
state: urlParams.get('state'),
6464
scope: urlParams.get('scope'),
65-
redirect_uri: urlParams.get('redirect_uri')
65+
redirect_uri: urlParams.get('redirect_uri'),
66+
code_challenge: urlParams.get('code_challenge'),
67+
code_challenge_method: urlParams.get('code_challenge_method')
6668
};
6769
}
6870

@@ -71,12 +73,24 @@ <h1 class="h3 mb-3 fw-normal">Please sign in</h1>
7173
const password = passwordInput.value;
7274

7375
// Extract query parameters from the current URL
74-
const {client_id, state, scope, redirect_uri} = getQueryParameters();
76+
const {client_id, state, scope, redirect_uri, code_challenge, code_challenge_method} = getQueryParameters();
7577

7678
// Basic Auth header creation
7779
const clientSecret = '12345'; // Enter client secret
7880
const basicAuth = btoa(`${client_id}:${clientSecret}`);
7981

82+
const bodyParams = {
83+
'username': username,
84+
'password': password,
85+
'grant_type': "password",
86+
'response_type': "code"
87+
};
88+
89+
if (code_challenge && code_challenge_method) {
90+
bodyParams['code_challenge'] = code_challenge;
91+
bodyParams['code_challenge_method'] = code_challenge_method;
92+
}
93+
8094
try {
8195
// First request to obtain the authorization code
8296
const tokenResponse = await fetch('/oauth2/token', {
@@ -85,12 +99,7 @@ <h1 class="h3 mb-3 fw-normal">Please sign in</h1>
8599
'Content-Type': 'application/x-www-form-urlencoded',
86100
'Authorization': `Basic ${basicAuth}`
87101
},
88-
body: new URLSearchParams({
89-
'username': username,
90-
'password': password,
91-
'grant_type': "password",
92-
'response_type': "code"
93-
})
102+
body: new URLSearchParams(bodyParams)
94103
});
95104

96105
if (!tokenResponse.ok) {
@@ -103,6 +112,7 @@ <h1 class="h3 mb-3 fw-normal">Please sign in</h1>
103112
const authorizationCode = tokenResult.code; // Extract authorization code
104113

105114
console.log(tokenResult)
115+
console.log("Success : login with the sample (oauth2/token (Access Token, Response Type = code) in the Postman")
106116

107117
// Build the dynamic authorization URL
108118
const authorizeUrl = `/oauth2/authorize?response_type=code&client_id=${client_id}&code=${authorizationCode}&state=${encodeURIComponent(state)}&scope=${encodeURIComponent(scope)}&redirect_uri=${encodeURIComponent(redirect_uri)}`;

lib/src/main/java/io/github/patternhelloworld/securityhelper/oauth2/api/config/security/provider/auth/endpoint/OpaqueGrantTypeAuthenticationProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public Authentication authenticate(Authentication authentication)
5757
// For reference, if an incorrect Basic header, such as base64(client_id:<--no secret here-->), is detected, the ClientSecretBasicAuthenticationConverter handles it directly and passes it to the AuthenticationFailureHandler.
5858
String clientId = token.getAdditionalParameters().getOrDefault("client_id", "").toString();
5959
if (clientId.isEmpty()) {
60-
throw new EasyPlusOauth2AuthenticationException(EasyPlusErrorMessages.builder().message("Invalid Request. OpaqueGrantTypeAccessTokenRequestConverter was not invoked. This may indicate incorrect payloads.").userMessage(iSecurityUserExceptionMessageService.getUserMessage(DefaultSecurityUserExceptionMessage.AUTHENTICATION_LOGIN_ERROR)).build());
60+
throw new EasyPlusOauth2AuthenticationException(EasyPlusErrorMessages.builder().message("Invalid Request. OpaqueGrantTypeAccessTokenRequestConverter was not invoked. This may indicate incorrect payloads or expired code or code_verifier.").userMessage(iSecurityUserExceptionMessageService.getUserMessage(DefaultSecurityUserExceptionMessage.AUTHENTICATION_LOGIN_ERROR)).build());
6161
}
6262

6363
Map<String, Object> modifiableAdditionalParameters = new HashMap<>(token.getAdditionalParameters());

postman/sc-oauth2-pji.postman_collection.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,14 @@
335335
},
336336
{
337337
"key": "code",
338-
"value": "692b2017-d14a-4279-b673-371c24fb18951",
338+
"value": "df330c3c-0f45-4b80-89c4-4c4a10e78e91",
339+
"description": "Only one time valid",
340+
"type": "text"
341+
},
342+
{
343+
"key": "code_verifier",
344+
"value": "EAp91aanXdoMcoOc2Il55H3UDDIV909k9olEEcl6L24J6_9X",
345+
"description": "Only one time valid",
339346
"type": "text"
340347
}
341348
]

reference/docs/img4.png

32.4 KB
Loading

0 commit comments

Comments
 (0)