From c8d627371b0725a95d7a3acdc882c4701e28593f Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Mon, 25 Nov 2024 18:48:01 +0200 Subject: [PATCH 1/2] fixed oauth2 authorization for apps of version 1.3.0 and less --- ...tomOAuth2AuthorizationRequestResolver.java | 36 +++++++++++++++---- .../dao/oauth2/OAuth2ClientService.java | 2 +- .../server/dao/oauth2/OAuth2ClientDao.java | 2 +- .../dao/oauth2/OAuth2ClientServiceImpl.java | 10 ++++-- .../dao/sql/oauth2/JpaOAuth2ClientDao.java | 4 +-- .../sql/oauth2/OAuth2ClientRepository.java | 5 +-- 6 files changed, 43 insertions(+), 16 deletions(-) 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 Date: Wed, 27 Nov 2024 11:26:56 +0200 Subject: [PATCH 2/2] updated log level and message, deleted redundant null-check --- .../config/CustomOAuth2AuthorizationRequestResolver.java | 3 ++- .../thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) 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 f8935f00d6..c0dfaa599a 100644 --- a/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java +++ b/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java @@ -147,7 +147,8 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza try { callbackUrlScheme = validateMobileAppToken(oauth2ClientId, appPackage, PlatformType.ANDROID, appToken); } catch (IllegalArgumentException e) { - log.warn("Failed attempt to validate android application token", 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); } } 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 0db0faed69..6febd651bb 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 @@ -81,7 +81,7 @@ public class JpaOAuth2ClientDao extends JpaAbstractDao