Merge pull request #12119 from dashevchenko/mobileOauth2Fix
Fixed oauth2 authorization for apps of version 1.3.0 and less
This commit is contained in:
		
						commit
						9ec95d481b
					
				@ -38,6 +38,7 @@ import org.springframework.web.util.UriComponents;
 | 
			
		||||
import org.springframework.web.util.UriComponentsBuilder;
 | 
			
		||||
import org.thingsboard.server.common.data.StringUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.id.OAuth2ClientId;
 | 
			
		||||
import org.thingsboard.server.common.data.oauth2.PlatformType;
 | 
			
		||||
import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
 | 
			
		||||
import org.thingsboard.server.dao.oauth2.OAuth2ClientService;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
@ -85,8 +86,9 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
 | 
			
		||||
        String registrationId = this.resolveRegistrationId(request);
 | 
			
		||||
        String redirectUriAction = getAction(request, "login");
 | 
			
		||||
        String appPackage = getAppPackage(request);
 | 
			
		||||
        String platform = getPlatform(request);
 | 
			
		||||
        String appToken = getAppToken(request);
 | 
			
		||||
        return resolve(request, registrationId, redirectUriAction, appPackage, appToken);
 | 
			
		||||
        return resolve(request, registrationId, redirectUriAction, appPackage, platform, appToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@ -96,8 +98,9 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
 | 
			
		||||
        }
 | 
			
		||||
        String redirectUriAction = getAction(request, "authorize");
 | 
			
		||||
        String appPackage = getAppPackage(request);
 | 
			
		||||
        String platform = getPlatform(request);
 | 
			
		||||
        String appToken = getAppToken(request);
 | 
			
		||||
        return resolve(request, registrationId, redirectUriAction, appPackage, appToken);
 | 
			
		||||
        return resolve(request, registrationId, redirectUriAction, appPackage, platform, appToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getAction(HttpServletRequest request, String defaultAction) {
 | 
			
		||||
@ -112,11 +115,15 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
 | 
			
		||||
        return request.getParameter("pkg");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getPlatform(HttpServletRequest request) {
 | 
			
		||||
        return request.getParameter("platform");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getAppToken(HttpServletRequest request) {
 | 
			
		||||
        return request.getParameter("appToken");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String oauth2ClientId, String redirectUriAction, String appPackage, String appToken) {
 | 
			
		||||
    private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String oauth2ClientId, String redirectUriAction, String appPackage, String platform, String appToken) {
 | 
			
		||||
        if (oauth2ClientId == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
@ -132,11 +139,19 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
 | 
			
		||||
            if (StringUtils.isEmpty(appToken)) {
 | 
			
		||||
                throw new IllegalArgumentException("Invalid application token.");
 | 
			
		||||
            } else {
 | 
			
		||||
                String appSecret = this.oAuth2ClientService.findAppSecret(new OAuth2ClientId(UUID.fromString(oauth2ClientId)), appPackage);
 | 
			
		||||
                if (StringUtils.isEmpty(appSecret)) {
 | 
			
		||||
                    throw new IllegalArgumentException("Invalid package: " + appPackage + ". No application secret found for Client Registration with given application package.");
 | 
			
		||||
                String callbackUrlScheme;
 | 
			
		||||
                if (platform != null) {
 | 
			
		||||
                    callbackUrlScheme = validateMobileAppToken(oauth2ClientId, appPackage, PlatformType.valueOf(platform), appToken);
 | 
			
		||||
                } else {
 | 
			
		||||
                    // for backward compatibility with mobile apps of version 1.3.0 and less try to validate token with android and then ios app secret
 | 
			
		||||
                    try {
 | 
			
		||||
                        callbackUrlScheme = validateMobileAppToken(oauth2ClientId, appPackage, PlatformType.ANDROID, appToken);
 | 
			
		||||
                    } catch (IllegalArgumentException e) {
 | 
			
		||||
                        log.debug("Failed attempt to validate android application token, oauth client id: [{}], package name: [{}], appToken [{}] ",
 | 
			
		||||
                                oauth2ClientId, appPackage, appToken, e);
 | 
			
		||||
                        callbackUrlScheme = validateMobileAppToken(oauth2ClientId, appPackage, PlatformType.IOS, appToken);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                String callbackUrlScheme = this.oAuth2AppTokenFactory.validateTokenAndGetCallbackUrlScheme(appPackage, appToken, appSecret);
 | 
			
		||||
                attributes.put(TbOAuth2ParameterNames.CALLBACK_URL_SCHEME, callbackUrlScheme);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -174,6 +189,14 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
 | 
			
		||||
                .build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String validateMobileAppToken(String oauth2ClientId, String appPackage, PlatformType platformType, String appToken) {
 | 
			
		||||
        String appSecret = this.oAuth2ClientService.findAppSecret(new OAuth2ClientId(UUID.fromString(oauth2ClientId)), appPackage, platformType);
 | 
			
		||||
        if (StringUtils.isEmpty(appSecret)) {
 | 
			
		||||
            throw new IllegalArgumentException("Invalid package: " + appPackage + ". No application secret found for Client Registration with given application package.");
 | 
			
		||||
        }
 | 
			
		||||
        return this.oAuth2AppTokenFactory.validateTokenAndGetCallbackUrlScheme(appPackage, appToken, appSecret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String resolveRegistrationId(HttpServletRequest request) {
 | 
			
		||||
        if (this.authorizationRequestMatcher.matches(request)) {
 | 
			
		||||
            return this.authorizationRequestMatcher
 | 
			
		||||
 | 
			
		||||
@ -40,7 +40,7 @@ public interface OAuth2ClientService extends EntityDaoService {
 | 
			
		||||
 | 
			
		||||
    OAuth2Client findOAuth2ClientById(TenantId tenantId, OAuth2ClientId providerId);
 | 
			
		||||
 | 
			
		||||
    String findAppSecret(OAuth2ClientId oAuth2ClientId, String pkgName);
 | 
			
		||||
    String findAppSecret(OAuth2ClientId oAuth2ClientId, String pkgName, PlatformType platformType);
 | 
			
		||||
 | 
			
		||||
    void deleteOAuth2ClientById(TenantId tenantId, OAuth2ClientId oAuth2ClientId);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ public interface OAuth2ClientDao extends Dao<OAuth2Client> {
 | 
			
		||||
 | 
			
		||||
    List<OAuth2Client> findByMobileAppBundleId(UUID mobileAppBundleId);
 | 
			
		||||
 | 
			
		||||
    String findAppSecret(UUID id, String pkgName);
 | 
			
		||||
    String findAppSecret(UUID id, String pkgName, PlatformType platformType);
 | 
			
		||||
 | 
			
		||||
    void deleteByTenantId(UUID tenantId);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,7 @@ import org.thingsboard.server.dao.entity.AbstractEntityService;
 | 
			
		||||
import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
 | 
			
		||||
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
 | 
			
		||||
import org.thingsboard.server.dao.service.DataValidator;
 | 
			
		||||
import org.thingsboard.server.dao.service.Validator;
 | 
			
		||||
 | 
			
		||||
import java.util.Comparator;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@ -45,6 +46,8 @@ import java.util.stream.Collectors;
 | 
			
		||||
@Service("OAuth2ClientService")
 | 
			
		||||
public class OAuth2ClientServiceImpl extends AbstractEntityService implements OAuth2ClientService {
 | 
			
		||||
 | 
			
		||||
    private static final String PLATFORM_TYPE_IS_REQUIRED = "Platform type is required if package name is specified";
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private OAuth2ClientDao oauth2ClientDao;
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -90,9 +93,10 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String findAppSecret(OAuth2ClientId oAuth2ClientId, String pkgName) {
 | 
			
		||||
        log.trace("Executing findAppSecret oAuth2ClientId = [{}] pkgName = [{}]", oAuth2ClientId, pkgName);
 | 
			
		||||
        return oauth2ClientDao.findAppSecret(oAuth2ClientId.getId(), pkgName);
 | 
			
		||||
    public String findAppSecret(OAuth2ClientId oAuth2ClientId, String pkgName, PlatformType platformType) {
 | 
			
		||||
        log.trace("Executing findAppSecret oAuth2ClientId = [{}] pkgName = [{}], platform [{}]", oAuth2ClientId, pkgName, platformType);
 | 
			
		||||
        Validator.checkNotNull(platformType, PLATFORM_TYPE_IS_REQUIRED);
 | 
			
		||||
        return oauth2ClientDao.findAppSecret(oAuth2ClientId.getId(), pkgName, platformType);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 | 
			
		||||
@ -80,8 +80,8 @@ public class JpaOAuth2ClientDao extends JpaAbstractDao<OAuth2ClientEntity, OAuth
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String findAppSecret(UUID id, String pkgName) {
 | 
			
		||||
        return repository.findAppSecret(id, pkgName);
 | 
			
		||||
    public String findAppSecret(UUID id, String pkgName, PlatformType platformType) {
 | 
			
		||||
        return repository.findAppSecret(id, pkgName, platformType.name());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 | 
			
		||||
@ -72,9 +72,10 @@ public interface OAuth2ClientRepository extends JpaRepository<OAuth2ClientEntity
 | 
			
		||||
            "LEFT JOIN MobileAppBundleOauth2ClientEntity bc ON bc.mobileAppBundleId = b.id " +
 | 
			
		||||
            "LEFT JOIN OAuth2ClientEntity c ON bc.oauth2ClientId = c.id " +
 | 
			
		||||
            "WHERE c.id = :clientId " +
 | 
			
		||||
            "AND a.pkgName = :pkgName")
 | 
			
		||||
            "AND a.pkgName = :pkgName and a.platformType = :platformType")
 | 
			
		||||
    String findAppSecret(@Param("clientId") UUID id,
 | 
			
		||||
                         @Param("pkgName") String pkgName);
 | 
			
		||||
                         @Param("pkgName") String pkgName,
 | 
			
		||||
                         @Param("platformType") String platformType);
 | 
			
		||||
 | 
			
		||||
    @Transactional
 | 
			
		||||
    @Modifying
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user