diff --git a/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java b/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java index 542a7c71cb..f8935f00d6 100644 --- a/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java +++ b/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java @@ -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,18 @@ 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.warn("Failed attempt to validate android application token", 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 +188,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 diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientService.java index 317221fe0a..f293462cc6 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientService.java @@ -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); diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java index 01d56feb20..16dda80840 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java @@ -38,7 +38,7 @@ public interface OAuth2ClientDao extends Dao { List findByMobileAppBundleId(UUID mobileAppBundleId); - String findAppSecret(UUID id, String pkgName); + String findAppSecret(UUID id, String pkgName, PlatformType platformType); void deleteByTenantId(UUID tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java index 880329335c..683c323ab5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java @@ -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 diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java index d694ca0f93..0db0faed69 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java @@ -80,8 +80,8 @@ public class JpaOAuth2ClientDao extends JpaAbstractDao