mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 23:12:06 -03:30
Persistent user session for client scopes evaluate function
Closes #37202 Signed-off-by: Giuseppe Graziano <g.graziano94@gmail.com>
This commit is contained in:
parent
603ecf20eb
commit
5505f26cf8
@ -165,6 +165,9 @@ public interface ClientResource {
|
|||||||
@Path("/roles")
|
@Path("/roles")
|
||||||
RolesResource roles();
|
RolesResource roles();
|
||||||
|
|
||||||
|
@Path("/evaluate-scopes")
|
||||||
|
ClientScopeEvaluateResource clientScopesEvaluate();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get default client scopes. Only name and ids are returned.
|
* Get default client scopes. Only name and ids are returned.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.admin.client.resource;
|
||||||
|
|
||||||
|
import jakarta.ws.rs.GET;
|
||||||
|
import jakarta.ws.rs.Path;
|
||||||
|
import jakarta.ws.rs.QueryParam;
|
||||||
|
import org.keycloak.representations.AccessToken;
|
||||||
|
import org.keycloak.representations.IDToken;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:ggrazian@redhat.com">Giuseppe Graziano</a>
|
||||||
|
*/
|
||||||
|
public interface ClientScopeEvaluateResource {
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("generate-example-access-token")
|
||||||
|
AccessToken generateAccessToken(@QueryParam("scope") String scopeParam, @QueryParam("userId") String userId, @QueryParam("audience") String audience);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("generate-example-id-token")
|
||||||
|
IDToken generateExampleIdToken(@QueryParam("scope") String scopeParam, @QueryParam("userId") String userId, @QueryParam("audience") String audience);
|
||||||
|
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("generate-example-userinfo")
|
||||||
|
Map<String, Object> generateExampleUserinfo(@QueryParam("scope") String scopeParam, @QueryParam("userId") String userId);
|
||||||
|
|
||||||
|
}
|
||||||
@ -274,6 +274,7 @@ public class ClientScopeEvaluateResource {
|
|||||||
|
|
||||||
private<R> R sessionAware(UserModel user, String scopeParam, String audienceParam, TriFunction<UserSessionModel, ClientSessionContext, ClientModel[], R> function) {
|
private<R> R sessionAware(UserModel user, String scopeParam, String audienceParam, TriFunction<UserSessionModel, ClientSessionContext, ClientModel[], R> function) {
|
||||||
AuthenticationSessionModel authSession = null;
|
AuthenticationSessionModel authSession = null;
|
||||||
|
UserSessionModel userSession = null;
|
||||||
AuthenticationSessionManager authSessionManager = new AuthenticationSessionManager(session);
|
AuthenticationSessionManager authSessionManager = new AuthenticationSessionManager(session);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -285,8 +286,8 @@ public class ClientScopeEvaluateResource {
|
|||||||
authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
|
authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
|
||||||
authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, scopeParam);
|
authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, scopeParam);
|
||||||
|
|
||||||
UserSessionModel userSession = new UserSessionManager(session).createUserSession(authSession.getParentSession().getId(), realm, user, user.getUsername(),
|
userSession = new UserSessionManager(session).createUserSession(authSession.getParentSession().getId(), realm, user, user.getUsername(),
|
||||||
clientConnection.getRemoteHost(), "example-auth", false, null, null, UserSessionModel.SessionPersistenceState.TRANSIENT);
|
clientConnection.getRemoteHost(), "example-auth", false, null, null, UserSessionModel.SessionPersistenceState.PERSISTENT);
|
||||||
|
|
||||||
AuthenticationManager.setClientScopesInSession(session, authSession);
|
AuthenticationManager.setClientScopesInSession(session, authSession);
|
||||||
ClientSessionContext clientSessionCtx = TokenManager.attachAuthenticationSession(session, userSession, authSession);
|
ClientSessionContext clientSessionCtx = TokenManager.attachAuthenticationSession(session, userSession, authSession);
|
||||||
@ -302,6 +303,9 @@ public class ClientScopeEvaluateResource {
|
|||||||
if (authSession != null) {
|
if (authSession != null) {
|
||||||
authSessionManager.removeAuthenticationSession(realm, authSession, false);
|
authSessionManager.removeAuthenticationSession(realm, authSession, false);
|
||||||
}
|
}
|
||||||
|
if (userSession != null) {
|
||||||
|
session.sessions().removeUserSession(realm, userSession);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.testsuite.admin.client;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
|
import org.keycloak.representations.AccessToken;
|
||||||
|
import org.keycloak.representations.IDToken;
|
||||||
|
import org.keycloak.representations.idm.UserSessionRepresentation;
|
||||||
|
import org.keycloak.testsuite.admin.ApiUtil;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:ggrazian@redhat.com">Giuseppe Graziano</a>
|
||||||
|
*/
|
||||||
|
public class ClientScopeEvaluateTest extends AbstractClientTest {
|
||||||
|
|
||||||
|
private ClientResource accountClient;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
accountClient = findClientResourceById("account");
|
||||||
|
createTestUserWithAdminClient();
|
||||||
|
getCleanup().addUserId(testUser.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerateAccessToken() {
|
||||||
|
AccessToken accessToken = accountClient.clientScopesEvaluate().generateAccessToken("openid", testUser.getId(), null);
|
||||||
|
assertNotNull(accessToken);
|
||||||
|
assertNotNull(accessToken.getSubject());
|
||||||
|
assertNotNull(accessToken.getPreferredUsername());
|
||||||
|
|
||||||
|
List<UserSessionRepresentation> sessions = accountClient.getUserSessions(0, 5);
|
||||||
|
assertEquals(0, sessions.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerateIdToken() {
|
||||||
|
IDToken idToken = accountClient.clientScopesEvaluate().generateExampleIdToken("openid", testUser.getId(), null);
|
||||||
|
assertNotNull(idToken);
|
||||||
|
assertNotNull(idToken.getSubject());
|
||||||
|
assertNotNull(idToken.getPreferredUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerateUserInfo() {
|
||||||
|
Map<String, Object> userinfo = accountClient.clientScopesEvaluate().generateExampleUserinfo("openid", testUser.getId());
|
||||||
|
assertFalse(userinfo.isEmpty());
|
||||||
|
assertNotNull(userinfo.get(IDToken.SUBJECT));
|
||||||
|
assertNotNull(userinfo.get(IDToken.PREFERRED_USERNAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerateAccessTokenWithoutBasicScope() {
|
||||||
|
String basicScopeId = ApiUtil.findClientScopeByName(testRealmResource(),"basic").toRepresentation().getId();
|
||||||
|
accountClient.removeDefaultClientScope(basicScopeId);
|
||||||
|
|
||||||
|
AccessToken accessToken = accountClient.clientScopesEvaluate().generateAccessToken("openid", testUser.getId(), null);
|
||||||
|
assertNotNull(accessToken);
|
||||||
|
assertNull(accessToken.getSubject());
|
||||||
|
|
||||||
|
accountClient.addDefaultClientScope(basicScopeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerateAccessTokenWithOptionalScope() {
|
||||||
|
String emailScopeId = ApiUtil.findClientScopeByName(testRealmResource(),"email").toRepresentation().getId();
|
||||||
|
accountClient.removeDefaultClientScope(emailScopeId);
|
||||||
|
accountClient.addOptionalClientScope(emailScopeId);
|
||||||
|
|
||||||
|
AccessToken accessToken = accountClient.clientScopesEvaluate().generateAccessToken("openid", testUser.getId(), null);
|
||||||
|
assertNotNull(accessToken);
|
||||||
|
assertNull(accessToken.getEmail());
|
||||||
|
|
||||||
|
accessToken = accountClient.clientScopesEvaluate().generateAccessToken("openid email", testUser.getId(), null);
|
||||||
|
assertNotNull(accessToken);
|
||||||
|
assertNotNull(accessToken.getEmail());
|
||||||
|
|
||||||
|
accountClient.removeOptionalClientScope(emailScopeId);
|
||||||
|
accountClient.addDefaultClientScope(emailScopeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user