Client /dto update

pull/4/head
shengzhaoli.shengz 2023-10-13 15:21:03 +08:00
parent a686b0b18b
commit 7e56e71335
12 changed files with 941 additions and 260 deletions

View File

@ -2,17 +2,32 @@ package com.monkeyk.sos.domain.oauth;
import com.monkeyk.sos.infrastructure.DateUtils; import com.monkeyk.sos.infrastructure.DateUtils;
import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.time.Instant;
import java.time.LocalDateTime; import java.time.LocalDateTime;
/** /**
* table: oauth2_registered_client
*
* @author Shengzhao Li * @author Shengzhao Li
* @see org.springframework.security.oauth2.server.authorization.client.RegisteredClient
* @since 1.0.0
*/ */
public class OauthClientDetails implements Serializable { public class OauthClientDetails implements Serializable {
@Serial
private static final long serialVersionUID = -6947822646185526939L; private static final long serialVersionUID = -6947822646185526939L;
/**
* id
*
* @since 3.0.0
*/
private String id;
/** /**
* *
*/ */
@ -26,81 +41,151 @@ public class OauthClientDetails implements Serializable {
private String clientId; private String clientId;
/** /**
* @deprecated OAuth2.1 not used from v3.0.0 * client
*
*
* @since 3.0.0
*/ */
private String resourceIds; private String clientName;
/** /**
* Encrypted * client
*
* @since 3.0.0
*/
private Instant clientIdIssuedAt = Instant.now();
/**
* Encrypted
*/ */
private String clientSecret; private String clientSecret;
/**
* Available values: read,write
*/
private String scope;
/** /**
* grant types include * secret
* "authorization_code", "password", "assertion", and "refresh_token". * null
* Default value is "authorization_code,refresh_token". * 使
*
* @since 3.0.0
*/ */
private String authorizedGrantTypes = "authorization_code,refresh_token"; private Instant clientSecretExpiresAt;
/** /**
*
* : client_secret_basic,client_secret_post
*
* @see org.springframework.security.oauth2.core.ClientAuthenticationMethod
* @since 3.0.0
*/
private String clientAuthenticationMethods;
/**
* OIDC scope ,
* : openid,profile,email
*
* @see org.springframework.security.oauth2.core.oidc.OidcScopes
*/
private String scopes;
/**
* grant_type (OAuth2.1),
* : authorization_code,refresh_token
*
* @see org.springframework.security.oauth2.core.AuthorizationGrantType
*/
private String authorizationGrantTypes;
/**
* OAuth2 uri code,
* The re-direct URI(s) established during registration (optional, comma separated). * The re-direct URI(s) established during registration (optional, comma separated).
*/ */
private String webServerRedirectUri; private String redirectUris;
/** /**
* Authorities that are granted to the client (comma-separated). Distinct from the authorities * OAuth2 退 post uri
* granted to the user on behalf of whom the client is acting. *
* <p/> * client
* For example: ROLE_USER *
* @since 3.0.0
*/ */
private String authorities; private String postLogoutRedirectUris;
/** /**
* The access token validity period in seconds (optional). *
* If unspecified a global default will be applied by the token services. * PKCE(consent)
* {ClientSettings}
*
* @see org.springframework.security.oauth2.server.authorization.settings.ClientSettings
* @since 3.0.0
*/ */
private Integer accessTokenValidity; private String clientSettings;
/** /**
* The refresh token validity period in seconds (optional). * token
* If unspecified a global default will be applied by the token services. * tokenrefresh_token
* {TokenSettings}
*
* @see org.springframework.security.oauth2.server.authorization.settings.TokenSettings
* @since 3.0.0
*/ */
private Integer refreshTokenValidity; private String tokenSettings;
// optional
private String additionalInformation;
/**
* The client is trusted or not. If it is trust, will skip approve step
* default false.
*/
private boolean trusted = false;
/**
* Value is 'true' or 'false', default 'false'
*/
private String autoApprove;
public OauthClientDetails() { public OauthClientDetails() {
} }
public String autoApprove() {
return autoApprove; /**
* @since 3.0.0
*/
public String id() {
return id;
} }
public OauthClientDetails autoApprove(String autoApprove) { /**
this.autoApprove = autoApprove; * @since 3.0.0
*/
public OauthClientDetails id(String id) {
this.id = id;
return this; return this;
} }
public boolean trusted() { /**
return trusted; * @since 3.0.0
*/
public String tokenSettings() {
return tokenSettings;
} }
/**
* @since 3.0.0
*/
public OauthClientDetails tokenSettings(String tokenSettings) {
this.tokenSettings = tokenSettings;
return this;
}
/**
* @since 3.0.0
*/
public String clientSettings() {
return clientSettings;
}
/**
* @since 3.0.0
*/
public OauthClientDetails clientSettings(String clientSettings) {
this.clientSettings = clientSettings;
return this;
}
public LocalDateTime createTime() { public LocalDateTime createTime() {
return createTime; return createTime;
} }
@ -118,42 +203,112 @@ public class OauthClientDetails implements Serializable {
return clientId; return clientId;
} }
public String resourceIds() {
return resourceIds;
}
public String clientSecret() { public String clientSecret() {
return clientSecret; return clientSecret;
} }
public String scope() { /**
return scope; * @since 3.0.0
*/
public String clientName() {
return clientName;
} }
public String authorizedGrantTypes() { /**
return authorizedGrantTypes; * @since 3.0.0
*/
public OauthClientDetails clientName(String clientName) {
this.clientName = clientName;
return this;
} }
public String webServerRedirectUri() { /**
return webServerRedirectUri; * @since 3.0.0
*/
public Instant clientIdIssuedAt() {
return clientIdIssuedAt;
} }
public String authorities() { /**
return authorities; * @since 3.0.0
*/
public OauthClientDetails clientIdIssuedAt(Instant clientIdIssuedAt) {
this.clientIdIssuedAt = clientIdIssuedAt;
return this;
} }
public Integer accessTokenValidity() { /**
return accessTokenValidity; * @since 3.0.0
*/
public Instant clientSecretExpiresAt() {
return clientSecretExpiresAt;
} }
public Integer refreshTokenValidity() { /**
return refreshTokenValidity; * @since 3.0.0
*/
public OauthClientDetails clientSecretExpiresAt(Instant clientSecretExpiresAt) {
this.clientSecretExpiresAt = clientSecretExpiresAt;
return this;
} }
public String additionalInformation() { /**
return additionalInformation; * @since 3.0.0
*/
public String clientAuthenticationMethods() {
return clientAuthenticationMethods;
} }
/**
* @since 3.0.0
*/
public OauthClientDetails clientAuthenticationMethods(String clientAuthenticationMethods) {
this.clientAuthenticationMethods = clientAuthenticationMethods;
return this;
}
public String scopes() {
return scopes;
}
public OauthClientDetails scopes(String scopes) {
this.scopes = scopes;
return this;
}
public String authorizationGrantTypes() {
return authorizationGrantTypes;
}
public OauthClientDetails authorizationGrantTypes(String authorizationGrantTypes) {
this.authorizationGrantTypes = authorizationGrantTypes;
return this;
}
public String redirectUris() {
return redirectUris;
}
public OauthClientDetails redirectUris(String redirectUris) {
this.redirectUris = redirectUris;
return this;
}
/**
* @since 3.0.0
*/
public String postLogoutRedirectUris() {
return postLogoutRedirectUris;
}
/**
* @since 3.0.0
*/
public OauthClientDetails postLogoutRedirectUris(String postLogoutRedirectUris) {
this.postLogoutRedirectUris = postLogoutRedirectUris;
return this;
}
@Override @Override
public String toString() { public String toString() {
@ -162,15 +317,15 @@ public class OauthClientDetails implements Serializable {
sb.append("{createTime=").append(createTime); sb.append("{createTime=").append(createTime);
sb.append(", archived=").append(archived); sb.append(", archived=").append(archived);
sb.append(", clientId='").append(clientId).append('\''); sb.append(", clientId='").append(clientId).append('\'');
sb.append(", resourceIds='").append(resourceIds).append('\''); sb.append(", clientName='").append(clientName).append('\'');
sb.append(", scope='").append(scope).append('\''); sb.append(", scopes='").append(scopes).append('\'');
sb.append(", authorizedGrantTypes='").append(authorizedGrantTypes).append('\''); sb.append(", authorizationGrantTypes='").append(authorizationGrantTypes).append('\'');
sb.append(", webServerRedirectUri='").append(webServerRedirectUri).append('\''); sb.append(", redirectUris='").append(redirectUris).append('\'');
sb.append(", authorities='").append(authorities).append('\''); sb.append(", clientIdIssuedAt='").append(clientIdIssuedAt).append('\'');
sb.append(", accessTokenValidity=").append(accessTokenValidity); sb.append(", clientSettings=").append(clientSettings);
sb.append(", refreshTokenValidity=").append(refreshTokenValidity); sb.append(", tokenSettings=").append(tokenSettings);
sb.append(", additionalInformation='").append(additionalInformation).append('\''); sb.append(", postLogoutRedirectUris='").append(postLogoutRedirectUris).append('\'');
sb.append(", trusted=").append(trusted); sb.append(", clientAuthenticationMethods=").append(clientAuthenticationMethods);
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
@ -185,53 +340,6 @@ public class OauthClientDetails implements Serializable {
return this; return this;
} }
/**
* @deprecated OAuth2.1 not used from v3.0.0
*/
public OauthClientDetails resourceIds(String resourceIds) {
this.resourceIds = resourceIds;
return this;
}
public OauthClientDetails authorizedGrantTypes(String authorizedGrantTypes) {
this.authorizedGrantTypes = authorizedGrantTypes;
return this;
}
public OauthClientDetails scope(String scope) {
this.scope = scope;
return this;
}
public OauthClientDetails webServerRedirectUri(String webServerRedirectUri) {
this.webServerRedirectUri = webServerRedirectUri;
return this;
}
public OauthClientDetails authorities(String authorities) {
this.authorities = authorities;
return this;
}
public OauthClientDetails accessTokenValidity(Integer accessTokenValidity) {
this.accessTokenValidity = accessTokenValidity;
return this;
}
public OauthClientDetails refreshTokenValidity(Integer refreshTokenValidity) {
this.refreshTokenValidity = refreshTokenValidity;
return this;
}
public OauthClientDetails trusted(boolean trusted) {
this.trusted = trusted;
return this;
}
public OauthClientDetails additionalInformation(String additionalInformation) {
this.additionalInformation = additionalInformation;
return this;
}
public OauthClientDetails archived(boolean archived) { public OauthClientDetails archived(boolean archived) {
this.archived = archived; this.archived = archived;

View File

@ -6,6 +6,7 @@ import java.util.List;
/** /**
* @author Shengzhao Li * @author Shengzhao Li
* @since 1.0.0
*/ */
public interface OauthRepository extends Repository { public interface OauthRepository extends Repository {

View File

@ -0,0 +1,108 @@
package com.monkeyk.sos.infrastructure;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.jackson2.SecurityJackson2Modules;
import org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationServerJackson2Module;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.ConfigurationSettingNames;
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import java.util.List;
import java.util.Map;
/**
* 2023/10/13 14:49
*
* @author Shengzhao Li
* @since 3.0.0
*/
public abstract class SettingsUtils {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
// ClassLoader classLoader = JdbcRegisteredClientRepository.class.getClassLoader();
ClassLoader classLoader = SettingsUtils.class.getClassLoader();
List<Module> securityModules = SecurityJackson2Modules.getModules(classLoader);
objectMapper.registerModules(securityModules);
objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
}
private SettingsUtils() {
}
/**
* text settings -> TokenSettings
*
* @param settings text
* @return TokenSettings
*/
public static TokenSettings buildTokenSettings(String settings) {
Map<String, Object> map = parseMap(settings);
TokenSettings.Builder builder = TokenSettings.withSettings(map);
if (!map.containsKey(ConfigurationSettingNames.Token.ACCESS_TOKEN_FORMAT)) {
builder.accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED);
}
return builder.build();
}
/**
* TokenSettings -> text
*
* @param settings TokenSettings
* @return text
*/
public static String textTokenSettings(TokenSettings settings) {
Map<String, Object> map = settings.getSettings();
return writeMap(map);
}
/**
* ClientSettings -> text
*
* @param settings ClientSettings
* @return text
*/
public static String textClientSettings(ClientSettings settings) {
Map<String, Object> map = settings.getSettings();
return writeMap(map);
}
/**
* text settings -> ClientSettings
*
* @param settings text
* @return ClientSettings
*/
public static ClientSettings buildClientSettings(String settings) {
Map<String, Object> map = parseMap(settings);
return ClientSettings.withSettings(map)
.build();
}
private static Map<String, Object> parseMap(String data) {
try {
return objectMapper.readValue(data, new TypeReference<>() {
});
} catch (Exception ex) {
throw new IllegalArgumentException(ex.getMessage(), ex);
}
}
private static String writeMap(Map<String, Object> data) {
try {
return objectMapper.writeValueAsString(data);
} catch (Exception ex) {
throw new IllegalArgumentException(ex.getMessage(), ex);
}
}
}

View File

@ -34,23 +34,23 @@ public class OauthClientDetailsRowMapper implements RowMapper<OauthClientDetails
OauthClientDetails clientDetails = new OauthClientDetails(); OauthClientDetails clientDetails = new OauthClientDetails();
clientDetails.clientId(rs.getString("client_id")); clientDetails.clientId(rs.getString("client_id"));
clientDetails.resourceIds(rs.getString("resource_ids")); // clientDetails.resourceIds(rs.getString("resource_ids"));
clientDetails.clientSecret(rs.getString("client_secret")); clientDetails.clientSecret(rs.getString("client_secret"));
clientDetails.scope(rs.getString("scope")); // clientDetails.scope(rs.getString("scope"));
clientDetails.authorizedGrantTypes(rs.getString("authorized_grant_types")); // clientDetails.authorizedGrantTypes(rs.getString("authorized_grant_types"));
clientDetails.webServerRedirectUri(rs.getString("web_server_redirect_uri")); // clientDetails.webServerRedirectUri(rs.getString("web_server_redirect_uri"));
clientDetails.authorities(rs.getString("authorities")); // clientDetails.authorities(rs.getString("authorities"));
clientDetails.accessTokenValidity(getInteger(rs, "access_token_validity")); // clientDetails.accessTokenValidity(getInteger(rs, "access_token_validity"));
clientDetails.refreshTokenValidity(getInteger(rs, "refresh_token_validity")); // clientDetails.refreshTokenValidity(getInteger(rs, "refresh_token_validity"));
clientDetails.additionalInformation(rs.getString("additional_information")); // clientDetails.additionalInformation(rs.getString("additional_information"));
clientDetails.createTime(rs.getTimestamp("create_time").toLocalDateTime()); clientDetails.createTime(rs.getTimestamp("create_time").toLocalDateTime());
clientDetails.archived(rs.getBoolean("archived")); clientDetails.archived(rs.getBoolean("archived"));
clientDetails.trusted(rs.getBoolean("trusted")); // clientDetails.trusted(rs.getBoolean("trusted"));
clientDetails.autoApprove(rs.getString("autoapprove")); // clientDetails.autoApprove(rs.getString("autoapprove"));
return clientDetails; return clientDetails;
} }

View File

@ -62,22 +62,22 @@ public class OauthRepositoryJdbc implements OauthRepository {
this.jdbcTemplate.update(sql, ps -> { this.jdbcTemplate.update(sql, ps -> {
ps.setString(1, clientDetails.clientId()); ps.setString(1, clientDetails.clientId());
ps.setString(2, clientDetails.resourceIds()); // ps.setString(2, clientDetails.resourceIds());
ps.setString(3, clientDetails.clientSecret()); ps.setString(3, clientDetails.clientSecret());
ps.setString(4, clientDetails.scope()); // ps.setString(4, clientDetails.scope());
ps.setString(5, clientDetails.authorizedGrantTypes()); // ps.setString(5, clientDetails.authorizedGrantTypes());
ps.setString(6, clientDetails.webServerRedirectUri()); // ps.setString(6, clientDetails.webServerRedirectUri());
ps.setString(7, clientDetails.authorities()); // ps.setString(7, clientDetails.authorities());
ps.setObject(8, clientDetails.accessTokenValidity()); // ps.setObject(8, clientDetails.accessTokenValidity());
ps.setObject(9, clientDetails.refreshTokenValidity()); // ps.setObject(9, clientDetails.refreshTokenValidity());
ps.setString(10, clientDetails.additionalInformation()); // ps.setString(10, clientDetails.additionalInformation());
ps.setBoolean(11, clientDetails.trusted()); // ps.setBoolean(11, clientDetails.trusted());
ps.setString(12, clientDetails.autoApprove()); // ps.setString(12, clientDetails.autoApprove());
}); });
} }

View File

@ -0,0 +1,109 @@
package com.monkeyk.sos.service.dto;
import com.monkeyk.sos.infrastructure.SettingsUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.oauth2.jose.jws.JwsAlgorithm;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import java.io.Serial;
import java.io.Serializable;
import static org.springframework.security.oauth2.jose.jws.JwsAlgorithms.RS256;
/**
* 2023/10/13 11:52
* <p>
* .requireProofKey(false)
* .requireAuthorizationConsent(false);
*
* @author Shengzhao Li
* @see org.springframework.security.oauth2.server.authorization.settings.ClientSettings
* @since 3.0.0
*/
public class ClientSettingsDto implements Serializable {
@Serial
private static final long serialVersionUID = -7335241589844569340L;
/**
* PKCEtrue
* false
*/
private boolean requireProofKey;
/**
* true
* false
*/
private boolean requireAuthorizationConsent;
/**
* client jwk URL
* , null
*/
private String jwkSetUrl;
/**
* jwt token
* JwsAlgorithm
*
* @see JwsAlgorithm
*/
private String tokenEndpointAuthenticationSigningAlgorithm = RS256;
public ClientSettingsDto() {
}
public ClientSettingsDto(String clientSettings) {
ClientSettings settings = SettingsUtils.buildClientSettings(clientSettings);
this.requireAuthorizationConsent = settings.isRequireAuthorizationConsent();
this.requireProofKey = settings.isRequireProofKey();
this.tokenEndpointAuthenticationSigningAlgorithm = settings.getTokenEndpointAuthenticationSigningAlgorithm().getName();
this.jwkSetUrl = settings.getJwkSetUrl();
}
public ClientSettings toSettings() {
ClientSettings.Builder builder = ClientSettings.builder()
.requireProofKey(requireProofKey)
.tokenEndpointAuthenticationSigningAlgorithm(SignatureAlgorithm.valueOf(tokenEndpointAuthenticationSigningAlgorithm));
if (StringUtils.isNotBlank(jwkSetUrl)) {
builder.jwkSetUrl(jwkSetUrl);
}
return builder.build();
}
public boolean isRequireProofKey() {
return requireProofKey;
}
public void setRequireProofKey(boolean requireProofKey) {
this.requireProofKey = requireProofKey;
}
public boolean isRequireAuthorizationConsent() {
return requireAuthorizationConsent;
}
public void setRequireAuthorizationConsent(boolean requireAuthorizationConsent) {
this.requireAuthorizationConsent = requireAuthorizationConsent;
}
public String getJwkSetUrl() {
return jwkSetUrl;
}
public void setJwkSetUrl(String jwkSetUrl) {
this.jwkSetUrl = jwkSetUrl;
}
public String getTokenEndpointAuthenticationSigningAlgorithm() {
return tokenEndpointAuthenticationSigningAlgorithm;
}
public void setTokenEndpointAuthenticationSigningAlgorithm(String tokenEndpointAuthenticationSigningAlgorithm) {
this.tokenEndpointAuthenticationSigningAlgorithm = tokenEndpointAuthenticationSigningAlgorithm;
}
}

View File

@ -8,41 +8,126 @@ import org.apache.commons.lang3.StringUtils;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* @author Shengzhao Li * @author Shengzhao Li
* @since 1.0.0
*/ */
public class OauthClientDetailsDto implements Serializable { public class OauthClientDetailsDto implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 4011292111995231569L; private static final long serialVersionUID = 4011292111995231569L;
/**
* id
*
* @since 3.0.0
*/
private String id;
private String createTime; private String createTime;
private boolean archived; private boolean archived;
private String clientId = GuidGenerator.generate(); private String clientId = GuidGenerator.generate();
private String resourceIds;
/**
* client
*
*
* @since 3.0.0
*/
private String clientName;
/**
* client
*
* @since 3.0.0
*/
private String clientIdIssuedAt;
private String clientSecret = GuidGenerator.generateClientSecret(); private String clientSecret = GuidGenerator.generateClientSecret();
private String scope;
private String authorizedGrantTypes; /**
* secret
* null
* 使
*
* @since 3.0.0
*/
private String clientSecretExpiresAt;
private String webServerRedirectUri;
private String authorities; /**
*
* : client_secret_basic,client_secret_post
*
* @see org.springframework.security.oauth2.core.ClientAuthenticationMethod
* @since 3.0.0
*/
private String clientAuthenticationMethods;
private Integer accessTokenValidity;
private Integer refreshTokenValidity; /**
* OIDC scope ,
* : openid,profile,email
*
* @see org.springframework.security.oauth2.core.oidc.OidcScopes
*/
private String scopes;
// optional /**
private String additionalInformation; * grant_type (OAuth2.1),
* : authorization_code,refresh_token
*
* @see org.springframework.security.oauth2.core.AuthorizationGrantType
*/
private String authorizationGrantTypes;
/**
* OAuth2 uri code,
* The re-direct URI(s) established during registration (optional, comma separated).
*/
private String redirectUris;
/**
* OAuth2 退 post uri
*
* client
*
* @since 3.0.0
*/
private String postLogoutRedirectUris;
/**
*
* PKCE(consent)
* {ClientSettings}
*
* @see org.springframework.security.oauth2.server.authorization.settings.ClientSettings
* @since 3.0.0
*/
private ClientSettingsDto clientSettings;
/**
* token
* tokenrefresh_token
* {TokenSettings}
*
* @see org.springframework.security.oauth2.server.authorization.settings.TokenSettings
* @since 3.0.0
*/
private TokenSettingsDto tokenSettings;
private boolean trusted;
public OauthClientDetailsDto() { public OauthClientDetailsDto() {
} }
@ -50,21 +135,26 @@ public class OauthClientDetailsDto implements Serializable {
public OauthClientDetailsDto(OauthClientDetails clientDetails) { public OauthClientDetailsDto(OauthClientDetails clientDetails) {
this.clientId = clientDetails.clientId(); this.clientId = clientDetails.clientId();
this.clientSecret = clientDetails.clientSecret(); this.clientSecret = clientDetails.clientSecret();
this.scope = clientDetails.scope(); this.scopes = clientDetails.scopes();
this.createTime = DateUtils.toDateTime(clientDetails.createTime()); this.createTime = DateUtils.toDateTime(clientDetails.createTime());
this.archived = clientDetails.archived(); this.archived = clientDetails.archived();
this.resourceIds = clientDetails.resourceIds(); this.postLogoutRedirectUris = clientDetails.postLogoutRedirectUris();
this.webServerRedirectUri = clientDetails.webServerRedirectUri(); this.redirectUris = clientDetails.redirectUris();
this.authorities = clientDetails.authorities(); this.clientIdIssuedAt = clientDetails.clientIdIssuedAt().toString();
this.accessTokenValidity = clientDetails.accessTokenValidity(); Instant clientSecretExpiresAt1 = clientDetails.clientSecretExpiresAt();
if (clientSecretExpiresAt1 != null) {
this.clientSecretExpiresAt = clientSecretExpiresAt1.toString();
}
this.refreshTokenValidity = clientDetails.refreshTokenValidity(); this.clientAuthenticationMethods = clientDetails.clientAuthenticationMethods();
this.additionalInformation = clientDetails.additionalInformation(); this.clientName = clientDetails.clientName();
this.trusted = clientDetails.trusted(); this.id = clientDetails.id();
this.authorizedGrantTypes = clientDetails.authorizedGrantTypes(); this.authorizationGrantTypes = clientDetails.authorizationGrantTypes();
this.clientSettings = new ClientSettingsDto(clientDetails.clientSettings());
this.tokenSettings = new TokenSettingsDto(clientDetails.tokenSettings());
} }
@ -92,13 +182,6 @@ public class OauthClientDetailsDto implements Serializable {
this.clientId = clientId; this.clientId = clientId;
} }
public String getResourceIds() {
return resourceIds;
}
public void setResourceIds(String resourceIds) {
this.resourceIds = resourceIds;
}
public String getClientSecret() { public String getClientSecret() {
return clientSecret; return clientSecret;
@ -108,77 +191,6 @@ public class OauthClientDetailsDto implements Serializable {
this.clientSecret = clientSecret; this.clientSecret = clientSecret;
} }
public String getScope() {
return scope;
}
public String getScopeWithBlank() {
if (scope != null && scope.contains(",")) {
return scope.replaceAll(",", " ");
}
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getAuthorizedGrantTypes() {
return authorizedGrantTypes;
}
public void setAuthorizedGrantTypes(String authorizedGrantTypes) {
this.authorizedGrantTypes = authorizedGrantTypes;
}
public String getWebServerRedirectUri() {
return webServerRedirectUri;
}
public void setWebServerRedirectUri(String webServerRedirectUri) {
this.webServerRedirectUri = webServerRedirectUri;
}
public String getAuthorities() {
return authorities;
}
public void setAuthorities(String authorities) {
this.authorities = authorities;
}
public Integer getAccessTokenValidity() {
return accessTokenValidity;
}
public void setAccessTokenValidity(Integer accessTokenValidity) {
this.accessTokenValidity = accessTokenValidity;
}
public Integer getRefreshTokenValidity() {
return refreshTokenValidity;
}
public void setRefreshTokenValidity(Integer refreshTokenValidity) {
this.refreshTokenValidity = refreshTokenValidity;
}
public String getAdditionalInformation() {
return additionalInformation;
}
public void setAdditionalInformation(String additionalInformation) {
this.additionalInformation = additionalInformation;
}
public boolean isTrusted() {
return trusted;
}
public void setTrusted(boolean trusted) {
this.trusted = trusted;
}
public static List<OauthClientDetailsDto> toDtos(List<OauthClientDetails> clientDetailses) { public static List<OauthClientDetailsDto> toDtos(List<OauthClientDetails> clientDetailses) {
List<OauthClientDetailsDto> dtos = new ArrayList<>(clientDetailses.size()); List<OauthClientDetailsDto> dtos = new ArrayList<>(clientDetailses.size());
@ -190,51 +202,141 @@ public class OauthClientDetailsDto implements Serializable {
public boolean isContainsAuthorizationCode() { public boolean isContainsAuthorizationCode() {
return this.authorizedGrantTypes.contains("authorization_code"); return this.authorizationGrantTypes.contains("authorization_code");
} }
public boolean isContainsPassword() { public boolean isContainsPassword() {
return this.authorizedGrantTypes.contains("password"); return this.authorizationGrantTypes.contains("password");
} }
public boolean isContainsImplicit() { // public boolean isContainsImplicit() {
return this.authorizedGrantTypes.contains("implicit"); // return this.authorizationGrantTypes.contains("implicit");
} // }
public boolean isContainsClientCredentials() { public boolean isContainsClientCredentials() {
return this.authorizedGrantTypes.contains("client_credentials"); return this.authorizationGrantTypes.contains("client_credentials");
} }
public boolean isContainsRefreshToken() { public boolean isContainsRefreshToken() {
return this.authorizedGrantTypes.contains("refresh_token"); return this.authorizationGrantTypes.contains("refresh_token");
} }
public OauthClientDetails createDomain() { public OauthClientDetails createDomain() {
OauthClientDetails clientDetails = new OauthClientDetails() OauthClientDetails clientDetails = new OauthClientDetails()
.id(GuidGenerator.generate())
.clientId(clientId) .clientId(clientId)
.clientName(clientName)
// encrypted client secret // encrypted client secret
.clientSecret(PasswordHandler.encode(clientSecret)) .clientSecret(PasswordHandler.encode(clientSecret))
.resourceIds(resourceIds) .postLogoutRedirectUris(postLogoutRedirectUris)
.authorizedGrantTypes(authorizedGrantTypes) .authorizationGrantTypes(authorizationGrantTypes)
.scope(scope); .scopes(scopes);
if (StringUtils.isNotEmpty(webServerRedirectUri)) { if (StringUtils.isNotBlank(clientIdIssuedAt)) {
clientDetails.webServerRedirectUri(webServerRedirectUri); clientDetails.clientIdIssuedAt(Instant.parse(this.clientIdIssuedAt));
} }
if (StringUtils.isNotEmpty(authorities)) { if (StringUtils.isNotBlank(clientSecretExpiresAt)) {
clientDetails.authorities(authorities); clientDetails.clientSecretExpiresAt(Instant.parse(this.clientSecretExpiresAt));
} }
clientDetails.accessTokenValidity(accessTokenValidity) if (StringUtils.isNotEmpty(redirectUris)) {
.refreshTokenValidity(refreshTokenValidity) clientDetails.redirectUris(redirectUris);
.trusted(trusted);
if (StringUtils.isNotEmpty(additionalInformation)) {
clientDetails.additionalInformation(additionalInformation);
} }
clientDetails.clientSettings(this.clientSettings.toSettings().toString());
clientDetails.tokenSettings(this.tokenSettings.toSettings().toString());
return clientDetails; return clientDetails;
} }
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getClientIdIssuedAt() {
return clientIdIssuedAt;
}
public void setClientIdIssuedAt(String clientIdIssuedAt) {
this.clientIdIssuedAt = clientIdIssuedAt;
}
public String getClientSecretExpiresAt() {
return clientSecretExpiresAt;
}
public void setClientSecretExpiresAt(String clientSecretExpiresAt) {
this.clientSecretExpiresAt = clientSecretExpiresAt;
}
public String getClientAuthenticationMethods() {
return clientAuthenticationMethods;
}
public void setClientAuthenticationMethods(String clientAuthenticationMethods) {
this.clientAuthenticationMethods = clientAuthenticationMethods;
}
public String getScopes() {
return scopes;
}
public void setScopes(String scopes) {
this.scopes = scopes;
}
public String getAuthorizationGrantTypes() {
return authorizationGrantTypes;
}
public void setAuthorizationGrantTypes(String authorizationGrantTypes) {
this.authorizationGrantTypes = authorizationGrantTypes;
}
public String getRedirectUris() {
return redirectUris;
}
public void setRedirectUris(String redirectUris) {
this.redirectUris = redirectUris;
}
public String getPostLogoutRedirectUris() {
return postLogoutRedirectUris;
}
public void setPostLogoutRedirectUris(String postLogoutRedirectUris) {
this.postLogoutRedirectUris = postLogoutRedirectUris;
}
public ClientSettingsDto getClientSettings() {
return clientSettings;
}
public void setClientSettings(ClientSettingsDto clientSettings) {
this.clientSettings = clientSettings;
}
public TokenSettingsDto getTokenSettings() {
return tokenSettings;
}
public void setTokenSettings(TokenSettingsDto tokenSettings) {
this.tokenSettings = tokenSettings;
}
} }

View File

@ -0,0 +1,175 @@
package com.monkeyk.sos.service.dto;
import com.monkeyk.sos.infrastructure.SettingsUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import java.io.Serial;
import java.io.Serializable;
import java.time.Duration;
/**
* 2023/10/13 12:07
* <p>
* <p>
* .authorizationCodeTimeToLive(Duration.ofMinutes(5))
* .accessTokenTimeToLive(Duration.ofMinutes(5))
* .accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED)
* .deviceCodeTimeToLive(Duration.ofMinutes(5))
* .reuseRefreshTokens(true)
* .refreshTokenTimeToLive(Duration.ofMinutes(60))
* .idTokenSignatureAlgorithm(SignatureAlgorithm.RS256);
*
* @author Shengzhao Li
* @see org.springframework.security.oauth2.server.authorization.settings.TokenSettings
* @since 3.0.0
*/
public class TokenSettingsDto implements Serializable {
@Serial
private static final long serialVersionUID = -8918978047051059724L;
/**
* authorizationCode
* 300 5)
*/
private long authorizationCodeTimeToLive = 300L;
/**
* access_token
* 3600 1)
*/
private long accessTokenTimeToLive = 3600L;
/**
* token ,
* self-contained -> jwt
* reference -> uuid
*
* @see OAuth2TokenFormat
*/
private String accessTokenFormat = "self-contained";
/**
* device_code
* 300 5
*/
private long deviceCodeTimeToLive = 300L;
/**
* refresh_token
* true
*/
private boolean reuseRefreshTokens = true;
/**
* refresh_token
* 4320012
*/
private long refreshTokenTimeToLive = 43200L;
/**
* id_token使
* jwks
*
* @see SignatureAlgorithm
*/
private String idTokenSignatureAlgorithm;
public TokenSettingsDto() {
}
public TokenSettingsDto(String tokenSettings) {
TokenSettings settings = SettingsUtils.buildTokenSettings(tokenSettings);
this.accessTokenFormat = settings.getAccessTokenFormat().getValue();
this.idTokenSignatureAlgorithm = settings.getIdTokenSignatureAlgorithm().getName();
this.refreshTokenTimeToLive = settings.getRefreshTokenTimeToLive().toSeconds();
this.accessTokenFormat= settings.getAccessTokenFormat().getValue();
this.accessTokenTimeToLive=settings.getAccessTokenTimeToLive().toSeconds();
this.deviceCodeTimeToLive= settings.getDeviceCodeTimeToLive().toSeconds();
this.authorizationCodeTimeToLive= settings.getAuthorizationCodeTimeToLive().toSeconds();
}
public TokenSettings toSettings() {
TokenSettings.Builder builder = TokenSettings.builder()
.refreshTokenTimeToLive(Duration.ofSeconds(this.refreshTokenTimeToLive))
.accessTokenTimeToLive(Duration.ofSeconds(this.accessTokenTimeToLive))
.reuseRefreshTokens(this.reuseRefreshTokens)
.deviceCodeTimeToLive(Duration.ofSeconds(this.deviceCodeTimeToLive))
.authorizationCodeTimeToLive(Duration.ofSeconds(this.authorizationCodeTimeToLive));
if (StringUtils.isNotBlank(idTokenSignatureAlgorithm)) {
builder.idTokenSignatureAlgorithm(SignatureAlgorithm.valueOf(idTokenSignatureAlgorithm));
}
if (StringUtils.isNotBlank(accessTokenFormat)) {
builder.accessTokenFormat(new OAuth2TokenFormat(accessTokenFormat));
}
return builder.build();
}
public long getAuthorizationCodeTimeToLive() {
return authorizationCodeTimeToLive;
}
public void setAuthorizationCodeTimeToLive(long authorizationCodeTimeToLive) {
this.authorizationCodeTimeToLive = authorizationCodeTimeToLive;
}
public long getAccessTokenTimeToLive() {
return accessTokenTimeToLive;
}
public void setAccessTokenTimeToLive(long accessTokenTimeToLive) {
this.accessTokenTimeToLive = accessTokenTimeToLive;
}
public String getAccessTokenFormat() {
return accessTokenFormat;
}
public void setAccessTokenFormat(String accessTokenFormat) {
this.accessTokenFormat = accessTokenFormat;
}
public long getDeviceCodeTimeToLive() {
return deviceCodeTimeToLive;
}
public void setDeviceCodeTimeToLive(long deviceCodeTimeToLive) {
this.deviceCodeTimeToLive = deviceCodeTimeToLive;
}
public boolean isReuseRefreshTokens() {
return reuseRefreshTokens;
}
public void setReuseRefreshTokens(boolean reuseRefreshTokens) {
this.reuseRefreshTokens = reuseRefreshTokens;
}
public long getRefreshTokenTimeToLive() {
return refreshTokenTimeToLive;
}
public void setRefreshTokenTimeToLive(long refreshTokenTimeToLive) {
this.refreshTokenTimeToLive = refreshTokenTimeToLive;
}
public String getIdTokenSignatureAlgorithm() {
return idTokenSignatureAlgorithm;
}
public void setIdTokenSignatureAlgorithm(String idTokenSignatureAlgorithm) {
this.idTokenSignatureAlgorithm = idTokenSignatureAlgorithm;
}
}

View File

@ -35,14 +35,14 @@ public class OauthClientDetailsDtoValidator implements Validator {
} }
private void validateGrantTypes(OauthClientDetailsDto clientDetailsDto, Errors errors) { private void validateGrantTypes(OauthClientDetailsDto clientDetailsDto, Errors errors) {
final String grantTypes = clientDetailsDto.getAuthorizedGrantTypes(); final String grantTypes = clientDetailsDto.getAuthorizationGrantTypes();
if (StringUtils.isEmpty(grantTypes)) { if (StringUtils.isEmpty(grantTypes)) {
errors.rejectValue("authorizedGrantTypes", null, "grant_type(s) is required"); errors.rejectValue("authorizationGrantTypes", null, "grant_type(s) is required");
return; return;
} }
if ("refresh_token".equalsIgnoreCase(grantTypes)) { if ("refresh_token".equalsIgnoreCase(grantTypes)) {
errors.rejectValue("authorizedGrantTypes", null, "grant_type(s) 不能只是[refresh_token]"); errors.rejectValue("authorizationGrantTypes", null, "grant_type(s) 不能只是[refresh_token]");
} }
} }

View File

@ -0,0 +1,49 @@
package com.monkeyk.sos.infrastructure;
import org.junit.jupiter.api.Test;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import static org.junit.jupiter.api.Assertions.*;
/**
* 2023/10/13 14:59
*
* @author Shengzhao Li
* @since 3.0.0
*/
class SettingsUtilsTest {
@Test
void textTokenSettings() {
TokenSettings settings = TokenSettings.builder()
.reuseRefreshTokens(false)
.build();
String s = SettingsUtils.textTokenSettings(settings);
assertNotNull(s);
// System.out.println(s);
TokenSettings tokenSettings = SettingsUtils.buildTokenSettings(s);
assertNotNull(tokenSettings);
}
@Test
void textClientSettings() {
ClientSettings settings = ClientSettings.builder()
.requireProofKey(true)
.build();
String s = SettingsUtils.textClientSettings(settings);
assertNotNull(s);
// System.out.println(s);
ClientSettings clientSettings = SettingsUtils.buildClientSettings(s);
assertNotNull(clientSettings);
}
}

View File

@ -53,10 +53,10 @@ public abstract class AbstractInlineAccessTokenInvokerTest extends AbstractRepos
OauthClientDetails clientDetails = new OauthClientDetails(); OauthClientDetails clientDetails = new OauthClientDetails();
clientDetails.clientId(clientId) clientDetails.clientId(clientId)
.clientSecret(PasswordHandler.encode(clientSecret)) .clientSecret(PasswordHandler.encode(clientSecret))
.authorizedGrantTypes(grantTypes()) .authorizationGrantTypes(grantTypes())
.scope("read") .scopes("openid");
.accessTokenValidity(200) // .accessTokenValidity(200)
.resourceIds(RESOURCE_ID); // .resourceIds(RESOURCE_ID);
oauthRepository.saveOauthClientDetails(clientDetails); oauthRepository.saveOauthClientDetails(clientDetails);

View File

@ -0,0 +1,29 @@
package com.monkeyk.sos.service.dto;
import org.junit.jupiter.api.Test;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import static org.junit.jupiter.api.Assertions.*;
/**
* 2023/10/13 14:24
*
* @author Shengzhao Li
*/
class TokenSettingsDtoTest {
@Test
void toSettings() {
TokenSettingsDto settingsDto = new TokenSettingsDto();
TokenSettings tokenSettings = settingsDto.toSettings();
assertNotNull(tokenSettings);
// System.out.println(tokenSettings);
}
}