Remove access token from access code, and create token when code is exchanged for token
This commit is contained in:
parent
3514d5cd78
commit
b196d0dded
9 changed files with 150 additions and 129 deletions
|
@ -1,6 +1,5 @@
|
||||||
package org.keycloak.representations;
|
package org.keycloak.representations;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,15 +9,18 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
public class AccessCode {
|
public class AccessCode {
|
||||||
protected String id;
|
protected String id;
|
||||||
|
protected String clientId;
|
||||||
|
protected String userId;
|
||||||
protected String usernameUsed;
|
protected String usernameUsed;
|
||||||
protected String state;
|
protected String state;
|
||||||
|
protected String sessionState;
|
||||||
protected String redirectUri;
|
protected String redirectUri;
|
||||||
protected boolean rememberMe;
|
protected boolean rememberMe;
|
||||||
protected String authMethod;
|
protected String authMethod;
|
||||||
protected int timestamp;
|
protected int timestamp;
|
||||||
protected int expiration;
|
protected int expiration;
|
||||||
protected AccessToken accessToken;
|
|
||||||
protected Set<String> requiredActions;
|
protected Set<String> requiredActions;
|
||||||
|
protected Set<String> requestedRoles;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -28,6 +30,22 @@ public class AccessCode {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getClientId() {
|
||||||
|
return clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientId(String clientId) {
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(String userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getState() {
|
public String getState() {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +54,14 @@ public class AccessCode {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSessionState() {
|
||||||
|
return sessionState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSessionState(String sessionState) {
|
||||||
|
this.sessionState = sessionState;
|
||||||
|
}
|
||||||
|
|
||||||
public String getRedirectUri() {
|
public String getRedirectUri() {
|
||||||
return redirectUri;
|
return redirectUri;
|
||||||
}
|
}
|
||||||
|
@ -68,14 +94,6 @@ public class AccessCode {
|
||||||
this.expiration = expiration;
|
this.expiration = expiration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessToken getAccessToken() {
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAccessToken(AccessToken accessToken) {
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTimestamp() {
|
public int getTimestamp() {
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
@ -99,4 +117,12 @@ public class AccessCode {
|
||||||
public void setUsernameUsed(String usernameUsed) {
|
public void setUsernameUsed(String usernameUsed) {
|
||||||
this.usernameUsed = usernameUsed;
|
this.usernameUsed = usernameUsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> getRequestedRoles() {
|
||||||
|
return requestedRoles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequestedRoles(Set<String> requestedRoles) {
|
||||||
|
this.requestedRoles = requestedRoles;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package org.keycloak.services.managers;
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.jose.jws.JWSBuilder;
|
import org.keycloak.jose.jws.JWSBuilder;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserModel.RequiredAction;
|
import org.keycloak.models.UserModel.RequiredAction;
|
||||||
import org.keycloak.representations.AccessCode;
|
import org.keycloak.representations.AccessCode;
|
||||||
|
@ -33,29 +35,45 @@ public class AccessCodeEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserModel getUser() {
|
public UserModel getUser() {
|
||||||
return keycloakSession.users().getUserById(accessCode.getAccessToken().getSubject(), realm);
|
return keycloakSession.users().getUserById(accessCode.getUserId(), realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSessionState() {
|
public String getSessionState() {
|
||||||
return accessCode.getAccessToken().getSessionState();
|
return accessCode.getSessionState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSessionState(String state) {
|
||||||
|
accessCode.setSessionState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isExpired() {
|
public boolean isExpired() {
|
||||||
return accessCode.getExpiration() != 0 && Time.currentTime() > accessCode.getExpiration();
|
return accessCode.getExpiration() != 0 && Time.currentTime() > accessCode.getExpiration();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessToken getToken() {
|
public Set<RoleModel> getRequestedRoles() {
|
||||||
return accessCode.getAccessToken();
|
Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
|
||||||
|
for (String roleId : accessCode.getRequestedRoles()) {
|
||||||
|
RoleModel role = realm.getRoleById(roleId);
|
||||||
|
if (role == null) {
|
||||||
|
new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid role " + roleId);
|
||||||
|
}
|
||||||
|
requestedRoles.add(realm.getRoleById(roleId));
|
||||||
|
}
|
||||||
|
return requestedRoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientModel getClient() {
|
public ClientModel getClient() {
|
||||||
return realm.findClient(accessCode.getAccessToken().getIssuedFor());
|
return realm.findClient(accessCode.getClientId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getState() {
|
public String getState() {
|
||||||
return accessCode.getState();
|
return accessCode.getState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setState(String state) {
|
||||||
|
accessCode.setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
public String getRedirectUri() {
|
public String getRedirectUri() {
|
||||||
return accessCode.getRedirectUri();
|
return accessCode.getRedirectUri();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.keycloak.services.managers;
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
|
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.audit.Audit;
|
import org.keycloak.audit.Audit;
|
||||||
import org.keycloak.audit.Details;
|
import org.keycloak.audit.Details;
|
||||||
|
@ -24,12 +23,9 @@ import org.keycloak.representations.IDToken;
|
||||||
import org.keycloak.representations.RefreshToken;
|
import org.keycloak.representations.RefreshToken;
|
||||||
import org.keycloak.util.Time;
|
import org.keycloak.util.Time;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -80,21 +76,24 @@ public class TokenManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessCodeEntry createAccessCodeEntry(String scopeParam, String state, String redirect, KeycloakSession keycloakSession, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) {
|
private AccessCodeEntry createAccessCodeEntry(String scopeParam, String state, String redirect, KeycloakSession keycloakSession, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) {
|
||||||
List<RoleModel> realmRolesRequested = new LinkedList<RoleModel>();
|
|
||||||
MultivaluedMap<String, RoleModel> resourceRolesRequested = new MultivaluedMapImpl<String, RoleModel>();
|
|
||||||
|
|
||||||
AccessToken token = createClientAccessToken(scopeParam, realm, client, user, session, realmRolesRequested, resourceRolesRequested);
|
|
||||||
if (session != null) token.setSessionState(session.getId());
|
|
||||||
AccessCode code = new AccessCode();
|
AccessCode code = new AccessCode();
|
||||||
code.setId(UUID.randomUUID().toString() + System.currentTimeMillis());
|
code.setId(UUID.randomUUID().toString() + System.currentTimeMillis());
|
||||||
code.setAccessToken(token);
|
code.setClientId(client.getClientId());
|
||||||
|
code.setUserId(user.getId());
|
||||||
code.setTimestamp(Time.currentTime());
|
code.setTimestamp(Time.currentTime());
|
||||||
code.setExpiration(Time.currentTime() + realm.getAccessCodeLifespan());
|
code.setExpiration(Time.currentTime() + realm.getAccessCodeLifespan());
|
||||||
code.setState(state);
|
code.setSessionState(session != null ? session.getId() : null);
|
||||||
code.setRedirectUri(redirect);
|
code.setRedirectUri(redirect);
|
||||||
|
code.setState(state);
|
||||||
|
|
||||||
|
Set<String> requestedRoles = new HashSet<String>();
|
||||||
|
for (RoleModel r : getAccess(scopeParam, client, user)) {
|
||||||
|
requestedRoles.add(r.getId());
|
||||||
|
}
|
||||||
|
code.setRequestedRoles(requestedRoles);
|
||||||
|
|
||||||
AccessCodeEntry entry = new AccessCodeEntry(keycloakSession, realm, code);
|
AccessCodeEntry entry = new AccessCodeEntry(keycloakSession, realm, code);
|
||||||
return entry;
|
return entry;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessToken refreshAccessToken(KeycloakSession session, UriInfo uriInfo, RealmModel realm, ClientModel client, String encodedRefreshToken, Audit audit) throws OAuthErrorException {
|
public AccessToken refreshAccessToken(KeycloakSession session, UriInfo uriInfo, RealmModel realm, ClientModel client, String encodedRefreshToken, Audit audit) throws OAuthErrorException {
|
||||||
|
@ -142,11 +141,54 @@ public class TokenManager {
|
||||||
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
|
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verifyAccess(refreshToken, realm, client, user);
|
||||||
|
|
||||||
|
AccessToken accessToken = initToken(realm, client, user, userSession);
|
||||||
|
accessToken.setRealmAccess(refreshToken.getRealmAccess());
|
||||||
|
accessToken.setResourceAccess(refreshToken.getResourceAccess());
|
||||||
|
|
||||||
|
// only refresh session if next token refresh will be after idle timeout
|
||||||
|
if (currentTime + realm.getAccessTokenLifespan() > userSession.getLastSessionRefresh() + realm.getSsoSessionIdleTimeout()) {
|
||||||
|
userSession.setLastSessionRefresh(currentTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessToken createClientAccessToken(Set<RoleModel> requestedRoles, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) {
|
||||||
|
AccessToken token = initToken(realm, client, user, session);
|
||||||
|
for (RoleModel role : requestedRoles) {
|
||||||
|
addComposites(token, role);
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<RoleModel> getAccess(String scopeParam, ClientModel client, UserModel user) {
|
||||||
|
// todo scopeParam is ignored until we figure out a scheme that fits with openid connect
|
||||||
|
Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
|
||||||
|
|
||||||
|
Set<RoleModel> roleMappings = user.getRoleMappings();
|
||||||
|
Set<RoleModel> scopeMappings = client.getScopeMappings();
|
||||||
|
if (client instanceof ApplicationModel) {
|
||||||
|
scopeMappings.addAll(((ApplicationModel) client).getRoles());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (RoleModel role : roleMappings) {
|
||||||
|
for (RoleModel desiredRole : scopeMappings) {
|
||||||
|
Set<RoleModel> visited = new HashSet<RoleModel>();
|
||||||
|
applyScope(role, desiredRole, visited, requestedRoles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestedRoles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void verifyAccess(AccessToken token, RealmModel realm, ClientModel client, UserModel user) throws OAuthErrorException {
|
||||||
ApplicationModel clientApp = (client instanceof ApplicationModel) ? (ApplicationModel)client : null;
|
ApplicationModel clientApp = (client instanceof ApplicationModel) ? (ApplicationModel)client : null;
|
||||||
|
|
||||||
|
|
||||||
if (refreshToken.getRealmAccess() != null) {
|
if (token.getRealmAccess() != null) {
|
||||||
for (String roleName : refreshToken.getRealmAccess().getRoles()) {
|
for (String roleName : token.getRealmAccess().getRoles()) {
|
||||||
RoleModel role = realm.getRole(roleName);
|
RoleModel role = realm.getRole(roleName);
|
||||||
if (role == null) {
|
if (role == null) {
|
||||||
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid realm role " + roleName);
|
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid realm role " + roleName);
|
||||||
|
@ -159,8 +201,8 @@ public class TokenManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (refreshToken.getResourceAccess() != null) {
|
if (token.getResourceAccess() != null) {
|
||||||
for (Map.Entry<String, AccessToken.Access> entry : refreshToken.getResourceAccess().entrySet()) {
|
for (Map.Entry<String, AccessToken.Access> entry : token.getResourceAccess().entrySet()) {
|
||||||
ApplicationModel app = realm.getApplicationByName(entry.getKey());
|
ApplicationModel app = realm.getApplicationByName(entry.getKey());
|
||||||
if (app == null) {
|
if (app == null) {
|
||||||
throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Application no longer exists", "Application no longer exists: " + app.getName());
|
throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Application no longer exists", "Application no longer exists: " + app.getName());
|
||||||
|
@ -180,67 +222,6 @@ public class TokenManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessToken accessToken = initToken(realm, client, user, userSession);
|
|
||||||
accessToken.setRealmAccess(refreshToken.getRealmAccess());
|
|
||||||
accessToken.setResourceAccess(refreshToken.getResourceAccess());
|
|
||||||
|
|
||||||
// only refresh session if next token refresh will be after idle timeout
|
|
||||||
if (currentTime + realm.getAccessTokenLifespan() > userSession.getLastSessionRefresh() + realm.getSsoSessionIdleTimeout()) {
|
|
||||||
userSession.setLastSessionRefresh(currentTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AccessToken createClientAccessToken(String scopeParam, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) {
|
|
||||||
return createClientAccessToken(scopeParam, realm, client, user, session, new LinkedList<RoleModel>(), new MultivaluedMapImpl<String, RoleModel>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public AccessToken createClientAccessToken(String scopeParam, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested) {
|
|
||||||
// todo scopeParam is ignored until we figure out a scheme that fits with openid connect
|
|
||||||
|
|
||||||
Set<RoleModel> roleMappings = user.getRoleMappings();
|
|
||||||
Set<RoleModel> scopeMappings = client.getScopeMappings();
|
|
||||||
ApplicationModel clientApp = (client instanceof ApplicationModel) ? (ApplicationModel)client : null;
|
|
||||||
Set<RoleModel> clientAppRoles = clientApp == null ? null : clientApp.getRoles();
|
|
||||||
if (clientAppRoles != null) scopeMappings.addAll(clientAppRoles);
|
|
||||||
|
|
||||||
Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
|
|
||||||
|
|
||||||
for (RoleModel role : roleMappings) {
|
|
||||||
if (clientApp != null && role.getContainer().equals(clientApp)) requestedRoles.add(role);
|
|
||||||
for (RoleModel desiredRole : scopeMappings) {
|
|
||||||
Set<RoleModel> visited = new HashSet<RoleModel>();
|
|
||||||
applyScope(role, desiredRole, visited, requestedRoles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (RoleModel role : requestedRoles) {
|
|
||||||
if (role.getContainer() instanceof RealmModel) {
|
|
||||||
realmRolesRequested.add(role);
|
|
||||||
} else if (role.getContainer() instanceof ApplicationModel) {
|
|
||||||
ApplicationModel app = (ApplicationModel)role.getContainer();
|
|
||||||
resourceRolesRequested.add(app.getName(), role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AccessToken token = initToken(realm, client, user, session);
|
|
||||||
|
|
||||||
if (realmRolesRequested.size() > 0) {
|
|
||||||
for (RoleModel role : realmRolesRequested) {
|
|
||||||
addComposites(token, role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resourceRolesRequested.size() > 0) {
|
|
||||||
for (List<RoleModel> roles : resourceRolesRequested.values()) {
|
|
||||||
for (RoleModel role : roles) {
|
|
||||||
addComposites(token, role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initClaims(IDToken token, ClientModel model, UserModel user) {
|
public void initClaims(IDToken token, ClientModel model, UserModel user) {
|
||||||
|
@ -363,7 +344,8 @@ public class TokenManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessTokenResponseBuilder generateAccessToken(String scopeParam, ClientModel client, UserModel user, UserSessionModel session) {
|
public AccessTokenResponseBuilder generateAccessToken(String scopeParam, ClientModel client, UserModel user, UserSessionModel session) {
|
||||||
accessToken = createClientAccessToken(scopeParam, realm, client, user, session);
|
Set<RoleModel> requestedRoles = getAccess(scopeParam, client, user);
|
||||||
|
accessToken = createClientAccessToken(requestedRoles, realm, client, user, session);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@ public class RequiredActionsService {
|
||||||
// Password reset through email won't have an associated session
|
// Password reset through email won't have an associated session
|
||||||
if (accessCode.getSessionState() == null) {
|
if (accessCode.getSessionState() == null) {
|
||||||
UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserById(accessCode.getUser().getId(), realm), clientConnection.getRemoteAddr());
|
UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserById(accessCode.getUser().getId(), realm), clientConnection.getRemoteAddr());
|
||||||
accessCode.getToken().setSessionState(userSession.getId());
|
accessCode.setSessionState(userSession.getId());
|
||||||
audit.session(userSession);
|
audit.session(userSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RequiredCredentialModel;
|
import org.keycloak.models.RequiredCredentialModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
|
@ -641,14 +642,6 @@ public class TokenService {
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
if (!accessCode.getToken().isActive()) {
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put(OAuth2Constants.ERROR, "invalid_grant");
|
|
||||||
res.put(OAuth2Constants.ERROR_DESCRIPTION, "Token expired");
|
|
||||||
audit.error(Errors.INVALID_CODE);
|
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
audit.user(accessCode.getUser());
|
audit.user(accessCode.getUser());
|
||||||
audit.session(accessCode.getSessionState());
|
audit.session(accessCode.getSessionState());
|
||||||
|
@ -698,8 +691,20 @@ public class TokenService {
|
||||||
|
|
||||||
userSession.associateClient(client);
|
userSession.associateClient(client);
|
||||||
|
|
||||||
|
AccessToken token = tokenManager.createClientAccessToken(accessCode.getRequestedRoles(), realm, client, user, userSession);
|
||||||
|
|
||||||
|
try {
|
||||||
|
tokenManager.verifyAccess(token, realm, client, user);
|
||||||
|
} catch (OAuthErrorException e) {
|
||||||
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
|
error.put(OAuth2Constants.ERROR, e.getError());
|
||||||
|
if (e.getDescription() != null) error.put(OAuth2Constants.ERROR_DESCRIPTION, e.getDescription());
|
||||||
|
audit.error(Errors.INVALID_CODE);
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||||
|
}
|
||||||
|
|
||||||
AccessTokenResponse res = tokenManager.responseBuilder(realm, client, audit)
|
AccessTokenResponse res = tokenManager.responseBuilder(realm, client, audit)
|
||||||
.accessToken(accessCode.getToken())
|
.accessToken(token)
|
||||||
.generateIDToken()
|
.generateIDToken()
|
||||||
.generateRefreshToken().build();
|
.generateRefreshToken().build();
|
||||||
|
|
||||||
|
|
|
@ -157,32 +157,22 @@ public class OAuthFlows {
|
||||||
|
|
||||||
if (!isResource) {
|
if (!isResource) {
|
||||||
accessCode.resetExpiration();
|
accessCode.resetExpiration();
|
||||||
List<RoleModel> realmRolesRequested = new LinkedList<RoleModel>();
|
|
||||||
MultivaluedMap<String, RoleModel> appRolesRequested = new MultivaluedMapImpl<String, RoleModel>();
|
|
||||||
if (accessCode.getToken().getRealmAccess() != null) {
|
|
||||||
if (accessCode.getToken().getRealmAccess().getRoles() != null) {
|
|
||||||
for (String role : accessCode.getToken().getRealmAccess().getRoles()) {
|
|
||||||
RoleModel roleModel = realm.getRole(role);
|
|
||||||
if (roleModel != null) realmRolesRequested.add(roleModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (accessCode.getToken().getResourceAccess().size() > 0) {
|
|
||||||
for (Map.Entry<String, AccessToken.Access> entry : accessCode.getToken().getResourceAccess().entrySet()) {
|
|
||||||
ApplicationModel app = realm.getApplicationByName(entry.getKey());
|
|
||||||
if (app == null) continue;
|
|
||||||
if (entry.getValue().getRoles() != null) {
|
|
||||||
for (String role : entry.getValue().getRoles()) {
|
|
||||||
RoleModel roleModel = app.getRole(role);
|
|
||||||
if (roleModel != null) appRolesRequested.add(entry.getKey(), roleModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
List<RoleModel> realmRoles = new LinkedList<RoleModel>();
|
||||||
|
MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<String, RoleModel>();
|
||||||
|
for (RoleModel r : accessCode.getRequestedRoles()) {
|
||||||
|
if (r.getContainer() instanceof RealmModel) {
|
||||||
|
realmRoles.add(r);
|
||||||
|
} else {
|
||||||
|
resourceRoles.add(((ApplicationModel) r.getContainer()).getName(), r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Flows.forms(this.session, realm, uriInfo).setAccessCode(accessCode.getCode()).
|
|
||||||
setAccessRequest(realmRolesRequested, appRolesRequested).
|
return Flows.forms(this.session, realm, uriInfo)
|
||||||
setClient(client).createOAuthGrant();
|
.setAccessCode(accessCode.getCode())
|
||||||
|
.setAccessRequest(realmRoles, resourceRoles)
|
||||||
|
.setClient(client)
|
||||||
|
.createOAuthGrant();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redirect != null) {
|
if (redirect != null) {
|
||||||
|
|
|
@ -101,7 +101,7 @@ public class AdapterTest {
|
||||||
TokenManager tm = new TokenManager();
|
TokenManager tm = new TokenManager();
|
||||||
UserModel admin = session.users().getUserByUsername("admin", adminRealm);
|
UserModel admin = session.users().getUserByUsername("admin", adminRealm);
|
||||||
UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null);
|
UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null);
|
||||||
AccessToken token = tm.createClientAccessToken(null, adminRealm, adminConsole, admin, userSession);
|
AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession);
|
||||||
return tm.encodeToken(adminRealm, token);
|
return tm.encodeToken(adminRealm, token);
|
||||||
} finally {
|
} finally {
|
||||||
keycloakRule.stopSession(session, true);
|
keycloakRule.stopSession(session, true);
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class RelativeUriAdapterTest {
|
||||||
TokenManager tm = new TokenManager();
|
TokenManager tm = new TokenManager();
|
||||||
UserModel admin = session.users().getUserByUsername("admin", adminRealm);
|
UserModel admin = session.users().getUserByUsername("admin", adminRealm);
|
||||||
UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null);
|
UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null);
|
||||||
AccessToken token = tm.createClientAccessToken(null, adminRealm, adminConsole, admin, userSession);
|
AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession);
|
||||||
adminToken = tm.encodeToken(adminRealm, token);
|
adminToken = tm.encodeToken(adminRealm, token);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ public class AdminAPITest {
|
||||||
TokenManager tm = new TokenManager();
|
TokenManager tm = new TokenManager();
|
||||||
UserModel admin = session.users().getUserByUsername("admin", adminRealm);
|
UserModel admin = session.users().getUserByUsername("admin", adminRealm);
|
||||||
UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null);
|
UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null);
|
||||||
AccessToken token = tm.createClientAccessToken(null, adminRealm, adminConsole, admin, userSession);
|
AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession);
|
||||||
return tm.encodeToken(adminRealm, token);
|
return tm.encodeToken(adminRealm, token);
|
||||||
} finally {
|
} finally {
|
||||||
keycloakRule.stopSession(session, true);
|
keycloakRule.stopSession(session, true);
|
||||||
|
|
Loading…
Reference in a new issue