8000 Add the nonce attribute when the client session context is recreated (25) by rmartinc · Pull Request #33509 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1118,8 +1118,12 @@ public AccessTokenResponseBuilder generateRefreshToken(RefreshToken oldRefreshTo
String scope = oldRefreshToken.getScope();
Object reuseId = oldRefreshToken.getOtherClaims().get(Constants.REUSE_ID);
boolean offlineTokenRequested = Arrays.asList(scope.split(" ")).contains(OAuth2Constants.OFFLINE_ACCESS) ;
if (offlineTokenRequested)
if (offlineTokenRequested) {
clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(clientSession, scope, session);
if (oldRefreshToken.getNonce() != null) {
clientSessionCtx.setAttribute(OIDCLoginProtocol.NONCE_PARAM, oldRefreshToken.getNonce());
}
}
generateRefreshToken(offlineTokenRequested);
if (realm.isRevokeRefreshToken()) {
refreshToken.getOtherClaims().put(Constants.REUSE_ID, reuseId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class ArtifactResolutionService implements Provider<Source>, Runnable {
private ArtifactResponseType artifactResponseType;
private final String endpointAddress;
private ArtifactResolveType lastArtifactResolve;
private boolean running = true;
private volatile boolean running = true;

/**
* Standard constructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.util.TokenUtil;

/**
*
Expand All @@ -62,15 +63,26 @@ public void configureTestRealm(RealmRepresentation testRealm) {

@Test
public void testNonceWithoutMapper() throws JsonProcessingException {
testNonce(false);
testNonce(false, false);
}

@Test
public void testNonceWithMapper() throws JsonProcessingException {
ClientResource testApp = ApiUtil.findClientByClientId(testRealm(), "test-app");
String mapperId = createNonceMapper(testApp);
try {
testNonce(true);
testNonce(true, false);
} finally {
testApp.getProtocolMappers().delete(mapperId);
}
}

@Test
public void testOfflineSessionNonceWithMapper() throws JsonProcessingException {
ClientResource testApp = ApiUtil.findClientByClientId(testRealm(), "test-app");
String mapperId = createNonceMapper(testApp);
try {
testNonce(true, true);
} finally {
testApp.getProtocolMappers().delete(mapperId);
}
Expand Down Expand Up @@ -142,9 +154,12 @@ private void testNonceImplicit(boolean mapper) throws JsonProcessingException {
testIntrospection(idTokenString, nonce, true);
}

private void testNonce(boolean mapper) throws JsonProcessingException {
private void testNonce(boolean mapper, boolean offlineSession) throws JsonProcessingException {
String nonce = KeycloakModelUtils.generateId();
oauth.nonce(nonce);
if (offlineSession) {
oauth.scope(OAuth2Constants.OFFLINE_ACCESS);
}
oauth.doLogin("test-user@localhost", "password");
EventRepresentation loginEvent = events.expectLogin().assertEvent();

Expand All @@ -158,12 +173,14 @@ private void testNonce(boolean mapper) throws JsonProcessingException {
RefreshToken refreshToken = oauth.parseRefreshToken(response.getRefreshToken());
checkNonce(nonce, refreshToken.getNonce(), mapper);

EventRepresentation tokenEvent = events.expectCodeToToken(loginEvent.getDetails().get(Details.CODE_ID),
loginEvent.getSessionId()).assertEvent();
EventRepresentation tokenEvent = events.expectCodeToToken(loginEvent.getDetails().get(Details.CODE_ID), loginEvent.getSessionId())
.detail(Details.REFRESH_TOKEN_TYPE, offlineSession? TokenUtil.TOKEN_TYPE_OFFLINE : TokenUtil.TOKEN_TYPE_REFRESH)
.assertEvent();

response = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
events.expectRefresh(tokenEvent.getDetails().get(Details.REFRESH_TOKEN_ID),
loginEvent.getSessionId()).assertEvent();
events.expectRefresh(tokenEvent.getDetails().get(Details.REFRESH_TOKEN_ID), loginEvent.getSessionId())
.detail(Details.REFRESH_TOKEN_TYPE, offlineSession? TokenUtil.TOKEN_TYPE_OFFLINE : TokenUtil.TOKEN_TYPE_REFRESH)
.assertEvent();

token = oauth.verifyToken(response.getAccessToken());
checkNonce(nonce, token.getNonce(), mapper);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public void testReceiveArtifactLoginFullWithPost() throws ParsingException, Conf
ArtifactResolutionService ars = new ArtifactResolutionService("http://127.0.0.1:8082/").setResponseDocument(doc);
Thread arsThread = new Thread(ars);
try {
arsThread.start();
synchronized (ars) {
arsThread.start();
ars.wait();
SAMLDocumentHolder response = builder.artifactMessage(camb).build().login().user(bburkeUser).build().getSamlResponse(SamlClient.Binding.POST);
assertThat(response.getSamlObject(), instanceOf(ResponseType.class));
Expand Down Expand Up @@ -90,8 +90,8 @@ public void testReceiveArtifactLoginFullWithRedirect() throws ParsingException,
ArtifactResolutionService ars = new ArtifactResolutionService("http://127.0.0.1:8082/").setResponseDocument(doc);
Thread arsThread = new Thread(ars);
try {
arsThread.start();
synchronized (ars) {
arsThread.start();
ars.wait();
SAMLDocumentHolder response = builder.artifactMessage(camb).build().login().user(bburkeUser).build().getSamlResponse(REDIRECT);
assertThat(response.getSamlObject(), instanceOf(ResponseType.class));
Expand Down Expand Up @@ -124,8 +124,8 @@ public void testReceiveArtifactNonExistingClient() throws ParsingException, Conf
ArtifactResolutionService ars = new ArtifactResolutionService("http://127.0.0.1:8082/").setResponseDocument(doc);
Thread arsThread = new Thread(ars);
try {
arsThread.start();
synchronized (ars) {
arsThread.start();
ars.wait();
String response = builder.artifactMessage(camb).build().executeAndTransform(resp -> EntityUtils.toString(resp.getEntity()));
assertThat(response, containsString("Invalid Request"));
Expand All @@ -151,8 +151,8 @@ public void testReceiveEmptyArtifactResponse() throws InterruptedException {
ArtifactResolutionService ars = new ArtifactResolutionService("http://127.0.0.1:8082/").setEmptyArtifactResponse(SAML_CLIENT_ID_SALES_POST);
Thread arsThread = new Thread(ars);
try {
arsThread.start();
synchronized (ars) {
arsThread.start();
ars.wait();
builder.artifactMessage(camb).build().execute(r -> {
assertThat(r, statusCodeIsHC(400));
Expand Down Expand Up @@ -180,8 +180,8 @@ public void testReceiveArtifactLogoutFullWithPost() throws InterruptedException
ArtifactResolutionService ars = new ArtifactResolutionService("http://127.0.0.1:8082/");
Thread arsThread = new Thread(ars);
try {
arsThread.start();
synchronized (ars) {
arsThread.start();
ars.wait();
SAMLDocumentHolder samlResponse = builder.authnRequest(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST, SAML_ASSERTION_CONSUMER_URL_SALES_POST, POST).build()
.login().user(bburkeUser).build()
Expand Down Expand Up @@ -220,8 +220,8 @@ public void testReceiveArtifactLogoutFullWithRedirect() throws InterruptedExcept
ArtifactResolutionService ars = new ArtifactResolutionService("http://127.0.0.1:8082/");
Thread arsThread = new Thread(ars);
try {
arsThread.start();
synchronized (ars) {
arsThread.start();
ars.wait();
SAMLDocumentHolder samlResponse = builder
.authnRequest(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST,
Expand Down
0