Adjustements to the behaviour of dpop_bound_access_tokens switch

closes #21920
This commit is contained in:
Takashi Norimatsu
2023-07-27 11:00:32 +09:00
committed by Marek Posolda
parent 74200f2779
commit 9a921441cc
4 changed files with 30 additions and 30 deletions
@@ -498,8 +498,8 @@ public class TokenManager {
}
if (Profile.isFeatureEnabled(Profile.Feature.DPOP)) {
if (OIDCAdvancedConfigWrapper.fromClientModel(client).isUseDPoP() && client.isPublicClient()) {
DPoP dPoP = (DPoP) session.getAttribute(DPoPUtil.DPOP_SESSION_ATTRIBUTE);
DPoP dPoP = (DPoP) session.getAttribute(DPoPUtil.DPOP_SESSION_ATTRIBUTE);
if (client.isPublicClient() && (OIDCAdvancedConfigWrapper.fromClientModel(client).isUseDPoP() || dPoP != null )) {
try {
DPoPUtil.validateBinding(refreshToken, dPoP);
} catch (VerificationException ex) {
@@ -334,7 +334,7 @@ public class TokenEndpoint {
private void checkAndRetrieveDPoPProof(boolean isDPoPSupported) {
if (!isDPoPSupported) return;
if (clientConfig.isUseDPoP()) {
if (clientConfig.isUseDPoP() || request.getHttpHeaders().getHeaderString(DPoPUtil.DPOP_HTTP_HEADER) != null) {
try {
dPoP = new DPoPUtil.Validator(session).request(request).uriInfo(session.getContext().getUri()).validate();
session.setAttribute(DPoPUtil.DPOP_SESSION_ATTRIBUTE, dPoP);
@@ -547,7 +547,7 @@ public class TokenEndpoint {
private void checkAndBindDPoPToken(TokenManager.AccessTokenResponseBuilder responseBuilder, boolean useRefreshToken, boolean isDPoPSupported) {
if (!isDPoPSupported) return;
if (clientConfig.isUseDPoP()) {
if (clientConfig.isUseDPoP() || dPoP != null) {
DPoPUtil.bindToken(responseBuilder.getAccessToken(), dPoP);
// TODO Probably uncomment as the accessToken type "DPoP" will have more sense than "Bearer". It will require some changes in the introspection endpoint too...
// responseBuilder.getAccessToken().type(DPoPUtil.DPOP_TOKEN_TYPE);
@@ -69,7 +69,7 @@ public class DPoPUtil {
DISABLED
}
private static final String DPOP_HTTP_HEADER = "DPoP";
public static final String DPOP_HTTP_HEADER = "DPoP";
private static final String DPOP_JWT_HEADER_TYPE = "dpop+jwt";
private static final String DPOP_ATH_ALG = "RS256";
@@ -226,37 +226,37 @@ public class DPoPTest extends AbstractTestRealmKeycloakTest {
public void testDPoPDisabledByPublicClient() throws Exception {
changeDPoPBound(TEST_PUBLIC_CLIENT_ID, false);
try {
// with DPoP proof
testDPoPByPublicClient();
oauth.clientId(TEST_PUBLIC_CLIENT_ID);
oauth.doLogin(TEST_USER_NAME, TEST_USER_PASSWORD);
// without DPoP proof
oauth.clientId(TEST_PUBLIC_CLIENT_ID);
oauth.dpopProof(null);
oauth.doLogin(TEST_USER_NAME, TEST_USER_PASSWORD);
String dpopProofEcEncoded = generateSignedDPoPProof(UUID.randomUUID().toString(), HttpMethod.POST.toString(), oauth.getAccessTokenUrl(), Long.valueOf(Time.currentTime()), Algorithm.ES256, jwsEcHeader, ecKeyPair.getPrivate());
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null);
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
oauth.dpopProof(dpopProofEcEncoded);
OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null);
assertEquals(Status.OK.getStatusCode(), response.getStatusCode());
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
assertEquals(null, accessToken.getConfirmation());
RefreshToken refreshToken = oauth.parseRefreshToken(response.getRefreshToken());
assertEquals(null, refreshToken.getConfirmation());
assertEquals(Status.OK.getStatusCode(), response.getStatusCode());
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
assertEquals(null, accessToken.getConfirmation());
RefreshToken refreshToken = oauth.parseRefreshToken(response.getRefreshToken());
assertEquals(null, refreshToken.getConfirmation());
// token refresh
response = oauth.doRefreshTokenRequest(response.getRefreshToken(), null);
// token refresh
dpopProofEcEncoded = generateSignedDPoPProof(UUID.randomUUID().toString(), HttpMethod.POST.toString(), oauth.getAccessTokenUrl(), Long.valueOf(Time.currentTime()), Algorithm.ES256, jwsEcHeader, ecKeyPair.getPrivate());
assertEquals(Status.OK.getStatusCode(), response.getStatusCode());
accessToken = oauth.verifyToken(response.getAccessToken());
assertEquals(null, accessToken.getConfirmation());
refreshToken = oauth.parseRefreshToken(response.getRefreshToken());
assertEquals(null, refreshToken.getConfirmation());
oauth.dpopProof(dpopProofEcEncoded);
response = oauth.doRefreshTokenRequest(response.getRefreshToken(), null);
assertEquals(Status.OK.getStatusCode(), response.getStatusCode());
accessToken = oauth.verifyToken(response.getAccessToken());
assertEquals(null, accessToken.getConfirmation());
refreshToken = oauth.parseRefreshToken(response.getRefreshToken());
assertEquals(null, refreshToken.getConfirmation());
oauth.idTokenHint(response.getIdToken()).openLogout();
changeDPoPBound(TEST_PUBLIC_CLIENT_ID, true);
oauth.idTokenHint(response.getIdToken()).openLogout();
} finally {
changeDPoPBound(TEST_PUBLIC_CLIENT_ID, true);
}
}
@Test