#IAZNZS oauth2单点注销没有生效修复

This commit is contained in:
shimingxy 2024-11-20 09:48:39 +08:00
parent c2628b271a
commit 4ceaebf80c
16 changed files with 289 additions and 61 deletions

View File

@ -20,8 +20,8 @@ package org.dromara.maxkey.authn.session;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import org.dromara.maxkey.entity.apps.Apps;
import org.dromara.maxkey.web.WebContext; import org.dromara.maxkey.web.WebContext;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -40,7 +40,7 @@ public class Session implements Serializable{
public Authentication authentication; public Authentication authentication;
private HashMap<String , Apps> authorizedApps = new HashMap<String , Apps>(); Map<String , VisitedDto> visited = new HashMap<>();
public Session() { public Session() {
super(); super();
@ -105,19 +105,19 @@ public class Session implements Serializable{
this.authentication = authentication; this.authentication = authentication;
} }
public HashMap<String, Apps> getAuthorizedApps() { public void visited(VisitedDto visited) {
return authorizedApps; this.visited.put(visited.getAppId(), visited);
} }
public void setAuthorizedApps(HashMap<String, Apps> authorizedApps) { public Map<String, VisitedDto> getVisited() {
this.authorizedApps = authorizedApps; return visited;
} }
public void setAuthorizedApp(Apps authorizedApp) {
this.authorizedApps.put(authorizedApp.getId(), authorizedApp);
}
@Override public void setVisited(Map<String, VisitedDto> visited) {
this.visited = visited;
}
@Override
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("Session [id="); builder.append("Session [id=");

View File

@ -39,4 +39,6 @@ public interface SessionManager {
public int getValiditySeconds(); public int getValiditySeconds();
public void terminate(String sessionId,String userId,String username); public void terminate(String sessionId,String userId,String username);
public void visited(String sessionId , VisitedDto visited);
} }

View File

@ -0,0 +1,156 @@
/*
* Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
*
* 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.dromara.maxkey.authn.session;
import java.io.Serializable;
import org.dromara.maxkey.entity.apps.Apps;
import org.dromara.maxkey.entity.apps.AppsCasDetails;
public class VisitedDto implements Serializable{
/**
*
*/
private static final long serialVersionUID = -6694914707659511202L;
/**
* appId or client id
*/
String appId;
/**
* protocol
*/
String protocol;
/**
* ticket
*/
String ticket;
/**
* token
*/
String token;
/**
* refreshToken
*/
String refreshToken;
/**
* logoutType
*/
int logoutType;
/**
* logoutUrl
*/
String logoutUrl;
public VisitedDto(AppsCasDetails app,String ticket ) {
this.appId = app.getId();
this.protocol = app.getProtocol();
this.logoutType = app.getLogoutType();
this.logoutUrl = app.getLogoutUrl();
this.ticket = ticket;
}
public VisitedDto(Apps app,String ticket ) {
this.appId = app.getId();
this.protocol = app.getProtocol();
this.logoutType = app.getLogoutType();
this.logoutUrl = app.getLogoutUrl();
this.ticket = ticket;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getTicket() {
return ticket;
}
public void setTicket(String ticket) {
this.ticket = ticket;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public int getLogoutType() {
return logoutType;
}
public void setLogoutType(int logoutType) {
this.logoutType = logoutType;
}
public String getLogoutUrl() {
return logoutUrl;
}
public void setLogoutUrl(String logoutUrl) {
this.logoutUrl = logoutUrl;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("VisitedDto [appId=");
builder.append(appId);
builder.append(", protocol=");
builder.append(protocol);
builder.append(", ticket=");
builder.append(ticket);
builder.append(", token=");
builder.append(token);
builder.append(", refreshToken=");
builder.append(refreshToken);
builder.append(", logoutType=");
builder.append(logoutType);
builder.append(", logoutUrl=");
builder.append(logoutUrl);
builder.append("]");
return builder.toString();
}
}

View File

@ -15,12 +15,15 @@
*/ */
package org.dromara.maxkey.authn.session; package org.dromara.maxkey.authn.session.impl;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.dromara.maxkey.authn.session.Session;
import org.dromara.maxkey.authn.session.SessionManager;
import org.dromara.maxkey.authn.session.VisitedDto;
import org.dromara.maxkey.entity.history.HistoryLogin; import org.dromara.maxkey.entity.history.HistoryLogin;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -113,4 +116,14 @@ public class InMemorySessionManager implements SessionManager{
// not need implement // not need implement
} }
@Override
public void visited(String sessionId, VisitedDto visited) {
Session session = this.get(sessionId);
//set token or ticket to Visited , bind user session
session.visited(visited);
//override the session
this.create(sessionId, session);
_logger.debug("session {} store visited {} ." , sessionId , visited);
}
} }

View File

@ -15,11 +15,14 @@
*/ */
package org.dromara.maxkey.authn.session; package org.dromara.maxkey.authn.session.impl;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import org.dromara.maxkey.authn.session.Session;
import org.dromara.maxkey.authn.session.SessionManager;
import org.dromara.maxkey.authn.session.VisitedDto;
import org.dromara.maxkey.entity.history.HistoryLogin; import org.dromara.maxkey.entity.history.HistoryLogin;
import org.dromara.maxkey.persistence.redis.RedisConnection; import org.dromara.maxkey.persistence.redis.RedisConnection;
import org.dromara.maxkey.persistence.redis.RedisConnectionFactory; import org.dromara.maxkey.persistence.redis.RedisConnectionFactory;
@ -135,5 +138,15 @@ public class RedisSessionManager implements SessionManager {
// not need implement // not need implement
} }
@Override
public void visited(String sessionId, VisitedDto visited) {
Session session = this.get(sessionId);
//set token or ticket to Visited , bind user session
session.visited(visited);
//override the session
this.create(sessionId, session);
_logger.debug("session {} store visited {} ." , sessionId , visited);
}
} }

View File

@ -15,7 +15,7 @@
*/ */
package org.dromara.maxkey.authn.session; package org.dromara.maxkey.authn.session.impl;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -24,6 +24,9 @@ import java.time.LocalDateTime;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import org.dromara.maxkey.authn.session.Session;
import org.dromara.maxkey.authn.session.SessionManager;
import org.dromara.maxkey.authn.session.VisitedDto;
import org.dromara.maxkey.constants.ConstsPersistence; import org.dromara.maxkey.constants.ConstsPersistence;
import org.dromara.maxkey.entity.history.HistoryLogin; import org.dromara.maxkey.entity.history.HistoryLogin;
import org.dromara.maxkey.entity.idm.UserInfo; import org.dromara.maxkey.entity.idm.UserInfo;
@ -42,9 +45,9 @@ import org.springframework.jdbc.core.RowMapper;
* @author shimh * @author shimh
* *
*/ */
public class SessionManagerFactory implements SessionManager{ public class SessionManagerImpl implements SessionManager{
private static final Logger _logger = private static final Logger _logger =
LoggerFactory.getLogger(SessionManagerFactory.class); LoggerFactory.getLogger(SessionManagerImpl.class);
private static final String DEFAULT_DEFAULT_SELECT_STATEMENT = private static final String DEFAULT_DEFAULT_SELECT_STATEMENT =
"select id,sessionid,userId,username,displayname,logintime from mxk_history_login where sessionstatus = 1"; "select id,sessionid,userId,username,displayname,logintime from mxk_history_login where sessionstatus = 1";
@ -68,7 +71,7 @@ public class SessionManagerFactory implements SessionManager{
private int validitySeconds ; private int validitySeconds ;
public SessionManagerFactory(int persistence, public SessionManagerImpl(int persistence,
JdbcTemplate jdbcTemplate, JdbcTemplate jdbcTemplate,
RedisConnectionFactory redisConnFactory, RedisConnectionFactory redisConnFactory,
int validitySeconds) { int validitySeconds) {
@ -192,4 +195,13 @@ public class SessionManagerFactory implements SessionManager{
return history; return history;
} }
} }
@Override
public void visited(String sessionId, VisitedDto visited) {
if(isRedis) {
redisSessionManager.visited(sessionId,visited);
}else {
inMemorySessionManager.visited(sessionId,visited);
}
}
} }

View File

@ -18,7 +18,7 @@
package org.dromara.maxkey.autoconfigure; package org.dromara.maxkey.autoconfigure;
import org.dromara.maxkey.authn.session.SessionManager; import org.dromara.maxkey.authn.session.SessionManager;
import org.dromara.maxkey.authn.session.SessionManagerFactory; import org.dromara.maxkey.authn.session.impl.SessionManagerImpl;
import org.dromara.maxkey.authn.web.HttpSessionListenerAdapter; import org.dromara.maxkey.authn.web.HttpSessionListenerAdapter;
import org.dromara.maxkey.authn.web.SavedRequestAwareAuthenticationSuccessHandler; import org.dromara.maxkey.authn.web.SavedRequestAwareAuthenticationSuccessHandler;
import org.dromara.maxkey.persistence.redis.RedisConnectionFactory; import org.dromara.maxkey.persistence.redis.RedisConnectionFactory;
@ -50,7 +50,7 @@ public class SessionAutoConfiguration {
@Value("${maxkey.auth.session.timeout:1800}") int timeout @Value("${maxkey.auth.session.timeout:1800}") int timeout
) { ) {
_logger.debug("session timeout {}" , timeout); _logger.debug("session timeout {}" , timeout);
return new SessionManagerFactory( return new SessionManagerImpl(
persistence, jdbcTemplate, redisConnFactory,timeout); persistence, jdbcTemplate, redisConnFactory,timeout);
} }

View File

@ -170,8 +170,6 @@ public class Apps extends JpaEntity implements Serializable {
private String instName; private String instName;
protected String loginDateTime; protected String loginDateTime;
protected String onlineTicket;
public Apps() { public Apps() {
super(); super();
@ -600,14 +598,6 @@ public class Apps extends JpaEntity implements Serializable {
this.loginDateTime = loginDateTime; this.loginDateTime = loginDateTime;
} }
public String getOnlineTicket() {
return onlineTicket;
}
public void setOnlineTicket(String onlineTicket) {
this.onlineTicket = onlineTicket;
}
public String getAdapterId() { public String getAdapterId() {
return adapterId; return adapterId;
} }
@ -713,8 +703,6 @@ public class Apps extends JpaEntity implements Serializable {
builder.append(description); builder.append(description);
builder.append(", loginDateTime="); builder.append(", loginDateTime=");
builder.append(loginDateTime); builder.append(loginDateTime);
builder.append(", onlineTicket=");
builder.append(onlineTicket);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }

View File

@ -20,22 +20,21 @@ package org.dromara.maxkey.authz.singlelogout;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
import org.dromara.maxkey.authn.SignPrincipal; import org.dromara.maxkey.authn.session.VisitedDto;
import org.dromara.maxkey.entity.apps.Apps;
import org.dromara.maxkey.util.DateUtils; import org.dromara.maxkey.util.DateUtils;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
public class DefaultSingleLogout extends SingleLogout{ public class DefaultSingleLogout extends SingleLogout{
@Override @Override
public void sendRequest(Authentication authentication,Apps logoutApp) { public void sendRequest(Authentication authentication,VisitedDto visited) {
HashMap<String,Object> logoutParameters = new HashMap<String,Object>(); HashMap<String,Object> logoutParameters = new HashMap<String,Object>();
logoutParameters.put("id", UUID.randomUUID().toString()); logoutParameters.put("id", UUID.randomUUID().toString());
logoutParameters.put("principal", authentication.getName()); logoutParameters.put("principal", authentication.getName());
logoutParameters.put("request", "logoutRequest"); logoutParameters.put("request", "logoutRequest");
logoutParameters.put("issueInstant", DateUtils.getCurrentDateAsString(DateUtils.FORMAT_DATE_ISO_TIMESTAMP)); logoutParameters.put("issueInstant", DateUtils.getCurrentDateAsString(DateUtils.FORMAT_DATE_ISO_TIMESTAMP));
logoutParameters.put("ticket", ((SignPrincipal)authentication.getPrincipal()).getSessionId()); logoutParameters.put("ticket", visited.getTicket());
postMessage(logoutApp.getLogoutUrl(),logoutParameters); postMessage(visited.getLogoutUrl(),logoutParameters);
} }

View File

@ -20,7 +20,7 @@ package org.dromara.maxkey.authz.singlelogout;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
import org.dromara.maxkey.entity.apps.Apps; import org.dromara.maxkey.authn.session.VisitedDto;
import org.dromara.maxkey.util.DateUtils; import org.dromara.maxkey.util.DateUtils;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -43,17 +43,17 @@ public class SamlSingleLogout extends SingleLogout{
+ "</saml:NameID><samlp:SessionIndex>%s</samlp:SessionIndex></samlp:LogoutRequest>"; + "</saml:NameID><samlp:SessionIndex>%s</samlp:SessionIndex></samlp:LogoutRequest>";
@Override @Override
public void sendRequest(Authentication authentication,Apps logoutApp) { public void sendRequest(Authentication authentication,VisitedDto visited) {
String requestMessage = String.format(logoutRequestMessage, String requestMessage = String.format(logoutRequestMessage,
UUID.randomUUID().toString(), UUID.randomUUID().toString(),
DateUtils.getCurrentDateAsString(DateUtils.FORMAT_DATE_ISO_TIMESTAMP), DateUtils.getCurrentDateAsString(DateUtils.FORMAT_DATE_ISO_TIMESTAMP),
authentication.getName(), authentication.getName(),
logoutApp.getOnlineTicket() visited.getTicket()
); );
HashMap<String,Object> logoutParameters = new HashMap<String,Object>(); HashMap<String,Object> logoutParameters = new HashMap<String,Object>();
logoutParameters.put(LOGOUT_REQUEST_PARAMETER, requestMessage); logoutParameters.put(LOGOUT_REQUEST_PARAMETER, requestMessage);
postMessage(logoutApp.getLogoutUrl(),logoutParameters); postMessage(visited.getLogoutUrl(),logoutParameters);
} }
public SamlSingleLogout() { public SamlSingleLogout() {

View File

@ -19,7 +19,7 @@ package org.dromara.maxkey.authz.singlelogout;
import java.util.Map; import java.util.Map;
import org.dromara.maxkey.entity.apps.Apps; import org.dromara.maxkey.authn.session.VisitedDto;
import org.dromara.maxkey.web.HttpRequestAdapter; import org.dromara.maxkey.web.HttpRequestAdapter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -28,7 +28,7 @@ import org.springframework.security.core.Authentication;
public abstract class SingleLogout { public abstract class SingleLogout {
private static final Logger _logger = LoggerFactory.getLogger(SingleLogout.class); private static final Logger _logger = LoggerFactory.getLogger(SingleLogout.class);
public abstract void sendRequest(Authentication authentication,Apps logoutApp) ; public abstract void sendRequest(Authentication authentication,VisitedDto visited) ;
public void postMessage(String url,Map<String, Object> paramMap) { public void postMessage(String url,Map<String, Object> paramMap) {
_logger.debug("post logout message to url {}" , url); _logger.debug("post logout message to url {}" , url);

View File

@ -24,7 +24,7 @@ import java.security.Principal;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.dromara.maxkey.authn.session.Session; import org.dromara.maxkey.authn.session.VisitedDto;
import org.dromara.maxkey.authn.web.AuthorizationUtils; import org.dromara.maxkey.authn.web.AuthorizationUtils;
import org.dromara.maxkey.authz.cas.endpoint.ticket.CasConstants; import org.dromara.maxkey.authz.cas.endpoint.ticket.CasConstants;
import org.dromara.maxkey.authz.cas.endpoint.ticket.ServiceTicketImpl; import org.dromara.maxkey.authz.cas.endpoint.ticket.ServiceTicketImpl;
@ -155,15 +155,9 @@ public class CasAuthorizeEndpoint extends CasBaseAuthorizeEndpoint{
if(casDetails.getLogoutType()==LogoutType.BACK_CHANNEL) { if(casDetails.getLogoutType()==LogoutType.BACK_CHANNEL) {
_logger.debug("CAS LogoutType BACK_CHANNEL ... "); _logger.debug("CAS LogoutType BACK_CHANNEL ... ");
String sessionId = AuthorizationUtils.getPrincipal().getSessionId(); String sessionId = AuthorizationUtils.getPrincipal().getSessionId();
_logger.trace("get session by id {} . ",sessionId); VisitedDto visited = new VisitedDto(casDetails,ticket);
Session session = sessionManager.get(sessionId); sessionManager.visited(sessionId, visited);
_logger.trace("current session {} ",session); _logger.debug("App id {} , name {} , CAS LogoutType BACK_CHANNEL ... " , casDetails.getId(),casDetails.getAppName());
//set cas ticket as OnlineTicketId
casDetails.setOnlineTicket(ticket);
session.setAuthorizedApp(casDetails);
_logger.trace("session store ticket {} .",ticket);
sessionManager.create(sessionId, session);
_logger.debug("CAS LogoutType session store ticket to AuthorizedApp .");
} }
_logger.debug("redirect to CAS Client URL {}" , callbackUrl); _logger.debug("redirect to CAS Client URL {}" , callbackUrl);

View File

@ -17,11 +17,15 @@ import java.util.Date;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import org.dromara.maxkey.authn.SignPrincipal;
import org.dromara.maxkey.authn.session.SessionManager;
import org.dromara.maxkey.authn.session.VisitedDto;
import org.dromara.maxkey.authz.oauth2.common.DefaultExpiringOAuth2RefreshToken; import org.dromara.maxkey.authz.oauth2.common.DefaultExpiringOAuth2RefreshToken;
import org.dromara.maxkey.authz.oauth2.common.DefaultOAuth2AccessToken; import org.dromara.maxkey.authz.oauth2.common.DefaultOAuth2AccessToken;
import org.dromara.maxkey.authz.oauth2.common.DefaultOAuth2RefreshToken; import org.dromara.maxkey.authz.oauth2.common.DefaultOAuth2RefreshToken;
import org.dromara.maxkey.authz.oauth2.common.ExpiringOAuth2RefreshToken; import org.dromara.maxkey.authz.oauth2.common.ExpiringOAuth2RefreshToken;
import org.dromara.maxkey.authz.oauth2.common.OAuth2AccessToken; import org.dromara.maxkey.authz.oauth2.common.OAuth2AccessToken;
import org.dromara.maxkey.authz.oauth2.common.OAuth2Constants;
import org.dromara.maxkey.authz.oauth2.common.OAuth2RefreshToken; import org.dromara.maxkey.authz.oauth2.common.OAuth2RefreshToken;
import org.dromara.maxkey.authz.oauth2.common.exceptions.InvalidGrantException; import org.dromara.maxkey.authz.oauth2.common.exceptions.InvalidGrantException;
import org.dromara.maxkey.authz.oauth2.common.exceptions.InvalidScopeException; import org.dromara.maxkey.authz.oauth2.common.exceptions.InvalidScopeException;
@ -31,7 +35,11 @@ import org.dromara.maxkey.authz.oauth2.provider.ClientRegistrationException;
import org.dromara.maxkey.authz.oauth2.provider.OAuth2Authentication; import org.dromara.maxkey.authz.oauth2.provider.OAuth2Authentication;
import org.dromara.maxkey.authz.oauth2.provider.OAuth2Request; import org.dromara.maxkey.authz.oauth2.provider.OAuth2Request;
import org.dromara.maxkey.authz.oauth2.provider.TokenRequest; import org.dromara.maxkey.authz.oauth2.provider.TokenRequest;
import org.dromara.maxkey.entity.apps.Apps;
import org.dromara.maxkey.entity.apps.oauth2.provider.ClientDetails; import org.dromara.maxkey.entity.apps.oauth2.provider.ClientDetails;
import org.dromara.maxkey.persistence.service.AppsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -54,6 +62,7 @@ import org.springframework.util.Assert;
*/ */
public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices,
ConsumerTokenServices, InitializingBean { ConsumerTokenServices, InitializingBean {
static final Logger _logger = LoggerFactory.getLogger(DefaultTokenServices.class);
private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; // default 30 days. private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; // default 30 days.
@ -70,6 +79,10 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R
private TokenEnhancer accessTokenEnhancer; private TokenEnhancer accessTokenEnhancer;
private AuthenticationManager authenticationManager; private AuthenticationManager authenticationManager;
private AppsService appsService;
private SessionManager sessionManager;
/** /**
* Initialize these token services. If no random generator is set, one will be created. * Initialize these token services. If no random generator is set, one will be created.
@ -125,6 +138,18 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R
if (refreshToken != null) { if (refreshToken != null) {
tokenStore.storeRefreshToken(refreshToken, authentication); tokenStore.storeRefreshToken(refreshToken, authentication);
} }
//存储oauthoidc等的token,用户退出时清除
if(authentication.getUserAuthentication().getPrincipal() instanceof SignPrincipal principal) {
_logger.debug("{}({}) , session {} access for logout clear ",
principal.getUsername(),principal.getUserId(),principal.getSessionId());
String clientId = authentication.getOAuth2Request().getRequestParameters().get(OAuth2Constants.PARAMETER.CLIENT_ID);
_logger.debug("client_id {} token {}",clientId,accessToken);
Apps app = appsService.get(clientId, true);
VisitedDto visited = new VisitedDto(app,principal.getSessionId());
visited.setToken(accessToken.getValue());
visited.setRefreshToken(accessToken.getRefreshToken().getValue());
sessionManager.visited(principal.getSessionId(), visited);
}
return accessToken; return accessToken;
} }
@ -432,4 +457,13 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R
this.clientDetailsService = clientDetailsService; this.clientDetailsService = clientDetailsService;
} }
public void setAppsService(AppsService appsService) {
this.appsService = appsService;
}
public void setSessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
} }

View File

@ -23,6 +23,7 @@ import java.security.spec.InvalidKeySpecException;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.dromara.maxkey.authn.session.SessionManager;
import org.dromara.maxkey.authz.oauth2.common.OAuth2Constants; import org.dromara.maxkey.authz.oauth2.common.OAuth2Constants;
import org.dromara.maxkey.authz.oauth2.provider.ClientDetailsService; import org.dromara.maxkey.authz.oauth2.provider.ClientDetailsService;
import org.dromara.maxkey.authz.oauth2.provider.OAuth2UserDetailsService; import org.dromara.maxkey.authz.oauth2.provider.OAuth2UserDetailsService;
@ -48,6 +49,7 @@ import org.dromara.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptio
import org.dromara.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService; import org.dromara.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
import org.dromara.maxkey.persistence.redis.RedisConnectionFactory; import org.dromara.maxkey.persistence.redis.RedisConnectionFactory;
import org.dromara.maxkey.persistence.repository.LoginRepository; import org.dromara.maxkey.persistence.repository.LoginRepository;
import org.dromara.maxkey.persistence.service.AppsService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
@ -259,12 +261,16 @@ public class Oauth20AutoConfiguration implements InitializingBean {
DefaultTokenServices defaultTokenServices( DefaultTokenServices defaultTokenServices(
JdbcClientDetailsService oauth20JdbcClientDetailsService, JdbcClientDetailsService oauth20JdbcClientDetailsService,
TokenStore oauth20TokenStore, TokenStore oauth20TokenStore,
OIDCIdTokenEnhancer tokenEnhancer) { OIDCIdTokenEnhancer tokenEnhancer,
AppsService appsService,
SessionManager sessionManager) {
DefaultTokenServices tokenServices = new DefaultTokenServices(); DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setClientDetailsService(oauth20JdbcClientDetailsService); tokenServices.setClientDetailsService(oauth20JdbcClientDetailsService);
tokenServices.setTokenEnhancer(tokenEnhancer); tokenServices.setTokenEnhancer(tokenEnhancer);
tokenServices.setTokenStore(oauth20TokenStore); tokenServices.setTokenStore(oauth20TokenStore);
tokenServices.setSupportRefreshToken(true); tokenServices.setSupportRefreshToken(true);
tokenServices.setAppsService(appsService);
tokenServices.setSessionManager(sessionManager);
_logger.debug("OAuth 2 Token Services init."); _logger.debug("OAuth 2 Token Services init.");
return tokenServices; return tokenServices;
} }

View File

@ -25,6 +25,8 @@ import org.apache.commons.lang3.StringUtils;
import org.dromara.maxkey.authn.annotation.CurrentUser; import org.dromara.maxkey.authn.annotation.CurrentUser;
import org.dromara.maxkey.authn.session.Session; import org.dromara.maxkey.authn.session.Session;
import org.dromara.maxkey.authn.session.SessionManager; import org.dromara.maxkey.authn.session.SessionManager;
import org.dromara.maxkey.authn.session.VisitedDto;
import org.dromara.maxkey.authz.oauth2.provider.token.DefaultTokenServices;
import org.dromara.maxkey.authz.singlelogout.DefaultSingleLogout; import org.dromara.maxkey.authz.singlelogout.DefaultSingleLogout;
import org.dromara.maxkey.authz.singlelogout.LogoutType; import org.dromara.maxkey.authz.singlelogout.LogoutType;
import org.dromara.maxkey.authz.singlelogout.SamlSingleLogout; import org.dromara.maxkey.authz.singlelogout.SamlSingleLogout;
@ -32,7 +34,6 @@ import org.dromara.maxkey.authz.singlelogout.SingleLogout;
import org.dromara.maxkey.configuration.ApplicationConfig; import org.dromara.maxkey.configuration.ApplicationConfig;
import org.dromara.maxkey.constants.ConstsProtocols; import org.dromara.maxkey.constants.ConstsProtocols;
import org.dromara.maxkey.entity.Message; import org.dromara.maxkey.entity.Message;
import org.dromara.maxkey.entity.apps.Apps;
import org.dromara.maxkey.entity.idm.UserInfo; import org.dromara.maxkey.entity.idm.UserInfo;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -59,6 +60,9 @@ public class LogoutEndpoint {
@Autowired @Autowired
SessionManager sessionManager; SessionManager sessionManager;
@Autowired
DefaultTokenServices oauth20TokenServices;
/** /**
* for front end * for front end
* @param currentUser * @param currentUser
@ -73,11 +77,12 @@ public class LogoutEndpoint {
Session session = sessionManager.get(sessionId); Session session = sessionManager.get(sessionId);
if(session != null) { if(session != null) {
logger.debug("/logout frontend clean Session id {}",session.getId()); logger.debug("/logout frontend clean Session id {}",session.getId());
Set<Entry<String, Apps>> entrySet = session.getAuthorizedApps().entrySet(); Set<Entry<String, VisitedDto>> entrySet = session.getVisited().entrySet();
Iterator<Entry<String, Apps>> iterator = entrySet.iterator(); Iterator<Entry<String, VisitedDto>> iterator = entrySet.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
Entry<String, Apps> mapEntry = iterator.next(); Entry<String, VisitedDto> mapEntry = iterator.next();
VisitedDto visited = mapEntry.getValue();
logger.debug("App Id : {} , {} " , mapEntry.getKey() ,mapEntry.getValue()); logger.debug("App Id : {} , {} " , mapEntry.getKey() ,mapEntry.getValue());
if( mapEntry.getValue().getLogoutType() == LogoutType.BACK_CHANNEL){ if( mapEntry.getValue().getLogoutType() == LogoutType.BACK_CHANNEL){
SingleLogout singleLogout; SingleLogout singleLogout;
@ -86,7 +91,14 @@ public class LogoutEndpoint {
}else { }else {
singleLogout = new DefaultSingleLogout(); singleLogout = new DefaultSingleLogout();
} }
singleLogout.sendRequest(session.getAuthentication(), mapEntry.getValue()); singleLogout.sendRequest(session.getAuthentication(), visited);
}
//oauth , oidc revoke token
if(visited.getProtocol().equalsIgnoreCase(ConstsProtocols.OAUTH20)
||visited.getProtocol().equalsIgnoreCase(ConstsProtocols.OAUTH21)
||visited.getProtocol().equalsIgnoreCase(ConstsProtocols.OPEN_ID_CONNECT10)) {
oauth20TokenServices.revokeToken(visited.getToken());
logger.debug("revoke token");
} }
} }
//terminate session //terminate session

View File

@ -101,8 +101,7 @@ public class SingleSignOnInterceptor implements AsyncHandlerInterceptor {
logger.debug("appId {}",appId); logger.debug("appId {}",appId);
app = appsService.get(appId,true); app = appsService.get(appId,true);
}else if(requestURI.contains("/authz/oauth/v20/authorize")) {//oauth }else if(requestURI.contains("/authz/oauth/v20/authorize")) {//oauth
app = appsService.get( app = appsService.get(request.getParameter(OAuth2Constants.PARAMETER.CLIENT_ID),true);
request.getParameter(OAuth2Constants.PARAMETER.CLIENT_ID),true);
} }
} }