From 5713fcf9eafac32336bf7683103940e7f09bc4b5 Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Thu, 23 Mar 2023 10:29:37 +0100 Subject: [PATCH 01/16] Bump dev version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index f464290..9e19300 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ plugins { allprojects { group = "org.radarbase" - version = "1.2.0" + version = "1.2.1-SNAPSHOT" } subprojects { From 500aca92f23a9fbfddf69955479693016346c34a Mon Sep 17 00:00:00 2001 From: Pauline Date: Thu, 2 Nov 2023 16:35:20 +0000 Subject: [PATCH 02/16] Add fixes to support radar-auth 2.1.0 --- radar-spring-auth/build.gradle.kts | 2 +- .../radar/spring/auth/common/Authorization.kt | 10 +- .../ManagementPortalAuthValidator.kt | 15 ++- .../ManagementPortalAuthorization.kt | 91 +++++++++++++------ 4 files changed, 76 insertions(+), 42 deletions(-) diff --git a/radar-spring-auth/build.gradle.kts b/radar-spring-auth/build.gradle.kts index 19078fa..664b89c 100644 --- a/radar-spring-auth/build.gradle.kts +++ b/radar-spring-auth/build.gradle.kts @@ -7,7 +7,7 @@ description = "This library provides functionality to add RADAR-base authorizati dependencies { val mpVersion: String by project - api(group = "org.radarbase", name = "radar-auth", version = mpVersion) + api(group = "org.radarbase", name = "radar-auth", version = "2.1.0") val slf4jVersion: String by project api(group = "org.slf4j", name = "slf4j-api", version = slf4jVersion) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt index a4b8df5..31c17c5 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt @@ -1,5 +1,7 @@ package radar.spring.auth.common +import kotlinx.coroutines.runBlocking + /** Abstract Authorization interface to be used with a custom token [T]. * See [radar.spring.auth.managementportal.ManagementPortalAuthorization] * **/ @@ -19,15 +21,16 @@ interface Authorization { user: String? = null, source: String? = null ): Boolean { - return hasPermission(token, permission, entity, permissionOn, project, user, source) && + return runBlocking { + hasPermission(token, permission, entity, permissionOn, project, user, source) && hasRole(token, project, role) && hasScopes(token, scopes) && - hasAuthorities(token, authorities) && hasAudiences(token, audiences) && hasGrantTypes(token, grantTypes) + } } - fun hasPermission( + suspend fun hasPermission( token: T, permission: String, entity: String, @@ -39,7 +42,6 @@ interface Authorization { fun hasRole(token: T, project: String?, role: String?): Boolean fun hasScopes(token: T, scopes: Array): Boolean - fun hasAuthorities(token: T, authorities: Array): Boolean fun hasAudiences(token: T, audiences: Array): Boolean fun hasGrantTypes(token: T, grantTypes: Array): Boolean } diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt index 700848b..576a5d3 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt @@ -2,9 +2,9 @@ package radar.spring.auth.managementportal import jakarta.servlet.http.HttpServletRequest import org.radarbase.auth.authentication.TokenValidator -import org.radarbase.auth.config.TokenValidatorConfig -import org.radarbase.auth.config.TokenVerifierPublicKeyConfig +import org.radarbase.auth.authentication.TokenVerifierLoader import org.radarbase.auth.exception.TokenValidationException +import org.radarbase.auth.jwks.JwksTokenVerifierLoader import org.radarbase.auth.token.RadarToken import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired @@ -12,16 +12,15 @@ import org.springframework.stereotype.Component import radar.spring.auth.common.RadarAuthValidator import radar.spring.auth.config.ManagementPortalAuthProperties import java.net.URI +import org.radarbase.auth.jwks.JwkAlgorithmParser /** The [radar.spring.auth.common.AuthValidator] for Management Portal tokens. **/ @Component class ManagementPortalAuthValidator @JvmOverloads constructor( @Autowired private val managementPortalProperties: ManagementPortalAuthProperties, - private val tokenValidatorConfig: TokenValidatorConfig = TokenVerifierPublicKeyConfig().apply { - publicKeyEndpoints = listOf(URI(managementPortalProperties.publicKeyUrl)) - resourceName = managementPortalProperties.resourceName - }, - private val tokenValidator: TokenValidator = TokenValidator(tokenValidatorConfig) + private val tokenVerifiers: List = listOf(URI(managementPortalProperties.publicKeyUrl)) + .map { JwksTokenVerifierLoader(it.toString(), managementPortalProperties.resourceName, JwkAlgorithmParser()) }, + private val tokenValidator: TokenValidator = TokenValidator(tokenVerifiers) ) : RadarAuthValidator { @@ -39,7 +38,7 @@ class ManagementPortalAuthValidator @JvmOverloads constructor( @Throws(TokenValidationException::class) override fun verify(token: String, request: HttpServletRequest): RadarToken? { - return tokenValidator.validateAccessToken(token) + return tokenValidator.validateBlocking(token) } companion object { diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt index 014feac..9366892 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt @@ -1,14 +1,15 @@ package radar.spring.auth.managementportal +import org.radarbase.auth.authorization.AuthorizationOracle +import org.radarbase.auth.authorization.EntityDetails import org.radarbase.auth.authorization.Permission import org.radarbase.auth.token.RadarToken import org.slf4j.LoggerFactory import radar.spring.auth.common.Authorization import radar.spring.auth.common.PermissionOn -class ManagementPortalAuthorization : Authorization { - - override fun hasPermission( +class ManagementPortalAuthorization(val oracle: AuthorizationOracle) : Authorization { + override suspend fun hasPermission( token: RadarToken, permission: String, entity: String, @@ -17,25 +18,40 @@ class ManagementPortalAuthorization : Authorization { user: String?, source: String? ): Boolean { - val mpPermission = Permission.of( - Permission.Entity.valueOf(entity), - Permission.Operation.valueOf(permission) - ) + val mpPermission = + Permission.of( + Permission.Entity.valueOf(entity), + Permission.Operation.valueOf(permission) + ) return when (permissionOn) { PermissionOn.PROJECT -> checkPermissionOnProject(token, mpPermission, project) PermissionOn.SUBJECT -> checkPermissionOnSubject(token, mpPermission, project, user) - PermissionOn.SOURCE -> checkPermissionOnSource( - token, - mpPermission, - project, - user, - source - ) - else -> token.hasPermission(mpPermission) + PermissionOn.SOURCE -> + checkPermissionOnSource( + token, + mpPermission, + project, + user, + source + ) + else -> + oracle.hasPermission( + token, + mpPermission, + EntityDetails( + project, + user, + source + ) + ) } } - override fun hasRole(token: RadarToken, project: String?, role: String?): Boolean { + override fun hasRole( + token: RadarToken, + project: String?, + role: String? + ): Boolean { if (role.isNullOrBlank()) { return true } @@ -48,26 +64,31 @@ class ManagementPortalAuthorization : Authorization { .any { it.authority == role } } - override fun hasScopes(token: RadarToken, scopes: Array): Boolean { + override fun hasScopes( + token: RadarToken, + scopes: Array + ): Boolean { return token.scopes.containsAll(scopes.toList()) } - override fun hasAuthorities(token: RadarToken, authorities: Array): Boolean { - return token.authorities.containsAll(authorities.toList()) - } - - override fun hasAudiences(token: RadarToken, audiences: Array): Boolean { + override fun hasAudiences( + token: RadarToken, + audiences: Array + ): Boolean { return token.audience.containsAll(audiences.toList()) } - override fun hasGrantTypes(token: RadarToken, grantTypes: Array): Boolean { + override fun hasGrantTypes( + token: RadarToken, + grantTypes: Array + ): Boolean { if (grantTypes.isEmpty()) { return true } return grantTypes.contains(token.grantType) } - private fun checkPermissionOnProject( + private suspend fun checkPermissionOnProject( token: RadarToken, mpPermission: Permission, project: String? @@ -78,10 +99,14 @@ class ManagementPortalAuthorization : Authorization { ) return false } - return token.hasPermissionOnProject(mpPermission, project) + return oracle.hasPermission( + token, + mpPermission, + EntityDetails(project = project) + ) } - private fun checkPermissionOnSubject( + private suspend fun checkPermissionOnSubject( token: RadarToken, mpPermission: Permission, project: String?, @@ -93,10 +118,14 @@ class ManagementPortalAuthorization : Authorization { ) return false } - return token.hasPermissionOnSubject(mpPermission, project, user) + return oracle.hasPermission( + token, + mpPermission, + EntityDetails(user = user) + ) } - private fun checkPermissionOnSource( + private suspend fun checkPermissionOnSource( token: RadarToken, mpPermission: Permission, project: String?, @@ -110,7 +139,11 @@ class ManagementPortalAuthorization : Authorization { ) return false } - return token.hasPermissionOnSource(mpPermission, project, user, source) + return oracle.hasPermission( + token, + mpPermission, + EntityDetails(user = user, source = source) + ) } companion object { From be05f56f16289d1ab940b1ee91749c35bf1fa1fd Mon Sep 17 00:00:00 2001 From: Pauline Date: Thu, 2 Nov 2023 16:36:34 +0000 Subject: [PATCH 03/16] Fix versions --- build.gradle.kts | 2 +- gradle.properties | 2 +- radar-spring-auth/build.gradle.kts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index f464290..9e19300 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ plugins { allprojects { group = "org.radarbase" - version = "1.2.0" + version = "1.2.1-SNAPSHOT" } subprojects { diff --git a/gradle.properties b/gradle.properties index ee7d6c5..f0fcfdf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ nexusPluginVersion=1.3.0 jacksonVersion=2.14.2 jsoupVersion=1.15.4 -mpVersion=2.0.0 +mpVersion=2.1.0 springVersion=6.0.6 slf4jVersion=2.0.6 aspectJVersion=1.9.19 diff --git a/radar-spring-auth/build.gradle.kts b/radar-spring-auth/build.gradle.kts index 664b89c..19078fa 100644 --- a/radar-spring-auth/build.gradle.kts +++ b/radar-spring-auth/build.gradle.kts @@ -7,7 +7,7 @@ description = "This library provides functionality to add RADAR-base authorizati dependencies { val mpVersion: String by project - api(group = "org.radarbase", name = "radar-auth", version = "2.1.0") + api(group = "org.radarbase", name = "radar-auth", version = mpVersion) val slf4jVersion: String by project api(group = "org.slf4j", name = "slf4j-api", version = slf4jVersion) From 102923cfae564c0f92d76bd904c4f976527fb48d Mon Sep 17 00:00:00 2001 From: Pauline Date: Fri, 3 Nov 2023 10:31:08 +0000 Subject: [PATCH 04/16] Fix lint errors --- .../radar/spring/auth/common/Authorization.kt | 33 ++++++++++++++----- .../ManagementPortalAuthValidator.kt | 22 ++++++++----- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt index 31c17c5..04bb6fd 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt @@ -6,7 +6,6 @@ import kotlinx.coroutines.runBlocking * See [radar.spring.auth.managementportal.ManagementPortalAuthorization] * **/ interface Authorization { - fun authorize( token: T, permission: String, @@ -23,10 +22,10 @@ interface Authorization { ): Boolean { return runBlocking { hasPermission(token, permission, entity, permissionOn, project, user, source) && - hasRole(token, project, role) && - hasScopes(token, scopes) && - hasAudiences(token, audiences) && - hasGrantTypes(token, grantTypes) + hasRole(token, project, role) && + hasScopes(token, scopes) && + hasAudiences(token, audiences) && + hasGrantTypes(token, grantTypes) } } @@ -40,8 +39,24 @@ interface Authorization { source: String? ): Boolean - fun hasRole(token: T, project: String?, role: String?): Boolean - fun hasScopes(token: T, scopes: Array): Boolean - fun hasAudiences(token: T, audiences: Array): Boolean - fun hasGrantTypes(token: T, grantTypes: Array): Boolean + fun hasRole( + token: T, + project: String?, + role: String? + ): Boolean + + fun hasScopes( + token: T, + scopes: Array + ): Boolean + + fun hasAudiences( + token: T, + audiences: Array + ): Boolean + + fun hasGrantTypes( + token: T, + grantTypes: Array + ): Boolean } diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt index 576a5d3..7ae3901 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt @@ -4,6 +4,7 @@ import jakarta.servlet.http.HttpServletRequest import org.radarbase.auth.authentication.TokenValidator import org.radarbase.auth.authentication.TokenVerifierLoader import org.radarbase.auth.exception.TokenValidationException +import org.radarbase.auth.jwks.JwkAlgorithmParser import org.radarbase.auth.jwks.JwksTokenVerifierLoader import org.radarbase.auth.token.RadarToken import org.slf4j.LoggerFactory @@ -12,18 +13,23 @@ import org.springframework.stereotype.Component import radar.spring.auth.common.RadarAuthValidator import radar.spring.auth.config.ManagementPortalAuthProperties import java.net.URI -import org.radarbase.auth.jwks.JwkAlgorithmParser -/** The [radar.spring.auth.common.AuthValidator] for Management Portal tokens. **/ +/** The [radar.spring.auth.common.AuthValidator] for Management Portal tokens. */ @Component -class ManagementPortalAuthValidator @JvmOverloads constructor( +class ManagementPortalAuthValidator +@JvmOverloads +constructor( @Autowired private val managementPortalProperties: ManagementPortalAuthProperties, - private val tokenVerifiers: List = listOf(URI(managementPortalProperties.publicKeyUrl)) - .map { JwksTokenVerifierLoader(it.toString(), managementPortalProperties.resourceName, JwkAlgorithmParser()) }, + private val tokenVerifiers: List = + listOf(URI(managementPortalProperties.publicKeyUrl)).map { + JwksTokenVerifierLoader( + it.toString(), + managementPortalProperties.resourceName, + JwkAlgorithmParser() + ) + }, private val tokenValidator: TokenValidator = TokenValidator(tokenVerifiers) -) : - RadarAuthValidator { - +) : RadarAuthValidator { init { try { this.tokenValidator.refresh() From 1ce69ccee218b264cc74bee30b36bba4adeed754 Mon Sep 17 00:00:00 2001 From: Pauline Date: Thu, 9 Nov 2023 12:46:32 +0000 Subject: [PATCH 05/16] Fix ManagementPortal Authorization --- .../radar/spring/auth/common/Authorization.kt | 2 +- .../ManagementPortalAuthorization.kt | 78 +++++++++---------- 2 files changed, 36 insertions(+), 44 deletions(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt index 04bb6fd..b170ffc 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt @@ -29,7 +29,7 @@ interface Authorization { } } - suspend fun hasPermission( + fun hasPermission( token: T, permission: String, entity: String, diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt index 9366892..1214288 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt @@ -1,15 +1,25 @@ package radar.spring.auth.managementportal -import org.radarbase.auth.authorization.AuthorizationOracle +import kotlinx.coroutines.runBlocking import org.radarbase.auth.authorization.EntityDetails +import org.radarbase.auth.authorization.EntityRelationService +import org.radarbase.auth.authorization.MPAuthorizationOracle import org.radarbase.auth.authorization.Permission import org.radarbase.auth.token.RadarToken import org.slf4j.LoggerFactory import radar.spring.auth.common.Authorization import radar.spring.auth.common.PermissionOn -class ManagementPortalAuthorization(val oracle: AuthorizationOracle) : Authorization { - override suspend fun hasPermission( +class ManagementPortalAuthorization() : Authorization { + private val relationService = + object : EntityRelationService { + override suspend fun findOrganizationOfProject(project: String): String? { + return null + } + } + val oracle: MPAuthorizationOracle = MPAuthorizationOracle(relationService) + + override fun hasPermission( token: RadarToken, permission: String, entity: String, @@ -18,32 +28,24 @@ class ManagementPortalAuthorization(val oracle: AuthorizationOracle) : Authoriza user: String?, source: String? ): Boolean { - val mpPermission = - Permission.of( - Permission.Entity.valueOf(entity), - Permission.Operation.valueOf(permission) - ) - return when (permissionOn) { - PermissionOn.PROJECT -> checkPermissionOnProject(token, mpPermission, project) - PermissionOn.SUBJECT -> checkPermissionOnSubject(token, mpPermission, project, user) - PermissionOn.SOURCE -> - checkPermissionOnSource( - token, - mpPermission, - project, - user, - source + return runBlocking { + val mpPermission = + Permission.of( + Permission.Entity.valueOf(entity), + Permission.Operation.valueOf(permission) ) - else -> - oracle.hasPermission( - token, - mpPermission, - EntityDetails( - project, - user, - source + when (permissionOn) { + PermissionOn.PROJECT -> checkPermissionOnProject(token, mpPermission, project) + PermissionOn.SUBJECT -> checkPermissionOnSubject(token, mpPermission, project, user) + PermissionOn.SOURCE -> + checkPermissionOnSource(token, mpPermission, project, user, source) + else -> + oracle.hasPermission( + token, + mpPermission, + EntityDetails(project, user, source) ) - ) + } } } @@ -59,9 +61,9 @@ class ManagementPortalAuthorization(val oracle: AuthorizationOracle) : Authoriza logger.warn("Project must be specified when checking a role.") return false } - return token.roles.asSequence() - .filter { it.referent == project } - .any { it.authority == role } + return token.roles.asSequence().filter { it.referent == project }.any { + it.authority == role + } } override fun hasScopes( @@ -94,16 +96,10 @@ class ManagementPortalAuthorization(val oracle: AuthorizationOracle) : Authoriza project: String? ): Boolean { if (project.isNullOrBlank()) { - logger.warn( - "The project must be specified when checking permissions on PROJECT." - ) + logger.warn("The project must be specified when checking permissions on PROJECT.") return false } - return oracle.hasPermission( - token, - mpPermission, - EntityDetails(project = project) - ) + return oracle.hasPermission(token, mpPermission, EntityDetails(project = project)) } private suspend fun checkPermissionOnSubject( @@ -118,11 +114,7 @@ class ManagementPortalAuthorization(val oracle: AuthorizationOracle) : Authoriza ) return false } - return oracle.hasPermission( - token, - mpPermission, - EntityDetails(user = user) - ) + return oracle.hasPermission(token, mpPermission, EntityDetails(user = user)) } private suspend fun checkPermissionOnSource( From 4abcf75442dbbafb3f4e3e958c03bcb651756958 Mon Sep 17 00:00:00 2001 From: Pauline Date: Wed, 6 Mar 2024 15:00:53 +0000 Subject: [PATCH 06/16] Update checking of permissions on projects and subjects --- .../ManagementPortalAuthorization.kt | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt index 1214288..a8a295e 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt @@ -29,21 +29,23 @@ class ManagementPortalAuthorization() : Authorization { source: String? ): Boolean { return runBlocking { + val subject = user.takeIf { it != null } ?: token.subject val mpPermission = Permission.of( Permission.Entity.valueOf(entity), Permission.Operation.valueOf(permission) ) when (permissionOn) { - PermissionOn.PROJECT -> checkPermissionOnProject(token, mpPermission, project) - PermissionOn.SUBJECT -> checkPermissionOnSubject(token, mpPermission, project, user) + PermissionOn.PROJECT -> checkPermissionOnProject(token, mpPermission, project, subject) + PermissionOn.SUBJECT -> checkPermissionOnSubject(token, mpPermission, project, subject) PermissionOn.SOURCE -> - checkPermissionOnSource(token, mpPermission, project, user, source) + checkPermissionOnSource(token, mpPermission, project, subject, source) + PermissionOn.DEFAULT -> true else -> oracle.hasPermission( token, mpPermission, - EntityDetails(project, user, source) + EntityDetails(project, subject, source) ) } } @@ -93,28 +95,29 @@ class ManagementPortalAuthorization() : Authorization { private suspend fun checkPermissionOnProject( token: RadarToken, mpPermission: Permission, - project: String? + project: String?, + subject: String? ): Boolean { if (project.isNullOrBlank()) { logger.warn("The project must be specified when checking permissions on PROJECT.") return false } - return oracle.hasPermission(token, mpPermission, EntityDetails(project = project)) + return oracle.hasPermission(token, mpPermission, EntityDetails(subject = subject, project = project)) } private suspend fun checkPermissionOnSubject( token: RadarToken, mpPermission: Permission, project: String?, - user: String? + subject: String? ): Boolean { - if (project.isNullOrBlank() || user.isNullOrBlank()) { + if (project.isNullOrBlank() || subject.isNullOrBlank()) { logger.warn( "The project and subject must be specified when checking permissions on SUBJECT." ) return false } - return oracle.hasPermission(token, mpPermission, EntityDetails(user = user)) + return oracle.hasPermission(token, mpPermission, EntityDetails(subject = subject, project = project)) } private suspend fun checkPermissionOnSource( From 7e4e248fe7614363226647622317b3fcbcc3b723 Mon Sep 17 00:00:00 2001 From: Pauline Date: Wed, 6 Mar 2024 17:02:57 +0000 Subject: [PATCH 07/16] Fix pulling of public key endpoints --- .../config/ManagementPortalAuthProperties.kt | 5 +- .../ManagementPortalAuthValidator.kt | 67 ++++++++++--------- .../ManagementPortalAuthorization.kt | 2 +- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/config/ManagementPortalAuthProperties.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/config/ManagementPortalAuthProperties.kt index 6a2b7ac..2b74da5 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/config/ManagementPortalAuthProperties.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/config/ManagementPortalAuthProperties.kt @@ -1,7 +1,10 @@ package radar.spring.auth.config +import java.net.URI + open class ManagementPortalAuthProperties @JvmOverloads constructor( val baseUrl: String, val resourceName: String, - val publicKeyUrl: String = "$baseUrl/oauth/token_key" + val publicKeyEndpoints: List = emptyList(), + val publicKeyUrl: String = "$baseUrl/oauth/token_key", ) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt index 7ae3901..c380756 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt @@ -12,42 +12,47 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component import radar.spring.auth.common.RadarAuthValidator import radar.spring.auth.config.ManagementPortalAuthProperties -import java.net.URI /** The [radar.spring.auth.common.AuthValidator] for Management Portal tokens. */ @Component class ManagementPortalAuthValidator -@JvmOverloads -constructor( - @Autowired private val managementPortalProperties: ManagementPortalAuthProperties, - private val tokenVerifiers: List = - listOf(URI(managementPortalProperties.publicKeyUrl)).map { - JwksTokenVerifierLoader( - it.toString(), - managementPortalProperties.resourceName, - JwkAlgorithmParser() - ) - }, - private val tokenValidator: TokenValidator = TokenValidator(tokenVerifiers) -) : RadarAuthValidator { - init { - try { - this.tokenValidator.refresh() - logger.debug("Refreshed Token Validator keys") - } catch (ex: Exception) { - logger.error( - "Failed to immediately initialize token validator, will try again later: {}", - ex.toString() - ) + @JvmOverloads + constructor( + @Autowired private val managementPortalProperties: ManagementPortalAuthProperties, + private val tokenVerifiers: List = + managementPortalProperties.publicKeyEndpoints.map { + JwksTokenVerifierLoader(it.toString(), managementPortalProperties.resourceName, JwkAlgorithmParser()) + } + + listOf( + JwksTokenVerifierLoader( + managementPortalProperties.publicKeyUrl, + managementPortalProperties.resourceName, + JwkAlgorithmParser() + ) + ), + private val tokenValidator: TokenValidator = TokenValidator(tokenVerifiers) + ) : RadarAuthValidator { + init { + try { + this.tokenValidator.refresh() + logger.debug("Refreshed Token Validator keys") + } catch (ex: Exception) { + logger.error( + "Failed to immediately initialize token validator, will try again later: {}", + ex.toString() + ) + } } - } - @Throws(TokenValidationException::class) - override fun verify(token: String, request: HttpServletRequest): RadarToken? { - return tokenValidator.validateBlocking(token) - } + @Throws(TokenValidationException::class) + override fun verify( + token: String, + request: HttpServletRequest + ): RadarToken? { + return tokenValidator.validateBlocking(token) + } - companion object { - private val logger = LoggerFactory.getLogger(ManagementPortalAuthValidator::class.java) + companion object { + private val logger = LoggerFactory.getLogger(ManagementPortalAuthValidator::class.java) + } } -} diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt index a8a295e..53423f7 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt @@ -29,7 +29,7 @@ class ManagementPortalAuthorization() : Authorization { source: String? ): Boolean { return runBlocking { - val subject = user.takeIf { it != null } ?: token.subject + val subject = user ?: token.subject val mpPermission = Permission.of( Permission.Entity.valueOf(entity), From 901b26c22bd316aaf966490d44b2be51aacda54a Mon Sep 17 00:00:00 2001 From: Pauline Date: Wed, 6 Mar 2024 17:07:05 +0000 Subject: [PATCH 08/16] Fix lint issues --- .../ManagementPortalAuthValidator.kt | 74 ++++++++++--------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt index c380756..ea5bd49 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthValidator.kt @@ -16,43 +16,47 @@ import radar.spring.auth.config.ManagementPortalAuthProperties /** The [radar.spring.auth.common.AuthValidator] for Management Portal tokens. */ @Component class ManagementPortalAuthValidator - @JvmOverloads - constructor( - @Autowired private val managementPortalProperties: ManagementPortalAuthProperties, - private val tokenVerifiers: List = - managementPortalProperties.publicKeyEndpoints.map { - JwksTokenVerifierLoader(it.toString(), managementPortalProperties.resourceName, JwkAlgorithmParser()) - } + - listOf( - JwksTokenVerifierLoader( - managementPortalProperties.publicKeyUrl, - managementPortalProperties.resourceName, - JwkAlgorithmParser() - ) - ), - private val tokenValidator: TokenValidator = TokenValidator(tokenVerifiers) - ) : RadarAuthValidator { - init { - try { - this.tokenValidator.refresh() - logger.debug("Refreshed Token Validator keys") - } catch (ex: Exception) { - logger.error( - "Failed to immediately initialize token validator, will try again later: {}", - ex.toString() +@JvmOverloads +constructor( + @Autowired private val managementPortalProperties: ManagementPortalAuthProperties, + private val tokenVerifiers: List = + managementPortalProperties.publicKeyEndpoints.map { + JwksTokenVerifierLoader( + it.toString(), + managementPortalProperties.resourceName, + JwkAlgorithmParser() + ) + } + + listOf( + JwksTokenVerifierLoader( + managementPortalProperties.publicKeyUrl, + managementPortalProperties.resourceName, + JwkAlgorithmParser() ) - } + ), + private val tokenValidator: TokenValidator = TokenValidator(tokenVerifiers) +) : RadarAuthValidator { + init { + try { + this.tokenValidator.refresh() + logger.debug("Refreshed Token Validator keys") + } catch (ex: Exception) { + logger.error( + "Failed to immediately initialize token validator, will try again later: {}", + ex.toString() + ) } + } - @Throws(TokenValidationException::class) - override fun verify( - token: String, - request: HttpServletRequest - ): RadarToken? { - return tokenValidator.validateBlocking(token) - } + @Throws(TokenValidationException::class) + override fun verify( + token: String, + request: HttpServletRequest + ): RadarToken? { + return tokenValidator.validateBlocking(token) + } - companion object { - private val logger = LoggerFactory.getLogger(ManagementPortalAuthValidator::class.java) - } + companion object { + private val logger = LoggerFactory.getLogger(ManagementPortalAuthValidator::class.java) } +} From 07be3eb34e521758da3762023e2ac307e431c015 Mon Sep 17 00:00:00 2001 From: Pauline Conde Date: Fri, 8 Mar 2024 16:10:16 +0000 Subject: [PATCH 09/16] Bump version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9e19300..dac199e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ plugins { allprojects { group = "org.radarbase" - version = "1.2.1-SNAPSHOT" + version = "1.2.1" } subprojects { From 570652082e7a0bb617244e2cd5f11797c4be626a Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 11 Mar 2024 15:43:46 +0000 Subject: [PATCH 10/16] Add check for authorities --- .../radar/spring/auth/common/Authorization.kt | 31 +++++++------------ .../ManagementPortalAuthorization.kt | 25 ++++++++++++--- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt index b170ffc..a65429d 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt @@ -2,9 +2,10 @@ package radar.spring.auth.common import kotlinx.coroutines.runBlocking -/** Abstract Authorization interface to be used with a custom token [T]. - * See [radar.spring.auth.managementportal.ManagementPortalAuthorization] - * **/ +/** + * Abstract Authorization interface to be used with a custom token [T]. See + * [radar.spring.auth.managementportal.ManagementPortalAuthorization] + */ interface Authorization { fun authorize( token: T, @@ -24,6 +25,7 @@ interface Authorization { hasPermission(token, permission, entity, permissionOn, project, user, source) && hasRole(token, project, role) && hasScopes(token, scopes) && + hasAuthorities(token, authorities) && hasAudiences(token, audiences) && hasGrantTypes(token, grantTypes) } @@ -39,24 +41,13 @@ interface Authorization { source: String? ): Boolean - fun hasRole( - token: T, - project: String?, - role: String? - ): Boolean + fun hasRole(token: T, project: String?, role: String?): Boolean - fun hasScopes( - token: T, - scopes: Array - ): Boolean + fun hasScopes(token: T, scopes: Array): Boolean - fun hasAudiences( - token: T, - audiences: Array - ): Boolean + fun hasAuthorities(token: T, authorities: Array): Boolean - fun hasGrantTypes( - token: T, - grantTypes: Array - ): Boolean + fun hasAudiences(token: T, audiences: Array): Boolean + + fun hasGrantTypes(token: T, grantTypes: Array): Boolean } diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt index 53423f7..ee9de6a 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt @@ -36,8 +36,10 @@ class ManagementPortalAuthorization() : Authorization { Permission.Operation.valueOf(permission) ) when (permissionOn) { - PermissionOn.PROJECT -> checkPermissionOnProject(token, mpPermission, project, subject) - PermissionOn.SUBJECT -> checkPermissionOnSubject(token, mpPermission, project, subject) + PermissionOn.PROJECT -> + checkPermissionOnProject(token, mpPermission, project, subject) + PermissionOn.SUBJECT -> + checkPermissionOnSubject(token, mpPermission, project, subject) PermissionOn.SOURCE -> checkPermissionOnSource(token, mpPermission, project, subject, source) PermissionOn.DEFAULT -> true @@ -75,6 +77,13 @@ class ManagementPortalAuthorization() : Authorization { return token.scopes.containsAll(scopes.toList()) } + override fun hasAuthorities( + token: RadarToken, + authorities: Array + ): Boolean { + return token.roles.asIterable().map { it.authority }.containsAll(authorities.toList()) + } + override fun hasAudiences( token: RadarToken, audiences: Array @@ -102,7 +111,11 @@ class ManagementPortalAuthorization() : Authorization { logger.warn("The project must be specified when checking permissions on PROJECT.") return false } - return oracle.hasPermission(token, mpPermission, EntityDetails(subject = subject, project = project)) + return oracle.hasPermission( + token, + mpPermission, + EntityDetails(subject = subject, project = project) + ) } private suspend fun checkPermissionOnSubject( @@ -117,7 +130,11 @@ class ManagementPortalAuthorization() : Authorization { ) return false } - return oracle.hasPermission(token, mpPermission, EntityDetails(subject = subject, project = project)) + return oracle.hasPermission( + token, + mpPermission, + EntityDetails(subject = subject, project = project) + ) } private suspend fun checkPermissionOnSource( From 06e1b90b8a5d85be770ee36294380a8d1349ae24 Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 11 Mar 2024 15:54:43 +0000 Subject: [PATCH 11/16] Fix spacing --- .../src/main/kotlin/radar/spring/auth/common/Authorization.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt index a65429d..2dcac04 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/common/Authorization.kt @@ -42,12 +42,8 @@ interface Authorization { ): Boolean fun hasRole(token: T, project: String?, role: String?): Boolean - fun hasScopes(token: T, scopes: Array): Boolean - fun hasAuthorities(token: T, authorities: Array): Boolean - fun hasAudiences(token: T, audiences: Array): Boolean - fun hasGrantTypes(token: T, grantTypes: Array): Boolean } From d397e637c3c7fae815e7d43ddcd96b69c6ba764a Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 11 Mar 2024 15:56:43 +0000 Subject: [PATCH 12/16] Fix spacing --- .../ManagementPortalAuthorization.kt | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt index ee9de6a..5560d0a 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt @@ -70,31 +70,19 @@ class ManagementPortalAuthorization() : Authorization { } } - override fun hasScopes( - token: RadarToken, - scopes: Array - ): Boolean { + override fun hasScopes(token: RadarToken, scopes: Array): Boolean { return token.scopes.containsAll(scopes.toList()) } - override fun hasAuthorities( - token: RadarToken, - authorities: Array - ): Boolean { + override fun hasAuthorities(token: RadarToken, authorities: Array): Boolean { return token.roles.asIterable().map { it.authority }.containsAll(authorities.toList()) } - override fun hasAudiences( - token: RadarToken, - audiences: Array - ): Boolean { + override fun hasAudiences(token: RadarToken, audiences: Array): Boolean { return token.audience.containsAll(audiences.toList()) } - override fun hasGrantTypes( - token: RadarToken, - grantTypes: Array - ): Boolean { + override fun hasGrantTypes(token: RadarToken, grantTypes: Array): Boolean { if (grantTypes.isEmpty()) { return true } From b91405d672ef01938fcff7588cdd4995c45e995a Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 11 Mar 2024 16:32:17 +0000 Subject: [PATCH 13/16] Add default project to entityrelationservice --- .../auth/managementportal/ManagementPortalAuthorization.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt index 5560d0a..a1f1afb 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt @@ -11,10 +11,11 @@ import radar.spring.auth.common.Authorization import radar.spring.auth.common.PermissionOn class ManagementPortalAuthorization() : Authorization { + private val DEFAULT_PROJECT = "main" private val relationService = object : EntityRelationService { override suspend fun findOrganizationOfProject(project: String): String? { - return null + return DEFAULT_PROJECT } } val oracle: MPAuthorizationOracle = MPAuthorizationOracle(relationService) From 5e50d83bf52428505dadf4b485c1d636069fc8ce Mon Sep 17 00:00:00 2001 From: Pauline Date: Wed, 13 Mar 2024 15:55:00 +0000 Subject: [PATCH 14/16] Get project from referent and add comments --- .../auth/managementportal/ManagementPortalAuthorization.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt index a1f1afb..ec01cf2 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt @@ -15,6 +15,8 @@ class ManagementPortalAuthorization() : Authorization { private val relationService = object : EntityRelationService { override suspend fun findOrganizationOfProject(project: String): String? { + // NOTE: This will default to the default "main" project for now since we are not using organizations + // TODO: Implement organizations return DEFAULT_PROJECT } } @@ -31,6 +33,8 @@ class ManagementPortalAuthorization() : Authorization { ): Boolean { return runBlocking { val subject = user ?: token.subject + val project = project ?: token.roles?.firstOrNull()?.referent + val mpPermission = Permission.of( Permission.Entity.valueOf(entity), From 23be1f2f398db95b9384d6ecba56dcc96deb0f6f Mon Sep 17 00:00:00 2001 From: Pauline Date: Wed, 13 Mar 2024 16:14:27 +0000 Subject: [PATCH 15/16] Fix PermissionOn.Default handling --- .../auth/managementportal/ManagementPortalAuthorization.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt index ec01cf2..f7907ac 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt @@ -47,12 +47,11 @@ class ManagementPortalAuthorization() : Authorization { checkPermissionOnSubject(token, mpPermission, project, subject) PermissionOn.SOURCE -> checkPermissionOnSource(token, mpPermission, project, subject, source) - PermissionOn.DEFAULT -> true else -> oracle.hasPermission( token, mpPermission, - EntityDetails(project, subject, source) + EntityDetails(project = project, subject = subject, source = source) ) } } From d28dfa2813175039f4f6ac0e320e5641c5fb9b7b Mon Sep 17 00:00:00 2001 From: Pauline Date: Wed, 13 Mar 2024 16:38:55 +0000 Subject: [PATCH 16/16] Rename default org --- .../auth/managementportal/ManagementPortalAuthorization.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt index f7907ac..1188c8c 100644 --- a/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt +++ b/radar-spring-auth/src/main/kotlin/radar/spring/auth/managementportal/ManagementPortalAuthorization.kt @@ -11,13 +11,13 @@ import radar.spring.auth.common.Authorization import radar.spring.auth.common.PermissionOn class ManagementPortalAuthorization() : Authorization { - private val DEFAULT_PROJECT = "main" + private val DEFAULT_ORG = "main" private val relationService = object : EntityRelationService { override suspend fun findOrganizationOfProject(project: String): String? { // NOTE: This will default to the default "main" project for now since we are not using organizations // TODO: Implement organizations - return DEFAULT_PROJECT + return DEFAULT_ORG } } val oracle: MPAuthorizationOracle = MPAuthorizationOracle(relationService)