提交 6cad9f0c 编写于 作者: M MaxKey

oauth2 Approval fix & sso login history

上级 e0e299ff
...@@ -25,6 +25,8 @@ import org.maxkey.authz.oauth2.provider.OAuth2Authentication; ...@@ -25,6 +25,8 @@ import org.maxkey.authz.oauth2.provider.OAuth2Authentication;
import org.maxkey.authz.oauth2.provider.approval.Approval.ApprovalStatus; import org.maxkey.authz.oauth2.provider.approval.Approval.ApprovalStatus;
import org.maxkey.authz.oauth2.provider.token.AuthorizationServerTokenServices; import org.maxkey.authz.oauth2.provider.token.AuthorizationServerTokenServices;
import org.maxkey.authz.oauth2.provider.token.TokenStore; import org.maxkey.authz.oauth2.provider.token.TokenStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* An {@link ApprovalStore} that works with an existing {@link TokenStore}, extracting implicit {@link Approval * An {@link ApprovalStore} that works with an existing {@link TokenStore}, extracting implicit {@link Approval
...@@ -38,6 +40,8 @@ import org.maxkey.authz.oauth2.provider.token.TokenStore; ...@@ -38,6 +40,8 @@ import org.maxkey.authz.oauth2.provider.token.TokenStore;
*/ */
public class TokenApprovalStore implements ApprovalStore { public class TokenApprovalStore implements ApprovalStore {
static final Logger _logger = LoggerFactory.getLogger(TokenApprovalStore.class);
private TokenStore store; private TokenStore store;
/** /**
...@@ -55,6 +59,7 @@ public class TokenApprovalStore implements ApprovalStore { ...@@ -55,6 +59,7 @@ public class TokenApprovalStore implements ApprovalStore {
*/ */
@Override @Override
public boolean addApprovals(Collection<Approval> approvals) { public boolean addApprovals(Collection<Approval> approvals) {
_logger.debug("add Approvals...");
return true; return true;
} }
...@@ -65,6 +70,7 @@ public class TokenApprovalStore implements ApprovalStore { ...@@ -65,6 +70,7 @@ public class TokenApprovalStore implements ApprovalStore {
*/ */
@Override @Override
public boolean revokeApprovals(Collection<Approval> approvals) { public boolean revokeApprovals(Collection<Approval> approvals) {
_logger.debug("revoke Approvals " + approvals);
boolean success = true; boolean success = true;
for (Approval approval : approvals) { for (Approval approval : approvals) {
Collection<OAuth2AccessToken> tokens = store.findTokensByClientIdAndUserName(approval.getClientId(), approval.getUserId()); Collection<OAuth2AccessToken> tokens = store.findTokensByClientIdAndUserName(approval.getClientId(), approval.getUserId());
...@@ -87,14 +93,22 @@ public class TokenApprovalStore implements ApprovalStore { ...@@ -87,14 +93,22 @@ public class TokenApprovalStore implements ApprovalStore {
*/ */
@Override @Override
public Collection<Approval> getApprovals(String userId, String clientId) { public Collection<Approval> getApprovals(String userId, String clientId) {
_logger.trace("userId " + userId+" , clientId " + clientId);
Collection<Approval> result = new HashSet<Approval>(); Collection<Approval> result = new HashSet<Approval>();
Collection<OAuth2AccessToken> tokens = store.findTokensByClientIdAndUserName(clientId, userId); Collection<OAuth2AccessToken> tokens = store.findTokensByClientIdAndUserName(clientId, userId);
_logger.trace("tokens Collection " + tokens);
for (OAuth2AccessToken token : tokens) { for (OAuth2AccessToken token : tokens) {
OAuth2Authentication authentication = store.readAuthentication(token); _logger.trace("token " + token);
if (authentication != null) { if(token != null) {
Date expiresAt = token.getExpiration(); OAuth2Authentication authentication = store.readAuthentication(token);
for (String scope : token.getScope()) { _logger.trace("authentication " + authentication);
result.add(new Approval(userId, clientId, scope, expiresAt, ApprovalStatus.APPROVED)); if (authentication != null) {
Date expiresAt = token.getExpiration();
for (String scope : token.getScope()) {
Approval approval = new Approval(userId, clientId, scope, expiresAt, ApprovalStatus.APPROVED);
result.add(approval);
_logger.trace("add approval " + approval);
}
} }
} }
} }
......
...@@ -77,48 +77,52 @@ public class OAuth20AccessConfirmationEndpoint { ...@@ -77,48 +77,52 @@ public class OAuth20AccessConfirmationEndpoint {
*/ */
@RequestMapping(OAuth2Constants.ENDPOINT.ENDPOINT_APPROVAL_CONFIRM) @RequestMapping(OAuth2Constants.ENDPOINT.ENDPOINT_APPROVAL_CONFIRM)
public ModelAndView getAccessConfirmation( public ModelAndView getAccessConfirmation(
@RequestParam Map<String, Object> model) throws Exception { @RequestParam Map<String, Object> model) {
model.remove("authorizationRequest"); try {
model.remove("authorizationRequest");
// Map<String, Object> model
AuthorizationRequest clientAuth = // Map<String, Object> model
(AuthorizationRequest) WebContext.getAttribute("authorizationRequest"); AuthorizationRequest clientAuth =
ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); (AuthorizationRequest) WebContext.getAttribute("authorizationRequest");
Apps app = (Apps)WebContext.getAttribute(WebConstants.AUTHORIZE_SIGN_ON_APP); ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
//session中为空或者id不一致重新加载 Apps app = (Apps)WebContext.getAttribute(WebConstants.AUTHORIZE_SIGN_ON_APP);
if (app == null || !app.getId().equalsIgnoreCase(clientAuth.getClientId())) { //session中为空或者id不一致重新加载
app = appsService.get(clientAuth.getClientId()); if (app == null || !app.getId().equalsIgnoreCase(clientAuth.getClientId())) {
WebContext.setAttribute(WebConstants.AUTHORIZE_SIGN_ON_APP, app); app = appsService.get(clientAuth.getClientId());
WebContext.setAttribute(app.getId(), app.getIcon()); WebContext.setAttribute(WebConstants.AUTHORIZE_SIGN_ON_APP, app);
} WebContext.setAttribute(app.getId(), app.getIcon());
}
model.put("auth_request", clientAuth);
model.put("client", client); model.put("auth_request", clientAuth);
model.put("app", app); model.put("client", client);
model.put("oauth_version", "oauth 2.0"); model.put("app", app);
Map<String, String> scopes = new LinkedHashMap<String, String>(); model.put("oauth_version", "oauth 2.0");
for (String scope : clientAuth.getScope()) { Map<String, String> scopes = new LinkedHashMap<String, String>();
scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false"); for (String scope : clientAuth.getScope()) {
} scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false");
String principal = }
((SigninPrincipal) WebContext.getAuthentication().getPrincipal()).getUsername(); String principal =
for (Approval approval : approvalStore.getApprovals(principal, client.getClientId())) { ((SigninPrincipal) WebContext.getAuthentication().getPrincipal()).getUsername();
if (clientAuth.getScope().contains(approval.getScope())) { for (Approval approval : approvalStore.getApprovals(principal, client.getClientId())) {
scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(), if (clientAuth.getScope().contains(approval.getScope())) {
approval.getStatus() == ApprovalStatus.APPROVED ? "true" : "false"); scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(),
} approval.getStatus() == ApprovalStatus.APPROVED ? "true" : "false");
} }
}
model.put("scopes", scopes);
model.put("scopes", scopes);
if(!model.containsKey(OAuth2Constants.PARAMETER.APPROVAL_PROMPT)) {
model.put(OAuth2Constants.PARAMETER.APPROVAL_PROMPT, client.getApprovalPrompt()); if(!model.containsKey(OAuth2Constants.PARAMETER.APPROVAL_PROMPT)) {
} model.put(OAuth2Constants.PARAMETER.APPROVAL_PROMPT, client.getApprovalPrompt());
}
}catch(Exception e) {
_logger.debug("OAuth Access Confirmation process error." ,e);
}
ModelAndView modelAndView = new ModelAndView("authorize/oauth_access_confirmation"); ModelAndView modelAndView = new ModelAndView("authorize/oauth_access_confirmation");
_logger.debug("Confirmation details "); _logger.trace("Confirmation details ");
for (Object key : model.keySet()) { for (Object key : model.keySet()) {
_logger.debug("key " + key +"=" + model.get(key)); _logger.trace("key " + key +"=" + model.get(key));
} }
modelAndView.addObject("model", model); modelAndView.addObject("model", model);
return modelAndView; return modelAndView;
......
...@@ -32,6 +32,8 @@ import org.maxkey.authz.oauth2.provider.token.TokenStore; ...@@ -32,6 +32,8 @@ import org.maxkey.authz.oauth2.provider.token.TokenStore;
import org.maxkey.persistence.redis.RedisConnection; import org.maxkey.persistence.redis.RedisConnection;
import org.maxkey.persistence.redis.RedisConnectionFactory; import org.maxkey.persistence.redis.RedisConnectionFactory;
import org.maxkey.util.ObjectTransformer; import org.maxkey.util.ObjectTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date; import java.util.Date;
...@@ -39,16 +41,17 @@ import java.util.Date; ...@@ -39,16 +41,17 @@ import java.util.Date;
* @author efenderbosch * @author efenderbosch
*/ */
public class RedisTokenStore implements TokenStore { public class RedisTokenStore implements TokenStore {
static final Logger _logger = LoggerFactory.getLogger(RedisTokenStore.class);
private static final String ACCESS = "REDIS_OAUTH_V20_access:";
private static final String AUTH_TO_ACCESS = "REDIS_OAUTH_V20_auth_to_access:"; private static final String ACCESS = "REDIS_OAUTH_V20_ACCESS_";
private static final String AUTH = "REDIS_OAUTH_V20_auth:"; private static final String AUTH_TO_ACCESS = "REDIS_OAUTH_V20_AUTH_TO_ACCESS_";
private static final String REFRESH_AUTH = "REDIS_OAUTH_V20_refresh_auth:"; private static final String AUTH = "REDIS_OAUTH_V20_AUTH_";
private static final String ACCESS_TO_REFRESH = "REDIS_OAUTH_V20_access_to_refresh:"; private static final String REFRESH_AUTH = "REDIS_OAUTH_V20_REFRESH_AUTH_";
private static final String REFRESH = "REDIS_OAUTH_V20_refresh:"; private static final String ACCESS_TO_REFRESH = "REDIS_OAUTH_V20_ACCESS_TO_REFRESH_";
private static final String REFRESH_TO_ACCESS = "REDIS_OAUTH_V20_refresh_to_access:"; private static final String REFRESH = "REDIS_OAUTH_V20_REFRESH_";
private static final String CLIENT_ID_TO_ACCESS = "REDIS_OAUTH_V20_client_id_to_access:"; private static final String REFRESH_TO_ACCESS = "REDIS_OAUTH_V20_REFRESH_TO_ACCESS_";
private static final String UNAME_TO_ACCESS = "REDIS_OAUTH_V20_uname_to_access:"; private static final String CLIENT_ID_TO_ACCESS = "REDIS_OAUTH_V20_CLIENT_ID_TO_ACCESS_";
private static final String UNAME_TO_ACCESS = "REDIS_OAUTH_V20_UNAME_TO_ACCESS_";
private final RedisConnectionFactory connectionFactory; private final RedisConnectionFactory connectionFactory;
private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();
...@@ -77,15 +80,19 @@ public class RedisTokenStore implements TokenStore { ...@@ -77,15 +80,19 @@ public class RedisTokenStore implements TokenStore {
String key = authenticationKeyGenerator.extractKey(authentication); String key = authenticationKeyGenerator.extractKey(authentication);
String serializedKey = (AUTH_TO_ACCESS + key); String serializedKey = (AUTH_TO_ACCESS + key);
RedisConnection conn = getConnection(); RedisConnection conn = getConnection();
OAuth2AccessToken accessToken =conn.getObject(serializedKey); try {
if (accessToken != null OAuth2AccessToken accessToken =conn.getObject(serializedKey);
&& !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) { if (accessToken != null
// Keep the stores consistent (maybe the same user is && !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) {
// represented by this authentication but the details have // Keep the stores consistent (maybe the same user is
// changed) // represented by this authentication but the details have
storeAccessToken(accessToken, authentication); // changed)
storeAccessToken(accessToken, authentication);
}
return accessToken;
} finally {
conn.close();
} }
return accessToken;
} }
@Override @Override
...@@ -95,9 +102,14 @@ public class RedisTokenStore implements TokenStore { ...@@ -95,9 +102,14 @@ public class RedisTokenStore implements TokenStore {
@Override @Override
public OAuth2Authentication readAuthentication(String token) { public OAuth2Authentication readAuthentication(String token) {
_logger.trace("read Authentication by token " + token + " , token key " + AUTH + token);
RedisConnection conn = getConnection(); RedisConnection conn = getConnection();
OAuth2Authentication auth = conn.getObject(AUTH + token); try {
return auth; OAuth2Authentication auth = conn.getObject(AUTH + token);
return auth;
} finally {
conn.close();
}
} }
@Override @Override
...@@ -122,6 +134,11 @@ public class RedisTokenStore implements TokenStore { ...@@ -122,6 +134,11 @@ public class RedisTokenStore implements TokenStore {
String authToAccessKey = (AUTH_TO_ACCESS + authenticationKeyGenerator.extractKey(authentication)); String authToAccessKey = (AUTH_TO_ACCESS + authenticationKeyGenerator.extractKey(authentication));
String approvalKey = (UNAME_TO_ACCESS + getApprovalKey(authentication)); String approvalKey = (UNAME_TO_ACCESS + getApprovalKey(authentication));
String clientId = (CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId()); String clientId = (CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId());
_logger.trace("accessKey " + accessKey);
_logger.trace("authKey " + authKey);
_logger.trace("authToAccessKey " + authToAccessKey);
_logger.trace("approvalKey " + approvalKey);
_logger.trace("clientId " + clientId);
RedisConnection conn = getConnection(); RedisConnection conn = getConnection();
try { try {
...@@ -146,8 +163,10 @@ public class RedisTokenStore implements TokenStore { ...@@ -146,8 +163,10 @@ public class RedisTokenStore implements TokenStore {
String refresh = (token.getRefreshToken().getValue()); String refresh = (token.getRefreshToken().getValue());
String auth = (token.getValue()); String auth = (token.getValue());
String refreshToAccessKey = (REFRESH_TO_ACCESS + token.getRefreshToken().getValue()); String refreshToAccessKey = (REFRESH_TO_ACCESS + token.getRefreshToken().getValue());
_logger.trace("refreshToAccessKey " + refreshToAccessKey);
conn.set(refreshToAccessKey, auth); conn.set(refreshToAccessKey, auth);
String accessToRefreshKey = (ACCESS_TO_REFRESH + token.getValue()); String accessToRefreshKey = (ACCESS_TO_REFRESH + token.getValue());
_logger.trace("accessToRefreshKey " + accessToRefreshKey);
conn.set(accessToRefreshKey, refresh); conn.set(accessToRefreshKey, refresh);
if (refreshToken instanceof ExpiringOAuth2RefreshToken) { if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken; ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken;
...@@ -173,7 +192,7 @@ public class RedisTokenStore implements TokenStore { ...@@ -173,7 +192,7 @@ public class RedisTokenStore implements TokenStore {
} }
private static String getApprovalKey(String clientId, String userName) { private static String getApprovalKey(String clientId, String userName) {
return clientId + (userName == null ? "" : ":" + userName); return clientId + (userName == null ? "" : "_" + userName);
} }
@Override @Override
...@@ -184,9 +203,13 @@ public class RedisTokenStore implements TokenStore { ...@@ -184,9 +203,13 @@ public class RedisTokenStore implements TokenStore {
@Override @Override
public OAuth2AccessToken readAccessToken(String tokenValue) { public OAuth2AccessToken readAccessToken(String tokenValue) {
RedisConnection conn = getConnection(); RedisConnection conn = getConnection();
String key = (ACCESS + tokenValue); try {
OAuth2AccessToken accessToken = conn.getObject(key); String key = (ACCESS + tokenValue);
return accessToken; OAuth2AccessToken accessToken = conn.getObject(key);
return accessToken;
} finally {
conn.close();
}
} }
public void removeAccessToken(String tokenValue) { public void removeAccessToken(String tokenValue) {
...@@ -251,9 +274,13 @@ public class RedisTokenStore implements TokenStore { ...@@ -251,9 +274,13 @@ public class RedisTokenStore implements TokenStore {
public OAuth2RefreshToken readRefreshToken(String tokenValue) { public OAuth2RefreshToken readRefreshToken(String tokenValue) {
String key = (REFRESH + tokenValue); String key = (REFRESH + tokenValue);
RedisConnection conn = getConnection(); RedisConnection conn = getConnection();
OAuth2RefreshToken refreshToken = conn.getObject(key); try {
conn.close(); OAuth2RefreshToken refreshToken = conn.getObject(key);
return refreshToken; conn.close();
return refreshToken;
} finally {
conn.close();
}
} }
@Override @Override
...@@ -309,6 +336,7 @@ public class RedisTokenStore implements TokenStore { ...@@ -309,6 +336,7 @@ public class RedisTokenStore implements TokenStore {
@Override @Override
public Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) { public Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {
String approvalKey = (UNAME_TO_ACCESS + getApprovalKey(clientId, userName)); String approvalKey = (UNAME_TO_ACCESS + getApprovalKey(clientId, userName));
_logger.trace("approvalKey " + approvalKey);
List<String> stringList = null; List<String> stringList = null;
RedisConnection conn = getConnection(); RedisConnection conn = getConnection();
try { try {
...@@ -321,6 +349,7 @@ public class RedisTokenStore implements TokenStore { ...@@ -321,6 +349,7 @@ public class RedisTokenStore implements TokenStore {
} }
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(stringList.size()); List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(stringList.size());
for (String str : stringList) { for (String str : stringList) {
//accessToken may expired
OAuth2AccessToken accessToken = conn.getObject(str); OAuth2AccessToken accessToken = conn.getObject(str);
accessTokens.add(accessToken); accessTokens.add(accessToken);
} }
...@@ -330,6 +359,7 @@ public class RedisTokenStore implements TokenStore { ...@@ -330,6 +359,7 @@ public class RedisTokenStore implements TokenStore {
@Override @Override
public Collection<OAuth2AccessToken> findTokensByClientId(String clientId) { public Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {
String key = (CLIENT_ID_TO_ACCESS + clientId); String key = (CLIENT_ID_TO_ACCESS + clientId);
_logger.trace("TokensByClientId " + key);
List<String> stringList = null; List<String> stringList = null;
RedisConnection conn = getConnection(); RedisConnection conn = getConnection();
try { try {
......
...@@ -211,12 +211,13 @@ public class MaxKeyMvcConfig implements WebMvcConfigurer { ...@@ -211,12 +211,13 @@ public class MaxKeyMvcConfig implements WebMvcConfigurer {
registry.addInterceptor(historyLoginAppAdapter) registry.addInterceptor(historyLoginAppAdapter)
.addPathPatterns("/authz/basic/*") .addPathPatterns("/authz/basic/*")
.addPathPatterns("/authz/ltpa/*") .addPathPatterns("/authz/ltpa/*")
.addPathPatterns("/authz/desktop/*") .addPathPatterns("/authz/api/*")
.addPathPatterns("/authz/formbased/*") .addPathPatterns("/authz/formbased/*")
.addPathPatterns("/authz/tokenbased/*") .addPathPatterns("/authz/tokenbased/*")
.addPathPatterns("/authz/saml20/idpinit/*") .addPathPatterns("/authz/saml20/idpinit/*")
.addPathPatterns("/authz/saml20/assertion") .addPathPatterns("/authz/saml20/assertion")
.addPathPatterns("/authz/cas/granting") .addPathPatterns("/authz/cas/granting")
.addPathPatterns("/authz/oauth/v20/approval_confirm")
; ;
_logger.debug("add HistoryLoginAppAdapter"); _logger.debug("add HistoryLoginAppAdapter");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册