Added logic to send 'access token' to custom mapper

This commit is contained in:
vzikratyi 2020-08-13 14:14:38 +03:00
parent da9f29c933
commit f89ce19b1f
11 changed files with 33 additions and 16 deletions

View File

@ -47,7 +47,8 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration (
basic_always_full_screen boolean, basic_always_full_screen boolean,
custom_url varchar(255), custom_url varchar(255),
custom_username varchar(255), custom_username varchar(255),
custom_password varchar(255) custom_password varchar(255),
custom_send_token boolean
); );
DROP TABLE IF EXISTS oauth2_client_registration_template; DROP TABLE IF EXISTS oauth2_client_registration_template;

View File

@ -35,7 +35,7 @@ public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implemen
private static final String END_PLACEHOLDER_PREFIX = "}"; private static final String END_PLACEHOLDER_PREFIX = "}";
@Override @Override
public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, TenantId parentTenantId, OAuth2MapperConfig config) { public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, TenantId parentTenantId, OAuth2MapperConfig config) {
OAuth2User oauth2User = new OAuth2User(); OAuth2User oauth2User = new OAuth2User();
Map<String, Object> attributes = token.getPrincipal().getAttributes(); Map<String, Object> attributes = token.getPrincipal().getAttributes();
String email = getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey()); String email = getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey());

View File

@ -32,21 +32,26 @@ import org.thingsboard.server.service.security.model.SecurityUser;
@Service(value = "customOAuth2ClientMapper") @Service(value = "customOAuth2ClientMapper")
@Slf4j @Slf4j
public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper { public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper {
private static final String PROVIDER_ACCESS_TOKEN = "provider-access-token";
private static final ObjectMapper json = new ObjectMapper(); private static final ObjectMapper json = new ObjectMapper();
private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(); private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
@Override @Override
public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, TenantId parentTenantId, OAuth2MapperConfig config) { public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, TenantId parentTenantId, OAuth2MapperConfig config) {
OAuth2User oauth2User = getOAuth2User(token, config.getCustom()); OAuth2User oauth2User = getOAuth2User(token, providerAccessToken, config.getCustom());
return getOrCreateSecurityUserFromOAuth2User(parentTenantId, oauth2User, config.isAllowUserCreation(), config.isActivateUser()); return getOrCreateSecurityUserFromOAuth2User(parentTenantId, oauth2User, config.isAllowUserCreation(), config.isActivateUser());
} }
private synchronized OAuth2User getOAuth2User(OAuth2AuthenticationToken token, OAuth2CustomMapperConfig custom) { private synchronized OAuth2User getOAuth2User(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2CustomMapperConfig custom) {
if (!StringUtils.isEmpty(custom.getUsername()) && !StringUtils.isEmpty(custom.getPassword())) { if (!StringUtils.isEmpty(custom.getUsername()) && !StringUtils.isEmpty(custom.getPassword())) {
restTemplateBuilder = restTemplateBuilder.basicAuthentication(custom.getUsername(), custom.getPassword()); restTemplateBuilder = restTemplateBuilder.basicAuthentication(custom.getUsername(), custom.getPassword());
} }
if (custom.isSendToken() && !StringUtils.isEmpty(providerAccessToken)) {
restTemplateBuilder = restTemplateBuilder.defaultHeader(PROVIDER_ACCESS_TOKEN, providerAccessToken);
}
RestTemplate restTemplate = restTemplateBuilder.build(); RestTemplate restTemplate = restTemplateBuilder.build();
String request; String request;
try { try {

View File

@ -21,5 +21,5 @@ import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.SecurityUser;
public interface OAuth2ClientMapper { public interface OAuth2ClientMapper {
SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, TenantId parentTenantId, OAuth2MapperConfig config); SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, TenantId parentTenantId, OAuth2MapperConfig config);
} }

View File

@ -15,14 +15,13 @@
*/ */
package org.thingsboard.server.service.security.auth.oauth2; package org.thingsboard.server.service.security.auth.oauth2;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration; import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration;
import org.thingsboard.server.dao.oauth2.OAuth2Service; import org.thingsboard.server.dao.oauth2.OAuth2Service;
import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;
@ -45,16 +44,19 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
private final RefreshTokenRepository refreshTokenRepository; private final RefreshTokenRepository refreshTokenRepository;
private final OAuth2ClientMapperProvider oauth2ClientMapperProvider; private final OAuth2ClientMapperProvider oauth2ClientMapperProvider;
private final OAuth2Service oAuth2Service; private final OAuth2Service oAuth2Service;
private final OAuth2AuthorizedClientService oAuth2AuthorizedClientService;
@Autowired @Autowired
public Oauth2AuthenticationSuccessHandler(final JwtTokenFactory tokenFactory, public Oauth2AuthenticationSuccessHandler(final JwtTokenFactory tokenFactory,
final RefreshTokenRepository refreshTokenRepository, final RefreshTokenRepository refreshTokenRepository,
final OAuth2ClientMapperProvider oauth2ClientMapperProvider, final OAuth2ClientMapperProvider oauth2ClientMapperProvider,
final OAuth2Service oAuth2Service) { final OAuth2Service oAuth2Service,
final OAuth2AuthorizedClientService oAuth2AuthorizedClientService) {
this.tokenFactory = tokenFactory; this.tokenFactory = tokenFactory;
this.refreshTokenRepository = refreshTokenRepository; this.refreshTokenRepository = refreshTokenRepository;
this.oauth2ClientMapperProvider = oauth2ClientMapperProvider; this.oauth2ClientMapperProvider = oauth2ClientMapperProvider;
this.oAuth2Service = oAuth2Service; this.oAuth2Service = oAuth2Service;
this.oAuth2AuthorizedClientService = oAuth2AuthorizedClientService;
} }
@Override @Override
@ -67,8 +69,12 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication; OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
OAuth2ClientRegistration clientRegistration = oAuth2Service.findClientRegistration(UUID.fromString(token.getAuthorizedClientRegistrationId())); OAuth2ClientRegistration clientRegistration = oAuth2Service.findClientRegistration(UUID.fromString(token.getAuthorizedClientRegistrationId()));
OAuth2AuthorizedClient oAuth2AuthorizedClient = oAuth2AuthorizedClientService.loadAuthorizedClient(
token.getAuthorizedClientRegistrationId(),
token.getPrincipal().getName());
OAuth2ClientMapper mapper = oauth2ClientMapperProvider.getOAuth2ClientMapperByType(clientRegistration.getMapperConfig().getType()); OAuth2ClientMapper mapper = oauth2ClientMapperProvider.getOAuth2ClientMapperByType(clientRegistration.getMapperConfig().getType());
SecurityUser securityUser = mapper.getOrCreateUserByClientPrincipal(token, clientRegistration.getTenantId(), clientRegistration.getMapperConfig()); SecurityUser securityUser = mapper.getOrCreateUserByClientPrincipal(token, oAuth2AuthorizedClient.getAccessToken().getTokenValue(),
clientRegistration.getTenantId(), clientRegistration.getMapperConfig());
JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser); JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser);
JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser); JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser);

View File

@ -25,4 +25,5 @@ public class OAuth2CustomMapperConfig {
private final String url; private final String url;
private final String username; private final String username;
private final String password; private final String password;
private final boolean sendToken;
} }

View File

@ -388,6 +388,7 @@ public class ModelConstants {
public static final String OAUTH2_MAPPER_URL_PROPERTY = "custom_url"; public static final String OAUTH2_MAPPER_URL_PROPERTY = "custom_url";
public static final String OAUTH2_MAPPER_USERNAME_PROPERTY = "custom_username"; public static final String OAUTH2_MAPPER_USERNAME_PROPERTY = "custom_username";
public static final String OAUTH2_MAPPER_PASSWORD_PROPERTY = "custom_password"; public static final String OAUTH2_MAPPER_PASSWORD_PROPERTY = "custom_password";
public static final String OAUTH2_MAPPER_SEND_TOKEN_PROPERTY = "custom_send_token";
public static final String OAUTH2_TEMPLATE_COMMENT_PROPERTY = "comment"; public static final String OAUTH2_TEMPLATE_COMMENT_PROPERTY = "comment";
/** /**

View File

@ -95,6 +95,8 @@ public class OAuth2ClientRegistrationEntity extends BaseSqlEntity<OAuth2ClientRe
private String username; private String username;
@Column(name = ModelConstants.OAUTH2_MAPPER_PASSWORD_PROPERTY) @Column(name = ModelConstants.OAUTH2_MAPPER_PASSWORD_PROPERTY)
private String password; private String password;
@Column(name = ModelConstants.OAUTH2_MAPPER_SEND_TOKEN_PROPERTY)
private Boolean sendToken;
public OAuth2ClientRegistrationEntity() { public OAuth2ClientRegistrationEntity() {
super(); super();
@ -142,6 +144,7 @@ public class OAuth2ClientRegistrationEntity extends BaseSqlEntity<OAuth2ClientRe
this.url = customConfig.getUrl(); this.url = customConfig.getUrl();
this.username = customConfig.getUsername(); this.username = customConfig.getUsername();
this.password = customConfig.getPassword(); this.password = customConfig.getPassword();
this.sendToken = customConfig.isSendToken();
} }
} }
} }
@ -178,6 +181,7 @@ public class OAuth2ClientRegistrationEntity extends BaseSqlEntity<OAuth2ClientRe
.url(url) .url(url)
.username(username) .username(username)
.password(password) .password(password)
.sendToken(sendToken)
.build() .build()
: null : null
) )

View File

@ -159,9 +159,6 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
if (StringUtils.isEmpty(clientRegistration.getUserNameAttributeName())) { if (StringUtils.isEmpty(clientRegistration.getUserNameAttributeName())) {
throw new DataValidationException("User name attribute name should be specified!"); throw new DataValidationException("User name attribute name should be specified!");
} }
if (StringUtils.isEmpty(clientRegistration.getJwkSetUri())) {
throw new DataValidationException("Jwk set uri should be specified!");
}
if (StringUtils.isEmpty(clientRegistration.getClientAuthenticationMethod())) { if (StringUtils.isEmpty(clientRegistration.getClientAuthenticationMethod())) {
throw new DataValidationException("Client authentication method should be specified!"); throw new DataValidationException("Client authentication method should be specified!");
} }

View File

@ -322,7 +322,8 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration (
basic_always_full_screen boolean, basic_always_full_screen boolean,
custom_url varchar(255), custom_url varchar(255),
custom_username varchar(255), custom_username varchar(255),
custom_password varchar(255) custom_password varchar(255),
custom_send_token boolean
); );
CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (

View File

@ -337,7 +337,8 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration (
basic_always_full_screen boolean, basic_always_full_screen boolean,
custom_url varchar(255), custom_url varchar(255),
custom_username varchar(255), custom_username varchar(255),
custom_password varchar(255) custom_password varchar(255),
custom_send_token boolean
); );
CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (