From 049634da66797f910a321ed96a08de21c26e462c Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 19 Jul 2023 10:46:39 +0800 Subject: [PATCH 01/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/service/oauth2/ClientService.kt | 4 +++ .../auth/service/oauth2/Oauth2Config.kt | 33 +++++++++++++++++++ .../service/oauth2/TokenEndpointService.kt | 4 +++ .../auth/service/oauth2/TokenService.kt | 13 ++++++++ .../oauth2/grant/AbstractTokenGranter.kt | 29 ++++++++++++++++ .../grant/AuthorizationCodeTokenGranter.kt | 23 +++++++++++++ .../grant/ClientCredentialsTokenGranter.kt | 16 +++++++++ .../oauth2/grant/CompositeTokenGranter.kt | 15 +++++++++ .../oauth2/grant/RefreshTokenGranter.kt | 20 +++++++++++ .../auth/service/oauth2/grant/TokenGranter.kt | 5 +++ 10 files changed, 162 insertions(+) create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenEndpointService.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenService.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt new file mode 100644 index 00000000000..c71ede0b917 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt @@ -0,0 +1,4 @@ +package com.tencent.devops.auth.service.oauth2 + +class ClientService { +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt new file mode 100644 index 00000000000..2d002d34a7a --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -0,0 +1,33 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.service.oauth2.grant.AuthorizationCodeTokenGranter +import com.tencent.devops.auth.service.oauth2.grant.ClientCredentialsTokenGranter +import com.tencent.devops.auth.service.oauth2.grant.CompositeTokenGranter +import com.tencent.devops.auth.service.oauth2.grant.RefreshTokenGranter +import com.tencent.devops.auth.service.oauth2.grant.TokenGranter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class Oauth2Config { + @Bean + fun tokenService(): TokenService { + return TokenService(compositeTokenGranter()) + } + + @Bean + fun compositeTokenGranter(): TokenGranter { + return CompositeTokenGranter(getDefaultTokenGranters()) + } + + private fun getDefaultTokenGranters(): List { + val tokenGranters = ArrayList() + val refreshTokenGranter = RefreshTokenGranter() + val clientCredentialsTokenGranter = ClientCredentialsTokenGranter() + val authorizationCodeTokenGranter = AuthorizationCodeTokenGranter() + tokenGranters.add(refreshTokenGranter) + tokenGranters.add(clientCredentialsTokenGranter) + tokenGranters.add(authorizationCodeTokenGranter) + return tokenGranters + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenEndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenEndpointService.kt new file mode 100644 index 00000000000..433e6aca9bd --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenEndpointService.kt @@ -0,0 +1,4 @@ +package com.tencent.devops.auth.service.oauth2 + +class TokenEndpointService { +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenService.kt new file mode 100644 index 00000000000..cee8fff4c78 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenService.kt @@ -0,0 +1,13 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.service.oauth2.grant.TokenGranter + +class TokenService constructor( + private val tokenGranter: TokenGranter +) { + fun getAccessToken(grantType: String): String? { + //1.校验是否登录 + //2.校验客户端ID和秘钥 + return tokenGranter.grant(grantType) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt new file mode 100644 index 00000000000..b3593ecf3bb --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -0,0 +1,29 @@ +package com.tencent.devops.auth.service.oauth2.grant + +import org.slf4j.LoggerFactory + +abstract class AbstractTokenGranter(private val grantType: String) : TokenGranter { + override fun grant(grantType: String): String? { + if (this.grantType != grantType) { + return null + } + //1.校验用户的授权类型是否合法 + logger.info("AbstractTokenGranter grant") + return getAccessToken(grantType) + } + + open fun getAccessToken(grantType: String): String { + logger.info("Default getAccessToken") + // 从入参中获取accessToken. + // 1、校验access_token是否为空 + // 2.1 若为空,创建新的access_token并存储,返回access_token,过期时间, + // 3.1 若不为空,校验access_token是否过期 + // 3.2 若过期,清除access_token记录,创建新的access_token并存储,返回access_token,过期时间。 + // 3.3 若未过期,返回access_token,过期时间 + return "Default" + } + + companion object { + private val logger = LoggerFactory.getLogger(AbstractTokenGranter::class.java) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt new file mode 100644 index 00000000000..16bb8a682f0 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -0,0 +1,23 @@ +package com.tencent.devops.auth.service.oauth2.grant + +import org.slf4j.LoggerFactory + + +class AuthorizationCodeTokenGranter : AbstractTokenGranter(GRANT_TYPE) { + companion object { + private const val GRANT_TYPE = "authorization_code" + private val logger = LoggerFactory.getLogger(AuthorizationCodeTokenGranter::class.java) + } + + override fun getAccessToken(grantType: String): String { + logger.info("authorization_code getAccessToken") + // 1.获取授权码,判断授权是否为空 + // 2.判断授权码和客户端id是否对应的上 + // 3.判断授权码是否过期 + // 4.若授权码没有问题,则直接消费授权码,授权码单次有效,直接数据库删除该授权码 + // 5、根据appcode+username获取accessToken + val accessToken = super.getAccessToken(grantType) + // 6、删除refreshToken,并创建新的refreshToken. + return accessToken + "refreshToken" + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt new file mode 100644 index 00000000000..c8f420aa41b --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -0,0 +1,16 @@ +package com.tencent.devops.auth.service.oauth2.grant + +import org.slf4j.LoggerFactory + +class ClientCredentialsTokenGranter : AbstractTokenGranter(GRANT_TYPE) { + companion object { + private const val GRANT_TYPE = "client_credentials" + private val logger = LoggerFactory.getLogger(ClientCredentialsTokenGranter::class.java) + } + + override fun getAccessToken(grantType: String): String { + logger.info("client_credentials getAccessToken") + // 1、根据appcode获取accessToken + return super.getAccessToken(grantType) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt new file mode 100644 index 00000000000..6d9d4983a1c --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt @@ -0,0 +1,15 @@ +package com.tencent.devops.auth.service.oauth2.grant + +class CompositeTokenGranter constructor( + private val tokenGranters: List +) : TokenGranter { + override fun grant(grantType: String): String? { + for (granter in tokenGranters) { + val grant = granter.grant(grantType) + if (grant != null) { + return grant + } + } + return null + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt new file mode 100644 index 00000000000..50db57bf924 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -0,0 +1,20 @@ +package com.tencent.devops.auth.service.oauth2.grant + +import org.slf4j.LoggerFactory + +class RefreshTokenGranter : AbstractTokenGranter(GRANT_TYPE) { + companion object { + private const val GRANT_TYPE = "refresh_token" + private val logger = LoggerFactory.getLogger(RefreshTokenGranter::class.java) + } + + override fun getAccessToken(grantType: String): String { + logger.info("refresh_token getAccessToken") + //1.校验refresh_token是否为空 + //2.清除跟该refresh_token授权码相关的access_token + //3.校验refresh_token是否过期 + //3.1 过期,清除refresh_token记录,则直接返回异常 + //3.2 未过期,走主流程,此时accessToken + return super.getAccessToken(grantType) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt new file mode 100644 index 00000000000..d1f53c7e3a8 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt @@ -0,0 +1,5 @@ +package com.tencent.devops.auth.service.oauth2.grant + +interface TokenGranter { + fun grant(grantType: String): String? +} From df4956ba9a99e740eddaa0cc59e4fb4fcd4db37b Mon Sep 17 00:00:00 2001 From: greysonfang Date: Sat, 22 Jul 2023 16:22:15 +0800 Subject: [PATCH 02/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/oauth2/Oauth2EndpointResource.kt | 48 +++++++++++++++++++ .../auth/pojo/dto/Oauth2AccessTokenDTO.kt | 18 +++++++ .../auth/pojo/vo/Oauth2AccessTokenVo.kt | 14 ++++++ .../resources/Oauth2EndpointResourceImpl.kt | 27 +++++++++++ .../auth/service/oauth2/Oauth2Config.kt | 4 +- .../service/oauth2/Oauth2EndpointService.kt | 35 ++++++++++++++ .../service/oauth2/TokenEndpointService.kt | 4 -- .../auth/service/oauth2/TokenService.kt | 13 ----- .../oauth2/grant/AbstractTokenGranter.kt | 16 +++++-- .../grant/AuthorizationCodeTokenGranter.kt | 11 +++-- .../grant/ClientCredentialsTokenGranter.kt | 9 +++- .../oauth2/grant/CompositeTokenGranter.kt | 10 +++- .../oauth2/grant/RefreshTokenGranter.kt | 9 +++- .../auth/service/oauth2/grant/TokenGranter.kt | 8 +++- 14 files changed, 193 insertions(+), 33 deletions(-) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AccessTokenVo.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt delete mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenEndpointService.kt delete mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenService.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt new file mode 100644 index 00000000000..022c1948d5d --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt @@ -0,0 +1,48 @@ +package com.tencent.devops.auth.api.oauth2 + +import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam +import javax.ws.rs.Consumes +import javax.ws.rs.GET +import javax.ws.rs.HeaderParam +import javax.ws.rs.Path +import javax.ws.rs.Produces +import javax.ws.rs.QueryParam +import javax.ws.rs.core.MediaType + +@Api(tags = ["OAUTH2_ENDPOINT"], description = "oauth2相关") +@Path("/oauth2/endpoint") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +interface Oauth2EndpointResource { + @GET + @Path("/getAuthorizationCode") + @ApiOperation("获取授权码") + fun getAuthorizationCode( + @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) + @ApiParam("待校验用户ID", required = true) + userId: String, + @QueryParam("clientId") + @ApiParam("客户端ID", required = true) + clientId: String, + @QueryParam("redirectUri") + @ApiParam("跳转链接", required = true) + redirectUri: String + ): Result + + @GET + @Path("/getAccessToken") + @ApiOperation("获取accessToken") + fun getAccessToken( + // 待定,如果客户端模式,此时并没有用户 + @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) + @ApiParam("待校验用户ID", required = true) + userId: String, + @ApiParam("oauth2获取token请求报文体", required = true) + oauth2AccessTokenDTO: Oauth2AccessTokenDTO + ): Result +} diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt new file mode 100644 index 00000000000..a1ea18fc89c --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt @@ -0,0 +1,18 @@ +package com.tencent.devops.auth.pojo.dto + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("oauth2获取token请求报文体") +data class Oauth2AccessTokenDTO( + @ApiModelProperty("客户端id", required = true) + val clientId: String, + @ApiModelProperty("客户端密钥", required = true) + val clientSecret: String, + @ApiModelProperty("授权类型", required = true) + val grantType: String, + @ApiModelProperty("授权码,用于授权码模式", required = false) + val code: String? = null, + @ApiModelProperty("refreshToken,用于刷新授权码模式", required = false) + val refreshToken: String? = null +) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AccessTokenVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AccessTokenVo.kt new file mode 100644 index 00000000000..bb95feaa9d0 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AccessTokenVo.kt @@ -0,0 +1,14 @@ +package com.tencent.devops.auth.pojo.vo + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("oauth2获取token返回报文体") +data class Oauth2AccessTokenVo( + @ApiModelProperty("accessToken", required = true) + val accessToken: String, + @ApiModelProperty("accessToken过期时间", required = true) + val expiredTime: Long, + @ApiModelProperty("refreshToken", required = true) + val refreshToken: String? = null +) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt new file mode 100644 index 00000000000..92fb3df73ee --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt @@ -0,0 +1,27 @@ +package com.tencent.devops.auth.resources + +import com.tencent.devops.auth.api.oauth2.Oauth2EndpointResource +import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.service.oauth2.Oauth2EndpointService +import com.tencent.devops.common.web.RestResource + +@RestResource +class Oauth2EndpointResourceImpl constructor( + oauth2EndpointService: Oauth2EndpointService +) : Oauth2EndpointResource { + override fun getAuthorizationCode( + userId: String, + clientId: String, + redirectUri: String + ): Result { + TODO("Not yet implemented") + } + + override fun getAccessToken( + userId: String, + oauth2AccessTokenDTO: Oauth2AccessTokenDTO + ): Result { + TODO("Not yet implemented") + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt index 2d002d34a7a..1914c4780c1 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -11,8 +11,8 @@ import org.springframework.context.annotation.Configuration @Configuration class Oauth2Config { @Bean - fun tokenService(): TokenService { - return TokenService(compositeTokenGranter()) + fun oauth2EndpointService(): Oauth2EndpointService { + return Oauth2EndpointService(compositeTokenGranter()) } @Bean diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt new file mode 100644 index 00000000000..db93700d1d3 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -0,0 +1,35 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.service.oauth2.grant.TokenGranter +import org.springframework.stereotype.Service + +@Service +class Oauth2EndpointService constructor( + private val tokenGranter: TokenGranter +) { + fun getAuthorizationCode( + userId: String, + clientId: String, + redirectUri: String + ): String { + // 1、校验用户是否登录 + // 2、校验clientId是否存在 + // 3、校验client是否为授权码模式 + // 4、校验redirectUri是否和数据库一致 + // 5、生成授权码并存储数据库,授权码有效期为5分钟 + // 6、返回授权码 + return "authorizationCode" + } + + fun getAccessToken( + userId: String, + oauth2AccessTokenDTO: Oauth2AccessTokenDTO + ): Oauth2AccessTokenVo? { + // 1、校验用户是否登录 + // 2、校验client_id和client_secret是否正确 + val grantType = oauth2AccessTokenDTO.grantType + return tokenGranter.grant(grantType, oauth2AccessTokenDTO) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenEndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenEndpointService.kt deleted file mode 100644 index 433e6aca9bd..00000000000 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenEndpointService.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.tencent.devops.auth.service.oauth2 - -class TokenEndpointService { -} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenService.kt deleted file mode 100644 index cee8fff4c78..00000000000 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/TokenService.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.tencent.devops.auth.service.oauth2 - -import com.tencent.devops.auth.service.oauth2.grant.TokenGranter - -class TokenService constructor( - private val tokenGranter: TokenGranter -) { - fun getAccessToken(grantType: String): String? { - //1.校验是否登录 - //2.校验客户端ID和秘钥 - return tokenGranter.grant(grantType) - } -} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index b3593ecf3bb..a53a1ec4916 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -1,18 +1,26 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory abstract class AbstractTokenGranter(private val grantType: String) : TokenGranter { - override fun grant(grantType: String): String? { + override fun grant( + grantType: String, + oauth2AccessTokenDTO: Oauth2AccessTokenDTO + ): Oauth2AccessTokenVo? { if (this.grantType != grantType) { return null } //1.校验用户的授权类型是否合法 logger.info("AbstractTokenGranter grant") - return getAccessToken(grantType) + return getAccessToken(oauth2AccessTokenDTO, null) } - open fun getAccessToken(grantType: String): String { + open fun getAccessToken( + oauth2AccessTokenDTO: Oauth2AccessTokenDTO, + accessToken: String? + ): Oauth2AccessTokenVo { logger.info("Default getAccessToken") // 从入参中获取accessToken. // 1、校验access_token是否为空 @@ -20,7 +28,7 @@ abstract class AbstractTokenGranter(private val grantType: String) : TokenGrante // 3.1 若不为空,校验access_token是否过期 // 3.2 若过期,清除access_token记录,创建新的access_token并存储,返回access_token,过期时间。 // 3.3 若未过期,返回access_token,过期时间 - return "Default" + return Oauth2AccessTokenVo("accessToken", 1000) } companion object { diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index 16bb8a682f0..4b22726ef3f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -1,5 +1,7 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory @@ -9,15 +11,18 @@ class AuthorizationCodeTokenGranter : AbstractTokenGranter(GRANT_TYPE) { private val logger = LoggerFactory.getLogger(AuthorizationCodeTokenGranter::class.java) } - override fun getAccessToken(grantType: String): String { + override fun getAccessToken( + oauth2AccessTokenDTO: Oauth2AccessTokenDTO, + accessToken: String? + ): Oauth2AccessTokenVo { logger.info("authorization_code getAccessToken") // 1.获取授权码,判断授权是否为空 // 2.判断授权码和客户端id是否对应的上 // 3.判断授权码是否过期 // 4.若授权码没有问题,则直接消费授权码,授权码单次有效,直接数据库删除该授权码 // 5、根据appcode+username获取accessToken - val accessToken = super.getAccessToken(grantType) + val accessToken = super.getAccessToken(oauth2AccessTokenDTO, accessToken) // 6、删除refreshToken,并创建新的refreshToken. - return accessToken + "refreshToken" + return Oauth2AccessTokenVo("accessToken", 1000) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index c8f420aa41b..8afc819eba7 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -1,5 +1,7 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory class ClientCredentialsTokenGranter : AbstractTokenGranter(GRANT_TYPE) { @@ -8,9 +10,12 @@ class ClientCredentialsTokenGranter : AbstractTokenGranter(GRANT_TYPE) { private val logger = LoggerFactory.getLogger(ClientCredentialsTokenGranter::class.java) } - override fun getAccessToken(grantType: String): String { + override fun getAccessToken( + oauth2AccessTokenDTO: Oauth2AccessTokenDTO, + accessToken: String? + ): Oauth2AccessTokenVo { logger.info("client_credentials getAccessToken") // 1、根据appcode获取accessToken - return super.getAccessToken(grantType) + return super.getAccessToken(oauth2AccessTokenDTO, accessToken) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt index 6d9d4983a1c..a1da8c83454 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt @@ -1,11 +1,17 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo + class CompositeTokenGranter constructor( private val tokenGranters: List ) : TokenGranter { - override fun grant(grantType: String): String? { + override fun grant( + grantType: String, + oauth2AccessTokenDTO: Oauth2AccessTokenDTO + ): Oauth2AccessTokenVo? { for (granter in tokenGranters) { - val grant = granter.grant(grantType) + val grant = granter.grant(grantType, oauth2AccessTokenDTO) if (grant != null) { return grant } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index 50db57bf924..a6e8a76613f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -1,5 +1,7 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory class RefreshTokenGranter : AbstractTokenGranter(GRANT_TYPE) { @@ -8,13 +10,16 @@ class RefreshTokenGranter : AbstractTokenGranter(GRANT_TYPE) { private val logger = LoggerFactory.getLogger(RefreshTokenGranter::class.java) } - override fun getAccessToken(grantType: String): String { + override fun getAccessToken( + oauth2AccessTokenDTO: Oauth2AccessTokenDTO, + accessToken: String? + ): Oauth2AccessTokenVo { logger.info("refresh_token getAccessToken") //1.校验refresh_token是否为空 //2.清除跟该refresh_token授权码相关的access_token //3.校验refresh_token是否过期 //3.1 过期,清除refresh_token记录,则直接返回异常 //3.2 未过期,走主流程,此时accessToken - return super.getAccessToken(grantType) + return super.getAccessToken(oauth2AccessTokenDTO, accessToken) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt index d1f53c7e3a8..14850074340 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt @@ -1,5 +1,11 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo + interface TokenGranter { - fun grant(grantType: String): String? + fun grant( + grantType: String, + oauth2AccessTokenDTO: Oauth2AccessTokenDTO + ): Oauth2AccessTokenVo? } From a1a26b632cce3b31f59b051b62c1b679111b907d Mon Sep 17 00:00:00 2001 From: greysonfang Date: Mon, 24 Jul 2023 15:51:50 +0800 Subject: [PATCH 03/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/auth/pojo/Oauth2AccessTokenInfo.kt | 12 ++++++++++ .../auth/pojo/vo/Oauth2AccessTokenVo.kt | 2 +- .../service/oauth2/Oauth2EndpointService.kt | 1 - .../oauth2/grant/AbstractTokenGranter.kt | 23 +++++++++++++------ .../grant/AuthorizationCodeTokenGranter.kt | 6 ++--- .../grant/ClientCredentialsTokenGranter.kt | 7 +++--- .../oauth2/grant/RefreshTokenGranter.kt | 7 +++--- 7 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt new file mode 100644 index 00000000000..dab3a048f69 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt @@ -0,0 +1,12 @@ +package com.tencent.devops.auth.pojo + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("oauth2获取token中间处理态") +data class Oauth2AccessTokenInfo( + @ApiModelProperty("accessToken", required = true) + var accessToken: String? = null, + @ApiModelProperty("accessToken过期时间", required = true) + var expiredTime: Long? = null +) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AccessTokenVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AccessTokenVo.kt index bb95feaa9d0..c58d363c51f 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AccessTokenVo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AccessTokenVo.kt @@ -3,7 +3,7 @@ package com.tencent.devops.auth.pojo.vo import io.swagger.annotations.ApiModel import io.swagger.annotations.ApiModelProperty -@ApiModel("oauth2获取token返回报文体") +@ApiModel("oauth2获取token请求返回体") data class Oauth2AccessTokenVo( @ApiModelProperty("accessToken", required = true) val accessToken: String, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index db93700d1d3..7545f999e06 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -28,7 +28,6 @@ class Oauth2EndpointService constructor( oauth2AccessTokenDTO: Oauth2AccessTokenDTO ): Oauth2AccessTokenVo? { // 1、校验用户是否登录 - // 2、校验client_id和client_secret是否正确 val grantType = oauth2AccessTokenDTO.grantType return tokenGranter.grant(grantType, oauth2AccessTokenDTO) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index a53a1ec4916..3722409e608 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -1,10 +1,13 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory -abstract class AbstractTokenGranter(private val grantType: String) : TokenGranter { +abstract class AbstractTokenGranter( + private val grantType: String +) : TokenGranter { override fun grant( grantType: String, oauth2AccessTokenDTO: Oauth2AccessTokenDTO @@ -12,16 +15,18 @@ abstract class AbstractTokenGranter(private val grantType: String) : TokenGrante if (this.grantType != grantType) { return null } - //1.校验用户的授权类型是否合法 + + // 1、校验client_id和client_secret是否正确 + // 2、校验用户的授权类型是否合法 logger.info("AbstractTokenGranter grant") - return getAccessToken(oauth2AccessTokenDTO, null) + // getAccessToken() 獲取到Oauth2AccessTokenInfo + // 从入参中获取accessToken + return getAccessToken(oauth2AccessTokenDTO) } - open fun getAccessToken( - oauth2AccessTokenDTO: Oauth2AccessTokenDTO, - accessToken: String? + fun handleAccessToken( + Oauth2AccessTokenInfo: Oauth2AccessTokenInfo ): Oauth2AccessTokenVo { - logger.info("Default getAccessToken") // 从入参中获取accessToken. // 1、校验access_token是否为空 // 2.1 若为空,创建新的access_token并存储,返回access_token,过期时间, @@ -31,6 +36,10 @@ abstract class AbstractTokenGranter(private val grantType: String) : TokenGrante return Oauth2AccessTokenVo("accessToken", 1000) } + abstract fun getAccessToken(oauth2AccessTokenDTO: Oauth2AccessTokenDTO): Oauth2AccessTokenVo + + private fun createAccessToken() {} + companion object { private val logger = LoggerFactory.getLogger(AbstractTokenGranter::class.java) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index 4b22726ef3f..88ae30411bc 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -1,5 +1,6 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory @@ -12,8 +13,7 @@ class AuthorizationCodeTokenGranter : AbstractTokenGranter(GRANT_TYPE) { } override fun getAccessToken( - oauth2AccessTokenDTO: Oauth2AccessTokenDTO, - accessToken: String? + oauth2AccessTokenDTO: Oauth2AccessTokenDTO ): Oauth2AccessTokenVo { logger.info("authorization_code getAccessToken") // 1.获取授权码,判断授权是否为空 @@ -21,7 +21,7 @@ class AuthorizationCodeTokenGranter : AbstractTokenGranter(GRANT_TYPE) { // 3.判断授权码是否过期 // 4.若授权码没有问题,则直接消费授权码,授权码单次有效,直接数据库删除该授权码 // 5、根据appcode+username获取accessToken - val accessToken = super.getAccessToken(oauth2AccessTokenDTO, accessToken) + val accessToken = super.handleAccessToken(Oauth2AccessTokenInfo()) // 6、删除refreshToken,并创建新的refreshToken. return Oauth2AccessTokenVo("accessToken", 1000) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 8afc819eba7..777fdbf4684 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -1,5 +1,6 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory @@ -11,11 +12,11 @@ class ClientCredentialsTokenGranter : AbstractTokenGranter(GRANT_TYPE) { } override fun getAccessToken( - oauth2AccessTokenDTO: Oauth2AccessTokenDTO, - accessToken: String? + oauth2AccessTokenDTO: Oauth2AccessTokenDTO ): Oauth2AccessTokenVo { logger.info("client_credentials getAccessToken") // 1、根据appcode获取accessToken - return super.getAccessToken(oauth2AccessTokenDTO, accessToken) + val accessToken = super.handleAccessToken(Oauth2AccessTokenInfo()) + return Oauth2AccessTokenVo("accessToken", 1000) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index a6e8a76613f..adea8f70232 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -1,5 +1,6 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory @@ -11,8 +12,7 @@ class RefreshTokenGranter : AbstractTokenGranter(GRANT_TYPE) { } override fun getAccessToken( - oauth2AccessTokenDTO: Oauth2AccessTokenDTO, - accessToken: String? + oauth2AccessTokenDTO: Oauth2AccessTokenDTO ): Oauth2AccessTokenVo { logger.info("refresh_token getAccessToken") //1.校验refresh_token是否为空 @@ -20,6 +20,7 @@ class RefreshTokenGranter : AbstractTokenGranter(GRANT_TYPE) { //3.校验refresh_token是否过期 //3.1 过期,清除refresh_token记录,则直接返回异常 //3.2 未过期,走主流程,此时accessToken - return super.getAccessToken(oauth2AccessTokenDTO, accessToken) + val accessToken = super.handleAccessToken(Oauth2AccessTokenInfo()) + return Oauth2AccessTokenVo("accessToken", 1000) } } From f2d2ec870f8b7d9a5e4b3f2a1cfeaba449a606b8 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Mon, 24 Jul 2023 17:47:44 +0800 Subject: [PATCH 04/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/auth/service/oauth2/Oauth2Config.kt | 11 ++++++----- .../oauth2/grant/AuthorizationCodeTokenGranter.kt | 3 ++- .../oauth2/grant/ClientCredentialsTokenGranter.kt | 2 ++ .../auth/service/oauth2/grant/RefreshTokenGranter.kt | 2 ++ 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt index 1914c4780c1..28473b861c5 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -9,7 +9,11 @@ import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration -class Oauth2Config { +class Oauth2Config constructor( + private val clientCredentialsTokenGranter: ClientCredentialsTokenGranter, + private val authorizationCodeTokenGranter: AuthorizationCodeTokenGranter, + private val refreshTokenGranter: RefreshTokenGranter, +) { @Bean fun oauth2EndpointService(): Oauth2EndpointService { return Oauth2EndpointService(compositeTokenGranter()) @@ -22,12 +26,9 @@ class Oauth2Config { private fun getDefaultTokenGranters(): List { val tokenGranters = ArrayList() - val refreshTokenGranter = RefreshTokenGranter() - val clientCredentialsTokenGranter = ClientCredentialsTokenGranter() - val authorizationCodeTokenGranter = AuthorizationCodeTokenGranter() - tokenGranters.add(refreshTokenGranter) tokenGranters.add(clientCredentialsTokenGranter) tokenGranters.add(authorizationCodeTokenGranter) + tokenGranters.add(refreshTokenGranter) return tokenGranters } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index 88ae30411bc..639b94ab492 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -4,8 +4,9 @@ import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service - +@Service class AuthorizationCodeTokenGranter : AbstractTokenGranter(GRANT_TYPE) { companion object { private const val GRANT_TYPE = "authorization_code" diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 777fdbf4684..0f0f7ef328d 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -4,7 +4,9 @@ import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service +@Service class ClientCredentialsTokenGranter : AbstractTokenGranter(GRANT_TYPE) { companion object { private const val GRANT_TYPE = "client_credentials" diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index adea8f70232..9efe75a04fc 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -4,7 +4,9 @@ import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service +@Service class RefreshTokenGranter : AbstractTokenGranter(GRANT_TYPE) { companion object { private const val GRANT_TYPE = "refresh_token" From efb59e95975533cc5575c43063352802490b2283 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 25 Jul 2023 11:07:26 +0800 Subject: [PATCH 05/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/render_tpl | 6 +- .../devops/auth/constant/AuthMessageCode.kt | 6 ++ .../devops/auth/pojo/Oauth2AccessTokenInfo.kt | 4 +- .../auth/pojo/dto/Oauth2AccessTokenDTO.kt | 3 + .../auth/dao/AuthOauth2AccessTokenDao.kt | 77 ++++++++++++++++ .../auth/dao/AuthOauth2ClientDetailsDao.kt | 20 +++++ .../devops/auth/dao/AuthOauth2CodeDao.kt | 51 +++++++++++ .../auth/dao/AuthOauth2RefreshTokenDao.kt | 51 +++++++++++ .../auth/service/oauth2/ClientService.kt | 56 +++++++++++- .../service/oauth2/Oauth2EndpointService.kt | 45 +++++++++- .../oauth2/grant/AbstractTokenGranter.kt | 80 ++++++++++++++--- .../grant/AuthorizationCodeTokenGranter.kt | 89 ++++++++++++++++++- .../grant/ClientCredentialsTokenGranter.kt | 31 ++++++- .../oauth2/grant/RefreshTokenGranter.kt | 56 ++++++++++-- 14 files changed, 546 insertions(+), 29 deletions(-) create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2RefreshTokenDao.kt diff --git a/scripts/render_tpl b/scripts/render_tpl index c2b21aed29d..a44c6a7503a 100755 --- a/scripts/render_tpl +++ b/scripts/render_tpl @@ -1,5 +1,5 @@ #!/bin/bash - +# ./render_tpl -m ci ../support-files/templates/* # 渲染蓝鲸的__VAR_NUM__ 类似的模板,通过环境变量自动替换它 set -o nounset # Treat unset variables as an error @@ -13,7 +13,7 @@ sed_script=$(mktemp /tmp/XXXXXX.sed) usage () { echo "Usage: $0 [-c] [-n] [-E k=v, -E k=v] tpl_path ..." -} +} usage_and_exit () { usage @@ -34,7 +34,7 @@ target_file_path () { echo ${_target_file%.tpl} } -[[ $# -eq 0 ]] && usage_and_exit 1 +[[ $# -eq 0 ]] && usage_and_exit 1 declare -i DRY_RUN=0 CHECK=0 declare MODULE="" declare -a EXTRA_ENV=() diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt index 186058f588d..1f08f6fcd2f 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt @@ -110,4 +110,10 @@ object AuthMessageCode { const val ERROR_MIGRATE_AUTH_COMPARE_FAIL = "2121061" // 迁移项目{0}失败,权限策略对比失败 const val ERROR_CREATOR_NOT_EXIST = "2121062" // 创建人离职 const val ERROR_RESOURCE_CREATE_FAIL = "2121063" // 资源创建失败 + + const val ERROR_CLIENT_NOT_EXIST = "2121064" // 客户端{0}不存在 + const val INVALID_AUTHORIZATION_TYPE = "2121065" // 授权类型{0}不合法 + const val INVALID_REDIRECT_URI = "2121066" // 跳转链接{0}不合法 + const val INVALID_CLIENT_SECRET = "2121067" // 客户端{0}密钥不合法 + const val INVALID_AUTHORIZATION_CODE = "2121068" //授权码不合法 } diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt index dab3a048f69..2603bb9a73e 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt @@ -7,6 +7,8 @@ import io.swagger.annotations.ApiModelProperty data class Oauth2AccessTokenInfo( @ApiModelProperty("accessToken", required = true) var accessToken: String? = null, + @ApiModelProperty("refreshToken", required = true) + var refreshToken: String? = null, @ApiModelProperty("accessToken过期时间", required = true) - var expiredTime: Long? = null + var expiredTime: Int? = null ) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt index a1ea18fc89c..d5a88416a79 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt @@ -2,11 +2,14 @@ package com.tencent.devops.auth.pojo.dto import io.swagger.annotations.ApiModel import io.swagger.annotations.ApiModelProperty +import javax.print.attribute.standard.JobOriginatingUserName @ApiModel("oauth2获取token请求报文体") data class Oauth2AccessTokenDTO( @ApiModelProperty("客户端id", required = true) val clientId: String, + @ApiModelProperty("用户名称", required = true) + val userName: String = "", @ApiModelProperty("客户端密钥", required = true) val clientSecret: String, @ApiModelProperty("授权类型", required = true) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt new file mode 100644 index 00000000000..fe0aa1de31d --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt @@ -0,0 +1,77 @@ +package com.tencent.devops.auth.dao + +import com.tencent.devops.model.auth.tables.TAuthOauth2AccessToken +import com.tencent.devops.model.auth.tables.records.TAuthOauth2AccessTokenRecord +import org.jooq.DSLContext +import org.jooq.Result +import org.springframework.stereotype.Repository + +@Repository +class AuthOauth2AccessTokenDao { + fun get( + dslContext: DSLContext, + clientId: String, + userName: String? = null + ): TAuthOauth2AccessTokenRecord? { + return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { + dslContext.selectFrom(this).where( + CLIENT_ID.eq(clientId) + ).let { + if (userName != null) { + it.and(USER_NAME.eq(userName)) + } else { + it + } + }.fetchOne() + } + } + + fun delete( + dslContext: DSLContext, + accessToken: String + ): Int { + return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { + dslContext.deleteFrom(this) + .where(ACCESS_TOKEN.eq(accessToken)) + .execute() + } + } + + fun deleteByRefreshToken( + dslContext: DSLContext, + refreshToken: String + ): Int { + return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { + dslContext.deleteFrom(this) + .where(REFRESH_TOKEN.eq(refreshToken)) + .execute() + } + } + + @Suppress("LongParameterList") + fun create( + dslContext: DSLContext, + clientId: String, + userName: String, + accessToken: String, + refreshToken: String, + expiredTime: Int + ): Int { + return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { + dslContext.insertInto( + this, + CLIENT_ID, + USER_NAME, + ACCESS_TOKEN, + REFRESH_TOKEN, + EXPIRED_TIME, + ).values( + clientId, + userName, + accessToken, + refreshToken, + expiredTime + ).execute() + } + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt new file mode 100644 index 00000000000..818c0ebad9b --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt @@ -0,0 +1,20 @@ +package com.tencent.devops.auth.dao + +import com.tencent.devops.model.auth.tables.TAuthOauth2ClientDetails +import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord +import org.jooq.DSLContext +import org.springframework.stereotype.Repository + +@Repository +class AuthOauth2ClientDetailsDao { + fun get( + dslContext: DSLContext, + clientId: String + ): TAuthOauth2ClientDetailsRecord? { + return with(TAuthOauth2ClientDetails.T_AUTH_OAUTH2_CLIENT_DETAILS) { + dslContext.selectFrom(this).where( + CLIENT_ID.eq(clientId) + ) + }.fetchOne() + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt new file mode 100644 index 00000000000..6b3c5ed55f4 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt @@ -0,0 +1,51 @@ +package com.tencent.devops.auth.dao + +import com.tencent.devops.model.auth.tables.TAuthOauth2Code +import com.tencent.devops.model.auth.tables.records.TAuthOauth2CodeRecord +import org.jooq.DSLContext +import org.jooq.Result +import org.springframework.stereotype.Repository + +@Repository +class AuthOauth2CodeDao { + fun get( + dslContext: DSLContext, + code: String + ): TAuthOauth2CodeRecord? { + return with(TAuthOauth2Code.T_AUTH_OAUTH2_CODE) { + dslContext.selectFrom(this).where(CODE.eq(code)) + .fetchOne() + } + } + + fun create( + dslContext: DSLContext, + code: String, + clientId: String, + expiredTime: Int + ): Int { + return with(TAuthOauth2Code.T_AUTH_OAUTH2_CODE) { + dslContext.insertInto( + this, + CLIENT_ID, + CODE, + EXPIRED_TIME + ).values( + clientId, + code, + expiredTime + ).execute() + } + } + + fun delete( + dslContext: DSLContext, + code: String + ): Int { + return with(TAuthOauth2Code.T_AUTH_OAUTH2_CODE) { + dslContext.deleteFrom(this) + .where(CODE.eq(code)) + .execute() + } + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2RefreshTokenDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2RefreshTokenDao.kt new file mode 100644 index 00000000000..81dca072cc6 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2RefreshTokenDao.kt @@ -0,0 +1,51 @@ +package com.tencent.devops.auth.dao + +import com.tencent.devops.model.auth.tables.TAuthOauth2RefreshToken +import com.tencent.devops.model.auth.tables.records.TAuthOauth2RefreshTokenRecord +import org.jooq.DSLContext +import org.springframework.stereotype.Repository + +@Repository +class AuthOauth2RefreshTokenDao { + fun get( + dslContext: DSLContext, + refreshToken: String + ): TAuthOauth2RefreshTokenRecord? { + return with(TAuthOauth2RefreshToken.T_AUTH_OAUTH2_REFRESH_TOKEN) { + dslContext.selectFrom(this) + .where(REFRESH_TOKEN.eq(refreshToken)) + .fetchOne() + } + } + + fun delete( + dslContext: DSLContext, + refreshToken: String + ): Int { + return with(TAuthOauth2RefreshToken.T_AUTH_OAUTH2_REFRESH_TOKEN) { + dslContext.deleteFrom(this) + .where(REFRESH_TOKEN.eq(refreshToken)) + .execute() + } + } + + fun create( + dslContext: DSLContext, + refreshToken: String, + clientId: String, + expiredTime: Int + ): Int { + return with(TAuthOauth2RefreshToken.T_AUTH_OAUTH2_REFRESH_TOKEN) { + dslContext.insertInto( + this, + CLIENT_ID, + REFRESH_TOKEN, + EXPIRED_TIME + ).values( + clientId, + refreshToken, + expiredTime + ).execute() + } + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt index c71ede0b917..39739f4d87a 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt @@ -1,4 +1,58 @@ package com.tencent.devops.auth.service.oauth2 -class ClientService { +import com.tencent.devops.auth.constant.AuthMessageCode +import com.tencent.devops.auth.dao.AuthOauth2ClientDetailsDao +import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord +import org.jooq.DSLContext +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service + +@Service +class ClientService constructor( + private val dslContext: DSLContext, + private val authOauth2ClientDetailsDao: AuthOauth2ClientDetailsDao +) { + + companion object { + private val logger = LoggerFactory.getLogger(ClientService::class.java) + } + + fun getClientDetail(clientId: String): TAuthOauth2ClientDetailsRecord { + return authOauth2ClientDetailsDao.get( + dslContext = dslContext, + clientId = clientId + ) ?: throw ErrorCodeException( + errorCode = AuthMessageCode.ERROR_CLIENT_NOT_EXIST, + params = arrayOf(clientId), + defaultMessage = "the client $clientId not exists" + ) + } + + fun verifyClientInformation( + clientId: String, + redirectUri: String, + grantType: String, + clientDetail: TAuthOauth2ClientDetailsRecord, + ): Boolean { + val authorizedGrantTypes = clientDetail.authorizedGrantTypes.split(",") + if (!authorizedGrantTypes.contains(grantType)) { + logger.warn("The client($clientId) does not support the authorization code type") + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_AUTHORIZATION_TYPE, + params = arrayOf(clientId), + defaultMessage = "The client($clientId) does not support the authorization code type" + ) + } + // 4、校验redirectUri是否和数据库一致 + if (redirectUri != clientDetail.webServerRedirectUri) { + logger.warn("The redirectUri is invalid|$clientId|$redirectUri") + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_REDIRECT_URI, + params = arrayOf(redirectUri), + defaultMessage = "The redirectUri($redirectUri) is invalid" + ) + } + return true + } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 7545f999e06..717560442ab 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -1,26 +1,67 @@ package com.tencent.devops.auth.service.oauth2 +import com.tencent.devops.auth.constant.AuthMessageCode +import com.tencent.devops.auth.dao.AuthOauth2CodeDao import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.grant.TokenGranter +import com.tencent.devops.common.api.exception.ErrorCodeException +import org.jooq.DSLContext +import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service class Oauth2EndpointService constructor( - private val tokenGranter: TokenGranter + private val tokenGranter: TokenGranter, + private val clientService: ClientService, + private val authOauth2CodeDao: AuthOauth2CodeDao, + private val dslContext: DSLContext, ) { + companion object { + private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) + private const val AUTHORIZATION_CODE_TYPE = "authorization_code" + } + fun getAuthorizationCode( userId: String, clientId: String, redirectUri: String ): String { + logger.info("Oauth2EndpointService|getAuthorizationCode: $userId $clientId, $redirectUri") // 1、校验用户是否登录 // 2、校验clientId是否存在 + val clientDetail = clientService.getClientDetail(clientId = clientId) // 3、校验client是否为授权码模式 + val grantType = clientDetail.authorizedGrantTypes.split(",") + if (!grantType.contains(AUTHORIZATION_CODE_TYPE)) { + logger.warn("The client($clientId) does not support the authorization code type") + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_AUTHORIZATION_TYPE, + params = arrayOf(clientId), + defaultMessage = "The client($clientId) does not support the authorization code type" + ) + } // 4、校验redirectUri是否和数据库一致 + if (redirectUri != clientDetail.webServerRedirectUri) { + logger.warn("The redirectUri is invalid|$clientId|$redirectUri") + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_REDIRECT_URI, + params = arrayOf(redirectUri), + defaultMessage = "The redirectUri($redirectUri) is invalid" + ) + } // 5、生成授权码并存储数据库,授权码有效期为5分钟 + // todo + val code = "authorizationCode" + authOauth2CodeDao.create( + dslContext = dslContext, + code = code, + clientId = clientId, + //todo + expiredTime = 111 + ) // 6、返回授权码 - return "authorizationCode" + return code } fun getAccessToken( diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index 3722409e608..33c419e4d8f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -1,12 +1,20 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.constant.AuthMessageCode +import com.tencent.devops.auth.dao.AuthOauth2AccessTokenDao import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.service.oauth2.ClientService +import com.tencent.devops.common.api.exception.ErrorCodeException +import org.jooq.DSLContext import org.slf4j.LoggerFactory abstract class AbstractTokenGranter( - private val grantType: String + private val grantType: String, + private val clientService: ClientService, + private val authOauth2AccessTokenDao: AuthOauth2AccessTokenDao, + private val dslContext: DSLContext ) : TokenGranter { override fun grant( grantType: String, @@ -15,30 +23,82 @@ abstract class AbstractTokenGranter( if (this.grantType != grantType) { return null } - // 1、校验client_id和client_secret是否正确 + val clientId = oauth2AccessTokenDTO.clientId + val clientDetail = clientService.getClientDetail(oauth2AccessTokenDTO.clientId) + if (oauth2AccessTokenDTO.clientSecret != clientDetail.clientSecret) { + logger.warn("The client($clientId) secret is invalid") + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_CLIENT_SECRET, + params = arrayOf(clientId), + defaultMessage = "The client($clientId) secret is invalid" + ) + } // 2、校验用户的授权类型是否合法 logger.info("AbstractTokenGranter grant") - // getAccessToken() 獲取到Oauth2AccessTokenInfo - // 从入参中获取accessToken + if (grantType != clientDetail.authorizedGrantTypes) { + logger.warn("The client($clientId) grant type is invalid") + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_AUTHORIZATION_TYPE, + params = arrayOf(clientId), + defaultMessage = "The client($clientId) grant type is invalid" + ) + } return getAccessToken(oauth2AccessTokenDTO) } fun handleAccessToken( - Oauth2AccessTokenInfo: Oauth2AccessTokenInfo + oauth2AccessTokenDTO: Oauth2AccessTokenDTO, + oauth2AccessTokenInfo: Oauth2AccessTokenInfo ): Oauth2AccessTokenVo { // 从入参中获取accessToken. // 1、校验access_token是否为空 + val accessToken = oauth2AccessTokenInfo.accessToken + val refreshToken = oauth2AccessTokenInfo.refreshToken + val clientId = oauth2AccessTokenDTO.clientId // 2.1 若为空,创建新的access_token并存储,返回access_token,过期时间, - // 3.1 若不为空,校验access_token是否过期 - // 3.2 若过期,清除access_token记录,创建新的access_token并存储,返回access_token,过期时间。 - // 3.3 若未过期,返回access_token,过期时间 - return Oauth2AccessTokenVo("accessToken", 1000) + return if (accessToken == null) { + authOauth2AccessTokenDao.create( + dslContext = dslContext, + clientId = clientId, + userName = oauth2AccessTokenDTO.userName, + // todo + accessToken = "accessToken", + refreshToken = "", + expiredTime = 1000 + ) + Oauth2AccessTokenVo("accessToken", 1000, refreshToken) + } else { + // 3.1 若不为空,校验access_token是否过期 + if (oauth2AccessTokenInfo.expiredTime!!.toLong() > System.currentTimeMillis()) { + // 3.2 若未过期,返回access_token,过期时间 + Oauth2AccessTokenVo(accessToken, 1000, refreshToken) + } else { + // 3.3 若过期,清除access_token记录,创建新的access_token并存储,返回access_token,过期时间。 + authOauth2AccessTokenDao.delete( + dslContext = dslContext, + accessToken = accessToken + ) + authOauth2AccessTokenDao.create( + dslContext = dslContext, + clientId = clientId, + userName = oauth2AccessTokenDTO.userName, + // todo + accessToken = "accessToken", + refreshToken = "", + expiredTime = 1000 + ) + Oauth2AccessTokenVo("accessToken", 1000, refreshToken) + } + } } abstract fun getAccessToken(oauth2AccessTokenDTO: Oauth2AccessTokenDTO): Oauth2AccessTokenVo - private fun createAccessToken() {} + private fun createAccessToken( + + ) { + } companion object { private val logger = LoggerFactory.getLogger(AbstractTokenGranter::class.java) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index 639b94ab492..74d3e2b11a1 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -1,13 +1,31 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.constant.AuthMessageCode.INVALID_AUTHORIZATION_CODE +import com.tencent.devops.auth.dao.AuthOauth2AccessTokenDao +import com.tencent.devops.auth.dao.AuthOauth2CodeDao +import com.tencent.devops.auth.dao.AuthOauth2RefreshTokenDao import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.service.oauth2.ClientService +import com.tencent.devops.common.api.exception.ErrorCodeException +import org.jooq.DSLContext import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service -class AuthorizationCodeTokenGranter : AbstractTokenGranter(GRANT_TYPE) { +class AuthorizationCodeTokenGranter constructor( + private val clientService: ClientService, + private val authOauth2RefreshTokenDao: AuthOauth2RefreshTokenDao, + private val authOauth2AccessTokenDao: AuthOauth2AccessTokenDao, + private val authOauth2CodeDao: AuthOauth2CodeDao, + private val dslContext: DSLContext +) : AbstractTokenGranter( + grantType = GRANT_TYPE, + clientService = clientService, + authOauth2AccessTokenDao = authOauth2AccessTokenDao, + dslContext = dslContext +) { companion object { private const val GRANT_TYPE = "authorization_code" private val logger = LoggerFactory.getLogger(AuthorizationCodeTokenGranter::class.java) @@ -17,13 +35,76 @@ class AuthorizationCodeTokenGranter : AbstractTokenGranter(GRANT_TYPE) { oauth2AccessTokenDTO: Oauth2AccessTokenDTO ): Oauth2AccessTokenVo { logger.info("authorization_code getAccessToken") + val clientId = oauth2AccessTokenDTO.clientId + val code = oauth2AccessTokenDTO.code + ?: throw ErrorCodeException( + errorCode = INVALID_AUTHORIZATION_CODE, + defaultMessage = "The authorization code must be provided" + ) // 1.获取授权码,判断授权是否为空 + val codeDetails = authOauth2CodeDao.get( + dslContext = dslContext, + code = code + ) ?: throw ErrorCodeException( + errorCode = INVALID_AUTHORIZATION_CODE, + defaultMessage = "The authorization code invalid" + ) // 2.判断授权码和客户端id是否对应的上 + if (codeDetails.clientId == clientId) { + throw ErrorCodeException( + errorCode = INVALID_AUTHORIZATION_CODE, + defaultMessage = "The authorization code does not belong to the client($clientId)" + ) + } // 3.判断授权码是否过期 + if (codeDetails.expiredTime < System.currentTimeMillis()) { + throw ErrorCodeException( + errorCode = INVALID_AUTHORIZATION_CODE, + defaultMessage = "The authorization code expired" + ) + } // 4.若授权码没有问题,则直接消费授权码,授权码单次有效,直接数据库删除该授权码 + authOauth2CodeDao.delete( + dslContext = dslContext, + code = code + ) // 5、根据appcode+username获取accessToken - val accessToken = super.handleAccessToken(Oauth2AccessTokenInfo()) - // 6、删除refreshToken,并创建新的refreshToken. - return Oauth2AccessTokenVo("accessToken", 1000) + val accessTokenRecord = authOauth2AccessTokenDao.get( + dslContext = dslContext, + clientId = clientId, + userName = oauth2AccessTokenDTO.userName + ) + val refreshToken = if (accessTokenRecord != null) { + val refreshTokenRecord = authOauth2RefreshTokenDao.get( + dslContext = dslContext, + refreshToken = accessTokenRecord.refreshToken, + ) + if (refreshTokenRecord!!.expiredTime > System.currentTimeMillis()) { + refreshTokenRecord.refreshToken + } else { + authOauth2RefreshTokenDao.delete( + dslContext = dslContext, + refreshToken = accessTokenRecord.refreshToken + ) + authOauth2RefreshTokenDao.create( + dslContext = dslContext, + refreshToken = "refreshToken", + clientId = clientId, + expiredTime = 1000 + ) + "refreshToken" + } + } else { + "refreshToken" + } + + return super.handleAccessToken( + oauth2AccessTokenDTO, + Oauth2AccessTokenInfo( + accessToken = accessTokenRecord?.accessToken, + refreshToken = refreshToken, + expiredTime = accessTokenRecord?.expiredTime + ) + ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 0f0f7ef328d..8a23bc9863f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -1,13 +1,29 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.dao.AuthOauth2AccessTokenDao +import com.tencent.devops.auth.dao.AuthOauth2CodeDao +import com.tencent.devops.auth.dao.AuthOauth2RefreshTokenDao import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.service.oauth2.ClientService +import org.jooq.DSLContext import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service -class ClientCredentialsTokenGranter : AbstractTokenGranter(GRANT_TYPE) { +class ClientCredentialsTokenGranter constructor( + private val clientService: ClientService, + private val authOauth2RefreshTokenDao: AuthOauth2RefreshTokenDao, + private val authOauth2AccessTokenDao: AuthOauth2AccessTokenDao, + private val authOauth2CodeDao: AuthOauth2CodeDao, + private val dslContext: DSLContext +) : AbstractTokenGranter( + grantType = GRANT_TYPE, + clientService = clientService, + authOauth2AccessTokenDao = authOauth2AccessTokenDao, + dslContext = dslContext +) { companion object { private const val GRANT_TYPE = "client_credentials" private val logger = LoggerFactory.getLogger(ClientCredentialsTokenGranter::class.java) @@ -18,7 +34,16 @@ class ClientCredentialsTokenGranter : AbstractTokenGranter(GRANT_TYPE) { ): Oauth2AccessTokenVo { logger.info("client_credentials getAccessToken") // 1、根据appcode获取accessToken - val accessToken = super.handleAccessToken(Oauth2AccessTokenInfo()) - return Oauth2AccessTokenVo("accessToken", 1000) + val accessTokenRecord = authOauth2AccessTokenDao.get( + dslContext = dslContext, + clientId = oauth2AccessTokenDTO.clientId + ) + return super.handleAccessToken( + oauth2AccessTokenDTO, + Oauth2AccessTokenInfo( + accessToken = accessTokenRecord?.accessToken, + expiredTime = accessTokenRecord?.expiredTime + ) + ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index 9efe75a04fc..e802fa0cdae 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -1,13 +1,29 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.dao.AuthOauth2AccessTokenDao +import com.tencent.devops.auth.dao.AuthOauth2CodeDao +import com.tencent.devops.auth.dao.AuthOauth2RefreshTokenDao import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.service.oauth2.ClientService +import com.tencent.devops.common.api.exception.ErrorCodeException +import org.jooq.DSLContext import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service -class RefreshTokenGranter : AbstractTokenGranter(GRANT_TYPE) { +class RefreshTokenGranter( + private val clientService: ClientService, + private val authOauth2RefreshTokenDao: AuthOauth2RefreshTokenDao, + private val authOauth2AccessTokenDao: AuthOauth2AccessTokenDao, + private val dslContext: DSLContext +) : AbstractTokenGranter( + grantType = GRANT_TYPE, + clientService = clientService, + authOauth2AccessTokenDao = authOauth2AccessTokenDao, + dslContext = dslContext +) { companion object { private const val GRANT_TYPE = "refresh_token" private val logger = LoggerFactory.getLogger(RefreshTokenGranter::class.java) @@ -18,11 +34,41 @@ class RefreshTokenGranter : AbstractTokenGranter(GRANT_TYPE) { ): Oauth2AccessTokenVo { logger.info("refresh_token getAccessToken") //1.校验refresh_token是否为空 + if (oauth2AccessTokenDTO.refreshToken == null) { + throw ErrorCodeException( + errorCode = "111", + defaultMessage = "The authorization code invalid" + ) + } + // 2.校验refresh_token是否存在 + val refreshTokenRecord = authOauth2RefreshTokenDao.get( + dslContext = dslContext, + refreshToken = oauth2AccessTokenDTO.refreshToken!! + ) ?: throw ErrorCodeException( + errorCode = "111", + defaultMessage = "The authorization code invalid" + ) + if (refreshTokenRecord.clientId != oauth2AccessTokenDTO.clientId) { + throw ErrorCodeException( + errorCode = "111", + defaultMessage = "The authorization code invalid" + ) + } //2.清除跟该refresh_token授权码相关的access_token + authOauth2AccessTokenDao.deleteByRefreshToken( + dslContext = dslContext, + refreshToken = oauth2AccessTokenDTO.refreshToken!! + ) //3.校验refresh_token是否过期 - //3.1 过期,清除refresh_token记录,则直接返回异常 - //3.2 未过期,走主流程,此时accessToken - val accessToken = super.handleAccessToken(Oauth2AccessTokenInfo()) - return Oauth2AccessTokenVo("accessToken", 1000) + if (refreshTokenRecord.expiredTime < System.currentTimeMillis()) { + throw ErrorCodeException( + errorCode = "111", + defaultMessage = "The authorization code invalid" + ) + } else { + return super.handleAccessToken( + oauth2AccessTokenDTO, Oauth2AccessTokenInfo() + ) + } } } From 6451375af02b304aa02a072c9bf0c9bbf84d4a33 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 25 Jul 2023 18:01:01 +0800 Subject: [PATCH 06/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/oauth2/Oauth2EndpointResource.kt | 7 +- .../devops/auth/constant/AuthMessageCode.kt | 5 +- .../devops/auth/pojo/Oauth2AccessTokenInfo.kt | 14 -- .../auth/pojo/Oauth2AccessTokenRequest.kt | 20 +++ .../auth/pojo/dto/Oauth2AccessTokenDTO.kt | 21 +-- .../auth/dao/AuthOauth2AccessTokenDao.kt | 8 +- .../devops/auth/dao/AuthOauth2CodeDao.kt | 4 +- .../resources/Oauth2EndpointResourceImpl.kt | 24 +++- .../oauth2/Oauth2AccessTokenService.kt | 54 ++++++++ ...lientService.kt => Oauth2ClientService.kt} | 22 ++- .../auth/service/oauth2/Oauth2CodeService.kt | 56 ++++++++ .../auth/service/oauth2/Oauth2Config.kt | 14 +- .../service/oauth2/Oauth2EndpointService.kt | 52 +++---- .../oauth2/Oauth2RefreshTokenService.kt | 44 ++++++ .../oauth2/grant/AbstractTokenGranter.kt | 130 ++++++++---------- .../grant/AuthorizationCodeTokenGranter.kt | 125 +++++++---------- .../grant/ClientCredentialsTokenGranter.kt | 37 +++-- .../oauth2/grant/CompositeTokenGranter.kt | 6 +- .../oauth2/grant/RefreshTokenGranter.kt | 70 +++++----- .../auth/service/oauth2/grant/TokenGranter.kt | 4 +- .../auth/service/AuthDeptServiceImplTest.kt | 6 + 21 files changed, 421 insertions(+), 302 deletions(-) delete mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt rename src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/{ClientService.kt => Oauth2ClientService.kt} (70%) create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt index 022c1948d5d..740b188aac5 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt @@ -1,6 +1,6 @@ package com.tencent.devops.auth.api.oauth2 -import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID import io.swagger.annotations.Api @@ -13,6 +13,7 @@ import javax.ws.rs.Path import javax.ws.rs.Produces import javax.ws.rs.QueryParam import javax.ws.rs.core.MediaType +import com.tencent.devops.common.api.pojo.Result @Api(tags = ["OAUTH2_ENDPOINT"], description = "oauth2相关") @Path("/oauth2/endpoint") @@ -43,6 +44,6 @@ interface Oauth2EndpointResource { @ApiParam("待校验用户ID", required = true) userId: String, @ApiParam("oauth2获取token请求报文体", required = true) - oauth2AccessTokenDTO: Oauth2AccessTokenDTO - ): Result + accessTokenRequest: Oauth2AccessTokenRequest + ): Result } diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt index 1f08f6fcd2f..86054c47bc0 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt @@ -115,5 +115,8 @@ object AuthMessageCode { const val INVALID_AUTHORIZATION_TYPE = "2121065" // 授权类型{0}不合法 const val INVALID_REDIRECT_URI = "2121066" // 跳转链接{0}不合法 const val INVALID_CLIENT_SECRET = "2121067" // 客户端{0}密钥不合法 - const val INVALID_AUTHORIZATION_CODE = "2121068" //授权码不合法 + const val INVALID_AUTHORIZATION_CODE = "2121068" // 授权码不合法 + const val ERROR_REFRESH_TOKEN_NOT_FOUND = "2121069" // refresh_token不能为空 + const val INVALID_REFRESH_TOKEN = "2121070" // refresh_token不合法 + const val ERROR_REFRESH_TOKEN_EXPIRED = "2121071" // refresh token已过期 } diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt deleted file mode 100644 index 2603bb9a73e..00000000000 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenInfo.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.tencent.devops.auth.pojo - -import io.swagger.annotations.ApiModel -import io.swagger.annotations.ApiModelProperty - -@ApiModel("oauth2获取token中间处理态") -data class Oauth2AccessTokenInfo( - @ApiModelProperty("accessToken", required = true) - var accessToken: String? = null, - @ApiModelProperty("refreshToken", required = true) - var refreshToken: String? = null, - @ApiModelProperty("accessToken过期时间", required = true) - var expiredTime: Int? = null -) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt new file mode 100644 index 00000000000..948668333c6 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt @@ -0,0 +1,20 @@ +package com.tencent.devops.auth.pojo + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("oauth2获取token请求报文体") +data class Oauth2AccessTokenRequest( + @ApiModelProperty("客户端id", required = true) + val clientId: String, + @ApiModelProperty("用户名称", required = true) + val userName: String = "", + @ApiModelProperty("客户端密钥", required = true) + val clientSecret: String, + @ApiModelProperty("授权类型", required = true) + val grantType: String, + @ApiModelProperty("授权码,用于授权码模式", required = false) + val code: String? = null, + @ApiModelProperty("refreshToken,用于刷新授权码模式", required = false) + val refreshToken: String? = null +) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt index d5a88416a79..4d77e1079d4 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt @@ -2,20 +2,13 @@ package com.tencent.devops.auth.pojo.dto import io.swagger.annotations.ApiModel import io.swagger.annotations.ApiModelProperty -import javax.print.attribute.standard.JobOriginatingUserName -@ApiModel("oauth2获取token请求报文体") +@ApiModel("oauth2获取token中间处理态") data class Oauth2AccessTokenDTO( - @ApiModelProperty("客户端id", required = true) - val clientId: String, - @ApiModelProperty("用户名称", required = true) - val userName: String = "", - @ApiModelProperty("客户端密钥", required = true) - val clientSecret: String, - @ApiModelProperty("授权类型", required = true) - val grantType: String, - @ApiModelProperty("授权码,用于授权码模式", required = false) - val code: String? = null, - @ApiModelProperty("refreshToken,用于刷新授权码模式", required = false) - val refreshToken: String? = null + @ApiModelProperty("accessToken", required = true) + var accessToken: String? = null, + @ApiModelProperty("refreshToken", required = true) + var refreshToken: String? = null, + @ApiModelProperty("accessToken过期时间", required = true) + var expiredTime: Int? = null ) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt index fe0aa1de31d..a0f2c64731b 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt @@ -52,10 +52,10 @@ class AuthOauth2AccessTokenDao { fun create( dslContext: DSLContext, clientId: String, - userName: String, + userName: String?, accessToken: String, - refreshToken: String, - expiredTime: Int + refreshToken: String? = null, + expiredTime: Long ): Int { return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { dslContext.insertInto( @@ -70,7 +70,7 @@ class AuthOauth2AccessTokenDao { userName, accessToken, refreshToken, - expiredTime + expiredTime.toInt() ).execute() } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt index 6b3c5ed55f4..a3802777b3d 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt @@ -22,7 +22,7 @@ class AuthOauth2CodeDao { dslContext: DSLContext, code: String, clientId: String, - expiredTime: Int + expiredTime: Long ): Int { return with(TAuthOauth2Code.T_AUTH_OAUTH2_CODE) { dslContext.insertInto( @@ -33,7 +33,7 @@ class AuthOauth2CodeDao { ).values( clientId, code, - expiredTime + expiredTime.toInt() ).execute() } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt index 92fb3df73ee..944bc2533fc 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt @@ -1,27 +1,39 @@ package com.tencent.devops.auth.resources import com.tencent.devops.auth.api.oauth2.Oauth2EndpointResource -import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.Oauth2EndpointService +import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.web.RestResource @RestResource class Oauth2EndpointResourceImpl constructor( - oauth2EndpointService: Oauth2EndpointService + private val endpointService: Oauth2EndpointService ) : Oauth2EndpointResource { override fun getAuthorizationCode( userId: String, clientId: String, redirectUri: String ): Result { - TODO("Not yet implemented") + return Result( + endpointService.getAuthorizationCode( + userId = userId, + clientId = clientId, + redirectUri = redirectUri + ) + ) } override fun getAccessToken( userId: String, - oauth2AccessTokenDTO: Oauth2AccessTokenDTO - ): Result { - TODO("Not yet implemented") + accessTokenRequest: Oauth2AccessTokenRequest + ): Result { + return Result( + endpointService.getAccessToken( + userId = userId, + accessTokenRequest = accessTokenRequest + ) + ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt new file mode 100644 index 00000000000..10ffbe51682 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt @@ -0,0 +1,54 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.dao.AuthOauth2AccessTokenDao +import com.tencent.devops.model.auth.tables.records.TAuthOauth2AccessTokenRecord +import org.jooq.DSLContext +import org.springframework.stereotype.Service + +@Service +class Oauth2AccessTokenService constructor( + private val oauth2AccessTokenDao: AuthOauth2AccessTokenDao, + private val dslContext: DSLContext +) { + fun get( + clientId: String, + userName: String? = null + ): TAuthOauth2AccessTokenRecord? { + return oauth2AccessTokenDao.get( + dslContext = dslContext, + clientId = clientId, + userName = userName + ) + } + + fun create( + clientId: String, + userName: String?, + accessToken: String, + refreshToken: String?, + expiredTime: Long + ) { + oauth2AccessTokenDao.create( + dslContext = dslContext, + clientId = clientId, + userName = userName, + accessToken = accessToken, + refreshToken = refreshToken, + expiredTime = expiredTime + ) + } + + fun delete(accessToken: String) { + oauth2AccessTokenDao.delete( + dslContext = dslContext, + accessToken = accessToken + ) + } + + fun deleteByRefreshToken(refreshToken: String) { + oauth2AccessTokenDao.deleteByRefreshToken( + dslContext = dslContext, + refreshToken = refreshToken + ) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt similarity index 70% rename from src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt rename to src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt index 39739f4d87a..d27f8bf6320 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt @@ -9,13 +9,13 @@ import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service -class ClientService constructor( +class Oauth2ClientService constructor( private val dslContext: DSLContext, private val authOauth2ClientDetailsDao: AuthOauth2ClientDetailsDao ) { companion object { - private val logger = LoggerFactory.getLogger(ClientService::class.java) + private val logger = LoggerFactory.getLogger(Oauth2ClientService::class.java) } fun getClientDetail(clientId: String): TAuthOauth2ClientDetailsRecord { @@ -31,12 +31,13 @@ class ClientService constructor( fun verifyClientInformation( clientId: String, - redirectUri: String, - grantType: String, clientDetail: TAuthOauth2ClientDetailsRecord, + clientSecret: String? = null, + redirectUri: String? = null, + grantType: String? = null, ): Boolean { val authorizedGrantTypes = clientDetail.authorizedGrantTypes.split(",") - if (!authorizedGrantTypes.contains(grantType)) { + if (grantType != null && !authorizedGrantTypes.contains(grantType)) { logger.warn("The client($clientId) does not support the authorization code type") throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_AUTHORIZATION_TYPE, @@ -44,8 +45,7 @@ class ClientService constructor( defaultMessage = "The client($clientId) does not support the authorization code type" ) } - // 4、校验redirectUri是否和数据库一致 - if (redirectUri != clientDetail.webServerRedirectUri) { + if (redirectUri != null && redirectUri != clientDetail.webServerRedirectUri) { logger.warn("The redirectUri is invalid|$clientId|$redirectUri") throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_REDIRECT_URI, @@ -53,6 +53,14 @@ class ClientService constructor( defaultMessage = "The redirectUri($redirectUri) is invalid" ) } + if (clientSecret != null && clientSecret != clientDetail.clientSecret) { + logger.warn("The client($clientId) secret is invalid") + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_CLIENT_SECRET, + params = arrayOf(clientId), + defaultMessage = "The client($clientId) secret is invalid" + ) + } return true } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt new file mode 100644 index 00000000000..e4b3c5048ef --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt @@ -0,0 +1,56 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.constant.AuthMessageCode +import com.tencent.devops.auth.dao.AuthOauth2CodeDao +import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.model.auth.tables.records.TAuthOauth2CodeRecord +import org.jooq.DSLContext +import org.springframework.stereotype.Service + +@Service +class Oauth2CodeService constructor( + private val authOauth2CodeDao: AuthOauth2CodeDao, + private val dslContext: DSLContext +) { + fun get( + code: String? + ): TAuthOauth2CodeRecord { + code ?: throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_AUTHORIZATION_CODE, + defaultMessage = "The authorization code must be provided" + ) + return authOauth2CodeDao.get( + dslContext = dslContext, + code = code + ) ?: throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_AUTHORIZATION_CODE, + defaultMessage = "The authorization code invalid" + ) + } + + fun consume(code: String) { + authOauth2CodeDao.delete( + dslContext = dslContext, + code = code + ) + } + + fun verifyCode( + clientId: String, + codeDetails: TAuthOauth2CodeRecord + ): Boolean { + if (codeDetails.clientId != clientId) { + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_AUTHORIZATION_CODE, + defaultMessage = "The authorization code does not belong to the client($clientId)" + ) + } + if (codeDetails.expiredTime < System.currentTimeMillis()) { + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_AUTHORIZATION_CODE, + defaultMessage = "The authorization code expired" + ) + } + return true + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt index 28473b861c5..1ff76477655 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -1,22 +1,32 @@ package com.tencent.devops.auth.service.oauth2 +import com.tencent.devops.auth.dao.AuthOauth2CodeDao import com.tencent.devops.auth.service.oauth2.grant.AuthorizationCodeTokenGranter import com.tencent.devops.auth.service.oauth2.grant.ClientCredentialsTokenGranter import com.tencent.devops.auth.service.oauth2.grant.CompositeTokenGranter import com.tencent.devops.auth.service.oauth2.grant.RefreshTokenGranter import com.tencent.devops.auth.service.oauth2.grant.TokenGranter +import org.jooq.DSLContext import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class Oauth2Config constructor( + private val oauth2ClientService: Oauth2ClientService, + private val authOauth2CodeDao: AuthOauth2CodeDao, + private val dslContext: DSLContext, private val clientCredentialsTokenGranter: ClientCredentialsTokenGranter, private val authorizationCodeTokenGranter: AuthorizationCodeTokenGranter, - private val refreshTokenGranter: RefreshTokenGranter, + private val refreshTokenGranter: RefreshTokenGranter ) { @Bean fun oauth2EndpointService(): Oauth2EndpointService { - return Oauth2EndpointService(compositeTokenGranter()) + return Oauth2EndpointService( + tokenGranter = compositeTokenGranter(), + clientService = oauth2ClientService, + authOauth2CodeDao = authOauth2CodeDao, + dslContext = dslContext + ) } @Bean diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 717560442ab..882db4f9096 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -1,25 +1,25 @@ package com.tencent.devops.auth.service.oauth2 -import com.tencent.devops.auth.constant.AuthMessageCode import com.tencent.devops.auth.dao.AuthOauth2CodeDao -import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.grant.TokenGranter -import com.tencent.devops.common.api.exception.ErrorCodeException import org.jooq.DSLContext import org.slf4j.LoggerFactory import org.springframework.stereotype.Service +import java.util.UUID @Service class Oauth2EndpointService constructor( private val tokenGranter: TokenGranter, - private val clientService: ClientService, + private val oauth2ClientService: Oauth2ClientService, private val authOauth2CodeDao: AuthOauth2CodeDao, private val dslContext: DSLContext, ) { companion object { private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) private const val AUTHORIZATION_CODE_TYPE = "authorization_code" + private const val codeValiditySeconds = 5 * 60 * 1000L } fun getAuthorizationCode( @@ -30,46 +30,32 @@ class Oauth2EndpointService constructor( logger.info("Oauth2EndpointService|getAuthorizationCode: $userId $clientId, $redirectUri") // 1、校验用户是否登录 // 2、校验clientId是否存在 - val clientDetail = clientService.getClientDetail(clientId = clientId) - // 3、校验client是否为授权码模式 - val grantType = clientDetail.authorizedGrantTypes.split(",") - if (!grantType.contains(AUTHORIZATION_CODE_TYPE)) { - logger.warn("The client($clientId) does not support the authorization code type") - throw ErrorCodeException( - errorCode = AuthMessageCode.INVALID_AUTHORIZATION_TYPE, - params = arrayOf(clientId), - defaultMessage = "The client($clientId) does not support the authorization code type" - ) - } - // 4、校验redirectUri是否和数据库一致 - if (redirectUri != clientDetail.webServerRedirectUri) { - logger.warn("The redirectUri is invalid|$clientId|$redirectUri") - throw ErrorCodeException( - errorCode = AuthMessageCode.INVALID_REDIRECT_URI, - params = arrayOf(redirectUri), - defaultMessage = "The redirectUri($redirectUri) is invalid" - ) - } - // 5、生成授权码并存储数据库,授权码有效期为5分钟 - // todo - val code = "authorizationCode" + val clientDetail = oauth2ClientService.getClientDetail(clientId = clientId) + // 3、校验客户端信息是否正确 + oauth2ClientService.verifyClientInformation( + clientId = clientId, + redirectUri = redirectUri, + grantType = AUTHORIZATION_CODE_TYPE, + clientDetail = clientDetail + ) + // 4、生成授权码并存储数据库,授权码有效期为5分钟 + val code = UUID.randomUUID().toString() authOauth2CodeDao.create( dslContext = dslContext, code = code, clientId = clientId, - //todo - expiredTime = 111 + expiredTime = System.currentTimeMillis() + codeValiditySeconds ) - // 6、返回授权码 + // 5、返回授权码 return code } fun getAccessToken( userId: String, - oauth2AccessTokenDTO: Oauth2AccessTokenDTO + accessTokenRequest: Oauth2AccessTokenRequest ): Oauth2AccessTokenVo? { // 1、校验用户是否登录 - val grantType = oauth2AccessTokenDTO.grantType - return tokenGranter.grant(grantType, oauth2AccessTokenDTO) + val grantType = accessTokenRequest.grantType + return tokenGranter.grant(grantType, accessTokenRequest) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt new file mode 100644 index 00000000000..c55beb07186 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt @@ -0,0 +1,44 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.constant.AuthMessageCode.INVALID_REFRESH_TOKEN +import com.tencent.devops.auth.dao.AuthOauth2RefreshTokenDao +import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.model.auth.tables.records.TAuthOauth2RefreshTokenRecord +import org.jooq.DSLContext +import org.springframework.stereotype.Service + +@Service +class Oauth2RefreshTokenService constructor( + private val authOauth2RefreshTokenDao: AuthOauth2RefreshTokenDao, + private val dslContext: DSLContext +) { + fun get(refreshToken: String): TAuthOauth2RefreshTokenRecord? { + return authOauth2RefreshTokenDao.get( + dslContext = dslContext, + refreshToken = refreshToken + ) ?: throw ErrorCodeException( + errorCode = INVALID_REFRESH_TOKEN, + defaultMessage = "The authorization code invalid" + ) + } + + fun delete(refreshToken: String) { + authOauth2RefreshTokenDao.delete( + dslContext = dslContext, + refreshToken = refreshToken + ) + } + + fun create( + refreshToken: String, + clientId: String, + expiredTime: Long + ) { + authOauth2RefreshTokenDao.create( + dslContext = dslContext, + refreshToken = refreshToken, + clientId = clientId, + expiredTime = expiredTime.toInt() + ) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index 33c419e4d8f..e45e59d4d0f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -1,104 +1,82 @@ package com.tencent.devops.auth.service.oauth2.grant -import com.tencent.devops.auth.constant.AuthMessageCode -import com.tencent.devops.auth.dao.AuthOauth2AccessTokenDao -import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo -import com.tencent.devops.auth.service.oauth2.ClientService -import com.tencent.devops.common.api.exception.ErrorCodeException -import org.jooq.DSLContext +import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService +import com.tencent.devops.auth.service.oauth2.Oauth2ClientService +import com.tencent.devops.common.api.util.UUIDUtil +import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory abstract class AbstractTokenGranter( private val grantType: String, - private val clientService: ClientService, - private val authOauth2AccessTokenDao: AuthOauth2AccessTokenDao, - private val dslContext: DSLContext + private val oauth2ClientService: Oauth2ClientService, + private val accessTokenService: Oauth2AccessTokenService, ) : TokenGranter { override fun grant( grantType: String, - oauth2AccessTokenDTO: Oauth2AccessTokenDTO + accessTokenRequest: Oauth2AccessTokenRequest ): Oauth2AccessTokenVo? { if (this.grantType != grantType) { return null } - // 1、校验client_id和client_secret是否正确 - val clientId = oauth2AccessTokenDTO.clientId - val clientDetail = clientService.getClientDetail(oauth2AccessTokenDTO.clientId) - if (oauth2AccessTokenDTO.clientSecret != clientDetail.clientSecret) { - logger.warn("The client($clientId) secret is invalid") - throw ErrorCodeException( - errorCode = AuthMessageCode.INVALID_CLIENT_SECRET, - params = arrayOf(clientId), - defaultMessage = "The client($clientId) secret is invalid" - ) - } - // 2、校验用户的授权类型是否合法 - logger.info("AbstractTokenGranter grant") - if (grantType != clientDetail.authorizedGrantTypes) { - logger.warn("The client($clientId) grant type is invalid") - throw ErrorCodeException( - errorCode = AuthMessageCode.INVALID_AUTHORIZATION_TYPE, - params = arrayOf(clientId), - defaultMessage = "The client($clientId) grant type is invalid" - ) - } - return getAccessToken(oauth2AccessTokenDTO) + val clientId = accessTokenRequest.clientId + val clientDetail = oauth2ClientService.getClientDetail( + clientId = clientId + ) + oauth2ClientService.verifyClientInformation( + clientId = clientId, + clientSecret = accessTokenRequest.clientSecret, + grantType = grantType, + clientDetail = clientDetail + ) + return getAccessToken( + accessTokenRequest = accessTokenRequest, + clientDetail = clientDetail + ) } fun handleAccessToken( - oauth2AccessTokenDTO: Oauth2AccessTokenDTO, - oauth2AccessTokenInfo: Oauth2AccessTokenInfo + accessTokenRequest: Oauth2AccessTokenRequest, + accessTokenDTO: Oauth2AccessTokenDTO, + clientDetail: TAuthOauth2ClientDetailsRecord ): Oauth2AccessTokenVo { - // 从入参中获取accessToken. - // 1、校验access_token是否为空 - val accessToken = oauth2AccessTokenInfo.accessToken - val refreshToken = oauth2AccessTokenInfo.refreshToken - val clientId = oauth2AccessTokenDTO.clientId - // 2.1 若为空,创建新的access_token并存储,返回access_token,过期时间, - return if (accessToken == null) { - authOauth2AccessTokenDao.create( - dslContext = dslContext, + val clientId = accessTokenRequest.clientId + val accessToken = accessTokenDTO.accessToken + val refreshToken = accessTokenDTO.refreshToken + + if (accessToken == null || accessTokenDTO.expiredTime!!.toLong() <= System.currentTimeMillis()) { + // 生成新的 access_token + val newAccessToken = UUIDUtil.generate() + val accessTokenValidity = clientDetail.accessTokenValidity + val accessTokenExpiredTime = System.currentTimeMillis() + accessTokenValidity * 1000 + + // 删除旧的 access_token 记录 + if (accessToken != null) { + accessTokenService.delete(accessToken) + } + + // 创建新的 access_token 记录 + accessTokenService.create( clientId = clientId, - userName = oauth2AccessTokenDTO.userName, - // todo - accessToken = "accessToken", - refreshToken = "", - expiredTime = 1000 + userName = accessTokenRequest.userName, + accessToken = newAccessToken, + refreshToken = refreshToken, + expiredTime = accessTokenExpiredTime ) - Oauth2AccessTokenVo("accessToken", 1000, refreshToken) + + return Oauth2AccessTokenVo(newAccessToken, accessTokenExpiredTime, refreshToken) } else { - // 3.1 若不为空,校验access_token是否过期 - if (oauth2AccessTokenInfo.expiredTime!!.toLong() > System.currentTimeMillis()) { - // 3.2 若未过期,返回access_token,过期时间 - Oauth2AccessTokenVo(accessToken, 1000, refreshToken) - } else { - // 3.3 若过期,清除access_token记录,创建新的access_token并存储,返回access_token,过期时间。 - authOauth2AccessTokenDao.delete( - dslContext = dslContext, - accessToken = accessToken - ) - authOauth2AccessTokenDao.create( - dslContext = dslContext, - clientId = clientId, - userName = oauth2AccessTokenDTO.userName, - // todo - accessToken = "accessToken", - refreshToken = "", - expiredTime = 1000 - ) - Oauth2AccessTokenVo("accessToken", 1000, refreshToken) - } + // 返回未过期的 access_token + return Oauth2AccessTokenVo(accessToken, accessTokenDTO.expiredTime!!.toLong(), refreshToken) } } - abstract fun getAccessToken(oauth2AccessTokenDTO: Oauth2AccessTokenDTO): Oauth2AccessTokenVo - - private fun createAccessToken( - - ) { - } + abstract fun getAccessToken( + accessTokenRequest: Oauth2AccessTokenRequest, + clientDetail: TAuthOauth2ClientDetailsRecord + ): Oauth2AccessTokenVo companion object { private val logger = LoggerFactory.getLogger(AbstractTokenGranter::class.java) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index 74d3e2b11a1..339f9e62179 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -1,30 +1,27 @@ package com.tencent.devops.auth.service.oauth2.grant -import com.tencent.devops.auth.constant.AuthMessageCode.INVALID_AUTHORIZATION_CODE -import com.tencent.devops.auth.dao.AuthOauth2AccessTokenDao -import com.tencent.devops.auth.dao.AuthOauth2CodeDao -import com.tencent.devops.auth.dao.AuthOauth2RefreshTokenDao -import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo -import com.tencent.devops.auth.service.oauth2.ClientService -import com.tencent.devops.common.api.exception.ErrorCodeException -import org.jooq.DSLContext +import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService +import com.tencent.devops.auth.service.oauth2.Oauth2ClientService +import com.tencent.devops.auth.service.oauth2.Oauth2CodeService +import com.tencent.devops.auth.service.oauth2.Oauth2RefreshTokenService +import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory import org.springframework.stereotype.Service +import java.util.UUID @Service class AuthorizationCodeTokenGranter constructor( - private val clientService: ClientService, - private val authOauth2RefreshTokenDao: AuthOauth2RefreshTokenDao, - private val authOauth2AccessTokenDao: AuthOauth2AccessTokenDao, - private val authOauth2CodeDao: AuthOauth2CodeDao, - private val dslContext: DSLContext + private val clientService: Oauth2ClientService, + private val codeService: Oauth2CodeService, + private val accessTokenService: Oauth2AccessTokenService, + private val refreshTokenService: Oauth2RefreshTokenService ) : AbstractTokenGranter( grantType = GRANT_TYPE, - clientService = clientService, - authOauth2AccessTokenDao = authOauth2AccessTokenDao, - dslContext = dslContext + oauth2ClientService = clientService, + accessTokenService = accessTokenService ) { companion object { private const val GRANT_TYPE = "authorization_code" @@ -32,79 +29,53 @@ class AuthorizationCodeTokenGranter constructor( } override fun getAccessToken( - oauth2AccessTokenDTO: Oauth2AccessTokenDTO + accessTokenRequest: Oauth2AccessTokenRequest, + clientDetail: TAuthOauth2ClientDetailsRecord ): Oauth2AccessTokenVo { - logger.info("authorization_code getAccessToken") - val clientId = oauth2AccessTokenDTO.clientId - val code = oauth2AccessTokenDTO.code - ?: throw ErrorCodeException( - errorCode = INVALID_AUTHORIZATION_CODE, - defaultMessage = "The authorization code must be provided" - ) - // 1.获取授权码,判断授权是否为空 - val codeDetails = authOauth2CodeDao.get( - dslContext = dslContext, + logger.info("authorization_code getAccessToken|$accessTokenRequest|$clientDetail") + val clientId = accessTokenRequest.clientId + val code = accessTokenRequest.code + val codeDetails = codeService.get( code = code - ) ?: throw ErrorCodeException( - errorCode = INVALID_AUTHORIZATION_CODE, - defaultMessage = "The authorization code invalid" ) - // 2.判断授权码和客户端id是否对应的上 - if (codeDetails.clientId == clientId) { - throw ErrorCodeException( - errorCode = INVALID_AUTHORIZATION_CODE, - defaultMessage = "The authorization code does not belong to the client($clientId)" - ) - } - // 3.判断授权码是否过期 - if (codeDetails.expiredTime < System.currentTimeMillis()) { - throw ErrorCodeException( - errorCode = INVALID_AUTHORIZATION_CODE, - defaultMessage = "The authorization code expired" - ) - } - // 4.若授权码没有问题,则直接消费授权码,授权码单次有效,直接数据库删除该授权码 - authOauth2CodeDao.delete( - dslContext = dslContext, - code = code + codeService.verifyCode( + clientId = clientId, + codeDetails = codeDetails + ) - // 5、根据appcode+username获取accessToken - val accessTokenRecord = authOauth2AccessTokenDao.get( - dslContext = dslContext, + // 若授权码没有问题,则直接消费授权码,授权码单次有效 + codeService.consume(code = code!!) + + val accessTokenRecord = accessTokenService.get( clientId = clientId, - userName = oauth2AccessTokenDTO.userName + userName = accessTokenRequest.userName ) - val refreshToken = if (accessTokenRecord != null) { - val refreshTokenRecord = authOauth2RefreshTokenDao.get( - dslContext = dslContext, - refreshToken = accessTokenRecord.refreshToken, - ) - if (refreshTokenRecord!!.expiredTime > System.currentTimeMillis()) { - refreshTokenRecord.refreshToken - } else { - authOauth2RefreshTokenDao.delete( - dslContext = dslContext, - refreshToken = accessTokenRecord.refreshToken - ) - authOauth2RefreshTokenDao.create( - dslContext = dslContext, - refreshToken = "refreshToken", - clientId = clientId, - expiredTime = 1000 - ) - "refreshToken" - } + val isAccessTokenValid = accessTokenRecord != null && accessTokenRecord.expiredTime < System.currentTimeMillis() + val refreshToken = if (isAccessTokenValid) { + // 若accessToken未过期,refreshToken不变 + accessTokenRecord!!.refreshToken } else { - "refreshToken" + val refreshToken = UUID.randomUUID().toString() + // 若accessToken过期,refreshToken重新生成 + refreshTokenService.delete( + refreshToken = accessTokenRecord?.refreshToken ?: "" + ) + val refreshTokenValidity = clientDetail.refreshTokenValidity + refreshTokenService.create( + refreshToken = refreshToken, + clientId = clientId, + expiredTime = System.currentTimeMillis() + refreshTokenValidity * 1000L + ) + refreshToken } - return super.handleAccessToken( - oauth2AccessTokenDTO, - Oauth2AccessTokenInfo( + accessTokenRequest, + Oauth2AccessTokenDTO( accessToken = accessTokenRecord?.accessToken, refreshToken = refreshToken, expiredTime = accessTokenRecord?.expiredTime - ) + ), + clientDetail = clientDetail ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 8a23bc9863f..84194b73625 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -1,28 +1,22 @@ package com.tencent.devops.auth.service.oauth2.grant -import com.tencent.devops.auth.dao.AuthOauth2AccessTokenDao -import com.tencent.devops.auth.dao.AuthOauth2CodeDao -import com.tencent.devops.auth.dao.AuthOauth2RefreshTokenDao -import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo -import com.tencent.devops.auth.service.oauth2.ClientService -import org.jooq.DSLContext +import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService +import com.tencent.devops.auth.service.oauth2.Oauth2ClientService +import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service class ClientCredentialsTokenGranter constructor( - private val clientService: ClientService, - private val authOauth2RefreshTokenDao: AuthOauth2RefreshTokenDao, - private val authOauth2AccessTokenDao: AuthOauth2AccessTokenDao, - private val authOauth2CodeDao: AuthOauth2CodeDao, - private val dslContext: DSLContext + private val clientService: Oauth2ClientService, + private val accessTokenService: Oauth2AccessTokenService ) : AbstractTokenGranter( grantType = GRANT_TYPE, - clientService = clientService, - authOauth2AccessTokenDao = authOauth2AccessTokenDao, - dslContext = dslContext + oauth2ClientService = clientService, + accessTokenService = accessTokenService ) { companion object { private const val GRANT_TYPE = "client_credentials" @@ -30,20 +24,21 @@ class ClientCredentialsTokenGranter constructor( } override fun getAccessToken( - oauth2AccessTokenDTO: Oauth2AccessTokenDTO + accessTokenRequest: Oauth2AccessTokenRequest, + clientDetail: TAuthOauth2ClientDetailsRecord ): Oauth2AccessTokenVo { logger.info("client_credentials getAccessToken") // 1、根据appcode获取accessToken - val accessTokenRecord = authOauth2AccessTokenDao.get( - dslContext = dslContext, - clientId = oauth2AccessTokenDTO.clientId + val accessTokenRecord = accessTokenService.get( + clientId = accessTokenRequest.clientId ) return super.handleAccessToken( - oauth2AccessTokenDTO, - Oauth2AccessTokenInfo( + accessTokenRequest, + Oauth2AccessTokenDTO( accessToken = accessTokenRecord?.accessToken, expiredTime = accessTokenRecord?.expiredTime - ) + ), + clientDetail = clientDetail ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt index a1da8c83454..d85f50a8668 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt @@ -1,6 +1,6 @@ package com.tencent.devops.auth.service.oauth2.grant -import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo class CompositeTokenGranter constructor( @@ -8,10 +8,10 @@ class CompositeTokenGranter constructor( ) : TokenGranter { override fun grant( grantType: String, - oauth2AccessTokenDTO: Oauth2AccessTokenDTO + accessTokenRequest: Oauth2AccessTokenRequest ): Oauth2AccessTokenVo? { for (granter in tokenGranters) { - val grant = granter.grant(grantType, oauth2AccessTokenDTO) + val grant = granter.grant(grantType, accessTokenRequest) if (grant != null) { return grant } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index e802fa0cdae..70b21cf3189 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -1,28 +1,28 @@ package com.tencent.devops.auth.service.oauth2.grant -import com.tencent.devops.auth.dao.AuthOauth2AccessTokenDao -import com.tencent.devops.auth.dao.AuthOauth2CodeDao -import com.tencent.devops.auth.dao.AuthOauth2RefreshTokenDao -import com.tencent.devops.auth.pojo.Oauth2AccessTokenInfo +import com.tencent.devops.auth.constant.AuthMessageCode +import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_EXPIRED +import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_NOT_FOUND import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo -import com.tencent.devops.auth.service.oauth2.ClientService +import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService +import com.tencent.devops.auth.service.oauth2.Oauth2ClientService +import com.tencent.devops.auth.service.oauth2.Oauth2RefreshTokenService import com.tencent.devops.common.api.exception.ErrorCodeException -import org.jooq.DSLContext +import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service class RefreshTokenGranter( - private val clientService: ClientService, - private val authOauth2RefreshTokenDao: AuthOauth2RefreshTokenDao, - private val authOauth2AccessTokenDao: AuthOauth2AccessTokenDao, - private val dslContext: DSLContext + private val clientService: Oauth2ClientService, + private val accessTokenService: Oauth2AccessTokenService, + private val refreshTokenService: Oauth2RefreshTokenService ) : AbstractTokenGranter( grantType = GRANT_TYPE, - clientService = clientService, - authOauth2AccessTokenDao = authOauth2AccessTokenDao, - dslContext = dslContext + oauth2ClientService = clientService, + accessTokenService = accessTokenService ) { companion object { private const val GRANT_TYPE = "refresh_token" @@ -30,45 +30,41 @@ class RefreshTokenGranter( } override fun getAccessToken( - oauth2AccessTokenDTO: Oauth2AccessTokenDTO + accessTokenRequest: Oauth2AccessTokenRequest, + clientDetail: TAuthOauth2ClientDetailsRecord ): Oauth2AccessTokenVo { logger.info("refresh_token getAccessToken") //1.校验refresh_token是否为空 - if (oauth2AccessTokenDTO.refreshToken == null) { - throw ErrorCodeException( - errorCode = "111", - defaultMessage = "The authorization code invalid" + val refreshToken = accessTokenRequest.refreshToken + ?: throw ErrorCodeException( + errorCode = ERROR_REFRESH_TOKEN_NOT_FOUND, + defaultMessage = "The refresh token must be provided" ) - } // 2.校验refresh_token是否存在 - val refreshTokenRecord = authOauth2RefreshTokenDao.get( - dslContext = dslContext, - refreshToken = oauth2AccessTokenDTO.refreshToken!! - ) ?: throw ErrorCodeException( - errorCode = "111", - defaultMessage = "The authorization code invalid" - ) - if (refreshTokenRecord.clientId != oauth2AccessTokenDTO.clientId) { + val refreshTokenRecord = refreshTokenService.get( + refreshToken = refreshToken + )!! + if (refreshTokenRecord.clientId != accessTokenRequest.clientId) { throw ErrorCodeException( - errorCode = "111", + errorCode = AuthMessageCode.INVALID_REFRESH_TOKEN, defaultMessage = "The authorization code invalid" ) } //2.清除跟该refresh_token授权码相关的access_token - authOauth2AccessTokenDao.deleteByRefreshToken( - dslContext = dslContext, - refreshToken = oauth2AccessTokenDTO.refreshToken!! + accessTokenService.deleteByRefreshToken( + refreshToken = accessTokenRequest.refreshToken!! ) //3.校验refresh_token是否过期 if (refreshTokenRecord.expiredTime < System.currentTimeMillis()) { throw ErrorCodeException( - errorCode = "111", - defaultMessage = "The authorization code invalid" - ) - } else { - return super.handleAccessToken( - oauth2AccessTokenDTO, Oauth2AccessTokenInfo() + errorCode = ERROR_REFRESH_TOKEN_EXPIRED, + defaultMessage = "The refresh token has expired!" ) } + return super.handleAccessToken( + accessTokenRequest = accessTokenRequest, + accessTokenDTO = Oauth2AccessTokenDTO(), + clientDetail = clientDetail + ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt index 14850074340..2bfd6c7e316 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt @@ -1,11 +1,11 @@ package com.tencent.devops.auth.service.oauth2.grant -import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo interface TokenGranter { fun grant( grantType: String, - oauth2AccessTokenDTO: Oauth2AccessTokenDTO + accessTokenRequest: Oauth2AccessTokenRequest ): Oauth2AccessTokenVo? } diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt index 069932cfce0..c4b26894bcb 100644 --- a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt +++ b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt @@ -30,6 +30,7 @@ package com.tencent.devops.auth.service import com.tencent.devops.common.test.BkCiAbstractTest import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test +import java.util.UUID class AuthDeptServiceImplTest : BkCiAbstractTest() { private val authDeptServiceImpl = AuthDeptServiceImpl(redisOperation, objectMapper) @@ -168,4 +169,9 @@ class AuthDeptServiceImplTest : BkCiAbstractTest() { mockUsers.add("9878") Assertions.assertEquals(users, mockUsers) } + + @Test + fun test2(){ + println(UUID.randomUUID().toString()) + } } From bad523e1daec9da9672f61ed8f540471124bceb9 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 25 Jul 2023 18:01:35 +0800 Subject: [PATCH 07/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/service/AuthDeptServiceImplTest.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt index c4b26894bcb..069932cfce0 100644 --- a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt +++ b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt @@ -30,7 +30,6 @@ package com.tencent.devops.auth.service import com.tencent.devops.common.test.BkCiAbstractTest import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test -import java.util.UUID class AuthDeptServiceImplTest : BkCiAbstractTest() { private val authDeptServiceImpl = AuthDeptServiceImpl(redisOperation, objectMapper) @@ -169,9 +168,4 @@ class AuthDeptServiceImplTest : BkCiAbstractTest() { mockUsers.add("9878") Assertions.assertEquals(users, mockUsers) } - - @Test - fun test2(){ - println(UUID.randomUUID().toString()) - } } From c8d8f1791df133f51d533a4ce4cb4c719008387c Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 25 Jul 2023 18:08:00 +0800 Subject: [PATCH 08/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/service/oauth2/Oauth2CodeService.kt | 18 ++++++++++++++++++ .../devops/auth/service/oauth2/Oauth2Config.kt | 8 ++------ .../service/oauth2/Oauth2EndpointService.kt | 17 ++++++----------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt index e4b3c5048ef..7efa1615089 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt @@ -5,6 +5,7 @@ import com.tencent.devops.auth.dao.AuthOauth2CodeDao import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.model.auth.tables.records.TAuthOauth2CodeRecord import org.jooq.DSLContext +import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service @@ -35,6 +36,18 @@ class Oauth2CodeService constructor( ) } + fun create( + code: String, + clientId: String + ) { + authOauth2CodeDao.create( + dslContext = dslContext, + code = code, + clientId = clientId, + expiredTime = System.currentTimeMillis() + codeValiditySeconds + ) + } + fun verifyCode( clientId: String, codeDetails: TAuthOauth2CodeRecord @@ -53,4 +66,9 @@ class Oauth2CodeService constructor( } return true } + + companion object { + private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) + private const val codeValiditySeconds = 5 * 60 * 1000L + } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt index 1ff76477655..4ed800836b4 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -1,20 +1,17 @@ package com.tencent.devops.auth.service.oauth2 -import com.tencent.devops.auth.dao.AuthOauth2CodeDao import com.tencent.devops.auth.service.oauth2.grant.AuthorizationCodeTokenGranter import com.tencent.devops.auth.service.oauth2.grant.ClientCredentialsTokenGranter import com.tencent.devops.auth.service.oauth2.grant.CompositeTokenGranter import com.tencent.devops.auth.service.oauth2.grant.RefreshTokenGranter import com.tencent.devops.auth.service.oauth2.grant.TokenGranter -import org.jooq.DSLContext import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class Oauth2Config constructor( private val oauth2ClientService: Oauth2ClientService, - private val authOauth2CodeDao: AuthOauth2CodeDao, - private val dslContext: DSLContext, + private val codeService: Oauth2CodeService, private val clientCredentialsTokenGranter: ClientCredentialsTokenGranter, private val authorizationCodeTokenGranter: AuthorizationCodeTokenGranter, private val refreshTokenGranter: RefreshTokenGranter @@ -24,8 +21,7 @@ class Oauth2Config constructor( return Oauth2EndpointService( tokenGranter = compositeTokenGranter(), clientService = oauth2ClientService, - authOauth2CodeDao = authOauth2CodeDao, - dslContext = dslContext + codeService = codeService ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 882db4f9096..cc6e6e850fe 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -1,6 +1,5 @@ package com.tencent.devops.auth.service.oauth2 -import com.tencent.devops.auth.dao.AuthOauth2CodeDao import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.grant.TokenGranter @@ -12,14 +11,12 @@ import java.util.UUID @Service class Oauth2EndpointService constructor( private val tokenGranter: TokenGranter, - private val oauth2ClientService: Oauth2ClientService, - private val authOauth2CodeDao: AuthOauth2CodeDao, - private val dslContext: DSLContext, + private val clientService: Oauth2ClientService, + private val codeService: Oauth2CodeService ) { companion object { private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) private const val AUTHORIZATION_CODE_TYPE = "authorization_code" - private const val codeValiditySeconds = 5 * 60 * 1000L } fun getAuthorizationCode( @@ -30,9 +27,9 @@ class Oauth2EndpointService constructor( logger.info("Oauth2EndpointService|getAuthorizationCode: $userId $clientId, $redirectUri") // 1、校验用户是否登录 // 2、校验clientId是否存在 - val clientDetail = oauth2ClientService.getClientDetail(clientId = clientId) + val clientDetail = clientService.getClientDetail(clientId = clientId) // 3、校验客户端信息是否正确 - oauth2ClientService.verifyClientInformation( + clientService.verifyClientInformation( clientId = clientId, redirectUri = redirectUri, grantType = AUTHORIZATION_CODE_TYPE, @@ -40,11 +37,9 @@ class Oauth2EndpointService constructor( ) // 4、生成授权码并存储数据库,授权码有效期为5分钟 val code = UUID.randomUUID().toString() - authOauth2CodeDao.create( - dslContext = dslContext, + codeService.create( code = code, clientId = clientId, - expiredTime = System.currentTimeMillis() + codeValiditySeconds ) // 5、返回授权码 return code @@ -56,6 +51,6 @@ class Oauth2EndpointService constructor( ): Oauth2AccessTokenVo? { // 1、校验用户是否登录 val grantType = accessTokenRequest.grantType - return tokenGranter.grant(grantType, accessTokenRequest) + return tokenGranter.grant(grantType = grantType, accessTokenRequest = accessTokenRequest) } } From 69186a81e41f6a9c5ecf2274f36eded7b8b25c50 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 25 Jul 2023 20:48:51 +0800 Subject: [PATCH 09/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/oauth2/grant/AbstractTokenGranter.kt | 9 +++++++-- .../oauth2/grant/AuthorizationCodeTokenGranter.kt | 14 +++++--------- .../oauth2/grant/ClientCredentialsTokenGranter.kt | 12 ++++-------- .../service/oauth2/grant/RefreshTokenGranter.kt | 8 ++------ 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index e45e59d4d0f..61d9f342ffb 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -31,10 +31,15 @@ abstract class AbstractTokenGranter( grantType = grantType, clientDetail = clientDetail ) - return getAccessToken( + val accessTokenDTO = getAccessToken( accessTokenRequest = accessTokenRequest, clientDetail = clientDetail ) + return handleAccessToken( + accessTokenRequest = accessTokenRequest, + accessTokenDTO = accessTokenDTO, + clientDetail = clientDetail + ) } fun handleAccessToken( @@ -76,7 +81,7 @@ abstract class AbstractTokenGranter( abstract fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, clientDetail: TAuthOauth2ClientDetailsRecord - ): Oauth2AccessTokenVo + ): Oauth2AccessTokenDTO companion object { private val logger = LoggerFactory.getLogger(AbstractTokenGranter::class.java) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index 339f9e62179..f7d1d02c06c 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -31,7 +31,7 @@ class AuthorizationCodeTokenGranter constructor( override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, clientDetail: TAuthOauth2ClientDetailsRecord - ): Oauth2AccessTokenVo { + ): Oauth2AccessTokenDTO { logger.info("authorization_code getAccessToken|$accessTokenRequest|$clientDetail") val clientId = accessTokenRequest.clientId val code = accessTokenRequest.code @@ -68,14 +68,10 @@ class AuthorizationCodeTokenGranter constructor( ) refreshToken } - return super.handleAccessToken( - accessTokenRequest, - Oauth2AccessTokenDTO( - accessToken = accessTokenRecord?.accessToken, - refreshToken = refreshToken, - expiredTime = accessTokenRecord?.expiredTime - ), - clientDetail = clientDetail + return Oauth2AccessTokenDTO( + accessToken = accessTokenRecord?.accessToken, + refreshToken = refreshToken, + expiredTime = accessTokenRecord?.expiredTime ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 84194b73625..6a0ab4ca675 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -26,19 +26,15 @@ class ClientCredentialsTokenGranter constructor( override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, clientDetail: TAuthOauth2ClientDetailsRecord - ): Oauth2AccessTokenVo { + ): Oauth2AccessTokenDTO { logger.info("client_credentials getAccessToken") // 1、根据appcode获取accessToken val accessTokenRecord = accessTokenService.get( clientId = accessTokenRequest.clientId ) - return super.handleAccessToken( - accessTokenRequest, - Oauth2AccessTokenDTO( - accessToken = accessTokenRecord?.accessToken, - expiredTime = accessTokenRecord?.expiredTime - ), - clientDetail = clientDetail + return Oauth2AccessTokenDTO( + accessToken = accessTokenRecord?.accessToken, + expiredTime = accessTokenRecord?.expiredTime ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index 70b21cf3189..735f6325330 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -32,7 +32,7 @@ class RefreshTokenGranter( override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, clientDetail: TAuthOauth2ClientDetailsRecord - ): Oauth2AccessTokenVo { + ): Oauth2AccessTokenDTO { logger.info("refresh_token getAccessToken") //1.校验refresh_token是否为空 val refreshToken = accessTokenRequest.refreshToken @@ -61,10 +61,6 @@ class RefreshTokenGranter( defaultMessage = "The refresh token has expired!" ) } - return super.handleAccessToken( - accessTokenRequest = accessTokenRequest, - accessTokenDTO = Oauth2AccessTokenDTO(), - clientDetail = clientDetail - ) + return Oauth2AccessTokenDTO() } } From 2355cacc524cf2a6cac01f52d45925cf87a83db4 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 26 Jul 2023 11:51:18 +0800 Subject: [PATCH 10/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/oauth2/Oauth2EndpointResource.kt | 9 ++---- .../auth/pojo/Oauth2AccessTokenRequest.kt | 2 -- .../auth/pojo/dto/Oauth2AccessTokenDTO.kt | 8 +++-- .../auth/dao/AuthOauth2AccessTokenDao.kt | 3 +- .../auth/dao/AuthOauth2ClientDetailsDao.kt | 2 +- .../devops/auth/dao/AuthOauth2CodeDao.kt | 6 ++-- .../auth/dao/AuthOauth2RefreshTokenDao.kt | 2 +- .../resources/Oauth2EndpointResourceImpl.kt | 2 -- .../auth/service/oauth2/Oauth2CodeService.kt | 8 +++-- .../service/oauth2/Oauth2EndpointService.kt | 21 ++++++------ .../oauth2/Oauth2RefreshTokenService.kt | 5 +-- .../oauth2/grant/AbstractTokenGranter.kt | 20 +++++++----- .../grant/AuthorizationCodeTokenGranter.kt | 32 ++++++++++--------- .../grant/ClientCredentialsTokenGranter.kt | 9 +++--- .../oauth2/grant/RefreshTokenGranter.kt | 15 +++++---- .../devops/common/api/util/DateTimeUtil.kt | 6 ++++ .../devops/common/auth/utils/AuthUtils.kt | 4 +++ .../#etc#ci#application-assembly.yml | 4 +-- 18 files changed, 88 insertions(+), 70 deletions(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt index 740b188aac5..7e7950f2fee 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt @@ -3,17 +3,18 @@ package com.tencent.devops.auth.api.oauth2 import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID +import com.tencent.devops.common.api.pojo.Result import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam import javax.ws.rs.Consumes import javax.ws.rs.GET import javax.ws.rs.HeaderParam +import javax.ws.rs.POST import javax.ws.rs.Path import javax.ws.rs.Produces import javax.ws.rs.QueryParam import javax.ws.rs.core.MediaType -import com.tencent.devops.common.api.pojo.Result @Api(tags = ["OAUTH2_ENDPOINT"], description = "oauth2相关") @Path("/oauth2/endpoint") @@ -35,14 +36,10 @@ interface Oauth2EndpointResource { redirectUri: String ): Result - @GET + @POST @Path("/getAccessToken") @ApiOperation("获取accessToken") fun getAccessToken( - // 待定,如果客户端模式,此时并没有用户 - @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) - @ApiParam("待校验用户ID", required = true) - userId: String, @ApiParam("oauth2获取token请求报文体", required = true) accessTokenRequest: Oauth2AccessTokenRequest ): Result diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt index 948668333c6..d407e467dfd 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt @@ -7,8 +7,6 @@ import io.swagger.annotations.ApiModelProperty data class Oauth2AccessTokenRequest( @ApiModelProperty("客户端id", required = true) val clientId: String, - @ApiModelProperty("用户名称", required = true) - val userName: String = "", @ApiModelProperty("客户端密钥", required = true) val clientSecret: String, @ApiModelProperty("授权类型", required = true) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt index 4d77e1079d4..8c8964c69e9 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt @@ -6,9 +6,11 @@ import io.swagger.annotations.ApiModelProperty @ApiModel("oauth2获取token中间处理态") data class Oauth2AccessTokenDTO( @ApiModelProperty("accessToken", required = true) - var accessToken: String? = null, + val accessToken: String? = null, @ApiModelProperty("refreshToken", required = true) - var refreshToken: String? = null, + val refreshToken: String? = null, @ApiModelProperty("accessToken过期时间", required = true) - var expiredTime: Int? = null + val expiredTime: Long? = null, + @ApiModelProperty("accessToken绑定的用户名称", required = true) + val userName: String? = null ) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt index a0f2c64731b..e16b452c371 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt @@ -3,7 +3,6 @@ package com.tencent.devops.auth.dao import com.tencent.devops.model.auth.tables.TAuthOauth2AccessToken import com.tencent.devops.model.auth.tables.records.TAuthOauth2AccessTokenRecord import org.jooq.DSLContext -import org.jooq.Result import org.springframework.stereotype.Repository @Repository @@ -70,7 +69,7 @@ class AuthOauth2AccessTokenDao { userName, accessToken, refreshToken, - expiredTime.toInt() + expiredTime ).execute() } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt index 818c0ebad9b..97c573a35f9 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt @@ -7,7 +7,7 @@ import org.springframework.stereotype.Repository @Repository class AuthOauth2ClientDetailsDao { - fun get( + fun get( dslContext: DSLContext, clientId: String ): TAuthOauth2ClientDetailsRecord? { diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt index a3802777b3d..9bf2b27abba 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt @@ -3,7 +3,6 @@ package com.tencent.devops.auth.dao import com.tencent.devops.model.auth.tables.TAuthOauth2Code import com.tencent.devops.model.auth.tables.records.TAuthOauth2CodeRecord import org.jooq.DSLContext -import org.jooq.Result import org.springframework.stereotype.Repository @Repository @@ -21,6 +20,7 @@ class AuthOauth2CodeDao { fun create( dslContext: DSLContext, code: String, + userId: String, clientId: String, expiredTime: Long ): Int { @@ -29,11 +29,13 @@ class AuthOauth2CodeDao { this, CLIENT_ID, CODE, + USER_NAME, EXPIRED_TIME ).values( clientId, code, - expiredTime.toInt() + userId, + expiredTime ).execute() } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2RefreshTokenDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2RefreshTokenDao.kt index 81dca072cc6..54dcfc15b04 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2RefreshTokenDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2RefreshTokenDao.kt @@ -33,7 +33,7 @@ class AuthOauth2RefreshTokenDao { dslContext: DSLContext, refreshToken: String, clientId: String, - expiredTime: Int + expiredTime: Long ): Int { return with(TAuthOauth2RefreshToken.T_AUTH_OAUTH2_REFRESH_TOKEN) { dslContext.insertInto( diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt index 944bc2533fc..85804c1c1fb 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt @@ -26,12 +26,10 @@ class Oauth2EndpointResourceImpl constructor( } override fun getAccessToken( - userId: String, accessTokenRequest: Oauth2AccessTokenRequest ): Result { return Result( endpointService.getAccessToken( - userId = userId, accessTokenRequest = accessTokenRequest ) ) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt index 7efa1615089..fc92ee992b4 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt @@ -3,6 +3,8 @@ package com.tencent.devops.auth.service.oauth2 import com.tencent.devops.auth.constant.AuthMessageCode import com.tencent.devops.auth.dao.AuthOauth2CodeDao import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.common.api.util.DateTimeUtil +import com.tencent.devops.common.auth.utils.AuthUtils import com.tencent.devops.model.auth.tables.records.TAuthOauth2CodeRecord import org.jooq.DSLContext import org.slf4j.LoggerFactory @@ -37,14 +39,16 @@ class Oauth2CodeService constructor( } fun create( + userId: String, code: String, clientId: String ) { authOauth2CodeDao.create( dslContext = dslContext, code = code, + userId = userId, clientId = clientId, - expiredTime = System.currentTimeMillis() + codeValiditySeconds + expiredTime = DateTimeUtil.getFutureTimestamp(codeValiditySeconds) ) } @@ -58,7 +62,7 @@ class Oauth2CodeService constructor( defaultMessage = "The authorization code does not belong to the client($clientId)" ) } - if (codeDetails.expiredTime < System.currentTimeMillis()) { + if (AuthUtils.isExpired(codeDetails.expiredTime)) { throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_AUTHORIZATION_CODE, defaultMessage = "The authorization code expired" diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index cc6e6e850fe..5f674984cc5 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -3,6 +3,7 @@ package com.tencent.devops.auth.service.oauth2 import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.grant.TokenGranter +import com.tencent.devops.common.api.util.UUIDUtil import org.jooq.DSLContext import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @@ -24,33 +25,33 @@ class Oauth2EndpointService constructor( clientId: String, redirectUri: String ): String { - logger.info("Oauth2EndpointService|getAuthorizationCode: $userId $clientId, $redirectUri") - // 1、校验用户是否登录 - // 2、校验clientId是否存在 + logger.info("Oauth2EndpointService|getAuthorizationCode:$userId|$clientId|$redirectUri") + // 1、校验clientId是否存在 val clientDetail = clientService.getClientDetail(clientId = clientId) - // 3、校验客户端信息是否正确 + // 2、校验客户端信息是否正确 clientService.verifyClientInformation( clientId = clientId, redirectUri = redirectUri, grantType = AUTHORIZATION_CODE_TYPE, clientDetail = clientDetail ) - // 4、生成授权码并存储数据库,授权码有效期为5分钟 - val code = UUID.randomUUID().toString() + // 3、生成授权码并存储数据库,授权码有效期为5分钟 + val code = UUIDUtil.generate() codeService.create( + userId = userId, code = code, clientId = clientId, ) - // 5、返回授权码 - return code + // 4、返回跳转链接及授权码 + return "$redirectUri?code=$code" } fun getAccessToken( - userId: String, accessTokenRequest: Oauth2AccessTokenRequest ): Oauth2AccessTokenVo? { - // 1、校验用户是否登录 val grantType = accessTokenRequest.grantType + val clientId = accessTokenRequest.clientId + logger.info("Oauth2EndpointService|getAccessToken:$clientId|$grantType") return tokenGranter.grant(grantType = grantType, accessTokenRequest = accessTokenRequest) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt index c55beb07186..d0c7f15ee0c 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt @@ -22,7 +22,8 @@ class Oauth2RefreshTokenService constructor( ) } - fun delete(refreshToken: String) { + fun delete(refreshToken: String?) { + refreshToken ?: return authOauth2RefreshTokenDao.delete( dslContext = dslContext, refreshToken = refreshToken @@ -38,7 +39,7 @@ class Oauth2RefreshTokenService constructor( dslContext = dslContext, refreshToken = refreshToken, clientId = clientId, - expiredTime = expiredTime.toInt() + expiredTime = expiredTime ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index 61d9f342ffb..0bda4831dcd 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -5,7 +5,10 @@ import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService import com.tencent.devops.auth.service.oauth2.Oauth2ClientService +import com.tencent.devops.auth.service.oauth2.Oauth2EndpointService +import com.tencent.devops.common.api.util.DateTimeUtil import com.tencent.devops.common.api.util.UUIDUtil +import com.tencent.devops.common.auth.utils.AuthUtils import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory @@ -21,6 +24,8 @@ abstract class AbstractTokenGranter( if (this.grantType != grantType) { return null } + // todo 记得要去掉改行日志,内包含敏感信息 + logger.info("AbstractTokenGranter|grant:$grantType|$accessTokenRequest") val clientId = accessTokenRequest.clientId val clientDetail = oauth2ClientService.getClientDetail( clientId = clientId @@ -42,39 +47,38 @@ abstract class AbstractTokenGranter( ) } - fun handleAccessToken( + private fun handleAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, accessTokenDTO: Oauth2AccessTokenDTO, clientDetail: TAuthOauth2ClientDetailsRecord ): Oauth2AccessTokenVo { + // todo 记得要去掉改行日志,内包含敏感信息 + logger.info("AbstractTokenGranter|handleAccessToken:$accessTokenRequest|$accessTokenDTO|$clientDetail") val clientId = accessTokenRequest.clientId val accessToken = accessTokenDTO.accessToken val refreshToken = accessTokenDTO.refreshToken - if (accessToken == null || accessTokenDTO.expiredTime!!.toLong() <= System.currentTimeMillis()) { + if (accessToken == null || AuthUtils.isExpired(accessTokenDTO.expiredTime!!)) { // 生成新的 access_token val newAccessToken = UUIDUtil.generate() val accessTokenValidity = clientDetail.accessTokenValidity - val accessTokenExpiredTime = System.currentTimeMillis() + accessTokenValidity * 1000 - + val accessTokenExpiredTime = DateTimeUtil.getFutureTimestamp(accessTokenValidity) // 删除旧的 access_token 记录 if (accessToken != null) { accessTokenService.delete(accessToken) } - // 创建新的 access_token 记录 accessTokenService.create( clientId = clientId, - userName = accessTokenRequest.userName, + userName = accessTokenDTO.userName, accessToken = newAccessToken, refreshToken = refreshToken, expiredTime = accessTokenExpiredTime ) - return Oauth2AccessTokenVo(newAccessToken, accessTokenExpiredTime, refreshToken) } else { // 返回未过期的 access_token - return Oauth2AccessTokenVo(accessToken, accessTokenDTO.expiredTime!!.toLong(), refreshToken) + return Oauth2AccessTokenVo(accessToken, accessTokenDTO.expiredTime!!, refreshToken) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index f7d1d02c06c..582d717f9ae 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -2,15 +2,16 @@ package com.tencent.devops.auth.service.oauth2.grant import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO -import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService import com.tencent.devops.auth.service.oauth2.Oauth2ClientService import com.tencent.devops.auth.service.oauth2.Oauth2CodeService import com.tencent.devops.auth.service.oauth2.Oauth2RefreshTokenService +import com.tencent.devops.common.api.util.DateTimeUtil +import com.tencent.devops.common.api.util.UUIDUtil +import com.tencent.devops.common.auth.utils.AuthUtils import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory import org.springframework.stereotype.Service -import java.util.UUID @Service class AuthorizationCodeTokenGranter constructor( @@ -32,7 +33,7 @@ class AuthorizationCodeTokenGranter constructor( accessTokenRequest: Oauth2AccessTokenRequest, clientDetail: TAuthOauth2ClientDetailsRecord ): Oauth2AccessTokenDTO { - logger.info("authorization_code getAccessToken|$accessTokenRequest|$clientDetail") + logger.info("authorization code getAccessToken|$accessTokenRequest|$clientDetail") val clientId = accessTokenRequest.clientId val code = accessTokenRequest.code val codeDetails = codeService.get( @@ -41,37 +42,38 @@ class AuthorizationCodeTokenGranter constructor( codeService.verifyCode( clientId = clientId, codeDetails = codeDetails - ) + val userName = codeDetails.userName // 若授权码没有问题,则直接消费授权码,授权码单次有效 codeService.consume(code = code!!) - val accessTokenRecord = accessTokenService.get( + val accessTokenInfo = accessTokenService.get( clientId = clientId, - userName = accessTokenRequest.userName + userName = codeDetails.userName ) - val isAccessTokenValid = accessTokenRecord != null && accessTokenRecord.expiredTime < System.currentTimeMillis() + val isAccessTokenValid = accessTokenInfo != null && AuthUtils.isExpired(accessTokenInfo.expiredTime) val refreshToken = if (isAccessTokenValid) { // 若accessToken未过期,refreshToken不变 - accessTokenRecord!!.refreshToken + accessTokenInfo!!.refreshToken } else { - val refreshToken = UUID.randomUUID().toString() + val newRefreshToken = UUIDUtil.generate() // 若accessToken过期,refreshToken重新生成 refreshTokenService.delete( - refreshToken = accessTokenRecord?.refreshToken ?: "" + refreshToken = accessTokenInfo?.refreshToken ) val refreshTokenValidity = clientDetail.refreshTokenValidity refreshTokenService.create( - refreshToken = refreshToken, + refreshToken = newRefreshToken, clientId = clientId, - expiredTime = System.currentTimeMillis() + refreshTokenValidity * 1000L + expiredTime = DateTimeUtil.getFutureTimestamp(refreshTokenValidity) ) - refreshToken + newRefreshToken } return Oauth2AccessTokenDTO( - accessToken = accessTokenRecord?.accessToken, + accessToken = accessTokenInfo?.accessToken, refreshToken = refreshToken, - expiredTime = accessTokenRecord?.expiredTime + expiredTime = accessTokenInfo?.expiredTime, + userName = userName ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 6a0ab4ca675..59da168aafb 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -2,7 +2,6 @@ package com.tencent.devops.auth.service.oauth2.grant import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO -import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService import com.tencent.devops.auth.service.oauth2.Oauth2ClientService import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord @@ -27,14 +26,14 @@ class ClientCredentialsTokenGranter constructor( accessTokenRequest: Oauth2AccessTokenRequest, clientDetail: TAuthOauth2ClientDetailsRecord ): Oauth2AccessTokenDTO { - logger.info("client_credentials getAccessToken") + logger.info("client credentials getAccessToken|$accessTokenRequest|$clientDetail") // 1、根据appcode获取accessToken - val accessTokenRecord = accessTokenService.get( + val accessTokenInfo = accessTokenService.get( clientId = accessTokenRequest.clientId ) return Oauth2AccessTokenDTO( - accessToken = accessTokenRecord?.accessToken, - expiredTime = accessTokenRecord?.expiredTime + accessToken = accessTokenInfo?.accessToken, + expiredTime = accessTokenInfo?.expiredTime ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index 735f6325330..a97bcd62cfb 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -5,11 +5,11 @@ import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_EXPI import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_NOT_FOUND import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest -import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService import com.tencent.devops.auth.service.oauth2.Oauth2ClientService import com.tencent.devops.auth.service.oauth2.Oauth2RefreshTokenService import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.common.auth.utils.AuthUtils import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @@ -33,7 +33,7 @@ class RefreshTokenGranter( accessTokenRequest: Oauth2AccessTokenRequest, clientDetail: TAuthOauth2ClientDetailsRecord ): Oauth2AccessTokenDTO { - logger.info("refresh_token getAccessToken") + logger.info("refresh token getAccessToken|$accessTokenRequest|$clientDetail") //1.校验refresh_token是否为空 val refreshToken = accessTokenRequest.refreshToken ?: throw ErrorCodeException( @@ -41,21 +41,22 @@ class RefreshTokenGranter( defaultMessage = "The refresh token must be provided" ) // 2.校验refresh_token是否存在 - val refreshTokenRecord = refreshTokenService.get( + val refreshTokenInfo = refreshTokenService.get( refreshToken = refreshToken )!! - if (refreshTokenRecord.clientId != accessTokenRequest.clientId) { + // 3.校验refresh_token是否跟client_id匹配 + if (refreshTokenInfo.clientId != accessTokenRequest.clientId) { throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_REFRESH_TOKEN, defaultMessage = "The authorization code invalid" ) } - //2.清除跟该refresh_token授权码相关的access_token + //4.清除跟该refresh_token授权码相关的access_token accessTokenService.deleteByRefreshToken( refreshToken = accessTokenRequest.refreshToken!! ) - //3.校验refresh_token是否过期 - if (refreshTokenRecord.expiredTime < System.currentTimeMillis()) { + //5.校验refresh_token是否过期 + if (AuthUtils.isExpired(refreshTokenInfo.expiredTime)) { throw ErrorCodeException( errorCode = ERROR_REFRESH_TOKEN_EXPIRED, defaultMessage = "The refresh token has expired!" diff --git a/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/util/DateTimeUtil.kt b/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/util/DateTimeUtil.kt index e66ba5ae5d4..cc1a4dc56a1 100644 --- a/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/util/DateTimeUtil.kt +++ b/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/util/DateTimeUtil.kt @@ -69,6 +69,8 @@ object DateTimeUtil { const val YYYYMMDD = "yyyyMMdd" + const val ONE_THOUSAND_MS = 1000L + /** * 单位转换,分钟转换秒 */ @@ -108,6 +110,10 @@ object DateTimeUtil { return cd.time } + fun getFutureTimestamp(seconds: Long): Long { + return System.currentTimeMillis() + seconds * ONE_THOUSAND_MS + } + /** * 按指定日期时间格式格式化日期时间 * @param date 日期时间 diff --git a/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt b/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt index a8e3806f4ea..9d0db7b78b9 100644 --- a/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt +++ b/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt @@ -248,6 +248,10 @@ object AuthUtils { return instanceList } + fun isExpired(expirationTimestamp: Long): Boolean { + return System.currentTimeMillis() > expirationTime + } + private fun checkProject(projectId: String, expression: ExpressionDTO): Pair> { val instanceList = mutableSetOf() val values = expression.value.toString().split(",") diff --git a/support-files/templates/#etc#ci#application-assembly.yml b/support-files/templates/#etc#ci#application-assembly.yml index 88f32aef67b..68e38d97831 100644 --- a/support-files/templates/#etc#ci#application-assembly.yml +++ b/support-files/templates/#etc#ci#application-assembly.yml @@ -337,7 +337,7 @@ statistics: cert: # 部署前修改好,后续升级如果再修改,会导致历史数据读取不了,所以如果修改需要先解密重新入库 aes-key: "gHi(xG9Af)jEvCx&" - +v credential: mixer: "******" # 部署前修改好,后续升级如果再修改,会导致历史数据读取不了,所以如果修改需要先解密重新入库 @@ -412,7 +412,7 @@ wework: enableDuplicateCheck: # 表示是否开启重复消息检查,0表示否,1表示是,默认0 duplicateCheckInterval: # 表示是否重复消息检查的时间间隔,默认1800s,最大不超过4小时 enableIdTrans: # 表示是否开启id转译,0表示否,1表示是,默认0。仅第三方应用需要用到,企业自建应用可以忽略。 - + # 分布式ID配置 leaf: segment: From 3a9e57d599d2ff6b03a96a4d19b16e95cdbe70da Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 26 Jul 2023 11:52:21 +0800 Subject: [PATCH 11/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- support-files/templates/#etc#ci#application-assembly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/templates/#etc#ci#application-assembly.yml b/support-files/templates/#etc#ci#application-assembly.yml index 68e38d97831..d8cbc969c09 100644 --- a/support-files/templates/#etc#ci#application-assembly.yml +++ b/support-files/templates/#etc#ci#application-assembly.yml @@ -337,7 +337,7 @@ statistics: cert: # 部署前修改好,后续升级如果再修改,会导致历史数据读取不了,所以如果修改需要先解密重新入库 aes-key: "gHi(xG9Af)jEvCx&" -v + credential: mixer: "******" # 部署前修改好,后续升级如果再修改,会导致历史数据读取不了,所以如果修改需要先解密重新入库 From 1028161da010f1aa074b07f3300122541aa8f4b5 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 26 Jul 2023 11:53:54 +0800 Subject: [PATCH 12/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt index 7e7950f2fee..33e841a2acd 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt @@ -17,7 +17,7 @@ import javax.ws.rs.QueryParam import javax.ws.rs.core.MediaType @Api(tags = ["OAUTH2_ENDPOINT"], description = "oauth2相关") -@Path("/oauth2/endpoint") +@Path("open/oauth2/endpoint") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) interface Oauth2EndpointResource { From 976fb0f3f9028b1d1ec12dda4090560a1b8edc1e Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 26 Jul 2023 11:55:06 +0800 Subject: [PATCH 13/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt index 97c573a35f9..818c0ebad9b 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt @@ -7,7 +7,7 @@ import org.springframework.stereotype.Repository @Repository class AuthOauth2ClientDetailsDao { - fun get( + fun get( dslContext: DSLContext, clientId: String ): TAuthOauth2ClientDetailsRecord? { From ae6fbfb6b59f79c4a4d91ed972daea504c0cb5bc Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 26 Jul 2023 12:07:52 +0800 Subject: [PATCH 14/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt b/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt index 9d0db7b78b9..caa2d3d1a70 100644 --- a/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt +++ b/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt @@ -249,7 +249,7 @@ object AuthUtils { } fun isExpired(expirationTimestamp: Long): Boolean { - return System.currentTimeMillis() > expirationTime + return System.currentTimeMillis() > expirationTimestamp } private fun checkProject(projectId: String, expression: ExpressionDTO): Pair> { From b7ac54ab1a7a4aaec7cddc1d9c82044c649726da Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 26 Jul 2023 14:43:19 +0800 Subject: [PATCH 15/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt index 33e841a2acd..608b42ea401 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt @@ -17,7 +17,7 @@ import javax.ws.rs.QueryParam import javax.ws.rs.core.MediaType @Api(tags = ["OAUTH2_ENDPOINT"], description = "oauth2相关") -@Path("open/oauth2/endpoint") +@Path("user/oauth2/endpoint") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) interface Oauth2EndpointResource { From c333de23a084017cd153ddf32495e9ef68adbf55 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 26 Jul 2023 16:36:10 +0800 Subject: [PATCH 16/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/auth/pojo/ClientDetailsInfo.kt | 22 +++++++++++++++ .../service/oauth2/Oauth2ClientService.kt | 26 +++++++++++++---- .../auth/service/oauth2/Oauth2CodeService.kt | 4 +-- .../service/oauth2/Oauth2EndpointService.kt | 21 ++++++++++---- .../oauth2/grant/AbstractTokenGranter.kt | 28 ++++++------------- .../grant/AuthorizationCodeTokenGranter.kt | 11 +++----- .../grant/ClientCredentialsTokenGranter.kt | 9 ++---- .../oauth2/grant/CompositeTokenGranter.kt | 4 ++- .../oauth2/grant/RefreshTokenGranter.kt | 11 +++----- .../auth/service/oauth2/grant/TokenGranter.kt | 2 ++ 10 files changed, 83 insertions(+), 55 deletions(-) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt new file mode 100644 index 00000000000..3e826dcf100 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt @@ -0,0 +1,22 @@ +package com.tencent.devops.auth.pojo + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("Oauth2客户端详情") +data class ClientDetailsInfo( + @ApiModelProperty("客户端id", required = true) + val clientId: String, + @ApiModelProperty("客户端密钥", required = true) + val clientSecret: String, + @ApiModelProperty("授权类型", required = true) + val authorizedGrantTypes: String, + @ApiModelProperty("跳转链接", required = true) + val redirectUri: String, + @ApiModelProperty("授权范围", required = true) + val scope: String, + @ApiModelProperty("accessToken有效期", required = true) + val accessTokenValidity: Long, + @ApiModelProperty("refreshToken有效期", required = true) + val refreshTokenValidity: Long +) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt index d27f8bf6320..b83b5b1dd35 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt @@ -2,6 +2,7 @@ package com.tencent.devops.auth.service.oauth2 import com.tencent.devops.auth.constant.AuthMessageCode import com.tencent.devops.auth.dao.AuthOauth2ClientDetailsDao +import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.jooq.DSLContext @@ -18,25 +19,38 @@ class Oauth2ClientService constructor( private val logger = LoggerFactory.getLogger(Oauth2ClientService::class.java) } - fun getClientDetail(clientId: String): TAuthOauth2ClientDetailsRecord { + fun getClientDetails(clientId: String): ClientDetailsInfo { return authOauth2ClientDetailsDao.get( dslContext = dslContext, clientId = clientId - ) ?: throw ErrorCodeException( + )?.convert() ?: throw ErrorCodeException( errorCode = AuthMessageCode.ERROR_CLIENT_NOT_EXIST, params = arrayOf(clientId), defaultMessage = "the client $clientId not exists" ) } + fun TAuthOauth2ClientDetailsRecord.convert(): ClientDetailsInfo { + return ClientDetailsInfo( + clientId = clientId, + clientSecret = clientSecret, + scope = scope, + authorizedGrantTypes = authorizedGrantTypes, + redirectUri = webServerRedirectUri, + accessTokenValidity = accessTokenValidity, + refreshTokenValidity = refreshTokenValidity, + ) + } + + @Suppress("ThrowsCount") fun verifyClientInformation( clientId: String, - clientDetail: TAuthOauth2ClientDetailsRecord, + clientDetails: ClientDetailsInfo, clientSecret: String? = null, redirectUri: String? = null, grantType: String? = null, ): Boolean { - val authorizedGrantTypes = clientDetail.authorizedGrantTypes.split(",") + val authorizedGrantTypes = clientDetails.authorizedGrantTypes.split(",") if (grantType != null && !authorizedGrantTypes.contains(grantType)) { logger.warn("The client($clientId) does not support the authorization code type") throw ErrorCodeException( @@ -45,7 +59,7 @@ class Oauth2ClientService constructor( defaultMessage = "The client($clientId) does not support the authorization code type" ) } - if (redirectUri != null && redirectUri != clientDetail.webServerRedirectUri) { + if (redirectUri != null && redirectUri != clientDetails.redirectUri) { logger.warn("The redirectUri is invalid|$clientId|$redirectUri") throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_REDIRECT_URI, @@ -53,7 +67,7 @@ class Oauth2ClientService constructor( defaultMessage = "The redirectUri($redirectUri) is invalid" ) } - if (clientSecret != null && clientSecret != clientDetail.clientSecret) { + if (clientSecret != null && clientSecret != clientDetails.clientSecret) { logger.warn("The client($clientId) secret is invalid") throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_CLIENT_SECRET, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt index fc92ee992b4..4c86b791235 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt @@ -7,7 +7,6 @@ import com.tencent.devops.common.api.util.DateTimeUtil import com.tencent.devops.common.auth.utils.AuthUtils import com.tencent.devops.model.auth.tables.records.TAuthOauth2CodeRecord import org.jooq.DSLContext -import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service @@ -72,7 +71,6 @@ class Oauth2CodeService constructor( } companion object { - private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) - private const val codeValiditySeconds = 5 * 60 * 1000L + private const val codeValiditySeconds = 300L } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 5f674984cc5..0ab6ce4477e 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -4,10 +4,8 @@ import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.grant.TokenGranter import com.tencent.devops.common.api.util.UUIDUtil -import org.jooq.DSLContext import org.slf4j.LoggerFactory import org.springframework.stereotype.Service -import java.util.UUID @Service class Oauth2EndpointService constructor( @@ -27,13 +25,13 @@ class Oauth2EndpointService constructor( ): String { logger.info("Oauth2EndpointService|getAuthorizationCode:$userId|$clientId|$redirectUri") // 1、校验clientId是否存在 - val clientDetail = clientService.getClientDetail(clientId = clientId) + val clientDetails = clientService.getClientDetails(clientId = clientId) // 2、校验客户端信息是否正确 clientService.verifyClientInformation( clientId = clientId, redirectUri = redirectUri, grantType = AUTHORIZATION_CODE_TYPE, - clientDetail = clientDetail + clientDetails = clientDetails ) // 3、生成授权码并存储数据库,授权码有效期为5分钟 val code = UUIDUtil.generate() @@ -52,6 +50,19 @@ class Oauth2EndpointService constructor( val grantType = accessTokenRequest.grantType val clientId = accessTokenRequest.clientId logger.info("Oauth2EndpointService|getAccessToken:$clientId|$grantType") - return tokenGranter.grant(grantType = grantType, accessTokenRequest = accessTokenRequest) + val clientDetails = clientService.getClientDetails( + clientId = clientId + ) + clientService.verifyClientInformation( + clientId = clientId, + clientSecret = accessTokenRequest.clientSecret, + grantType = grantType, + clientDetails = clientDetails + ) + return tokenGranter.grant( + grantType = grantType, + clientDetails = clientDetails, + accessTokenRequest = accessTokenRequest + ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index 0bda4831dcd..6e7e1b66e4e 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -1,24 +1,22 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService -import com.tencent.devops.auth.service.oauth2.Oauth2ClientService -import com.tencent.devops.auth.service.oauth2.Oauth2EndpointService import com.tencent.devops.common.api.util.DateTimeUtil import com.tencent.devops.common.api.util.UUIDUtil import com.tencent.devops.common.auth.utils.AuthUtils -import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory abstract class AbstractTokenGranter( private val grantType: String, - private val oauth2ClientService: Oauth2ClientService, private val accessTokenService: Oauth2AccessTokenService, ) : TokenGranter { override fun grant( grantType: String, + clientDetails: ClientDetailsInfo, accessTokenRequest: Oauth2AccessTokenRequest ): Oauth2AccessTokenVo? { if (this.grantType != grantType) { @@ -26,34 +24,24 @@ abstract class AbstractTokenGranter( } // todo 记得要去掉改行日志,内包含敏感信息 logger.info("AbstractTokenGranter|grant:$grantType|$accessTokenRequest") - val clientId = accessTokenRequest.clientId - val clientDetail = oauth2ClientService.getClientDetail( - clientId = clientId - ) - oauth2ClientService.verifyClientInformation( - clientId = clientId, - clientSecret = accessTokenRequest.clientSecret, - grantType = grantType, - clientDetail = clientDetail - ) val accessTokenDTO = getAccessToken( accessTokenRequest = accessTokenRequest, - clientDetail = clientDetail + clientDetails = clientDetails ) return handleAccessToken( accessTokenRequest = accessTokenRequest, accessTokenDTO = accessTokenDTO, - clientDetail = clientDetail + clientDetails = clientDetails ) } private fun handleAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, accessTokenDTO: Oauth2AccessTokenDTO, - clientDetail: TAuthOauth2ClientDetailsRecord + clientDetails: ClientDetailsInfo ): Oauth2AccessTokenVo { // todo 记得要去掉改行日志,内包含敏感信息 - logger.info("AbstractTokenGranter|handleAccessToken:$accessTokenRequest|$accessTokenDTO|$clientDetail") + logger.info("AbstractTokenGranter|handleAccessToken:$accessTokenRequest|$accessTokenDTO|$clientDetails") val clientId = accessTokenRequest.clientId val accessToken = accessTokenDTO.accessToken val refreshToken = accessTokenDTO.refreshToken @@ -61,7 +49,7 @@ abstract class AbstractTokenGranter( if (accessToken == null || AuthUtils.isExpired(accessTokenDTO.expiredTime!!)) { // 生成新的 access_token val newAccessToken = UUIDUtil.generate() - val accessTokenValidity = clientDetail.accessTokenValidity + val accessTokenValidity = clientDetails.accessTokenValidity val accessTokenExpiredTime = DateTimeUtil.getFutureTimestamp(accessTokenValidity) // 删除旧的 access_token 记录 if (accessToken != null) { @@ -84,7 +72,7 @@ abstract class AbstractTokenGranter( abstract fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, - clientDetail: TAuthOauth2ClientDetailsRecord + clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO companion object { diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index 582d717f9ae..e376329169b 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -1,27 +1,24 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService -import com.tencent.devops.auth.service.oauth2.Oauth2ClientService import com.tencent.devops.auth.service.oauth2.Oauth2CodeService import com.tencent.devops.auth.service.oauth2.Oauth2RefreshTokenService import com.tencent.devops.common.api.util.DateTimeUtil import com.tencent.devops.common.api.util.UUIDUtil import com.tencent.devops.common.auth.utils.AuthUtils -import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service class AuthorizationCodeTokenGranter constructor( - private val clientService: Oauth2ClientService, private val codeService: Oauth2CodeService, private val accessTokenService: Oauth2AccessTokenService, private val refreshTokenService: Oauth2RefreshTokenService ) : AbstractTokenGranter( grantType = GRANT_TYPE, - oauth2ClientService = clientService, accessTokenService = accessTokenService ) { companion object { @@ -31,9 +28,9 @@ class AuthorizationCodeTokenGranter constructor( override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, - clientDetail: TAuthOauth2ClientDetailsRecord + clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO { - logger.info("authorization code getAccessToken|$accessTokenRequest|$clientDetail") + logger.info("authorization code getAccessToken|$accessTokenRequest|$clientDetails") val clientId = accessTokenRequest.clientId val code = accessTokenRequest.code val codeDetails = codeService.get( @@ -61,7 +58,7 @@ class AuthorizationCodeTokenGranter constructor( refreshTokenService.delete( refreshToken = accessTokenInfo?.refreshToken ) - val refreshTokenValidity = clientDetail.refreshTokenValidity + val refreshTokenValidity = clientDetails.refreshTokenValidity refreshTokenService.create( refreshToken = newRefreshToken, clientId = clientId, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 59da168aafb..6a3d3f1700c 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -1,20 +1,17 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService -import com.tencent.devops.auth.service.oauth2.Oauth2ClientService -import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service class ClientCredentialsTokenGranter constructor( - private val clientService: Oauth2ClientService, private val accessTokenService: Oauth2AccessTokenService ) : AbstractTokenGranter( grantType = GRANT_TYPE, - oauth2ClientService = clientService, accessTokenService = accessTokenService ) { companion object { @@ -24,9 +21,9 @@ class ClientCredentialsTokenGranter constructor( override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, - clientDetail: TAuthOauth2ClientDetailsRecord + clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO { - logger.info("client credentials getAccessToken|$accessTokenRequest|$clientDetail") + logger.info("client credentials getAccessToken|$accessTokenRequest|$clientDetails") // 1、根据appcode获取accessToken val accessTokenInfo = accessTokenService.get( clientId = accessTokenRequest.clientId diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt index d85f50a8668..ca2565d512c 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/CompositeTokenGranter.kt @@ -1,5 +1,6 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo @@ -8,10 +9,11 @@ class CompositeTokenGranter constructor( ) : TokenGranter { override fun grant( grantType: String, + clientDetails: ClientDetailsInfo, accessTokenRequest: Oauth2AccessTokenRequest ): Oauth2AccessTokenVo? { for (granter in tokenGranters) { - val grant = granter.grant(grantType, accessTokenRequest) + val grant = granter.grant(grantType, clientDetails, accessTokenRequest) if (grant != null) { return grant } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index a97bcd62cfb..1cc7089ae64 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -3,25 +3,22 @@ package com.tencent.devops.auth.service.oauth2.grant import com.tencent.devops.auth.constant.AuthMessageCode import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_EXPIRED import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_NOT_FOUND -import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService -import com.tencent.devops.auth.service.oauth2.Oauth2ClientService import com.tencent.devops.auth.service.oauth2.Oauth2RefreshTokenService import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.common.auth.utils.AuthUtils -import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service class RefreshTokenGranter( - private val clientService: Oauth2ClientService, private val accessTokenService: Oauth2AccessTokenService, private val refreshTokenService: Oauth2RefreshTokenService ) : AbstractTokenGranter( grantType = GRANT_TYPE, - oauth2ClientService = clientService, accessTokenService = accessTokenService ) { companion object { @@ -31,9 +28,9 @@ class RefreshTokenGranter( override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, - clientDetail: TAuthOauth2ClientDetailsRecord + clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO { - logger.info("refresh token getAccessToken|$accessTokenRequest|$clientDetail") + logger.info("refresh token getAccessToken|$accessTokenRequest|$clientDetails") //1.校验refresh_token是否为空 val refreshToken = accessTokenRequest.refreshToken ?: throw ErrorCodeException( diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt index 2bfd6c7e316..0d798547f39 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/TokenGranter.kt @@ -1,11 +1,13 @@ package com.tencent.devops.auth.service.oauth2.grant +import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo interface TokenGranter { fun grant( grantType: String, + clientDetails: ClientDetailsInfo, accessTokenRequest: Oauth2AccessTokenRequest ): Oauth2AccessTokenVo? } From d2ac9c9b1fc7320ebf1126313565ad2677aef986 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 27 Jul 2023 10:13:37 +0800 Subject: [PATCH 17/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/dao/AuthOauth2AccessTokenDao.kt | 30 +++++++++++-------- .../oauth2/Oauth2AccessTokenService.kt | 18 +++++------ .../service/oauth2/Oauth2ClientService.kt | 4 +-- .../oauth2/grant/AbstractTokenGranter.kt | 1 + .../grant/ClientCredentialsTokenGranter.kt | 3 +- .../oauth2/grant/RefreshTokenGranter.kt | 16 ++++++++-- 6 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt index e16b452c371..1fb9f4d6cc2 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt @@ -10,7 +10,9 @@ class AuthOauth2AccessTokenDao { fun get( dslContext: DSLContext, clientId: String, - userName: String? = null + refreshToken: String?, + userName: String?, + grantType: String? ): TAuthOauth2AccessTokenRecord? { return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { dslContext.selectFrom(this).where( @@ -21,6 +23,18 @@ class AuthOauth2AccessTokenDao { } else { it } + }.let { + if (grantType != null) { + it.and(GRANT_TYPE.eq(grantType)) + } else { + it + } + }.let { + if (refreshToken != null) { + it.and(REFRESH_TOKEN.eq(refreshToken)) + } else { + it + } }.fetchOne() } } @@ -36,22 +50,12 @@ class AuthOauth2AccessTokenDao { } } - fun deleteByRefreshToken( - dslContext: DSLContext, - refreshToken: String - ): Int { - return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { - dslContext.deleteFrom(this) - .where(REFRESH_TOKEN.eq(refreshToken)) - .execute() - } - } - @Suppress("LongParameterList") fun create( dslContext: DSLContext, clientId: String, userName: String?, + grantType: String, accessToken: String, refreshToken: String? = null, expiredTime: Long @@ -61,12 +65,14 @@ class AuthOauth2AccessTokenDao { this, CLIENT_ID, USER_NAME, + GRANT_TYPE, ACCESS_TOKEN, REFRESH_TOKEN, EXPIRED_TIME, ).values( clientId, userName, + grantType, accessToken, refreshToken, expiredTime diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt index 10ffbe51682..c499d4b5863 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt @@ -12,18 +12,24 @@ class Oauth2AccessTokenService constructor( ) { fun get( clientId: String, - userName: String? = null + refreshToken: String? = null, + userName: String? = null, + grantType: String? = null ): TAuthOauth2AccessTokenRecord? { return oauth2AccessTokenDao.get( dslContext = dslContext, clientId = clientId, - userName = userName + refreshToken = refreshToken, + userName = userName, + grantType = grantType ) } + @Suppress("LongParameterList") fun create( clientId: String, userName: String?, + grantType: String, accessToken: String, refreshToken: String?, expiredTime: Long @@ -32,6 +38,7 @@ class Oauth2AccessTokenService constructor( dslContext = dslContext, clientId = clientId, userName = userName, + grantType = grantType, accessToken = accessToken, refreshToken = refreshToken, expiredTime = expiredTime @@ -44,11 +51,4 @@ class Oauth2AccessTokenService constructor( accessToken = accessToken ) } - - fun deleteByRefreshToken(refreshToken: String) { - oauth2AccessTokenDao.deleteByRefreshToken( - dslContext = dslContext, - refreshToken = refreshToken - ) - } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt index b83b5b1dd35..8553aa649db 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt @@ -52,11 +52,11 @@ class Oauth2ClientService constructor( ): Boolean { val authorizedGrantTypes = clientDetails.authorizedGrantTypes.split(",") if (grantType != null && !authorizedGrantTypes.contains(grantType)) { - logger.warn("The client($clientId) does not support the authorization code type") + logger.warn("The client($clientId) does not support $grantType type") throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_AUTHORIZATION_TYPE, params = arrayOf(clientId), - defaultMessage = "The client($clientId) does not support the authorization code type" + defaultMessage = "The client($clientId) does not not support $grantType type" ) } if (redirectUri != null && redirectUri != clientDetails.redirectUri) { diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index 6e7e1b66e4e..78e64a7963f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -59,6 +59,7 @@ abstract class AbstractTokenGranter( accessTokenService.create( clientId = clientId, userName = accessTokenDTO.userName, + grantType = grantType, accessToken = newAccessToken, refreshToken = refreshToken, expiredTime = accessTokenExpiredTime diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 6a3d3f1700c..53d7bc2bd69 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -26,7 +26,8 @@ class ClientCredentialsTokenGranter constructor( logger.info("client credentials getAccessToken|$accessTokenRequest|$clientDetails") // 1、根据appcode获取accessToken val accessTokenInfo = accessTokenService.get( - clientId = accessTokenRequest.clientId + clientId = accessTokenRequest.clientId, + grantType = GRANT_TYPE ) return Oauth2AccessTokenDTO( accessToken = accessTokenInfo?.accessToken, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index 1cc7089ae64..9d766f71fdd 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -48,9 +48,17 @@ class RefreshTokenGranter( defaultMessage = "The authorization code invalid" ) } - //4.清除跟该refresh_token授权码相关的access_token - accessTokenService.deleteByRefreshToken( + // 根据refresh_token获取access_token,获取access_token中的user_name + val accessTokenInfo = accessTokenService.get( + clientId = accessTokenRequest.clientId, refreshToken = accessTokenRequest.refreshToken!! + )?: throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_REFRESH_TOKEN, + defaultMessage = "The refresh token invalid" + ) + //4.清除跟该refresh_token授权码相关的access_token + accessTokenService.delete( + accessToken = accessTokenInfo.accessToken ) //5.校验refresh_token是否过期 if (AuthUtils.isExpired(refreshTokenInfo.expiredTime)) { @@ -59,6 +67,8 @@ class RefreshTokenGranter( defaultMessage = "The refresh token has expired!" ) } - return Oauth2AccessTokenDTO() + return Oauth2AccessTokenDTO( + userName = accessTokenInfo.userName + ) } } From 81a06a8a042847f03232e49fed8c60494a87c27e Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 27 Jul 2023 11:32:53 +0800 Subject: [PATCH 18/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oauth2/Oauth2RefreshTokenService.kt | 10 ++++-- .../grant/ClientCredentialsTokenGranter.kt | 1 - .../oauth2/grant/RefreshTokenGranter.kt | 31 ++++++++----------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt index d0c7f15ee0c..34202e60230 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2RefreshTokenService.kt @@ -1,5 +1,6 @@ package com.tencent.devops.auth.service.oauth2 +import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_NOT_FOUND import com.tencent.devops.auth.constant.AuthMessageCode.INVALID_REFRESH_TOKEN import com.tencent.devops.auth.dao.AuthOauth2RefreshTokenDao import com.tencent.devops.common.api.exception.ErrorCodeException @@ -12,13 +13,18 @@ class Oauth2RefreshTokenService constructor( private val authOauth2RefreshTokenDao: AuthOauth2RefreshTokenDao, private val dslContext: DSLContext ) { - fun get(refreshToken: String): TAuthOauth2RefreshTokenRecord? { + fun get(refreshToken: String?): TAuthOauth2RefreshTokenRecord? { + if (refreshToken == null) + throw ErrorCodeException( + errorCode = ERROR_REFRESH_TOKEN_NOT_FOUND, + defaultMessage = "The refresh token must be provided" + ) return authOauth2RefreshTokenDao.get( dslContext = dslContext, refreshToken = refreshToken ) ?: throw ErrorCodeException( errorCode = INVALID_REFRESH_TOKEN, - defaultMessage = "The authorization code invalid" + defaultMessage = "The refresh token invalid" ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 53d7bc2bd69..47cc485e3c9 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -24,7 +24,6 @@ class ClientCredentialsTokenGranter constructor( clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO { logger.info("client credentials getAccessToken|$accessTokenRequest|$clientDetails") - // 1、根据appcode获取accessToken val accessTokenInfo = accessTokenService.get( clientId = accessTokenRequest.clientId, grantType = GRANT_TYPE diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index 9d766f71fdd..a3a17d5cdd2 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -2,7 +2,6 @@ package com.tencent.devops.auth.service.oauth2.grant import com.tencent.devops.auth.constant.AuthMessageCode import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_EXPIRED -import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_NOT_FOUND import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO @@ -31,44 +30,40 @@ class RefreshTokenGranter( clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO { logger.info("refresh token getAccessToken|$accessTokenRequest|$clientDetails") - //1.校验refresh_token是否为空 val refreshToken = accessTokenRequest.refreshToken - ?: throw ErrorCodeException( - errorCode = ERROR_REFRESH_TOKEN_NOT_FOUND, - defaultMessage = "The refresh token must be provided" - ) - // 2.校验refresh_token是否存在 + // 1.校验refresh_token是否存在 val refreshTokenInfo = refreshTokenService.get( refreshToken = refreshToken )!! - // 3.校验refresh_token是否跟client_id匹配 + // 2.校验refresh_token是否跟client_id匹配 if (refreshTokenInfo.clientId != accessTokenRequest.clientId) { throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_REFRESH_TOKEN, - defaultMessage = "The authorization code invalid" + defaultMessage = "The refresh token invalid" ) } - // 根据refresh_token获取access_token,获取access_token中的user_name + // 3.根据refresh_token获取access_token,获取access_token中的user_name val accessTokenInfo = accessTokenService.get( clientId = accessTokenRequest.clientId, - refreshToken = accessTokenRequest.refreshToken!! - )?: throw ErrorCodeException( + refreshToken = accessTokenRequest.refreshToken + ) ?: throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_REFRESH_TOKEN, defaultMessage = "The refresh token invalid" ) - //4.清除跟该refresh_token授权码相关的access_token - accessTokenService.delete( - accessToken = accessTokenInfo.accessToken - ) - //5.校验refresh_token是否过期 + // 4.校验refresh_token是否过期 if (AuthUtils.isExpired(refreshTokenInfo.expiredTime)) { + // 5.删除掉refresh_token + refreshTokenService.delete(refreshToken = refreshToken) throw ErrorCodeException( errorCode = ERROR_REFRESH_TOKEN_EXPIRED, defaultMessage = "The refresh token has expired!" ) } return Oauth2AccessTokenDTO( - userName = accessTokenInfo.userName + accessToken = accessTokenInfo.accessToken, + userName = accessTokenInfo.userName, + expiredTime = 0L, + refreshToken = refreshToken ) } } From 9d2e855e1faa21fab788ad8a210888fa99dadbdd Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 27 Jul 2023 12:27:54 +0800 Subject: [PATCH 19/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/devops/auth/constant/AuthMessageCode.kt | 7 ++++--- .../devops/auth/service/oauth2/Oauth2CodeService.kt | 2 +- .../service/oauth2/grant/AuthorizationCodeTokenGranter.kt | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt index 86054c47bc0..f35b238c0c3 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt @@ -116,7 +116,8 @@ object AuthMessageCode { const val INVALID_REDIRECT_URI = "2121066" // 跳转链接{0}不合法 const val INVALID_CLIENT_SECRET = "2121067" // 客户端{0}密钥不合法 const val INVALID_AUTHORIZATION_CODE = "2121068" // 授权码不合法 - const val ERROR_REFRESH_TOKEN_NOT_FOUND = "2121069" // refresh_token不能为空 - const val INVALID_REFRESH_TOKEN = "2121070" // refresh_token不合法 - const val ERROR_REFRESH_TOKEN_EXPIRED = "2121071" // refresh token已过期 + const val INVALID_AUTHORIZATION_EXPIRED = "2121069" // 授权码已过期 + const val ERROR_REFRESH_TOKEN_NOT_FOUND = "2121070" // refresh_token不能为空 + const val INVALID_REFRESH_TOKEN = "2121071" // refresh_token不合法 + const val ERROR_REFRESH_TOKEN_EXPIRED = "2121072" // refresh token已过期 } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt index 4c86b791235..76667c4f3b4 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt @@ -63,7 +63,7 @@ class Oauth2CodeService constructor( } if (AuthUtils.isExpired(codeDetails.expiredTime)) { throw ErrorCodeException( - errorCode = AuthMessageCode.INVALID_AUTHORIZATION_CODE, + errorCode = AuthMessageCode.INVALID_AUTHORIZATION_EXPIRED, defaultMessage = "The authorization code expired" ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index e376329169b..d61801ac430 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -48,7 +48,7 @@ class AuthorizationCodeTokenGranter constructor( clientId = clientId, userName = codeDetails.userName ) - val isAccessTokenValid = accessTokenInfo != null && AuthUtils.isExpired(accessTokenInfo.expiredTime) + val isAccessTokenValid = accessTokenInfo != null && !AuthUtils.isExpired(accessTokenInfo.expiredTime) val refreshToken = if (isAccessTokenValid) { // 若accessToken未过期,refreshToken不变 accessTokenInfo!!.refreshToken From f17b313f3b46286fb376a61c573f77b744148ba6 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 27 Jul 2023 14:29:54 +0800 Subject: [PATCH 20/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/service/oauth2/grant/AbstractTokenGranter.kt | 5 ++--- .../auth/service/oauth2/grant/RefreshTokenGranter.kt | 10 ++++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index 78e64a7963f..f1259645851 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -41,17 +41,16 @@ abstract class AbstractTokenGranter( clientDetails: ClientDetailsInfo ): Oauth2AccessTokenVo { // todo 记得要去掉改行日志,内包含敏感信息 - logger.info("AbstractTokenGranter|handleAccessToken:$accessTokenRequest|$accessTokenDTO|$clientDetails") + logger.info("handle access token:$accessTokenRequest|$accessTokenDTO|$clientDetails") val clientId = accessTokenRequest.clientId val accessToken = accessTokenDTO.accessToken val refreshToken = accessTokenDTO.refreshToken if (accessToken == null || AuthUtils.isExpired(accessTokenDTO.expiredTime!!)) { - // 生成新的 access_token val newAccessToken = UUIDUtil.generate() val accessTokenValidity = clientDetails.accessTokenValidity val accessTokenExpiredTime = DateTimeUtil.getFutureTimestamp(accessTokenValidity) - // 删除旧的 access_token 记录 + // 删除过期的access_token记录 if (accessToken != null) { accessTokenService.delete(accessToken) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index a3a17d5cdd2..4056e176b4c 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -50,9 +50,13 @@ class RefreshTokenGranter( errorCode = AuthMessageCode.INVALID_REFRESH_TOKEN, defaultMessage = "The refresh token invalid" ) - // 4.校验refresh_token是否过期 + // 4.清除跟该refresh_token授权码相关的access_token + accessTokenService.delete( + accessToken = accessTokenInfo.accessToken + ) + // 5.校验refresh_token是否过期 if (AuthUtils.isExpired(refreshTokenInfo.expiredTime)) { - // 5.删除掉refresh_token + // 6.删除掉refresh_token refreshTokenService.delete(refreshToken = refreshToken) throw ErrorCodeException( errorCode = ERROR_REFRESH_TOKEN_EXPIRED, @@ -60,9 +64,7 @@ class RefreshTokenGranter( ) } return Oauth2AccessTokenDTO( - accessToken = accessTokenInfo.accessToken, userName = accessTokenInfo.userName, - expiredTime = 0L, refreshToken = refreshToken ) } From 97a985b800e7fb188f9b3b790ae869452c26d1ba Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 27 Jul 2023 15:11:07 +0800 Subject: [PATCH 21/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/service/oauth2/Oauth2EndpointService.kt | 4 ++-- .../auth/service/oauth2/grant/AbstractTokenGranter.kt | 10 +--------- .../oauth2/grant/AuthorizationCodeTokenGranter.kt | 2 -- .../oauth2/grant/ClientCredentialsTokenGranter.kt | 2 -- .../auth/service/oauth2/grant/RefreshTokenGranter.kt | 2 -- 5 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 0ab6ce4477e..9e79af54ce4 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -23,7 +23,7 @@ class Oauth2EndpointService constructor( clientId: String, redirectUri: String ): String { - logger.info("Oauth2EndpointService|getAuthorizationCode:$userId|$clientId|$redirectUri") + logger.info("get authorization code:$userId|$clientId|$redirectUri") // 1、校验clientId是否存在 val clientDetails = clientService.getClientDetails(clientId = clientId) // 2、校验客户端信息是否正确 @@ -49,7 +49,7 @@ class Oauth2EndpointService constructor( ): Oauth2AccessTokenVo? { val grantType = accessTokenRequest.grantType val clientId = accessTokenRequest.clientId - logger.info("Oauth2EndpointService|getAccessToken:$clientId|$grantType") + logger.info("get access token:$clientId|$grantType|$accessTokenRequest") val clientDetails = clientService.getClientDetails( clientId = clientId ) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index f1259645851..7ab08b60b75 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -22,8 +22,6 @@ abstract class AbstractTokenGranter( if (this.grantType != grantType) { return null } - // todo 记得要去掉改行日志,内包含敏感信息 - logger.info("AbstractTokenGranter|grant:$grantType|$accessTokenRequest") val accessTokenDTO = getAccessToken( accessTokenRequest = accessTokenRequest, clientDetails = clientDetails @@ -40,8 +38,6 @@ abstract class AbstractTokenGranter( accessTokenDTO: Oauth2AccessTokenDTO, clientDetails: ClientDetailsInfo ): Oauth2AccessTokenVo { - // todo 记得要去掉改行日志,内包含敏感信息 - logger.info("handle access token:$accessTokenRequest|$accessTokenDTO|$clientDetails") val clientId = accessTokenRequest.clientId val accessToken = accessTokenDTO.accessToken val refreshToken = accessTokenDTO.refreshToken @@ -54,7 +50,7 @@ abstract class AbstractTokenGranter( if (accessToken != null) { accessTokenService.delete(accessToken) } - // 创建新的 access_token 记录 + // 创建新的 access_token记录 accessTokenService.create( clientId = clientId, userName = accessTokenDTO.userName, @@ -74,8 +70,4 @@ abstract class AbstractTokenGranter( accessTokenRequest: Oauth2AccessTokenRequest, clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO - - companion object { - private val logger = LoggerFactory.getLogger(AbstractTokenGranter::class.java) - } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index d61801ac430..658793a9f77 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -23,14 +23,12 @@ class AuthorizationCodeTokenGranter constructor( ) { companion object { private const val GRANT_TYPE = "authorization_code" - private val logger = LoggerFactory.getLogger(AuthorizationCodeTokenGranter::class.java) } override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO { - logger.info("authorization code getAccessToken|$accessTokenRequest|$clientDetails") val clientId = accessTokenRequest.clientId val code = accessTokenRequest.code val codeDetails = codeService.get( diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 47cc485e3c9..af811104207 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -16,14 +16,12 @@ class ClientCredentialsTokenGranter constructor( ) { companion object { private const val GRANT_TYPE = "client_credentials" - private val logger = LoggerFactory.getLogger(ClientCredentialsTokenGranter::class.java) } override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO { - logger.info("client credentials getAccessToken|$accessTokenRequest|$clientDetails") val accessTokenInfo = accessTokenService.get( clientId = accessTokenRequest.clientId, grantType = GRANT_TYPE diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index 4056e176b4c..11efefc5d81 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -22,14 +22,12 @@ class RefreshTokenGranter( ) { companion object { private const val GRANT_TYPE = "refresh_token" - private val logger = LoggerFactory.getLogger(RefreshTokenGranter::class.java) } override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO { - logger.info("refresh token getAccessToken|$accessTokenRequest|$clientDetails") val refreshToken = accessTokenRequest.refreshToken // 1.校验refresh_token是否存在 val refreshTokenInfo = refreshTokenService.get( From dc46fd09f33c233e662655ff1ea9f9dd8fe033cd Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 28 Jul 2023 10:51:35 +0800 Subject: [PATCH 22/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/oauth2/Oauth2EndpointResource.kt | 10 +++++++++ .../resources/Oauth2EndpointResourceImpl.kt | 21 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt index 608b42ea401..a6994ce0fb5 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt @@ -21,6 +21,16 @@ import javax.ws.rs.core.MediaType @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) interface Oauth2EndpointResource { + @GET + @Path("/getHtml") + @ApiOperation("获取授权界面") + @Produces("text/html") + fun getHtml( + @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) + @ApiParam("待校验用户ID", required = true) + userId: String + ): String + @GET @Path("/getAuthorizationCode") @ApiOperation("获取授权码") diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt index 85804c1c1fb..36848fe92d2 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt @@ -11,6 +11,27 @@ import com.tencent.devops.common.web.RestResource class Oauth2EndpointResourceImpl constructor( private val endpointService: Oauth2EndpointService ) : Oauth2EndpointResource { + override fun getHtml(userId: String): String { + return """ + + + + OAuth2授权 + + +

授权信息:是否授权“行云”访问您在蓝盾的制品库

+ + + + + + """.trimIndent() + } + override fun getAuthorizationCode( userId: String, clientId: String, From c6cd13ff6566538905ca6b875aa395873e8b2b48 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 28 Jul 2023 11:37:03 +0800 Subject: [PATCH 23/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/oauth2/Oauth2EndpointResource.kt | 13 +++--- .../devops/auth/pojo/enum/Oauth2GrantType.kt | 40 +++++++++++++++++++ .../resources/Oauth2EndpointResourceImpl.kt | 20 ++++++++-- .../auth/service/oauth2/Oauth2CodeService.kt | 7 +--- .../service/oauth2/Oauth2EndpointService.kt | 6 ++- .../grant/AuthorizationCodeTokenGranter.kt | 7 +--- .../grant/ClientCredentialsTokenGranter.kt | 4 +- .../oauth2/grant/RefreshTokenGranter.kt | 8 +--- 8 files changed, 76 insertions(+), 29 deletions(-) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/enum/Oauth2GrantType.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt index a6994ce0fb5..086ba0a477e 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt @@ -22,13 +22,16 @@ import javax.ws.rs.core.MediaType @Consumes(MediaType.APPLICATION_JSON) interface Oauth2EndpointResource { @GET - @Path("/getHtml") + @Path("/getAuthorizationHtml") @ApiOperation("获取授权界面") @Produces("text/html") - fun getHtml( - @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) - @ApiParam("待校验用户ID", required = true) - userId: String + fun getAuthorizationHtml( + @QueryParam("clientId") + @ApiParam("客户端ID", required = true) + clientId: String, + @QueryParam("redirectUri") + @ApiParam("跳转链接", required = true) + redirectUri: String ): String @GET diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/enum/Oauth2GrantType.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/enum/Oauth2GrantType.kt new file mode 100644 index 00000000000..73fa82bcd28 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/enum/Oauth2GrantType.kt @@ -0,0 +1,40 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.auth.pojo.enum + +enum class Oauth2GrantType(val grantType: String) { + // 授权码模式 + AUTHORIZATION_CODE("authorization_code"), + + // 客户端模式 + CLIENT_CREDENTIALS("client_credentials"), + + // 刷新token模式 + REFRESH_TOKEN("refresh_token"); +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt index 36848fe92d2..cfbb0038ff3 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt @@ -11,20 +11,32 @@ import com.tencent.devops.common.web.RestResource class Oauth2EndpointResourceImpl constructor( private val endpointService: Oauth2EndpointService ) : Oauth2EndpointResource { - override fun getHtml(userId: String): String { + override fun getAuthorizationHtml( + clientId: String, + redirectUri: String + ): String { return """ - OAuth2授权 + OAuth2 授权

授权信息:是否授权“行云”访问您在蓝盾的制品库

- + diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt index 76667c4f3b4..bff727970f8 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt @@ -40,7 +40,8 @@ class Oauth2CodeService constructor( fun create( userId: String, code: String, - clientId: String + clientId: String, + codeValiditySeconds: Long ) { authOauth2CodeDao.create( dslContext = dslContext, @@ -69,8 +70,4 @@ class Oauth2CodeService constructor( } return true } - - companion object { - private const val codeValiditySeconds = 300L - } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 9e79af54ce4..c28910c4dea 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -1,6 +1,7 @@ package com.tencent.devops.auth.service.oauth2 import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.enum.Oauth2GrantType import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.service.oauth2.grant.TokenGranter import com.tencent.devops.common.api.util.UUIDUtil @@ -15,7 +16,7 @@ class Oauth2EndpointService constructor( ) { companion object { private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) - private const val AUTHORIZATION_CODE_TYPE = "authorization_code" + private const val codeValiditySeconds = 300L } fun getAuthorizationCode( @@ -30,7 +31,7 @@ class Oauth2EndpointService constructor( clientService.verifyClientInformation( clientId = clientId, redirectUri = redirectUri, - grantType = AUTHORIZATION_CODE_TYPE, + grantType = Oauth2GrantType.AUTHORIZATION_CODE.grantType, clientDetails = clientDetails ) // 3、生成授权码并存储数据库,授权码有效期为5分钟 @@ -39,6 +40,7 @@ class Oauth2EndpointService constructor( userId = userId, code = code, clientId = clientId, + codeValiditySeconds = codeValiditySeconds ) // 4、返回跳转链接及授权码 return "$redirectUri?code=$code" diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index 658793a9f77..76a97cd1df9 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -3,6 +3,7 @@ package com.tencent.devops.auth.service.oauth2.grant import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.enum.Oauth2GrantType import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService import com.tencent.devops.auth.service.oauth2.Oauth2CodeService import com.tencent.devops.auth.service.oauth2.Oauth2RefreshTokenService @@ -18,13 +19,9 @@ class AuthorizationCodeTokenGranter constructor( private val accessTokenService: Oauth2AccessTokenService, private val refreshTokenService: Oauth2RefreshTokenService ) : AbstractTokenGranter( - grantType = GRANT_TYPE, + grantType = Oauth2GrantType.AUTHORIZATION_CODE.grantType, accessTokenService = accessTokenService ) { - companion object { - private const val GRANT_TYPE = "authorization_code" - } - override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, clientDetails: ClientDetailsInfo diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index af811104207..17ad72275d3 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -3,8 +3,8 @@ package com.tencent.devops.auth.service.oauth2.grant import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.enum.Oauth2GrantType import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService -import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service @@ -15,7 +15,7 @@ class ClientCredentialsTokenGranter constructor( accessTokenService = accessTokenService ) { companion object { - private const val GRANT_TYPE = "client_credentials" + private val GRANT_TYPE = Oauth2GrantType.CLIENT_CREDENTIALS.grantType } override fun getAccessToken( diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index 11efefc5d81..58146c48921 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -5,11 +5,11 @@ import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_EXPI import com.tencent.devops.auth.pojo.ClientDetailsInfo import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO +import com.tencent.devops.auth.pojo.enum.Oauth2GrantType import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService import com.tencent.devops.auth.service.oauth2.Oauth2RefreshTokenService import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.common.auth.utils.AuthUtils -import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service @@ -17,13 +17,9 @@ class RefreshTokenGranter( private val accessTokenService: Oauth2AccessTokenService, private val refreshTokenService: Oauth2RefreshTokenService ) : AbstractTokenGranter( - grantType = GRANT_TYPE, + grantType = Oauth2GrantType.REFRESH_TOKEN.grantType, accessTokenService = accessTokenService ) { - companion object { - private const val GRANT_TYPE = "refresh_token" - } - override fun getAccessToken( accessTokenRequest: Oauth2AccessTokenRequest, clientDetails: ClientDetailsInfo From f1df3982024d682356b0ba7e27ecaef331b9659a Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 28 Jul 2023 11:54:53 +0800 Subject: [PATCH 24/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/auth/service/oauth2/Oauth2CodeService.kt | 10 ++++++---- .../auth/service/oauth2/grant/AbstractTokenGranter.kt | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt index bff727970f8..8245b1fd410 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt @@ -17,10 +17,12 @@ class Oauth2CodeService constructor( fun get( code: String? ): TAuthOauth2CodeRecord { - code ?: throw ErrorCodeException( - errorCode = AuthMessageCode.INVALID_AUTHORIZATION_CODE, - defaultMessage = "The authorization code must be provided" - ) + if (code == null) { + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_AUTHORIZATION_CODE, + defaultMessage = "The authorization code must be provided" + ) + } return authOauth2CodeDao.get( dslContext = dslContext, code = code diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index 7ab08b60b75..1200a94dc18 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -42,6 +42,7 @@ abstract class AbstractTokenGranter( val accessToken = accessTokenDTO.accessToken val refreshToken = accessTokenDTO.refreshToken + // 若access_token为空或者已过期,则重新生成access_token if (accessToken == null || AuthUtils.isExpired(accessTokenDTO.expiredTime!!)) { val newAccessToken = UUIDUtil.generate() val accessTokenValidity = clientDetails.accessTokenValidity From 0469320fbeb2e15ab15c52b20e5631287f47255a Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 28 Jul 2023 15:39:23 +0800 Subject: [PATCH 25/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/constant/AuthMessageCode.kt | 1 - .../devops/auth/service/oauth2/Oauth2ClientService.kt | 4 ++-- support-files/i18n/auth/message_en_US.properties | 10 ++++++++++ support-files/i18n/auth/message_zh_CN.properties | 10 ++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt index f35b238c0c3..d3b257cf3ee 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt @@ -110,7 +110,6 @@ object AuthMessageCode { const val ERROR_MIGRATE_AUTH_COMPARE_FAIL = "2121061" // 迁移项目{0}失败,权限策略对比失败 const val ERROR_CREATOR_NOT_EXIST = "2121062" // 创建人离职 const val ERROR_RESOURCE_CREATE_FAIL = "2121063" // 资源创建失败 - const val ERROR_CLIENT_NOT_EXIST = "2121064" // 客户端{0}不存在 const val INVALID_AUTHORIZATION_TYPE = "2121065" // 授权类型{0}不合法 const val INVALID_REDIRECT_URI = "2121066" // 跳转链接{0}不合法 diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt index 8553aa649db..39ea90b3bd3 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt @@ -56,7 +56,7 @@ class Oauth2ClientService constructor( throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_AUTHORIZATION_TYPE, params = arrayOf(clientId), - defaultMessage = "The client($clientId) does not not support $grantType type" + defaultMessage = "The client($clientId) does not support $grantType type" ) } if (redirectUri != null && redirectUri != clientDetails.redirectUri) { @@ -64,7 +64,7 @@ class Oauth2ClientService constructor( throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_REDIRECT_URI, params = arrayOf(redirectUri), - defaultMessage = "The redirectUri($redirectUri) is invalid" + defaultMessage = "The redirect uri($redirectUri) is invalid" ) } if (clientSecret != null && clientSecret != clientDetails.clientSecret) { diff --git a/support-files/i18n/auth/message_en_US.properties b/support-files/i18n/auth/message_en_US.properties index f262fa37046..e96fb91323f 100644 --- a/support-files/i18n/auth/message_en_US.properties +++ b/support-files/i18n/auth/message_en_US.properties @@ -60,6 +60,16 @@ 2121060=User group: {0}, migrated to {1} 2121061=Migration project {0} failed, permission policy comparison failed 2121062=The founder has left the company +2121063=Create resource failed +2121064=The client not exists +2121065=The client does not support this grant type +2121066=The redirect uri is invalid +2121067=The client secret is invalid +2121068=The authorization code invalid +2121069=The authorization code expired +2121070=The refresh token must be provided +2121071=The refresh token invalid +2121072=The refresh token has expired bkAdministratorNotExpired=Permission has not expired and no action is required bkAgreeRenew=Agree to renew bkApproverAgreeRenew=Approver agreed to your permission renewal diff --git a/support-files/i18n/auth/message_zh_CN.properties b/support-files/i18n/auth/message_zh_CN.properties index 43e16335692..2da950da5e5 100644 --- a/support-files/i18n/auth/message_zh_CN.properties +++ b/support-files/i18n/auth/message_zh_CN.properties @@ -60,6 +60,16 @@ 2121060=用户组:{0},迁移于{1} 2121061=迁移项目{0}失败,权限策略对比失败 2121062=创建人已离职 +2121063=资源创建失败 +2121064=客户端{0}不存在 +2121065=授权类型{0}不合法 +2121066=跳转链接{0}不合法 +2121067=客户端{0}密钥不合法 +2121068=授权码不合法 +2121069=授权码已过期 +2121070=refresh token不能为空 +2121071=refresh token不合法 +2121072=refresh token已过期 bkAdministratorNotExpired=权限还未过期,不需要操作 bkAgreeRenew=同意续期 bkApproverAgreeRenew=审批人同意了您的权限续期 From 413a279cc39c7a5c869cbefecc32241529bc2f5d Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 28 Jul 2023 16:43:27 +0800 Subject: [PATCH 26/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt index 086ba0a477e..2d05544f515 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt @@ -17,7 +17,7 @@ import javax.ws.rs.QueryParam import javax.ws.rs.core.MediaType @Api(tags = ["OAUTH2_ENDPOINT"], description = "oauth2相关") -@Path("user/oauth2/endpoint") +@Path("desktop/oauth2/endpoint") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) interface Oauth2EndpointResource { From 8c2fe1704dae2ffb21e5611b6be7c8b2ba14df85 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 2 Aug 2023 11:46:13 +0800 Subject: [PATCH 27/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/oauth2/Oauth2EndpointResource.kt | 20 +++---- .../devops/auth/pojo/ClientDetailsInfo.kt | 2 + .../auth/pojo/vo/Oauth2AuthorizationInfoVo.kt | 14 +++++ .../resources/Oauth2EndpointResourceImpl.kt | 42 ++++--------- .../service/oauth2/Oauth2ClientService.kt | 1 + .../service/oauth2/Oauth2EndpointService.kt | 59 ++++++++++++++++++- 6 files changed, 96 insertions(+), 42 deletions(-) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt index 2d05544f515..6484963567e 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt @@ -2,6 +2,7 @@ package com.tencent.devops.auth.api.oauth2 import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID import com.tencent.devops.common.api.pojo.Result import io.swagger.annotations.Api @@ -22,19 +23,18 @@ import javax.ws.rs.core.MediaType @Consumes(MediaType.APPLICATION_JSON) interface Oauth2EndpointResource { @GET - @Path("/getAuthorizationHtml") - @ApiOperation("获取授权界面") - @Produces("text/html") - fun getAuthorizationHtml( + @Path("/getAuthorizationInformation") + @ApiOperation("获取授权信息") + fun getAuthorizationInformation( + @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) + @ApiParam("待校验用户ID", required = true) + userId: String, @QueryParam("clientId") @ApiParam("客户端ID", required = true) - clientId: String, - @QueryParam("redirectUri") - @ApiParam("跳转链接", required = true) - redirectUri: String - ): String + clientId: String + ): Result - @GET + @POST @Path("/getAuthorizationCode") @ApiOperation("获取授权码") fun getAuthorizationCode( diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt index 3e826dcf100..9a04a5a5600 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt @@ -9,6 +9,8 @@ data class ClientDetailsInfo( val clientId: String, @ApiModelProperty("客户端密钥", required = true) val clientSecret: String, + @ApiModelProperty("客户端名称", required = true) + val clientName: String, @ApiModelProperty("授权类型", required = true) val authorizedGrantTypes: String, @ApiModelProperty("跳转链接", required = true) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt new file mode 100644 index 00000000000..8685703cd2e --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt @@ -0,0 +1,14 @@ +package com.tencent.devops.auth.pojo.vo + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("oauth2获取授权信息请求返回体") +data class Oauth2AuthorizationInfoVo( + @ApiModelProperty("用户名称", required = true) + val userName: String, + @ApiModelProperty("客户端名称", required = true) + val clientName: String, + @ApiModelProperty("授权范围", required = true) + val scope: Map +) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt index cfbb0038ff3..34e4338972b 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt @@ -3,6 +3,7 @@ package com.tencent.devops.auth.resources import com.tencent.devops.auth.api.oauth2.Oauth2EndpointResource import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo import com.tencent.devops.auth.service.oauth2.Oauth2EndpointService import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.web.RestResource @@ -11,37 +12,16 @@ import com.tencent.devops.common.web.RestResource class Oauth2EndpointResourceImpl constructor( private val endpointService: Oauth2EndpointService ) : Oauth2EndpointResource { - override fun getAuthorizationHtml( - clientId: String, - redirectUri: String - ): String { - return """ - - - - OAuth2 授权 - - -

授权信息:是否授权“行云”访问您在蓝盾的制品库

- - - - - - """.trimIndent() + override fun getAuthorizationInformation( + userId: String, + clientId: String + ): Result { + return Result( + endpointService.getAuthorizationInformation( + userId = userId, + clientId = clientId + ) + ) } override fun getAuthorizationCode( diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt index 39ea90b3bd3..6a6c54fa07d 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt @@ -34,6 +34,7 @@ class Oauth2ClientService constructor( return ClientDetailsInfo( clientId = clientId, clientSecret = clientSecret, + clientName = clientName, scope = scope, authorizedGrantTypes = authorizedGrantTypes, redirectUri = webServerRedirectUri, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index c28910c4dea..1c445c07ea4 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -1,24 +1,62 @@ package com.tencent.devops.auth.service.oauth2 +import com.github.benmanes.caffeine.cache.Caffeine +import com.tencent.devops.auth.constant.AuthMessageCode +import com.tencent.devops.auth.dao.AuthActionDao import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.enum.Oauth2GrantType +import com.tencent.devops.auth.pojo.vo.ActionInfoVo import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo import com.tencent.devops.auth.service.oauth2.grant.TokenGranter +import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.common.api.util.UUIDUtil +import org.jooq.DSLContext import org.slf4j.LoggerFactory import org.springframework.stereotype.Service +import java.util.concurrent.TimeUnit @Service class Oauth2EndpointService constructor( private val tokenGranter: TokenGranter, private val clientService: Oauth2ClientService, - private val codeService: Oauth2CodeService + private val codeService: Oauth2CodeService, + private val dslContext: DSLContext, + private val authActionDao: AuthActionDao ) { companion object { private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) private const val codeValiditySeconds = 300L } + private val actionCache = Caffeine.newBuilder() + .maximumSize(500) + .expireAfterWrite(7L, TimeUnit.DAYS) + .build() + + fun getAuthorizationInformation( + userId: String, + clientId: String + ): Oauth2AuthorizationInfoVo { + logger.info("get authorization information:$clientId") + // 1、校验clientId是否存在 + val clientDetails = clientService.getClientDetails(clientId = clientId) + // 2、校验客户端信息是否正确 + clientService.verifyClientInformation( + clientId = clientId, + grantType = Oauth2GrantType.AUTHORIZATION_CODE.grantType, + clientDetails = clientDetails + ) + val scope = clientDetails.scope.split(",") + .associate { getActionInfo(it).actionName.let { actionName -> it to actionName } } + + return Oauth2AuthorizationInfoVo( + userName = userId, + clientName = clientDetails.clientName, + scope = scope + ) + } + fun getAuthorizationCode( userId: String, clientId: String, @@ -67,4 +105,23 @@ class Oauth2EndpointService constructor( accessTokenRequest = accessTokenRequest ) } + + private fun getActionInfo(action: String): ActionInfoVo { + if (actionCache.getIfPresent(action) == null) { + val actionRecord = authActionDao.get(dslContext, action) + ?: throw ErrorCodeException( + errorCode = AuthMessageCode.ACTION_NOT_EXIST, + params = arrayOf(action), + defaultMessage = "the action($action) does not exist" + ) + val actionInfo = ActionInfoVo( + action = actionRecord.action, + actionName = actionRecord.actionName, + resourceType = actionRecord.resourceType, + relatedResourceType = actionRecord.relatedResourceType + ) + actionCache.put(action, actionInfo) + } + return actionCache.getIfPresent(action)!! + } } From 39cb06cbfa4de3af0a4971b81296dd1e2a01f7fb Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 2 Aug 2023 11:49:37 +0800 Subject: [PATCH 28/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 1c445c07ea4..70f28c811d7 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -38,7 +38,7 @@ class Oauth2EndpointService constructor( userId: String, clientId: String ): Oauth2AuthorizationInfoVo { - logger.info("get authorization information:$clientId") + logger.info("get authorization information:$userId|$clientId") // 1、校验clientId是否存在 val clientDetails = clientService.getClientDetails(clientId = clientId) // 2、校验客户端信息是否正确 From 0a77d2b072eac74694a24eeb94e5e574d8a5c642 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 2 Aug 2023 11:58:47 +0800 Subject: [PATCH 29/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/auth/service/oauth2/Oauth2Config.kt | 11 +++++++++-- .../auth/service/oauth2/Oauth2EndpointService.kt | 1 - 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt index 4ed800836b4..9b55d44f3e6 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -1,27 +1,34 @@ package com.tencent.devops.auth.service.oauth2 +import com.tencent.devops.auth.dao.AuthActionDao import com.tencent.devops.auth.service.oauth2.grant.AuthorizationCodeTokenGranter import com.tencent.devops.auth.service.oauth2.grant.ClientCredentialsTokenGranter import com.tencent.devops.auth.service.oauth2.grant.CompositeTokenGranter import com.tencent.devops.auth.service.oauth2.grant.RefreshTokenGranter import com.tencent.devops.auth.service.oauth2.grant.TokenGranter +import org.jooq.DSLContext import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration +@Suppress("LongParameterList") class Oauth2Config constructor( private val oauth2ClientService: Oauth2ClientService, private val codeService: Oauth2CodeService, private val clientCredentialsTokenGranter: ClientCredentialsTokenGranter, private val authorizationCodeTokenGranter: AuthorizationCodeTokenGranter, - private val refreshTokenGranter: RefreshTokenGranter + private val refreshTokenGranter: RefreshTokenGranter, + private val dslContext: DSLContext, + private val authActionDao: AuthActionDao ) { @Bean fun oauth2EndpointService(): Oauth2EndpointService { return Oauth2EndpointService( tokenGranter = compositeTokenGranter(), clientService = oauth2ClientService, - codeService = codeService + codeService = codeService, + dslContext = dslContext, + authActionDao = authActionDao ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 70f28c811d7..4cbc49a0ddd 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -16,7 +16,6 @@ import org.slf4j.LoggerFactory import org.springframework.stereotype.Service import java.util.concurrent.TimeUnit -@Service class Oauth2EndpointService constructor( private val tokenGranter: TokenGranter, private val clientService: Oauth2ClientService, From e56103882562e9d5e3e9c9e7656fe6d28fa17950 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 3 Aug 2023 12:06:23 +0800 Subject: [PATCH 30/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/oauth2/Oauth2EndpointResource.kt | 7 ++- .../devops/auth/constant/AuthMessageCode.kt | 4 ++ .../auth/pojo/dto/Oauth2AccessTokenDTO.kt | 4 +- .../pojo/dto/Oauth2AuthorizationCodeDTO.kt | 10 +++ .../auth/pojo/vo/Oauth2AuthorizationInfoVo.kt | 2 +- .../auth/dao/AuthOauth2AccessTokenDao.kt | 38 ++++++----- .../devops/auth/dao/AuthOauth2CodeDao.kt | 4 ++ .../devops/auth/dao/AuthOauth2ScopeDao.kt | 23 +++++++ .../resources/Oauth2EndpointResourceImpl.kt | 7 ++- .../oauth2/Oauth2AccessTokenService.kt | 17 ++++- .../service/oauth2/Oauth2ClientService.kt | 11 +++- .../auth/service/oauth2/Oauth2CodeService.kt | 2 + .../auth/service/oauth2/Oauth2Config.kt | 8 +-- .../service/oauth2/Oauth2EndpointService.kt | 63 ++++++------------- .../auth/service/oauth2/Oauth2ScopeService.kt | 20 ++++++ .../oauth2/grant/AbstractTokenGranter.kt | 9 ++- .../grant/AuthorizationCodeTokenGranter.kt | 50 +++++++++++---- .../grant/ClientCredentialsTokenGranter.kt | 11 +++- .../oauth2/grant/RefreshTokenGranter.kt | 3 +- 19 files changed, 200 insertions(+), 93 deletions(-) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AuthorizationCodeDTO.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeDao.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeService.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt index 6484963567e..b55e7df962e 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt @@ -1,6 +1,7 @@ package com.tencent.devops.auth.api.oauth2 import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.dto.Oauth2AuthorizationCodeDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID @@ -18,7 +19,7 @@ import javax.ws.rs.QueryParam import javax.ws.rs.core.MediaType @Api(tags = ["OAUTH2_ENDPOINT"], description = "oauth2相关") -@Path("desktop/oauth2/endpoint") +@Path("user/oauth2/endpoint") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) interface Oauth2EndpointResource { @@ -46,7 +47,9 @@ interface Oauth2EndpointResource { clientId: String, @QueryParam("redirectUri") @ApiParam("跳转链接", required = true) - redirectUri: String + redirectUri: String, + @ApiParam("oauth2获取授权码请求报文体", required = true) + authorizationCodeDTO: Oauth2AuthorizationCodeDTO ): Result @POST diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt index d3b257cf3ee..6c139776fc5 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt @@ -119,4 +119,8 @@ object AuthMessageCode { const val ERROR_REFRESH_TOKEN_NOT_FOUND = "2121070" // refresh_token不能为空 const val INVALID_REFRESH_TOKEN = "2121071" // refresh_token不合法 const val ERROR_REFRESH_TOKEN_EXPIRED = "2121072" // refresh token已过期 + const val ERROR_ACCESS_TOKEN_NOT_FOUND = "2121073" // access token不能为空 + const val INVALID_ACCESS_TOKEN = "2121074" // access token不合法 + const val ERROR_ACCESS_TOKEN_EXPIRED = "2121075" // access token已过期 + const val INVALID_SCOPE = "2121076" // scope不合法 } diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt index 8c8964c69e9..677db2cad8f 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AccessTokenDTO.kt @@ -12,5 +12,7 @@ data class Oauth2AccessTokenDTO( @ApiModelProperty("accessToken过期时间", required = true) val expiredTime: Long? = null, @ApiModelProperty("accessToken绑定的用户名称", required = true) - val userName: String? = null + val userName: String? = null, + @ApiModelProperty("授权范围Id", required = true) + val scopeId: Int ) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AuthorizationCodeDTO.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AuthorizationCodeDTO.kt new file mode 100644 index 00000000000..36e0084032c --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/Oauth2AuthorizationCodeDTO.kt @@ -0,0 +1,10 @@ +package com.tencent.devops.auth.pojo.dto + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("oauth2获取授权码请求报文体") +data class Oauth2AuthorizationCodeDTO( + @ApiModelProperty("授权范围", required = true) + val scope: List +) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt index 8685703cd2e..72a9b2f30c6 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt @@ -10,5 +10,5 @@ data class Oauth2AuthorizationInfoVo( @ApiModelProperty("客户端名称", required = true) val clientName: String, @ApiModelProperty("授权范围", required = true) - val scope: Map + val scope: Map ) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt index 1fb9f4d6cc2..07782b0615f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt @@ -18,23 +18,11 @@ class AuthOauth2AccessTokenDao { dslContext.selectFrom(this).where( CLIENT_ID.eq(clientId) ).let { - if (userName != null) { - it.and(USER_NAME.eq(userName)) - } else { - it - } + if (userName != null) { it.and(USER_NAME.eq(userName)) } else { it } }.let { - if (grantType != null) { - it.and(GRANT_TYPE.eq(grantType)) - } else { - it - } + if (grantType != null) { it.and(GRANT_TYPE.eq(grantType)) } else { it } }.let { - if (refreshToken != null) { - it.and(REFRESH_TOKEN.eq(refreshToken)) - } else { - it - } + if (refreshToken != null) { it.and(REFRESH_TOKEN.eq(refreshToken)) } else { it } }.fetchOne() } } @@ -58,7 +46,8 @@ class AuthOauth2AccessTokenDao { grantType: String, accessToken: String, refreshToken: String? = null, - expiredTime: Long + expiredTime: Long, + scopeId: Int ): Int { return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { dslContext.insertInto( @@ -69,14 +58,29 @@ class AuthOauth2AccessTokenDao { ACCESS_TOKEN, REFRESH_TOKEN, EXPIRED_TIME, + SCOPE_ID ).values( clientId, userName, grantType, accessToken, refreshToken, - expiredTime + expiredTime, + scopeId ).execute() } } + + fun update( + dslContext: DSLContext, + accessToken: String, + scopeId: Int + ){ + return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { + dslContext.update(this) + .set(SCOPE_ID, scopeId) + .where(ACCESS_TOKEN.eq(accessToken)) + .execute() + } + } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt index 9bf2b27abba..8f181ecd47c 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2CodeDao.kt @@ -17,11 +17,13 @@ class AuthOauth2CodeDao { } } + @Suppress("LongParameterList") fun create( dslContext: DSLContext, code: String, userId: String, clientId: String, + scopeId: Int, expiredTime: Long ): Int { return with(TAuthOauth2Code.T_AUTH_OAUTH2_CODE) { @@ -29,11 +31,13 @@ class AuthOauth2CodeDao { this, CLIENT_ID, CODE, + SCOPE_ID, USER_NAME, EXPIRED_TIME ).values( clientId, code, + scopeId, userId, expiredTime ).execute() diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeDao.kt new file mode 100644 index 00000000000..5784cd3e822 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeDao.kt @@ -0,0 +1,23 @@ +package com.tencent.devops.auth.dao + +import com.tencent.devops.model.auth.tables.TAuthOauth2Scope +import org.jooq.DSLContext +import org.springframework.stereotype.Repository + +@Repository +class AuthOauth2ScopeDao { + fun create( + dslContext: DSLContext, + scope: String + ): Int { + return with(TAuthOauth2Scope.T_AUTH_OAUTH2_SCOPE) { + dslContext.insertInto( + this, + SCOPE + ).values( + scope + ).returning(ID) + .fetchOne()!!.id + } + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt index 34e4338972b..41b7a24ec10 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt @@ -2,6 +2,7 @@ package com.tencent.devops.auth.resources import com.tencent.devops.auth.api.oauth2.Oauth2EndpointResource import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.dto.Oauth2AuthorizationCodeDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo import com.tencent.devops.auth.service.oauth2.Oauth2EndpointService @@ -27,13 +28,15 @@ class Oauth2EndpointResourceImpl constructor( override fun getAuthorizationCode( userId: String, clientId: String, - redirectUri: String + redirectUri: String, + authorizationCodeDTO: Oauth2AuthorizationCodeDTO ): Result { return Result( endpointService.getAuthorizationCode( userId = userId, clientId = clientId, - redirectUri = redirectUri + redirectUri = redirectUri, + authorizationCodeDTO = authorizationCodeDTO ) ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt index c499d4b5863..67cc35a31f9 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt @@ -32,7 +32,8 @@ class Oauth2AccessTokenService constructor( grantType: String, accessToken: String, refreshToken: String?, - expiredTime: Long + expiredTime: Long, + scopeId: Int ) { oauth2AccessTokenDao.create( dslContext = dslContext, @@ -41,7 +42,8 @@ class Oauth2AccessTokenService constructor( grantType = grantType, accessToken = accessToken, refreshToken = refreshToken, - expiredTime = expiredTime + expiredTime = expiredTime, + scopeId = scopeId ) } @@ -51,4 +53,15 @@ class Oauth2AccessTokenService constructor( accessToken = accessToken ) } + + fun update( + accessToken: String, + scopeId: Int + ){ + oauth2AccessTokenDao.update( + dslContext = dslContext, + accessToken = accessToken, + scopeId = scopeId + ) + } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt index 6a6c54fa07d..7929ee465a7 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt @@ -43,13 +43,14 @@ class Oauth2ClientService constructor( ) } - @Suppress("ThrowsCount") + @Suppress("ThrowsCount", "LongParameterList") fun verifyClientInformation( clientId: String, clientDetails: ClientDetailsInfo, clientSecret: String? = null, redirectUri: String? = null, grantType: String? = null, + scope: List? = null ): Boolean { val authorizedGrantTypes = clientDetails.authorizedGrantTypes.split(",") if (grantType != null && !authorizedGrantTypes.contains(grantType)) { @@ -76,6 +77,14 @@ class Oauth2ClientService constructor( defaultMessage = "The client($clientId) secret is invalid" ) } + if (scope != null && !clientDetails.scope.split(",").containsAll(scope)) { + logger.warn("The client($clientId) scope is invalid") + throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_SCOPE, + params = arrayOf(clientId), + defaultMessage = "The client($clientId) scope is invalid" + ) + } return true } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt index 8245b1fd410..e3967406ae4 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeService.kt @@ -43,6 +43,7 @@ class Oauth2CodeService constructor( userId: String, code: String, clientId: String, + scopeId: Int, codeValiditySeconds: Long ) { authOauth2CodeDao.create( @@ -50,6 +51,7 @@ class Oauth2CodeService constructor( code = code, userId = userId, clientId = clientId, + scopeId = scopeId, expiredTime = DateTimeUtil.getFutureTimestamp(codeValiditySeconds) ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt index 9b55d44f3e6..265d0871c94 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -15,11 +15,10 @@ import org.springframework.context.annotation.Configuration class Oauth2Config constructor( private val oauth2ClientService: Oauth2ClientService, private val codeService: Oauth2CodeService, + private val scopeService: Oauth2ScopeService, private val clientCredentialsTokenGranter: ClientCredentialsTokenGranter, private val authorizationCodeTokenGranter: AuthorizationCodeTokenGranter, - private val refreshTokenGranter: RefreshTokenGranter, - private val dslContext: DSLContext, - private val authActionDao: AuthActionDao + private val refreshTokenGranter: RefreshTokenGranter ) { @Bean fun oauth2EndpointService(): Oauth2EndpointService { @@ -27,8 +26,7 @@ class Oauth2Config constructor( tokenGranter = compositeTokenGranter(), clientService = oauth2ClientService, codeService = codeService, - dslContext = dslContext, - authActionDao = authActionDao + scopeService = scopeService ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 4cbc49a0ddd..5b9dd2761c7 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -1,38 +1,20 @@ package com.tencent.devops.auth.service.oauth2 -import com.github.benmanes.caffeine.cache.Caffeine -import com.tencent.devops.auth.constant.AuthMessageCode -import com.tencent.devops.auth.dao.AuthActionDao import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.dto.Oauth2AuthorizationCodeDTO import com.tencent.devops.auth.pojo.enum.Oauth2GrantType -import com.tencent.devops.auth.pojo.vo.ActionInfoVo import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo import com.tencent.devops.auth.service.oauth2.grant.TokenGranter -import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.common.api.util.UUIDUtil -import org.jooq.DSLContext import org.slf4j.LoggerFactory -import org.springframework.stereotype.Service -import java.util.concurrent.TimeUnit class Oauth2EndpointService constructor( private val tokenGranter: TokenGranter, private val clientService: Oauth2ClientService, private val codeService: Oauth2CodeService, - private val dslContext: DSLContext, - private val authActionDao: AuthActionDao + private val scopeService: Oauth2ScopeService ) { - companion object { - private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) - private const val codeValiditySeconds = 300L - } - - private val actionCache = Caffeine.newBuilder() - .maximumSize(500) - .expireAfterWrite(7L, TimeUnit.DAYS) - .build() - fun getAuthorizationInformation( userId: String, clientId: String @@ -46,20 +28,18 @@ class Oauth2EndpointService constructor( grantType = Oauth2GrantType.AUTHORIZATION_CODE.grantType, clientDetails = clientDetails ) - val scope = clientDetails.scope.split(",") - .associate { getActionInfo(it).actionName.let { actionName -> it to actionName } } - return Oauth2AuthorizationInfoVo( userName = userId, clientName = clientDetails.clientName, - scope = scope + scope = SCOPE ) } fun getAuthorizationCode( userId: String, clientId: String, - redirectUri: String + redirectUri: String, + authorizationCodeDTO: Oauth2AuthorizationCodeDTO ): String { logger.info("get authorization code:$userId|$clientId|$redirectUri") // 1、校验clientId是否存在 @@ -69,14 +49,18 @@ class Oauth2EndpointService constructor( clientId = clientId, redirectUri = redirectUri, grantType = Oauth2GrantType.AUTHORIZATION_CODE.grantType, - clientDetails = clientDetails + clientDetails = clientDetails, + scope = authorizationCodeDTO.scope ) - // 3、生成授权码并存储数据库,授权码有效期为5分钟 + // 3、存储scope信息 + val scopeId = scopeService.create(scope = authorizationCodeDTO.scope.joinToString(",")) + // 4、生成授权码并存储数据库,授权码有效期为5分钟 val code = UUIDUtil.generate() codeService.create( userId = userId, code = code, clientId = clientId, + scopeId = scopeId, codeValiditySeconds = codeValiditySeconds ) // 4、返回跳转链接及授权码 @@ -105,22 +89,13 @@ class Oauth2EndpointService constructor( ) } - private fun getActionInfo(action: String): ActionInfoVo { - if (actionCache.getIfPresent(action) == null) { - val actionRecord = authActionDao.get(dslContext, action) - ?: throw ErrorCodeException( - errorCode = AuthMessageCode.ACTION_NOT_EXIST, - params = arrayOf(action), - defaultMessage = "the action($action) does not exist" - ) - val actionInfo = ActionInfoVo( - action = actionRecord.action, - actionName = actionRecord.actionName, - resourceType = actionRecord.resourceType, - relatedResourceType = actionRecord.relatedResourceType - ) - actionCache.put(action, actionInfo) - } - return actionCache.getIfPresent(action)!! + companion object { + private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) + private const val codeValiditySeconds = 600L + private val SCOPE = mutableMapOf( + "project_list" to "获取你有权限的项目列表", + "pipeline_list" to "获取你有权限的流水线列表", + "pipeline_download" to "下载你有权限的制品", + ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeService.kt new file mode 100644 index 00000000000..6d7eb63abee --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeService.kt @@ -0,0 +1,20 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.dao.AuthOauth2ScopeDao +import org.jooq.DSLContext +import org.springframework.stereotype.Service + +@Service +class Oauth2ScopeService constructor( + private val dslContext: DSLContext, + private val authOauth2ScopeDao: AuthOauth2ScopeDao +) { + fun create( + scope: String + ): Int { + return authOauth2ScopeDao.create( + dslContext = dslContext, + scope = scope + ) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index 1200a94dc18..b0ca9671cb0 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -41,7 +41,6 @@ abstract class AbstractTokenGranter( val clientId = accessTokenRequest.clientId val accessToken = accessTokenDTO.accessToken val refreshToken = accessTokenDTO.refreshToken - // 若access_token为空或者已过期,则重新生成access_token if (accessToken == null || AuthUtils.isExpired(accessTokenDTO.expiredTime!!)) { val newAccessToken = UUIDUtil.generate() @@ -58,10 +57,16 @@ abstract class AbstractTokenGranter( grantType = grantType, accessToken = newAccessToken, refreshToken = refreshToken, - expiredTime = accessTokenExpiredTime + expiredTime = accessTokenExpiredTime, + scopeId = accessTokenDTO.scopeId ) return Oauth2AccessTokenVo(newAccessToken, accessTokenExpiredTime, refreshToken) } else { + // scope可能会变化,需要更新 + accessTokenService.update( + accessToken = accessToken, + scopeId = accessTokenDTO.scopeId + ) // 返回未过期的 access_token return Oauth2AccessTokenVo(accessToken, accessTokenDTO.expiredTime!!, refreshToken) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index 76a97cd1df9..330aaf7c5c3 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -10,7 +10,8 @@ import com.tencent.devops.auth.service.oauth2.Oauth2RefreshTokenService import com.tencent.devops.common.api.util.DateTimeUtil import com.tencent.devops.common.api.util.UUIDUtil import com.tencent.devops.common.auth.utils.AuthUtils -import org.slf4j.LoggerFactory +import com.tencent.devops.model.auth.tables.records.TAuthOauth2AccessTokenRecord +import com.tencent.devops.model.auth.tables.records.TAuthOauth2CodeRecord import org.springframework.stereotype.Service @Service @@ -28,6 +29,33 @@ class AuthorizationCodeTokenGranter constructor( ): Oauth2AccessTokenDTO { val clientId = accessTokenRequest.clientId val code = accessTokenRequest.code + val codeDetails = handleAuthorizationCode( + code = code, + clientId = clientId + ) + val userName = codeDetails.userName + val accessTokenInfo = accessTokenService.get( + clientId = clientId, + userName = codeDetails.userName + ) + val refreshToken = generateRefreshToken( + clientId = clientId, + clientDetails = clientDetails, + accessTokenInfo = accessTokenInfo + ) + return Oauth2AccessTokenDTO( + accessToken = accessTokenInfo?.accessToken, + refreshToken = refreshToken, + expiredTime = accessTokenInfo?.expiredTime, + userName = userName, + scopeId = codeDetails.scopeId + ) + } + + fun handleAuthorizationCode( + code: String?, + clientId: String + ): TAuthOauth2CodeRecord { val codeDetails = codeService.get( code = code ) @@ -35,16 +63,18 @@ class AuthorizationCodeTokenGranter constructor( clientId = clientId, codeDetails = codeDetails ) - val userName = codeDetails.userName // 若授权码没有问题,则直接消费授权码,授权码单次有效 codeService.consume(code = code!!) + return codeDetails + } - val accessTokenInfo = accessTokenService.get( - clientId = clientId, - userName = codeDetails.userName - ) + fun generateRefreshToken( + clientId: String, + clientDetails: ClientDetailsInfo, + accessTokenInfo: TAuthOauth2AccessTokenRecord? + ): String { val isAccessTokenValid = accessTokenInfo != null && !AuthUtils.isExpired(accessTokenInfo.expiredTime) - val refreshToken = if (isAccessTokenValid) { + return if (isAccessTokenValid) { // 若accessToken未过期,refreshToken不变 accessTokenInfo!!.refreshToken } else { @@ -61,11 +91,5 @@ class AuthorizationCodeTokenGranter constructor( ) newRefreshToken } - return Oauth2AccessTokenDTO( - accessToken = accessTokenInfo?.accessToken, - refreshToken = refreshToken, - expiredTime = accessTokenInfo?.expiredTime, - userName = userName - ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 17ad72275d3..85bd1a31f32 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -5,11 +5,13 @@ import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AccessTokenDTO import com.tencent.devops.auth.pojo.enum.Oauth2GrantType import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService +import com.tencent.devops.auth.service.oauth2.Oauth2ScopeService import org.springframework.stereotype.Service @Service class ClientCredentialsTokenGranter constructor( - private val accessTokenService: Oauth2AccessTokenService + private val accessTokenService: Oauth2AccessTokenService, + private val oauth2ScopeService: Oauth2ScopeService ) : AbstractTokenGranter( grantType = GRANT_TYPE, accessTokenService = accessTokenService @@ -26,9 +28,14 @@ class ClientCredentialsTokenGranter constructor( clientId = accessTokenRequest.clientId, grantType = GRANT_TYPE ) + val scopeId = oauth2ScopeService.create( + scope = clientDetails.scope + ) + return Oauth2AccessTokenDTO( accessToken = accessTokenInfo?.accessToken, - expiredTime = accessTokenInfo?.expiredTime + expiredTime = accessTokenInfo?.expiredTime, + scopeId = scopeId ) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index 58146c48921..c5d01ede973 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -59,7 +59,8 @@ class RefreshTokenGranter( } return Oauth2AccessTokenDTO( userName = accessTokenInfo.userName, - refreshToken = refreshToken + refreshToken = refreshToken, + scopeId = accessTokenInfo.scopeId, ) } } From f49a6f4a48ddec03d3526fc31c88f8c3ce073549 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 3 Aug 2023 12:09:52 +0800 Subject: [PATCH 31/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/devops/auth/service/oauth2/Oauth2Config.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt index 265d0871c94..573e447d7d0 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -1,12 +1,10 @@ package com.tencent.devops.auth.service.oauth2 -import com.tencent.devops.auth.dao.AuthActionDao import com.tencent.devops.auth.service.oauth2.grant.AuthorizationCodeTokenGranter import com.tencent.devops.auth.service.oauth2.grant.ClientCredentialsTokenGranter import com.tencent.devops.auth.service.oauth2.grant.CompositeTokenGranter import com.tencent.devops.auth.service.oauth2.grant.RefreshTokenGranter import com.tencent.devops.auth.service.oauth2.grant.TokenGranter -import org.jooq.DSLContext import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration From 776265176ce78c352635a72326d530e256008516 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 3 Aug 2023 14:45:55 +0800 Subject: [PATCH 32/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 5b9dd2761c7..e43ccea89ed 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -93,7 +93,7 @@ class Oauth2EndpointService constructor( private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) private const val codeValiditySeconds = 600L private val SCOPE = mutableMapOf( - "project_list" to "获取你有权限的项目列表", + "project_visit" to "获取你有权限的项目列表", "pipeline_list" to "获取你有权限的流水线列表", "pipeline_download" to "下载你有权限的制品", ) From bf173cf040c38e2eb1ddc065c7796175f2bf1126 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 4 Aug 2023 11:12:08 +0800 Subject: [PATCH 33/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ce.kt => Oauth2DesktopEndpointResource.kt} | 14 +---- .../oauth2/Oauth2ServiceEndpointResource.kt | 52 +++++++++++++++++++ .../auth/pojo/Oauth2AccessTokenRequest.kt | 4 -- .../auth/dao/AuthOauth2AccessTokenDao.kt | 26 +++++----- ...t => Oauth2DesktopEndpointResourceImpl.kt} | 18 ++----- .../Oauth2ServiceEndpointResourceImpl.kt | 41 +++++++++++++++ .../oauth2/Oauth2AccessTokenService.kt | 19 ++++++- .../service/oauth2/Oauth2EndpointService.kt | 38 ++++++++++++-- .../oauth2/grant/AbstractTokenGranter.kt | 3 +- .../grant/AuthorizationCodeTokenGranter.kt | 2 +- .../grant/ClientCredentialsTokenGranter.kt | 2 +- .../oauth2/grant/RefreshTokenGranter.kt | 4 +- .../tencent/devops/common/api/auth/Header.kt | 4 ++ 13 files changed, 173 insertions(+), 54 deletions(-) rename src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/{Oauth2EndpointResource.kt => Oauth2DesktopEndpointResource.kt} (80%) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2ServiceEndpointResource.kt rename src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/{Oauth2EndpointResourceImpl.kt => Oauth2DesktopEndpointResourceImpl.kt} (69%) create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2ServiceEndpointResourceImpl.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2DesktopEndpointResource.kt similarity index 80% rename from src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt rename to src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2DesktopEndpointResource.kt index b55e7df962e..49d8a898d53 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2EndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2DesktopEndpointResource.kt @@ -1,8 +1,6 @@ package com.tencent.devops.auth.api.oauth2 -import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AuthorizationCodeDTO -import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID import com.tencent.devops.common.api.pojo.Result @@ -19,10 +17,10 @@ import javax.ws.rs.QueryParam import javax.ws.rs.core.MediaType @Api(tags = ["OAUTH2_ENDPOINT"], description = "oauth2相关") -@Path("user/oauth2/endpoint") +@Path("/desktop/oauth2/endpoint") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) -interface Oauth2EndpointResource { +interface Oauth2DesktopEndpointResource { @GET @Path("/getAuthorizationInformation") @ApiOperation("获取授权信息") @@ -51,12 +49,4 @@ interface Oauth2EndpointResource { @ApiParam("oauth2获取授权码请求报文体", required = true) authorizationCodeDTO: Oauth2AuthorizationCodeDTO ): Result - - @POST - @Path("/getAccessToken") - @ApiOperation("获取accessToken") - fun getAccessToken( - @ApiParam("oauth2获取token请求报文体", required = true) - accessTokenRequest: Oauth2AccessTokenRequest - ): Result } diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2ServiceEndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2ServiceEndpointResource.kt new file mode 100644 index 00000000000..93b800266ee --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2ServiceEndpointResource.kt @@ -0,0 +1,52 @@ +package com.tencent.devops.auth.api.oauth2 + +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_AUTHORIZATION +import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_CLIENT_ID +import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_CLIENT_SECRET +import com.tencent.devops.common.api.pojo.Result +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam +import javax.ws.rs.Consumes +import javax.ws.rs.HeaderParam +import javax.ws.rs.POST +import javax.ws.rs.Path +import javax.ws.rs.Produces +import javax.ws.rs.core.MediaType + +@Api(tags = ["OAUTH2_ENDPOINT"], description = "oauth2相关") +@Path("/service/oauth2/endpoint") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +interface Oauth2ServiceEndpointResource { + @POST + @Path("/getAccessToken") + @ApiOperation("获取accessToken") + fun getAccessToken( + @HeaderParam(AUTH_HEADER_OAUTH2_CLIENT_ID) + @ApiParam("客户端id", required = true) + clientId: String, + @HeaderParam(AUTH_HEADER_OAUTH2_CLIENT_SECRET) + @ApiParam("客户端秘钥", required = true) + clientSecret: String, + @ApiParam("oauth2获取token请求报文体", required = true) + accessTokenRequest: Oauth2AccessTokenRequest + ): Result + + @POST + @Path("/verifyAccessToken") + @ApiOperation("校验accessToken") + fun verifyAccessToken( + @HeaderParam(AUTH_HEADER_OAUTH2_CLIENT_ID) + @ApiParam("客户端id", required = true) + clientId: String, + @HeaderParam(AUTH_HEADER_OAUTH2_CLIENT_SECRET) + @ApiParam("客户端秘钥", required = true) + clientSecret: String, + @HeaderParam(AUTH_HEADER_OAUTH2_AUTHORIZATION) + @ApiParam("access token", required = true) + accessToken: String + ): Result +} diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt index d407e467dfd..e17252781e2 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/Oauth2AccessTokenRequest.kt @@ -5,10 +5,6 @@ import io.swagger.annotations.ApiModelProperty @ApiModel("oauth2获取token请求报文体") data class Oauth2AccessTokenRequest( - @ApiModelProperty("客户端id", required = true) - val clientId: String, - @ApiModelProperty("客户端密钥", required = true) - val clientSecret: String, @ApiModelProperty("授权类型", required = true) val grantType: String, @ApiModelProperty("授权码,用于授权码模式", required = false) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt index 07782b0615f..9ec35bd5e19 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2AccessTokenDao.kt @@ -7,23 +7,23 @@ import org.springframework.stereotype.Repository @Repository class AuthOauth2AccessTokenDao { + @Suppress("LongParameterList") fun get( dslContext: DSLContext, clientId: String, - refreshToken: String?, - userName: String?, - grantType: String? + accessToken: String? = null, + refreshToken: String? = null, + userName: String? = null, + grantType: String? = null ): TAuthOauth2AccessTokenRecord? { return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { - dslContext.selectFrom(this).where( - CLIENT_ID.eq(clientId) - ).let { - if (userName != null) { it.and(USER_NAME.eq(userName)) } else { it } - }.let { - if (grantType != null) { it.and(GRANT_TYPE.eq(grantType)) } else { it } - }.let { - if (refreshToken != null) { it.and(REFRESH_TOKEN.eq(refreshToken)) } else { it } - }.fetchOne() + dslContext.selectFrom(this) + .where(CLIENT_ID.eq(clientId)) + .apply { accessToken?.let { and(ACCESS_TOKEN.eq(it)) } } + .apply { userName?.let { and(USER_NAME.eq(it)) } } + .apply { grantType?.let { and(GRANT_TYPE.eq(it)) } } + .apply { refreshToken?.let { and(REFRESH_TOKEN.eq(it)) } } + .fetchOne() } } @@ -75,7 +75,7 @@ class AuthOauth2AccessTokenDao { dslContext: DSLContext, accessToken: String, scopeId: Int - ){ + ) { return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) { dslContext.update(this) .set(SCOPE_ID, scopeId) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2DesktopEndpointResourceImpl.kt similarity index 69% rename from src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt rename to src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2DesktopEndpointResourceImpl.kt index 41b7a24ec10..eaf4035800e 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2EndpointResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2DesktopEndpointResourceImpl.kt @@ -1,18 +1,16 @@ package com.tencent.devops.auth.resources -import com.tencent.devops.auth.api.oauth2.Oauth2EndpointResource -import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.api.oauth2.Oauth2DesktopEndpointResource import com.tencent.devops.auth.pojo.dto.Oauth2AuthorizationCodeDTO -import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo import com.tencent.devops.auth.service.oauth2.Oauth2EndpointService import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.web.RestResource @RestResource -class Oauth2EndpointResourceImpl constructor( +class Oauth2DesktopEndpointResourceImpl constructor( private val endpointService: Oauth2EndpointService -) : Oauth2EndpointResource { +) : Oauth2DesktopEndpointResource { override fun getAuthorizationInformation( userId: String, clientId: String @@ -40,14 +38,4 @@ class Oauth2EndpointResourceImpl constructor( ) ) } - - override fun getAccessToken( - accessTokenRequest: Oauth2AccessTokenRequest - ): Result { - return Result( - endpointService.getAccessToken( - accessTokenRequest = accessTokenRequest - ) - ) - } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2ServiceEndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2ServiceEndpointResourceImpl.kt new file mode 100644 index 00000000000..5051c6680b1 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2ServiceEndpointResourceImpl.kt @@ -0,0 +1,41 @@ +package com.tencent.devops.auth.resources + +import com.tencent.devops.auth.api.oauth2.Oauth2ServiceEndpointResource +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.service.oauth2.Oauth2EndpointService +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.common.web.RestResource + +@RestResource +class Oauth2ServiceEndpointResourceImpl constructor( + private val endpointService: Oauth2EndpointService +) : Oauth2ServiceEndpointResource { + override fun getAccessToken( + clientId: String, + clientSecret: String, + accessTokenRequest: Oauth2AccessTokenRequest + ): Result { + return Result( + endpointService.getAccessToken( + clientId = clientId, + clientSecret = clientSecret, + accessTokenRequest = accessTokenRequest + ) + ) + } + + override fun verifyAccessToken( + clientId: String, + clientSecret: String, + accessToken: String + ): Result { + return Result( + endpointService.verifyAccessToken( + clientId = clientId, + clientSecret = clientSecret, + accessToken = accessToken + ) + ) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt index 67cc35a31f9..89aad1d245e 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2AccessTokenService.kt @@ -1,6 +1,8 @@ package com.tencent.devops.auth.service.oauth2 +import com.tencent.devops.auth.constant.AuthMessageCode import com.tencent.devops.auth.dao.AuthOauth2AccessTokenDao +import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.model.auth.tables.records.TAuthOauth2AccessTokenRecord import org.jooq.DSLContext import org.springframework.stereotype.Service @@ -10,6 +12,21 @@ class Oauth2AccessTokenService constructor( private val oauth2AccessTokenDao: AuthOauth2AccessTokenDao, private val dslContext: DSLContext ) { + fun get( + clientId: String, + accessToken: String + ): TAuthOauth2AccessTokenRecord { + return oauth2AccessTokenDao.get( + dslContext = dslContext, + clientId = clientId, + accessToken = accessToken + ) ?: throw ErrorCodeException( + errorCode = AuthMessageCode.INVALID_ACCESS_TOKEN, + params = arrayOf(clientId), + defaultMessage = "The access token invalid" + ) + } + fun get( clientId: String, refreshToken: String? = null, @@ -57,7 +74,7 @@ class Oauth2AccessTokenService constructor( fun update( accessToken: String, scopeId: Int - ){ + ) { oauth2AccessTokenDao.update( dslContext = dslContext, accessToken = accessToken, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index e43ccea89ed..4feb8f487f7 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -1,19 +1,23 @@ package com.tencent.devops.auth.service.oauth2 +import com.tencent.devops.auth.constant.AuthMessageCode import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.dto.Oauth2AuthorizationCodeDTO import com.tencent.devops.auth.pojo.enum.Oauth2GrantType import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo import com.tencent.devops.auth.service.oauth2.grant.TokenGranter +import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.common.api.util.UUIDUtil +import com.tencent.devops.common.auth.utils.AuthUtils import org.slf4j.LoggerFactory class Oauth2EndpointService constructor( private val tokenGranter: TokenGranter, private val clientService: Oauth2ClientService, private val codeService: Oauth2CodeService, - private val scopeService: Oauth2ScopeService + private val scopeService: Oauth2ScopeService, + private val accessTokenService: Oauth2AccessTokenService ) { fun getAuthorizationInformation( userId: String, @@ -68,17 +72,18 @@ class Oauth2EndpointService constructor( } fun getAccessToken( + clientId: String, + clientSecret: String, accessTokenRequest: Oauth2AccessTokenRequest ): Oauth2AccessTokenVo? { val grantType = accessTokenRequest.grantType - val clientId = accessTokenRequest.clientId logger.info("get access token:$clientId|$grantType|$accessTokenRequest") val clientDetails = clientService.getClientDetails( clientId = clientId ) clientService.verifyClientInformation( clientId = clientId, - clientSecret = accessTokenRequest.clientSecret, + clientSecret = clientSecret, grantType = grantType, clientDetails = clientDetails ) @@ -89,6 +94,33 @@ class Oauth2EndpointService constructor( ) } + fun verifyAccessToken( + clientId: String, + clientSecret: String, + accessToken: String + ): String { + val clientDetails = clientService.getClientDetails( + clientId = clientId + ) + clientService.verifyClientInformation( + clientId = clientId, + clientSecret = clientSecret, + clientDetails = clientDetails + ) + val accessTokenInfo = accessTokenService.get( + clientId = clientId, + accessToken = accessToken + ) + if (AuthUtils.isExpired(accessTokenInfo.expiredTime)) { + throw ErrorCodeException( + errorCode = AuthMessageCode.ERROR_ACCESS_TOKEN_EXPIRED, + params = arrayOf(clientId), + defaultMessage = "The access token has expired!" + ) + } + return accessTokenInfo.userName + } + companion object { private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) private const val codeValiditySeconds = 600L diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index b0ca9671cb0..04b0925e77f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -8,7 +8,6 @@ import com.tencent.devops.auth.service.oauth2.Oauth2AccessTokenService import com.tencent.devops.common.api.util.DateTimeUtil import com.tencent.devops.common.api.util.UUIDUtil import com.tencent.devops.common.auth.utils.AuthUtils -import org.slf4j.LoggerFactory abstract class AbstractTokenGranter( private val grantType: String, @@ -38,7 +37,7 @@ abstract class AbstractTokenGranter( accessTokenDTO: Oauth2AccessTokenDTO, clientDetails: ClientDetailsInfo ): Oauth2AccessTokenVo { - val clientId = accessTokenRequest.clientId + val clientId = clientDetails.clientId val accessToken = accessTokenDTO.accessToken val refreshToken = accessTokenDTO.refreshToken // 若access_token为空或者已过期,则重新生成access_token diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index 330aaf7c5c3..ba52dafe65f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -27,7 +27,7 @@ class AuthorizationCodeTokenGranter constructor( accessTokenRequest: Oauth2AccessTokenRequest, clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO { - val clientId = accessTokenRequest.clientId + val clientId = clientDetails.clientId val code = accessTokenRequest.code val codeDetails = handleAuthorizationCode( code = code, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt index 85bd1a31f32..93305a34fae 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/ClientCredentialsTokenGranter.kt @@ -25,7 +25,7 @@ class ClientCredentialsTokenGranter constructor( clientDetails: ClientDetailsInfo ): Oauth2AccessTokenDTO { val accessTokenInfo = accessTokenService.get( - clientId = accessTokenRequest.clientId, + clientId = clientDetails.clientId, grantType = GRANT_TYPE ) val scopeId = oauth2ScopeService.create( diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index c5d01ede973..7ae02b2e4d9 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -30,7 +30,7 @@ class RefreshTokenGranter( refreshToken = refreshToken )!! // 2.校验refresh_token是否跟client_id匹配 - if (refreshTokenInfo.clientId != accessTokenRequest.clientId) { + if (refreshTokenInfo.clientId != clientDetails.clientId) { throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_REFRESH_TOKEN, defaultMessage = "The refresh token invalid" @@ -38,7 +38,7 @@ class RefreshTokenGranter( } // 3.根据refresh_token获取access_token,获取access_token中的user_name val accessTokenInfo = accessTokenService.get( - clientId = accessTokenRequest.clientId, + clientId = clientDetails.clientId, refreshToken = accessTokenRequest.refreshToken ) ?: throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_REFRESH_TOKEN, diff --git a/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/auth/Header.kt b/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/auth/Header.kt index f426f5c22d3..4fd63f6950b 100644 --- a/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/auth/Header.kt +++ b/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/auth/Header.kt @@ -103,3 +103,7 @@ const val AUTH_HEADER_BK_CI_LOGIN_TOKEN = "X-DEVOPS-CI-LOGIN-TOKEN" const val AUTH_HEADER_DEVOPS_SERVICE_NAME = "X-DEVOPS-SERVICE-NAME" const val AUTH_HEADER_CODECC_OPENAPI_TOKEN = "X-CODECC-OPENAPI-TOKEN" + +const val AUTH_HEADER_OAUTH2_CLIENT_ID: String = "X-DEVOPS-OAUTH2-CLIENT-ID" +const val AUTH_HEADER_OAUTH2_CLIENT_SECRET: String = "X-DEVOPS-OAUTH2-CLIENT-SECRET" +const val AUTH_HEADER_OAUTH2_AUTHORIZATION: String = "X-DEVOPS-OAUTH2-AUTHORIZATION" From c2f1408f79ccd356e8218eaaa668449ecaa3ae35 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 4 Aug 2023 14:51:26 +0800 Subject: [PATCH 34/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/service/oauth2/Oauth2Config.kt | 4 +- .../service/oauth2/Oauth2EndpointService.kt | 3 +- .../apigw/v4/ApigwOauth2EndpointResourceV4.kt | 52 +++++++++++++++++++ .../v4/ApigwOauth2EndpointResourceV4Impl.kt | 36 +++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt create mode 100644 src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwOauth2EndpointResourceV4Impl.kt diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt index 573e447d7d0..b4053302783 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -14,6 +14,7 @@ class Oauth2Config constructor( private val oauth2ClientService: Oauth2ClientService, private val codeService: Oauth2CodeService, private val scopeService: Oauth2ScopeService, + private val accessTokenService: Oauth2AccessTokenService, private val clientCredentialsTokenGranter: ClientCredentialsTokenGranter, private val authorizationCodeTokenGranter: AuthorizationCodeTokenGranter, private val refreshTokenGranter: RefreshTokenGranter @@ -24,7 +25,8 @@ class Oauth2Config constructor( tokenGranter = compositeTokenGranter(), clientService = oauth2ClientService, codeService = codeService, - scopeService = scopeService + scopeService = scopeService, + accessTokenService = accessTokenService ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 4feb8f487f7..b8bb5181b64 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -109,7 +109,7 @@ class Oauth2EndpointService constructor( ) val accessTokenInfo = accessTokenService.get( clientId = clientId, - accessToken = accessToken + accessToken = accessToken.substringAfter(OAUTH2_SCHEME).trim() ) if (AuthUtils.isExpired(accessTokenInfo.expiredTime)) { throw ErrorCodeException( @@ -129,5 +129,6 @@ class Oauth2EndpointService constructor( "pipeline_list" to "获取你有权限的流水线列表", "pipeline_download" to "下载你有权限的制品", ) + private const val OAUTH2_SCHEME = "Bearer " } } diff --git a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt new file mode 100644 index 00000000000..9d520570e4a --- /dev/null +++ b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt @@ -0,0 +1,52 @@ +package com.tencent.devops.openapi.api.apigw.v4 + +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE +import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE +import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID +import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_CLIENT_ID +import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_CLIENT_SECRET +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.common.auth.api.pojo.BkAuthGroup +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam +import javax.ws.rs.Consumes +import javax.ws.rs.GET +import javax.ws.rs.HeaderParam +import javax.ws.rs.POST +import javax.ws.rs.Path +import javax.ws.rs.PathParam +import javax.ws.rs.Produces +import javax.ws.rs.QueryParam +import javax.ws.rs.core.MediaType + +@Api(tags = ["OPENAPI_OAUTH2_V4"], description = "OPENAPI-OAUTH2相关") +@Path("/{apigwType:apigw-user|apigw-app|apigw}/v4/auth/oauth2/endpoint/") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +interface ApigwOauth2EndpointResourceV4 { + @POST + @Path("/getAccessToken") + @ApiOperation( + "oauth2获取accessToken", + tags = ["v4_app_oauth2_access_token"] + ) + fun getAccessToken( + @ApiParam(value = "appCode", required = true, defaultValue = AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_DEVOPS_APP_CODE) + appCode: String?, + @ApiParam(value = "apigw Type", required = true) + @PathParam("apigwType") + apigwType: String?, + @HeaderParam(AUTH_HEADER_OAUTH2_CLIENT_ID) + @ApiParam("客户端id", required = true) + clientId: String, + @HeaderParam(AUTH_HEADER_OAUTH2_CLIENT_SECRET) + @ApiParam("客户端秘钥", required = true) + clientSecret: String, + @ApiParam("oauth2获取token请求报文体", required = true) + accessTokenRequest: Oauth2AccessTokenRequest + ): Result +} diff --git a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwOauth2EndpointResourceV4Impl.kt b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwOauth2EndpointResourceV4Impl.kt new file mode 100644 index 00000000000..cacfc07715d --- /dev/null +++ b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwOauth2EndpointResourceV4Impl.kt @@ -0,0 +1,36 @@ +package com.tencent.devops.openapi.resources.apigw.v4 + +import com.tencent.devops.auth.api.oauth2.Oauth2ServiceEndpointResource +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.common.client.Client +import com.tencent.devops.common.web.RestResource +import com.tencent.devops.openapi.api.apigw.v4.ApigwOauth2EndpointResourceV4 +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired + +@RestResource +class ApigwOauth2EndpointResourceV4Impl @Autowired constructor( + private val client: Client +) : ApigwOauth2EndpointResourceV4 { + + override fun getAccessToken( + appCode: String?, + apigwType: String?, + clientId: String, + clientSecret: String, + accessTokenRequest: Oauth2AccessTokenRequest + ): Result { + logger.info("OPENAPI_OAUTH2_ACCESS_TOKEN_V4|$appCode|$clientId") + return client.get(Oauth2ServiceEndpointResource::class).getAccessToken( + clientId = clientId, + clientSecret = clientSecret, + accessTokenRequest = accessTokenRequest + ) + } + + companion object { + val logger = LoggerFactory.getLogger(ApigwOauth2EndpointResourceV4Impl::class.java) + } +} From ba99cd08ab618139ff8c12fae6736f6a659baeb0 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 4 Aug 2023 16:26:17 +0800 Subject: [PATCH 35/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index b8bb5181b64..187c9d3185f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -23,7 +23,7 @@ class Oauth2EndpointService constructor( userId: String, clientId: String ): Oauth2AuthorizationInfoVo { - logger.info("get authorization information:$userId|$clientId") + logger.info("get authorization information :$userId|$clientId") // 1、校验clientId是否存在 val clientDetails = clientService.getClientDetails(clientId = clientId) // 2、校验客户端信息是否正确 From c264c784f4a716ee1b7d55909cb1ea1a92342f4d Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 4 Aug 2023 16:34:53 +0800 Subject: [PATCH 36/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../i18n/auth/message_en_US.properties | 4 ++ .../i18n/auth/message_zh_CN.properties | 4 ++ support-files/sql/1001_ci_auth_ddl_mysql.sql | 53 +++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/support-files/i18n/auth/message_en_US.properties b/support-files/i18n/auth/message_en_US.properties index e96fb91323f..1a76530794b 100644 --- a/support-files/i18n/auth/message_en_US.properties +++ b/support-files/i18n/auth/message_en_US.properties @@ -70,6 +70,10 @@ 2121070=The refresh token must be provided 2121071=The refresh token invalid 2121072=The refresh token has expired +2121073=The access token must be provided +2121074=The access token invalid +2121075=The access token has expired +2121076=The scope invalid bkAdministratorNotExpired=Permission has not expired and no action is required bkAgreeRenew=Agree to renew bkApproverAgreeRenew=Approver agreed to your permission renewal diff --git a/support-files/i18n/auth/message_zh_CN.properties b/support-files/i18n/auth/message_zh_CN.properties index 2da950da5e5..d39382c23ff 100644 --- a/support-files/i18n/auth/message_zh_CN.properties +++ b/support-files/i18n/auth/message_zh_CN.properties @@ -70,6 +70,10 @@ 2121070=refresh token不能为空 2121071=refresh token不合法 2121072=refresh token已过期 +2121073=access token不能为空 +2121074=access token不合法 +2121075=access token已过期 +2121076=scope不合法 bkAdministratorNotExpired=权限还未过期,不需要操作 bkAgreeRenew=同意续期 bkApproverAgreeRenew=审批人同意了您的权限续期 diff --git a/support-files/sql/1001_ci_auth_ddl_mysql.sql b/support-files/sql/1001_ci_auth_ddl_mysql.sql index 955bb0c5f60..a947ee1fd32 100644 --- a/support-files/sql/1001_ci_auth_ddl_mysql.sql +++ b/support-files/sql/1001_ci_auth_ddl_mysql.sql @@ -284,4 +284,57 @@ CREATE TABLE IF NOT EXISTS T_AUTH_MIGRATION( PRIMARY KEY (`PROJECT_CODE`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限迁移'; +CREATE TABLE `T_AUTH_OAUTH2_CLIENT_DETAILS` ( + `CLIENT_ID` VARCHAR(32) NOT NULL COMMENT '客户端标识', + `CLIENT_SECRET` VARCHAR(64) NOT NULL COMMENT '客户端秘钥', + `CLIENT_NAME` VARCHAR(255) NOT NULL COMMENT '客户端名称', + `SCOPE` MEDIUMTEXT DEFAULT NULL COMMENT '授权范围', + `AUTHORIZED_GRANT_TYPES` VARCHAR(64) NOT NULL COMMENT '授权模式', + `WEB_SERVER_REDIRECT_URI` VARCHAR(255) DEFAULT NULL COMMENT '跳转链接', + `ACCESS_TOKEN_VALIDITY` BIGINT(20) NOT NULL COMMENT 'access_token有效时间', + `REFRESH_TOKEN_VALIDITY` BIGINT(20) DEFAULT NULL COMMENT 'refresh_token有效时间', + `CREATE_USER` VARCHAR(32) NOT NULL DEFAULT '""' COMMENT '创建人', + `UPDATE_USER` VARCHAR(32) DEFAULT NULL COMMENT '修改人', + `CREATE_TIME` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `UPDATE_TIME` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`CLIENT_ID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户端信息表'; + +CREATE TABLE `T_AUTH_OAUTH2_CODE` ( + `CLIENT_ID` VARCHAR(32) NOT NULL COMMENT '客户端标识', + `CODE` VARCHAR(64) NOT NULL COMMENT '授权码', + `USER_NAME` VARCHAR(32) NOT NULL COMMENT '用户名', + `EXPIRED_TIME` BIGINT(20) NOT NULL COMMENT '过期时间', + `SCOPE_ID` INT NOT NULL COMMENT '授权范围ID', + `CREATE_TIME` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + INDEX `IDX_CODE` (`CODE`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='授权码表'; + +CREATE TABLE `T_AUTH_OAUTH2_ACCESS_TOKEN` ( + `ACCESS_TOKEN` VARCHAR(64) NOT NULL COMMENT 'ACCESS_TOKEN', + `CLIENT_ID` VARCHAR(32) NOT NULL COMMENT '客户端ID', + `USER_NAME` VARCHAR(32) DEFAULT NULL COMMENT '登录的用户名,客户端模式该值为空', + `GRANT_TYPE` VARCHAR(32) NOT NULL COMMENT '授权模式', + `EXPIRED_TIME` BIGINT(20) NOT NULL COMMENT '过期时间', + `REFRESH_TOKEN` VARCHAR(64) DEFAULT NULL COMMENT 'REFRESH_TOKEN,客户端模式该值为空', + `SCOPE_ID` INT NOT NULL COMMENT '授权范围ID', + `CREATE_TIME` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + INDEX `IDX_CLIENT_ID_USER_NAME` (`ACCESS_TOKEN`) +) ENGINE=INNODB DEFAULT CHARSET=UTF8 COMMENT='ACCESS_TOKEN表'; + +CREATE TABLE `T_AUTH_OAUTH2_REFRESH_TOKEN` ( + `REFRESH_TOKEN` VARCHAR(64) NOT NULL COMMENT 'REFRESH_TOKEN', + `CLIENT_ID` VARCHAR(32) NOT NULL COMMENT '客户端ID', + `EXPIRED_TIME` BIGINT(20) NOT NULL COMMENT '过期时间', + `CREATE_TIME` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + INDEX `IDX_REFRESH_TOKEN` (`REFRESH_TOKEN`) +) ENGINE=INNODB DEFAULT CHARSET=UTF8 COMMENT='REFRESH_TOKEN表'; + +CREATE TABLE `T_AUTH_OAUTH2_SCOPE` ( + `ID` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主健ID', + `SCOPE` MEDIUMTEXT NOT NULL COMMENT '授权范围', + `CREATE_TIME` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`ID`) +) ENGINE=INNODB DEFAULT CHARSET=UTF8 COMMENT='授权范围表'; + SET FOREIGN_KEY_CHECKS = 1; From 36bf249b1b0c24f22545fca1bff14c84654493d9 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 4 Aug 2023 16:36:11 +0800 Subject: [PATCH 37/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/render_tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/render_tpl b/scripts/render_tpl index a44c6a7503a..754535c0ea0 100755 --- a/scripts/render_tpl +++ b/scripts/render_tpl @@ -1,5 +1,5 @@ #!/bin/bash -# ./render_tpl -m ci ../support-files/templates/* + # 渲染蓝鲸的__VAR_NUM__ 类似的模板,通过环境变量自动替换它 set -o nounset # Treat unset variables as an error From a443b8c488d0416be254be85680406975f02262f Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 4 Aug 2023 16:56:55 +0800 Subject: [PATCH 38/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/service/oauth2/Oauth2ClientService.kt | 2 +- .../devops/auth/service/oauth2/Oauth2EndpointService.kt | 2 +- .../devops/auth/service/oauth2/grant/AbstractTokenGranter.kt | 2 +- .../devops/auth/service/oauth2/grant/RefreshTokenGranter.kt | 2 +- .../openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt | 4 ---- 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt index 7929ee465a7..1908e9d466e 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt @@ -39,7 +39,7 @@ class Oauth2ClientService constructor( authorizedGrantTypes = authorizedGrantTypes, redirectUri = webServerRedirectUri, accessTokenValidity = accessTokenValidity, - refreshTokenValidity = refreshTokenValidity, + refreshTokenValidity = refreshTokenValidity ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 187c9d3185f..fadd368f586 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -127,7 +127,7 @@ class Oauth2EndpointService constructor( private val SCOPE = mutableMapOf( "project_visit" to "获取你有权限的项目列表", "pipeline_list" to "获取你有权限的流水线列表", - "pipeline_download" to "下载你有权限的制品", + "pipeline_download" to "下载你有权限的制品" ) private const val OAUTH2_SCHEME = "Bearer " } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt index 04b0925e77f..2b453afddb4 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AbstractTokenGranter.kt @@ -11,7 +11,7 @@ import com.tencent.devops.common.auth.utils.AuthUtils abstract class AbstractTokenGranter( private val grantType: String, - private val accessTokenService: Oauth2AccessTokenService, + private val accessTokenService: Oauth2AccessTokenService ) : TokenGranter { override fun grant( grantType: String, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt index 7ae02b2e4d9..9ab95d12c51 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/RefreshTokenGranter.kt @@ -60,7 +60,7 @@ class RefreshTokenGranter( return Oauth2AccessTokenDTO( userName = accessTokenInfo.userName, refreshToken = refreshToken, - scopeId = accessTokenInfo.scopeId, + scopeId = accessTokenInfo.scopeId ) } } diff --git a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt index 9d520570e4a..dd45b966986 100644 --- a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt +++ b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt @@ -4,22 +4,18 @@ import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE -import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_CLIENT_ID import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_CLIENT_SECRET import com.tencent.devops.common.api.pojo.Result -import com.tencent.devops.common.auth.api.pojo.BkAuthGroup import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam import javax.ws.rs.Consumes -import javax.ws.rs.GET import javax.ws.rs.HeaderParam import javax.ws.rs.POST import javax.ws.rs.Path import javax.ws.rs.PathParam import javax.ws.rs.Produces -import javax.ws.rs.QueryParam import javax.ws.rs.core.MediaType @Api(tags = ["OPENAPI_OAUTH2_V4"], description = "OPENAPI-OAUTH2相关") From e553af909c2a14e4a1f2e83a3b5aecd9a3630daa Mon Sep 17 00:00:00 2001 From: greysonfang Date: Mon, 7 Aug 2023 18:06:54 +0800 Subject: [PATCH 39/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/auth/api/oauth2/Oauth2DesktopEndpointResource.kt | 5 ++++- .../auth/resources/Oauth2DesktopEndpointResourceImpl.kt | 6 ++++-- .../devops/auth/service/oauth2/Oauth2EndpointService.kt | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2DesktopEndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2DesktopEndpointResource.kt index 49d8a898d53..8c8cdf9bd69 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2DesktopEndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2DesktopEndpointResource.kt @@ -30,7 +30,10 @@ interface Oauth2DesktopEndpointResource { userId: String, @QueryParam("clientId") @ApiParam("客户端ID", required = true) - clientId: String + clientId: String, + @QueryParam("redirectUri") + @ApiParam("跳转链接", required = true) + redirectUri: String ): Result @POST diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2DesktopEndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2DesktopEndpointResourceImpl.kt index eaf4035800e..aae663c0ef3 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2DesktopEndpointResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2DesktopEndpointResourceImpl.kt @@ -13,12 +13,14 @@ class Oauth2DesktopEndpointResourceImpl constructor( ) : Oauth2DesktopEndpointResource { override fun getAuthorizationInformation( userId: String, - clientId: String + clientId: String, + redirectUri: String ): Result { return Result( endpointService.getAuthorizationInformation( userId = userId, - clientId = clientId + clientId = clientId, + redirectUri = redirectUri ) ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index fadd368f586..3b1767dd15f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -21,7 +21,8 @@ class Oauth2EndpointService constructor( ) { fun getAuthorizationInformation( userId: String, - clientId: String + clientId: String, + redirectUri: String ): Oauth2AuthorizationInfoVo { logger.info("get authorization information :$userId|$clientId") // 1、校验clientId是否存在 @@ -30,6 +31,7 @@ class Oauth2EndpointService constructor( clientService.verifyClientInformation( clientId = clientId, grantType = Oauth2GrantType.AUTHORIZATION_CODE.grantType, + redirectUri = redirectUri, clientDetails = clientDetails ) return Oauth2AuthorizationInfoVo( From 8217d0b0b462f15372d28fed67c26c606514e1f9 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 17 Aug 2023 12:01:21 +0800 Subject: [PATCH 40/73] =?UTF-8?q?=E8=93=9D=E7=9B=BEoauth2=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E5=AE=9E=E7=8E=B0=20#9110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt | 2 +- .../kotlin/com/tencent/devops/common/api/util/DateTimeUtil.kt | 2 +- .../kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 3b1767dd15f..9534f51caa0 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -60,7 +60,7 @@ class Oauth2EndpointService constructor( ) // 3、存储scope信息 val scopeId = scopeService.create(scope = authorizationCodeDTO.scope.joinToString(",")) - // 4、生成授权码并存储数据库,授权码有效期为5分钟 + // 4、生成授权码并存储数据库,授权码有效期为10分钟 val code = UUIDUtil.generate() codeService.create( userId = userId, diff --git a/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/util/DateTimeUtil.kt b/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/util/DateTimeUtil.kt index cc1a4dc56a1..b9a85e1a8dd 100644 --- a/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/util/DateTimeUtil.kt +++ b/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/util/DateTimeUtil.kt @@ -111,7 +111,7 @@ object DateTimeUtil { } fun getFutureTimestamp(seconds: Long): Long { - return System.currentTimeMillis() + seconds * ONE_THOUSAND_MS + return System.currentTimeMillis() / 1000 + seconds } /** diff --git a/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt b/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt index caa2d3d1a70..a8d455046e5 100644 --- a/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt +++ b/src/backend/ci/core/common/common-auth/common-auth-api/src/main/kotlin/com/tencent/devops/common/auth/utils/AuthUtils.kt @@ -249,7 +249,7 @@ object AuthUtils { } fun isExpired(expirationTimestamp: Long): Boolean { - return System.currentTimeMillis() > expirationTimestamp + return System.currentTimeMillis() / 1000 > expirationTimestamp } private fun checkProject(projectId: String, expression: ExpressionDTO): Pair> { From ad6daaafedb16eb78b5f9182bd9057fede8b0b4c Mon Sep 17 00:00:00 2001 From: greysonfang Date: Mon, 21 Aug 2023 19:23:20 +0800 Subject: [PATCH 41/73] =?UTF-8?q?=20feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20O?= =?UTF-8?q?auth2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#?= =?UTF-8?q?9353?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/auth/pojo/BkUserDeptInfo.kt | 16 +++++++ .../tencent/devops/auth/pojo/BkUserExtras.kt | 14 +++++++ .../tencent/devops/auth/pojo/BkUserInfo.kt | 6 ++- .../devops/auth/pojo/vo/UserAndDeptInfoVo.kt | 8 +++- .../tencent/devops/auth/common/Constants.kt | 2 +- .../auth/service/AuthDeptServiceImpl.kt | 24 ++++++----- .../apigw/v4/ApigwUserManagementResourceV4.kt | 42 +++++++++++++++++++ .../v4/ApigwUserManagementResourceV4Impl.kt | 32 ++++++++++++++ 8 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserDeptInfo.kt create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserExtras.kt create mode 100644 src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt create mode 100644 src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserDeptInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserDeptInfo.kt new file mode 100644 index 00000000000..6fa4926cb37 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserDeptInfo.kt @@ -0,0 +1,16 @@ +package com.tencent.devops.auth.pojo + +import com.fasterxml.jackson.annotation.JsonProperty +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("用户部门详细信息") +data class BkUserDeptInfo( + @ApiModelProperty("id") + val id: String, + @ApiModelProperty("部门名称") + val name: String, + @ApiModelProperty("部门详细名称") + @JsonProperty("full_name") + val fullName: String +) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserExtras.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserExtras.kt new file mode 100644 index 00000000000..a31a9cdd6c6 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserExtras.kt @@ -0,0 +1,14 @@ +package com.tencent.devops.auth.pojo + +import com.fasterxml.jackson.annotation.JsonProperty +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("用户额外信息") +data class BkUserExtras( + @ApiModelProperty("性别") + val gender: String, + @ApiModelProperty("postName") + @JsonProperty("postname") + val postName: String +) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt index ba4f0a157b1..4f5d140b24d 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt @@ -10,5 +10,9 @@ data class BkUserInfo( @ApiModelProperty("用户名") val username: String, @ApiModelProperty("是否启用") - val enabled: Boolean + val enabled: Boolean, + @ApiModelProperty("用户额外信息") + val extras: BkUserExtras, + @ApiModelProperty("用户部门") + val departments: BkUserDeptInfo ) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt index 8b3e763a7f2..bb7c051e7cd 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt @@ -1,6 +1,8 @@ package com.tencent.devops.auth.pojo.vo import com.tencent.bk.sdk.iam.constants.ManagerScopesEnum +import com.tencent.devops.auth.pojo.BkUserDeptInfo +import com.tencent.devops.auth.pojo.BkUserExtras import io.swagger.annotations.ApiModel import io.swagger.annotations.ApiModelProperty @@ -13,5 +15,9 @@ data class UserAndDeptInfoVo( @ApiModelProperty("信息类型") val type: ManagerScopesEnum, @ApiModelProperty("是否拥有子级") - val hasChild: Boolean? = false + val hasChild: Boolean? = false, + @ApiModelProperty("用户部门详细信息") + val deptInfo: BkUserDeptInfo? = null, + @ApiModelProperty("用户额外详细信息") + val extras: BkUserExtras? = null ) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/Constants.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/Constants.kt index 6b185670aff..9140e08e58b 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/Constants.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/Constants.kt @@ -30,7 +30,7 @@ package com.tencent.devops.auth.common object Constants { const val SUPER_MANAGER = -1 const val DEPT_LABEL = "id,name,parent,enabled,has_children" - const val USER_LABLE = "id,username,enabled" + const val USER_LABLE = "id,username,enabled,departments,extras" const val LEVEL = "level" const val PARENT = "parent" const val NAME = "name" diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt index b4c388a1cee..e7b5042486a 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt @@ -138,8 +138,8 @@ class AuthDeptServiceImpl @Autowired constructor( accessToken = accessToken ) val userSearch = SearchUserAndDeptEntity( - bk_app_code = appCode!!, - bk_app_secret = appSecret!!, + bk_app_code = appCode, + bk_app_secret = appSecret, bk_username = userId, fields = USER_LABLE, lookupField = USERNAME, @@ -163,7 +163,9 @@ class AuthDeptServiceImpl @Autowired constructor( UserAndDeptInfoVo( id = it.id, name = it.username, - type = ManagerScopesEnum.USER + type = ManagerScopesEnum.USER, + deptInfo = it.departments, + extras = it.extras ) ) } @@ -188,12 +190,14 @@ class AuthDeptServiceImpl @Autowired constructor( UserAndDeptInfoVo( id = it.id, name = it.username, - type = ManagerScopesEnum.USER + type = ManagerScopesEnum.USER, + deptInfo = it.departments, + extras = it.extras ) ) } - val depteInfos = getDeptInfo(deptSearch) - depteInfos.results.forEach { + val deptInfos = getDeptInfo(deptSearch) + deptInfos.results.forEach { userAndDeptInfos.add( UserAndDeptInfoVo( id = it.id, @@ -205,7 +209,6 @@ class AuthDeptServiceImpl @Autowired constructor( } } } - return userAndDeptInfos } @@ -296,12 +299,12 @@ class AuthDeptServiceImpl @Autowired constructor( private fun getDeptInfo(searchDeptEnity: SearchUserAndDeptEntity): DeptInfoVo { val responseDTO = callUserCenter(LIST_DEPARTMENTS, searchDeptEnity) - return objectMapper.readValue(responseDTO) + return objectMapper.readValue(responseDTO) } private fun getUserInfo(searchUserEntity: SearchUserAndDeptEntity): BkUserInfoVo { val responseDTO = callUserCenter(USER_INFO, searchUserEntity) - return objectMapper.readValue(responseDTO) + return objectMapper.readValue(responseDTO) } private fun callUserCenter(url: String, searchEntity: EsbBaseReq): String { @@ -337,7 +340,8 @@ class AuthDeptServiceImpl @Autowired constructor( throw OperationException( I18nUtil.getCodeLanMessage( messageCode = AuthMessageCode.USER_NOT_EXIST - )) + ) + ) } logger.info("user center response:${objectMapper.writeValueAsString(responseDTO.data)}") return objectMapper.writeValueAsString(responseDTO.data) diff --git a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt new file mode 100644 index 00000000000..db32ceb85f3 --- /dev/null +++ b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt @@ -0,0 +1,42 @@ +package com.tencent.devops.openapi.api.apigw.v4 + +import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo +import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE +import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE +import com.tencent.devops.common.api.auth.AUTH_HEADER_USER_ID +import com.tencent.devops.common.api.auth.AUTH_HEADER_USER_ID_DEFAULT_VALUE +import com.tencent.devops.common.api.pojo.Result +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam +import javax.ws.rs.Consumes +import javax.ws.rs.HeaderParam +import javax.ws.rs.POST +import javax.ws.rs.Path +import javax.ws.rs.PathParam +import javax.ws.rs.Produces +import javax.ws.rs.core.MediaType + +@Api(tags = ["OPENAPI_USER_MANAGEMENT_V4"], description = "OPENAPI-用户管理") +@Path("/{apigwType:apigw-user|apigw-app|apigw}/v4/auth/user/management/") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +interface ApigwUserManagementResourceV4 { + @POST + @Path("/getUserInfo") + @ApiOperation( + "获取用户信息", + tags = ["v4_app_user_info"] + ) + fun getUserInfo( + @ApiParam(value = "appCode", required = true, defaultValue = AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_DEVOPS_APP_CODE) + appCode: String?, + @ApiParam(value = "apigw Type", required = true) + @PathParam("apigwType") + apigwType: String?, + @ApiParam("用户ID", required = true, defaultValue = AUTH_HEADER_USER_ID_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_USER_ID) + userId: String + ): Result +} diff --git a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt new file mode 100644 index 00000000000..bc6695132f4 --- /dev/null +++ b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt @@ -0,0 +1,32 @@ +package com.tencent.devops.openapi.resources.apigw.v4 + +import com.tencent.devops.auth.api.service.ServiceDeptResource +import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.common.client.Client +import com.tencent.devops.common.web.RestResource +import com.tencent.devops.openapi.api.apigw.v4.ApigwUserManagementResourceV4 +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired + +@RestResource +class ApigwUserManagementResourceV4Impl @Autowired constructor( + private val client: Client +) : ApigwUserManagementResourceV4 { + + override fun getUserInfo( + appCode: String?, + apigwType: String?, + userId: String + ): Result { + logger.info("OPENAPI_GET_USER_INFO_V4|$appCode|$userId") + return client.get(ServiceDeptResource::class).getUserInfo( + userId = userId, + name = userId + ) + } + + companion object { + val logger = LoggerFactory.getLogger(ApigwUserManagementResourceV4Impl::class.java) + } +} From f4d5c51f0574ea278f5452190d7cf5c1c49a5b69 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 22 Aug 2023 09:55:02 +0800 Subject: [PATCH 42/73] =?UTF-8?q?=20feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20O?= =?UTF-8?q?auth2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#?= =?UTF-8?q?9353?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oauth2/Oauth2ServiceEndpointResource.kt | 37 +++++++++++++++++++ .../auth/dao/AuthOauth2ScopeOperationDao.kt | 19 ++++++++++ .../Oauth2ServiceEndpointResourceImpl.kt | 32 ++++++++++++++++ .../auth/service/oauth2/Oauth2Config.kt | 6 ++- .../service/oauth2/Oauth2EndpointService.kt | 11 ++---- .../oauth2/Oauth2ScopeOperationService.kt | 21 +++++++++++ support-files/sql/1001_ci_auth_ddl_mysql.sql | 11 +++++- 7 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2ServiceEndpointResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2ServiceEndpointResource.kt index 93b800266ee..98f448722eb 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2ServiceEndpointResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/Oauth2ServiceEndpointResource.kt @@ -1,7 +1,10 @@ package com.tencent.devops.auth.api.oauth2 import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.dto.Oauth2AuthorizationCodeDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo +import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_AUTHORIZATION import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_CLIENT_ID import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_CLIENT_SECRET @@ -10,10 +13,12 @@ import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam import javax.ws.rs.Consumes +import javax.ws.rs.GET import javax.ws.rs.HeaderParam import javax.ws.rs.POST import javax.ws.rs.Path import javax.ws.rs.Produces +import javax.ws.rs.QueryParam import javax.ws.rs.core.MediaType @Api(tags = ["OAUTH2_ENDPOINT"], description = "oauth2相关") @@ -21,6 +26,38 @@ import javax.ws.rs.core.MediaType @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) interface Oauth2ServiceEndpointResource { + @GET + @Path("/getAuthorizationInformation") + @ApiOperation("获取授权信息") + fun getAuthorizationInformation( + @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) + @ApiParam("待校验用户ID", required = true) + userId: String, + @QueryParam("clientId") + @ApiParam("客户端ID", required = true) + clientId: String, + @QueryParam("redirectUri") + @ApiParam("跳转链接", required = true) + redirectUri: String + ): Result + + @POST + @Path("/getAuthorizationCode") + @ApiOperation("获取授权码") + fun getAuthorizationCode( + @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) + @ApiParam("待校验用户ID", required = true) + userId: String, + @QueryParam("clientId") + @ApiParam("客户端ID", required = true) + clientId: String, + @QueryParam("redirectUri") + @ApiParam("跳转链接", required = true) + redirectUri: String, + @ApiParam("oauth2获取授权码请求报文体", required = true) + authorizationCodeDTO: Oauth2AuthorizationCodeDTO + ): Result + @POST @Path("/getAccessToken") @ApiOperation("获取accessToken") diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt new file mode 100644 index 00000000000..19c2ac7da6a --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt @@ -0,0 +1,19 @@ +package com.tencent.devops.auth.dao + +import com.tencent.devops.model.auth.tables.TAuthOauth2ScopeOperationInformation +import com.tencent.devops.model.auth.tables.records.TAuthOauth2ScopeOperationInformationRecord +import org.jooq.DSLContext +import org.springframework.stereotype.Repository + +@Repository +class AuthOauth2ScopeOperationDao { + fun get( + dslContext: DSLContext, + operationId: String + ): TAuthOauth2ScopeOperationInformationRecord? { + return with(TAuthOauth2ScopeOperationInformation.T_AUTH_OAUTH2_SCOPE_OPERATION_INFORMATION) { + dslContext.selectFrom(this).where(OPERATION_ID.eq(operationId)) + .fetchOne() + } + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2ServiceEndpointResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2ServiceEndpointResourceImpl.kt index 5051c6680b1..724017f236f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2ServiceEndpointResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/Oauth2ServiceEndpointResourceImpl.kt @@ -2,7 +2,9 @@ package com.tencent.devops.auth.resources import com.tencent.devops.auth.api.oauth2.Oauth2ServiceEndpointResource import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.pojo.dto.Oauth2AuthorizationCodeDTO import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo import com.tencent.devops.auth.service.oauth2.Oauth2EndpointService import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.web.RestResource @@ -11,6 +13,36 @@ import com.tencent.devops.common.web.RestResource class Oauth2ServiceEndpointResourceImpl constructor( private val endpointService: Oauth2EndpointService ) : Oauth2ServiceEndpointResource { + override fun getAuthorizationInformation( + userId: String, + clientId: String, + redirectUri: String + ): Result { + return Result( + endpointService.getAuthorizationInformation( + userId = userId, + clientId = clientId, + redirectUri = redirectUri + ) + ) + } + + override fun getAuthorizationCode( + userId: String, + clientId: String, + redirectUri: String, + authorizationCodeDTO: Oauth2AuthorizationCodeDTO + ): Result { + return Result( + endpointService.getAuthorizationCode( + userId = userId, + clientId = clientId, + redirectUri = redirectUri, + authorizationCodeDTO = authorizationCodeDTO + ) + ) + } + override fun getAccessToken( clientId: String, clientSecret: String, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt index b4053302783..fe6b66f9a41 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -17,7 +17,8 @@ class Oauth2Config constructor( private val accessTokenService: Oauth2AccessTokenService, private val clientCredentialsTokenGranter: ClientCredentialsTokenGranter, private val authorizationCodeTokenGranter: AuthorizationCodeTokenGranter, - private val refreshTokenGranter: RefreshTokenGranter + private val refreshTokenGranter: RefreshTokenGranter, + private val scopeOperationService: Oauth2ScopeOperationService ) { @Bean fun oauth2EndpointService(): Oauth2EndpointService { @@ -26,7 +27,8 @@ class Oauth2Config constructor( clientService = oauth2ClientService, codeService = codeService, scopeService = scopeService, - accessTokenService = accessTokenService + accessTokenService = accessTokenService, + scopeOperationService = scopeOperationService ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 9534f51caa0..4a259b6be5d 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -17,7 +17,8 @@ class Oauth2EndpointService constructor( private val clientService: Oauth2ClientService, private val codeService: Oauth2CodeService, private val scopeService: Oauth2ScopeService, - private val accessTokenService: Oauth2AccessTokenService + private val accessTokenService: Oauth2AccessTokenService, + private val scopeOperationService: Oauth2ScopeOperationService ) { fun getAuthorizationInformation( userId: String, @@ -34,10 +35,11 @@ class Oauth2EndpointService constructor( redirectUri = redirectUri, clientDetails = clientDetails ) + val scopeOperations = clientDetails.scope.split(",") return Oauth2AuthorizationInfoVo( userName = userId, clientName = clientDetails.clientName, - scope = SCOPE + scope = scopeOperations.associateWith { scopeOperationService.get(it)!!.operationNameCn } ) } @@ -126,11 +128,6 @@ class Oauth2EndpointService constructor( companion object { private val logger = LoggerFactory.getLogger(Oauth2EndpointService::class.java) private const val codeValiditySeconds = 600L - private val SCOPE = mutableMapOf( - "project_visit" to "获取你有权限的项目列表", - "pipeline_list" to "获取你有权限的流水线列表", - "pipeline_download" to "下载你有权限的制品" - ) private const val OAUTH2_SCHEME = "Bearer " } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt new file mode 100644 index 00000000000..cf68df5807d --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt @@ -0,0 +1,21 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.dao.AuthOauth2ScopeOperationDao +import com.tencent.devops.model.auth.tables.records.TAuthOauth2ScopeOperationInformationRecord +import org.jooq.DSLContext +import org.springframework.stereotype.Service + +@Service +class Oauth2ScopeOperationService constructor( + private val dslContext: DSLContext, + private val oauth2ScopeOperationDao: AuthOauth2ScopeOperationDao +) { + fun get( + operationId: String + ): TAuthOauth2ScopeOperationInformationRecord? { + return oauth2ScopeOperationDao.get( + dslContext = dslContext, + operationId = operationId + ) + } +} diff --git a/support-files/sql/1001_ci_auth_ddl_mysql.sql b/support-files/sql/1001_ci_auth_ddl_mysql.sql index a947ee1fd32..69fabfa0d10 100644 --- a/support-files/sql/1001_ci_auth_ddl_mysql.sql +++ b/support-files/sql/1001_ci_auth_ddl_mysql.sql @@ -288,7 +288,7 @@ CREATE TABLE `T_AUTH_OAUTH2_CLIENT_DETAILS` ( `CLIENT_ID` VARCHAR(32) NOT NULL COMMENT '客户端标识', `CLIENT_SECRET` VARCHAR(64) NOT NULL COMMENT '客户端秘钥', `CLIENT_NAME` VARCHAR(255) NOT NULL COMMENT '客户端名称', - `SCOPE` MEDIUMTEXT DEFAULT NULL COMMENT '授权范围', + `SCOPE` MEDIUMTEXT DEFAULT NULL COMMENT '授权操作范围', `AUTHORIZED_GRANT_TYPES` VARCHAR(64) NOT NULL COMMENT '授权模式', `WEB_SERVER_REDIRECT_URI` VARCHAR(255) DEFAULT NULL COMMENT '跳转链接', `ACCESS_TOKEN_VALIDITY` BIGINT(20) NOT NULL COMMENT 'access_token有效时间', @@ -337,4 +337,13 @@ CREATE TABLE `T_AUTH_OAUTH2_SCOPE` ( PRIMARY KEY (`ID`) ) ENGINE=INNODB DEFAULT CHARSET=UTF8 COMMENT='授权范围表'; +CREATE TABLE `T_AUTH_OAUTH2_SCOPE_OPERATION_INFORMATION` ( + `ID` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主健ID', + `OPERATION_ID` VARCHAR(64) NOT NULL COMMENT '授权操作ID', + `OPERATION_NAME_CN` VARCHAR(64) NOT NULL COMMENT '授权操作中文名称', + `OPERATION_NAME_EN` VARCHAR(64) NOT NULL COMMENT '授权操作英文名称', + `CREATE_TIME` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`ID`) +) ENGINE=INNODB DEFAULT CHARSET=UTF8 COMMENT='授权操作信息表'; + SET FOREIGN_KEY_CHECKS = 1; From 99672cb8144cc03a7ed2b545ff9598bf67fd007b Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 22 Aug 2023 10:03:51 +0800 Subject: [PATCH 43/73] =?UTF-8?q?=20feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20O?= =?UTF-8?q?auth2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#?= =?UTF-8?q?9353?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index 4a259b6be5d..af86da36420 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -25,7 +25,7 @@ class Oauth2EndpointService constructor( clientId: String, redirectUri: String ): Oauth2AuthorizationInfoVo { - logger.info("get authorization information :$userId|$clientId") + logger.info("get authorization information:$userId|$clientId") // 1、校验clientId是否存在 val clientDetails = clientService.getClientDetails(clientId = clientId) // 2、校验客户端信息是否正确 From c3cc857ea8adbb2936852bec93f82cb72d0b59e7 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 22 Aug 2023 11:18:19 +0800 Subject: [PATCH 44/73] =?UTF-8?q?=20feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20O?= =?UTF-8?q?auth2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#?= =?UTF-8?q?9353?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt index db32ceb85f3..b19db3e01b5 100644 --- a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt +++ b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt @@ -10,8 +10,8 @@ import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam import javax.ws.rs.Consumes +import javax.ws.rs.GET import javax.ws.rs.HeaderParam -import javax.ws.rs.POST import javax.ws.rs.Path import javax.ws.rs.PathParam import javax.ws.rs.Produces @@ -22,7 +22,7 @@ import javax.ws.rs.core.MediaType @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) interface ApigwUserManagementResourceV4 { - @POST + @GET @Path("/getUserInfo") @ApiOperation( "获取用户信息", From 7a26ff152c52a2709cef1518c5b728bfab511220 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 22 Aug 2023 11:34:12 +0800 Subject: [PATCH 45/73] =?UTF-8?q?=20feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20O?= =?UTF-8?q?auth2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#?= =?UTF-8?q?9353?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt | 2 +- .../kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt index 4f5d140b24d..17d4e07d91f 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt @@ -14,5 +14,5 @@ data class BkUserInfo( @ApiModelProperty("用户额外信息") val extras: BkUserExtras, @ApiModelProperty("用户部门") - val departments: BkUserDeptInfo + val departments: List ) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt index bb7c051e7cd..46be04f353d 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt @@ -17,7 +17,7 @@ data class UserAndDeptInfoVo( @ApiModelProperty("是否拥有子级") val hasChild: Boolean? = false, @ApiModelProperty("用户部门详细信息") - val deptInfo: BkUserDeptInfo? = null, + val deptInfo: List? = null, @ApiModelProperty("用户额外详细信息") val extras: BkUserExtras? = null ) From 12e5aa529d54995d326d49df5c88d2b4f30166be Mon Sep 17 00:00:00 2001 From: greysonfang Date: Mon, 28 Aug 2023 20:07:16 +0800 Subject: [PATCH 46/73] =?UTF-8?q?=20feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20O?= =?UTF-8?q?auth2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#?= =?UTF-8?q?9353?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/auth/dao/AuthOauth2ScopeOperationDao.kt | 8 ++++---- .../auth/service/oauth2/Oauth2ScopeOperationService.kt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt index 19c2ac7da6a..48471d9a40a 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt @@ -1,7 +1,7 @@ package com.tencent.devops.auth.dao -import com.tencent.devops.model.auth.tables.TAuthOauth2ScopeOperationInformation -import com.tencent.devops.model.auth.tables.records.TAuthOauth2ScopeOperationInformationRecord +import com.tencent.devops.model.auth.tables.TAuthOauth2ScopeOperation +import com.tencent.devops.model.auth.tables.records.TAuthOauth2ScopeOperationRecord import org.jooq.DSLContext import org.springframework.stereotype.Repository @@ -10,8 +10,8 @@ class AuthOauth2ScopeOperationDao { fun get( dslContext: DSLContext, operationId: String - ): TAuthOauth2ScopeOperationInformationRecord? { - return with(TAuthOauth2ScopeOperationInformation.T_AUTH_OAUTH2_SCOPE_OPERATION_INFORMATION) { + ): TAuthOauth2ScopeOperationRecord? { + return with(TAuthOauth2ScopeOperation.T_AUTH_OAUTH2_SCOPE_OPERATION) { dslContext.selectFrom(this).where(OPERATION_ID.eq(operationId)) .fetchOne() } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt index cf68df5807d..d3f8387c0fb 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt @@ -1,7 +1,7 @@ package com.tencent.devops.auth.service.oauth2 import com.tencent.devops.auth.dao.AuthOauth2ScopeOperationDao -import com.tencent.devops.model.auth.tables.records.TAuthOauth2ScopeOperationInformationRecord +import com.tencent.devops.model.auth.tables.records.TAuthOauth2ScopeOperationRecord import org.jooq.DSLContext import org.springframework.stereotype.Service @@ -12,7 +12,7 @@ class Oauth2ScopeOperationService constructor( ) { fun get( operationId: String - ): TAuthOauth2ScopeOperationInformationRecord? { + ): TAuthOauth2ScopeOperationRecord? { return oauth2ScopeOperationDao.get( dslContext = dslContext, operationId = operationId From ff2442e49bca1dedbaaa48e99c9df82320969fd4 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Mon, 28 Aug 2023 20:10:30 +0800 Subject: [PATCH 47/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- support-files/sql/1001_ci_auth_ddl_mysql.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/sql/1001_ci_auth_ddl_mysql.sql b/support-files/sql/1001_ci_auth_ddl_mysql.sql index 69fabfa0d10..f5db075f607 100644 --- a/support-files/sql/1001_ci_auth_ddl_mysql.sql +++ b/support-files/sql/1001_ci_auth_ddl_mysql.sql @@ -337,7 +337,7 @@ CREATE TABLE `T_AUTH_OAUTH2_SCOPE` ( PRIMARY KEY (`ID`) ) ENGINE=INNODB DEFAULT CHARSET=UTF8 COMMENT='授权范围表'; -CREATE TABLE `T_AUTH_OAUTH2_SCOPE_OPERATION_INFORMATION` ( +CREATE TABLE `T_AUTH_OAUTH2_SCOPE_OPERATION` ( `ID` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主健ID', `OPERATION_ID` VARCHAR(64) NOT NULL COMMENT '授权操作ID', `OPERATION_NAME_CN` VARCHAR(64) NOT NULL COMMENT '授权操作中文名称', From aa7460599044a4baba322eb43a15e597c22609c0 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 30 Aug 2023 15:53:52 +0800 Subject: [PATCH 48/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/tencent/devops/auth/pojo/BkUserDeptInfo.kt | 6 +++--- .../kotlin/com/tencent/devops/auth/pojo/BkUserExtras.kt | 4 ++-- .../main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserDeptInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserDeptInfo.kt index 6fa4926cb37..ff9027547ef 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserDeptInfo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserDeptInfo.kt @@ -7,10 +7,10 @@ import io.swagger.annotations.ApiModelProperty @ApiModel("用户部门详细信息") data class BkUserDeptInfo( @ApiModelProperty("id") - val id: String, + val id: String?, @ApiModelProperty("部门名称") - val name: String, + val name: String?, @ApiModelProperty("部门详细名称") @JsonProperty("full_name") - val fullName: String + val fullName: String? ) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserExtras.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserExtras.kt index a31a9cdd6c6..c0e2cc39c25 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserExtras.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserExtras.kt @@ -7,8 +7,8 @@ import io.swagger.annotations.ApiModelProperty @ApiModel("用户额外信息") data class BkUserExtras( @ApiModelProperty("性别") - val gender: String, + val gender: String?, @ApiModelProperty("postName") @JsonProperty("postname") - val postName: String + val postName: String? ) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt index 17d4e07d91f..07fefdb22be 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/BkUserInfo.kt @@ -12,7 +12,7 @@ data class BkUserInfo( @ApiModelProperty("是否启用") val enabled: Boolean, @ApiModelProperty("用户额外信息") - val extras: BkUserExtras, + val extras: BkUserExtras?, @ApiModelProperty("用户部门") - val departments: List + val departments: List? ) From d05a7808b4e9826fdb232d4d66f66bcbb227058e Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 14 Sep 2023 14:50:38 +0800 Subject: [PATCH 49/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apigw/v4/ApigwOauth2EndpointResourceV4.kt | 3 +-- .../v4/ApigwOauth2EndpointResourceV4Impl.kt | 24 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt index dd45b966986..95444b49b17 100644 --- a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt +++ b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwOauth2EndpointResourceV4.kt @@ -1,7 +1,6 @@ package com.tencent.devops.openapi.api.apigw.v4 import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest -import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE import com.tencent.devops.common.api.auth.AUTH_HEADER_OAUTH2_CLIENT_ID @@ -44,5 +43,5 @@ interface ApigwOauth2EndpointResourceV4 { clientSecret: String, @ApiParam("oauth2获取token请求报文体", required = true) accessTokenRequest: Oauth2AccessTokenRequest - ): Result + ): Result } diff --git a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwOauth2EndpointResourceV4Impl.kt b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwOauth2EndpointResourceV4Impl.kt index cacfc07715d..49d28aefd80 100644 --- a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwOauth2EndpointResourceV4Impl.kt +++ b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwOauth2EndpointResourceV4Impl.kt @@ -2,7 +2,8 @@ package com.tencent.devops.openapi.resources.apigw.v4 import com.tencent.devops.auth.api.oauth2.Oauth2ServiceEndpointResource import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest -import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo +import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.common.api.exception.RemoteServiceException import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.client.Client import com.tencent.devops.common.web.RestResource @@ -21,16 +22,25 @@ class ApigwOauth2EndpointResourceV4Impl @Autowired constructor( clientId: String, clientSecret: String, accessTokenRequest: Oauth2AccessTokenRequest - ): Result { + ): Result { logger.info("OPENAPI_OAUTH2_ACCESS_TOKEN_V4|$appCode|$clientId") - return client.get(Oauth2ServiceEndpointResource::class).getAccessToken( - clientId = clientId, - clientSecret = clientSecret, - accessTokenRequest = accessTokenRequest - ) + return try { + client.get(Oauth2ServiceEndpointResource::class).getAccessToken( + clientId = clientId, + clientSecret = clientSecret, + accessTokenRequest = accessTokenRequest + ) + } catch (ex: ErrorCodeException) { + Result(status = ex.errorCode.toInt(), message = ex.defaultMessage) + } catch (rex: RemoteServiceException) { + Result(status = rex.errorCode ?: REMOTE_EXCEPTION_CODE, message = rex.errorMessage) + } catch (ignore: Exception) { + throw ignore + } } companion object { val logger = LoggerFactory.getLogger(ApigwOauth2EndpointResourceV4Impl::class.java) + private const val REMOTE_EXCEPTION_CODE = 500 } } From e1c13aab3c532a9c09cd8ddf1b01079aa817bfca Mon Sep 17 00:00:00 2001 From: greysonfang Date: Mon, 23 Oct 2023 11:28:07 +0800 Subject: [PATCH 50/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/service/ServiceDeptResource.kt | 9 ++++++ .../devops/auth/constant/AuthMessageCode.kt | 3 ++ .../auth/pojo/dto/SecOpsWaterMarkDTO.kt | 12 ++++++++ .../auth/pojo/vo/SecOpsWaterMarkInfoVo.kt | 12 ++++++++ .../devops/auth/pojo/vo/UserAndDeptInfoVo.kt | 4 ++- .../common/MockAuthCoreAutoConfiguration.kt | 6 ++++ .../service/ServiceDeptResourceImpl.kt | 4 +++ .../auth/service/AuthDeptServiceImpl.kt | 29 +++++++++++++++++-- .../auth/service/DefaultDeptServiceImpl.kt | 6 ++++ .../devops/auth/service/DeptService.kt | 2 ++ .../secops/DefaultSecOpsServiceImpl.kt | 12 ++++++++ .../auth/service/secops/SecOpsService.kt | 13 +++++++++ .../v4/ApigwUserManagementResourceV4Impl.kt | 5 ++-- 13 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/SecOpsWaterMarkDTO.kt create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/SecOpsWaterMarkInfoVo.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/DefaultSecOpsServiceImpl.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/SecOpsService.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt index 885c02b876b..e170c248c50 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt @@ -79,4 +79,13 @@ interface ServiceDeptResource { @ApiParam("用户名称", required = true) name: String ): Result + + @GET + @Path("/getUserInfoAndWaterMark") + @ApiOperation("获取单个用户信息和水印信息") + fun getUserInfoAndWaterMark( + @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) + @ApiParam("用户ID", required = true) + userId: String + ): Result } diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt index eb96bde3c5b..87d970799c4 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/constant/AuthMessageCode.kt @@ -127,4 +127,7 @@ object AuthMessageCode { const val ERROR_MONITOR_SPACE_NOT_EXIST = "2121077" // 监控空间不存在 const val ERROR_MONITOR_READ_ONLY_ACTIONS_NOT_EXIST = "2121078" // 业务只读组不存在 const val ERROR_MONITOR_OPS_ACTIONS_NOT_EXIST = "2121079" // 业务运维组不存在 + + const val ERROR_WATER_MARK_NOT_EXIST = "2121080" // 水印信息不存在 + const val ERROR_USER_NOT_EXIST = "2121081" // 用户不存在 } diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/SecOpsWaterMarkDTO.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/SecOpsWaterMarkDTO.kt new file mode 100644 index 00000000000..164f5a5d57b --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/SecOpsWaterMarkDTO.kt @@ -0,0 +1,12 @@ +package com.tencent.devops.auth.pojo.dto + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("安全水印") +data class SecOpsWaterMarkDTO( + @ApiModelProperty("场景token") + val token: String, + @ApiModelProperty("用户名称") + val username: String +) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/SecOpsWaterMarkInfoVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/SecOpsWaterMarkInfoVo.kt new file mode 100644 index 00000000000..f2afd72d017 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/SecOpsWaterMarkInfoVo.kt @@ -0,0 +1,12 @@ +package com.tencent.devops.auth.pojo.vo + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("用户水印信息") +data class SecOpsWaterMarkInfoVo( + @ApiModelProperty("类型") + val type: String, + @ApiModelProperty("水印信息") + val data: String +) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt index 46be04f353d..ad9802e7a07 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt @@ -19,5 +19,7 @@ data class UserAndDeptInfoVo( @ApiModelProperty("用户部门详细信息") val deptInfo: List? = null, @ApiModelProperty("用户额外详细信息") - val extras: BkUserExtras? = null + val extras: BkUserExtras? = null, + @ApiModelProperty("水印信息") + val waterMark: String? = null ) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/MockAuthCoreAutoConfiguration.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/MockAuthCoreAutoConfiguration.kt index f43ca622130..9f7c38fca9f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/MockAuthCoreAutoConfiguration.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/MockAuthCoreAutoConfiguration.kt @@ -44,6 +44,8 @@ import com.tencent.devops.auth.service.sample.SamplePermissionRoleMemberService import com.tencent.devops.auth.service.sample.SamplePermissionRoleService import com.tencent.devops.auth.service.sample.SamplePermissionSuperManagerService import com.tencent.devops.auth.service.sample.SamplePermissionUrlServiceImpl +import com.tencent.devops.auth.service.secops.DefaultSecOpsServiceImpl +import com.tencent.devops.auth.service.secops.SecOpsService import com.tencent.devops.common.client.Client import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.context.annotation.Bean @@ -141,4 +143,8 @@ class MockAuthCoreAutoConfiguration { @Bean @ConditionalOnMissingBean(AuthMonitorSpaceService::class) fun sampleAuthMonitorSpaceService() = SampleAuthMonitorSpaceService() + + @Bean + @ConditionalOnMissingBean(SecOpsService::class) + fun defaultSecOpsServiceImpl() = DefaultSecOpsServiceImpl() } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt index 5905d7483ae..4d9a93508e2 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt @@ -50,4 +50,8 @@ class ServiceDeptResourceImpl @Autowired constructor( override fun getUserInfo(userId: String, name: String): Result { return Result(deptService.getUserInfo(userId, name)) } + + override fun getUserInfoAndWaterMark(userId: String): Result { + return Result(deptService.getUserInfoAndWaterMark(userId)) + } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt index e7b5042486a..ced85823649 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt @@ -48,24 +48,27 @@ import com.tencent.devops.auth.entity.UserDeptTreeInfo import com.tencent.devops.auth.pojo.vo.BkUserInfoVo import com.tencent.devops.auth.pojo.vo.DeptInfoVo import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo +import com.tencent.devops.auth.service.secops.SecOpsService +import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.common.api.exception.OperationException import com.tencent.devops.common.api.util.JsonUtil import com.tencent.devops.common.api.util.OkhttpUtils import com.tencent.devops.common.auth.api.pojo.EsbBaseReq import com.tencent.devops.common.redis.RedisOperation import com.tencent.devops.common.web.utils.I18nUtil -import java.util.Optional -import java.util.concurrent.TimeUnit import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.Request import okhttp3.RequestBody import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value +import java.util.Optional +import java.util.concurrent.TimeUnit class AuthDeptServiceImpl @Autowired constructor( val redisOperation: RedisOperation, - val objectMapper: ObjectMapper + val objectMapper: ObjectMapper, + val secOpsService: SecOpsService ) : DeptService { @Value("\${esb.code:#{null}}") @@ -263,6 +266,26 @@ class AuthDeptServiceImpl @Autowired constructor( return userInfoCache.getIfPresent(name)?.get() ?: getUserAndPutInCache(userId, name) } + override fun getUserInfoAndWaterMark(userId: String): UserAndDeptInfoVo? { + val userInfo = getUserInfo( + userId = userId, + name = userId + ) ?: throw ErrorCodeException( + errorCode = AuthMessageCode.ERROR_USER_NOT_EXIST, + defaultMessage = "user not exist!$userId" + ) + val userWaterMark = secOpsService.getUserWaterMark(userId = userId) + return UserAndDeptInfoVo( + id = userInfo.id, + name = userInfo.name, + type = userInfo.type, + hasChild = userInfo.hasChild, + deptInfo = userInfo.deptInfo, + extras = userInfo.extras, + waterMark = userWaterMark.data + ) + } + private fun getUserAndPutInCache(userId: String, name: String): UserAndDeptInfoVo? { return getUserAndDeptByName( name = name, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt index df5bb01fddd..7719e5867e0 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt @@ -73,4 +73,10 @@ class DefaultDeptServiceImpl : DeptService { name = name, type = ManagerScopesEnum.USER ) + + override fun getUserInfoAndWaterMark(userId: String): UserAndDeptInfoVo? = UserAndDeptInfoVo( + id = 0, + name = name, + type = ManagerScopesEnum.USER + ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt index ac49979a436..71d342e9ee7 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt @@ -55,4 +55,6 @@ interface DeptService { // 获取单个用户信息 fun getUserInfo(userId: String, name: String): UserAndDeptInfoVo? + + fun getUserInfoAndWaterMark(userId: String): UserAndDeptInfoVo? } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/DefaultSecOpsServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/DefaultSecOpsServiceImpl.kt new file mode 100644 index 00000000000..7e77d55b5e6 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/DefaultSecOpsServiceImpl.kt @@ -0,0 +1,12 @@ +package com.tencent.devops.auth.service.secops + +import com.tencent.devops.auth.pojo.vo.SecOpsWaterMarkInfoVo + +class DefaultSecOpsServiceImpl : SecOpsService { + override fun getUserWaterMark(userId: String): SecOpsWaterMarkInfoVo { + return SecOpsWaterMarkInfoVo( + type = "", + data = "" + ) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/SecOpsService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/SecOpsService.kt new file mode 100644 index 00000000000..40344251a78 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/SecOpsService.kt @@ -0,0 +1,13 @@ +package com.tencent.devops.auth.service.secops + +import com.tencent.devops.auth.pojo.vo.SecOpsWaterMarkInfoVo + +/** + * 安全相关接口 + */ +interface SecOpsService { + /** + * 获取用户水印信息 + */ + fun getUserWaterMark(userId: String): SecOpsWaterMarkInfoVo +} diff --git a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt index bc6695132f4..51041eb473b 100644 --- a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt +++ b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt @@ -20,9 +20,8 @@ class ApigwUserManagementResourceV4Impl @Autowired constructor( userId: String ): Result { logger.info("OPENAPI_GET_USER_INFO_V4|$appCode|$userId") - return client.get(ServiceDeptResource::class).getUserInfo( - userId = userId, - name = userId + return client.get(ServiceDeptResource::class).getUserInfoAndWaterMark( + userId = userId ) } From a152f563ce0b66ecb7e9b8a3e34190e9ab40e9ac Mon Sep 17 00:00:00 2001 From: greysonfang Date: Mon, 23 Oct 2023 12:08:41 +0800 Subject: [PATCH 51/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt index 7719e5867e0..12745b7a467 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt @@ -76,7 +76,7 @@ class DefaultDeptServiceImpl : DeptService { override fun getUserInfoAndWaterMark(userId: String): UserAndDeptInfoVo? = UserAndDeptInfoVo( id = 0, - name = name, + name = userId, type = ManagerScopesEnum.USER ) } From 3df1aba976e7ebcc77bcd619c92a0bdfb9a6b6cb Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 9 Nov 2023 20:50:08 +0800 Subject: [PATCH 52/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/service/ServiceDeptResource.kt | 5 ++++- .../devops/auth/pojo/vo/UserAndDeptInfoVo.kt | 6 ++++-- .../service/ServiceDeptResourceImpl.kt | 7 +++++-- .../devops/auth/service/AuthDeptServiceImpl.kt | 17 ++++++++++++++--- .../auth/service/DefaultDeptServiceImpl.kt | 5 ++++- .../tencent/devops/auth/service/DeptService.kt | 2 +- .../apigw/v4/ApigwUserManagementResourceV4.kt | 6 +++++- .../v4/ApigwUserManagementResourceV4Impl.kt | 6 ++++-- 8 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt index e170c248c50..601cf9845f4 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt @@ -86,6 +86,9 @@ interface ServiceDeptResource { fun getUserInfoAndWaterMark( @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) @ApiParam("用户ID", required = true) - userId: String + userId: String, + @ApiParam("项目ID", required = true) + @QueryParam("projectCode") + projectCode: String ): Result } diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt index ad9802e7a07..b7a90ee0556 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt @@ -6,7 +6,7 @@ import com.tencent.devops.auth.pojo.BkUserExtras import io.swagger.annotations.ApiModel import io.swagger.annotations.ApiModelProperty -@ApiModel("用户和组织信息返回") +@ApiModel("用户和组织信息返回实体") data class UserAndDeptInfoVo( @ApiModelProperty("id") val id: Int, @@ -21,5 +21,7 @@ data class UserAndDeptInfoVo( @ApiModelProperty("用户额外详细信息") val extras: BkUserExtras? = null, @ApiModelProperty("水印信息") - val waterMark: String? = null + val waterMark: String? = null, + @ApiModelProperty("是否是项目成员") + val belongProjectMember: Boolean? = null, ) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt index 4d9a93508e2..8e26a17b21a 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt @@ -51,7 +51,10 @@ class ServiceDeptResourceImpl @Autowired constructor( return Result(deptService.getUserInfo(userId, name)) } - override fun getUserInfoAndWaterMark(userId: String): Result { - return Result(deptService.getUserInfoAndWaterMark(userId)) + override fun getUserInfoAndWaterMark( + userId: String, + projectCode: String + ): Result { + return Result(deptService.getUserInfoAndWaterMark(userId, projectCode)) } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt index ced85823649..dd3b887b88f 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt @@ -48,6 +48,7 @@ import com.tencent.devops.auth.entity.UserDeptTreeInfo import com.tencent.devops.auth.pojo.vo.BkUserInfoVo import com.tencent.devops.auth.pojo.vo.DeptInfoVo import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo +import com.tencent.devops.auth.service.iam.PermissionProjectService import com.tencent.devops.auth.service.secops.SecOpsService import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.common.api.exception.OperationException @@ -68,7 +69,8 @@ import java.util.concurrent.TimeUnit class AuthDeptServiceImpl @Autowired constructor( val redisOperation: RedisOperation, val objectMapper: ObjectMapper, - val secOpsService: SecOpsService + val secOpsService: SecOpsService, + val permissionProjectService: PermissionProjectService ) : DeptService { @Value("\${esb.code:#{null}}") @@ -266,7 +268,10 @@ class AuthDeptServiceImpl @Autowired constructor( return userInfoCache.getIfPresent(name)?.get() ?: getUserAndPutInCache(userId, name) } - override fun getUserInfoAndWaterMark(userId: String): UserAndDeptInfoVo? { + override fun getUserInfoAndWaterMark( + userId: String, + projectCode: String + ): UserAndDeptInfoVo? { val userInfo = getUserInfo( userId = userId, name = userId @@ -275,6 +280,11 @@ class AuthDeptServiceImpl @Autowired constructor( defaultMessage = "user not exist!$userId" ) val userWaterMark = secOpsService.getUserWaterMark(userId = userId) + val belongProjectMember = permissionProjectService.isProjectUser( + userId = userId, + projectCode = projectCode, + group = null + ) return UserAndDeptInfoVo( id = userInfo.id, name = userInfo.name, @@ -282,7 +292,8 @@ class AuthDeptServiceImpl @Autowired constructor( hasChild = userInfo.hasChild, deptInfo = userInfo.deptInfo, extras = userInfo.extras, - waterMark = userWaterMark.data + waterMark = userWaterMark.data, + belongProjectMember = belongProjectMember ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt index 12745b7a467..6be0ef68091 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt @@ -74,7 +74,10 @@ class DefaultDeptServiceImpl : DeptService { type = ManagerScopesEnum.USER ) - override fun getUserInfoAndWaterMark(userId: String): UserAndDeptInfoVo? = UserAndDeptInfoVo( + override fun getUserInfoAndWaterMark( + userId: String, + projectCode: String + ): UserAndDeptInfoVo? = UserAndDeptInfoVo( id = 0, name = userId, type = ManagerScopesEnum.USER diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt index 71d342e9ee7..6c5bea82488 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt @@ -56,5 +56,5 @@ interface DeptService { // 获取单个用户信息 fun getUserInfo(userId: String, name: String): UserAndDeptInfoVo? - fun getUserInfoAndWaterMark(userId: String): UserAndDeptInfoVo? + fun getUserInfoAndWaterMark(userId: String, projectCode: String): UserAndDeptInfoVo? } diff --git a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt index b19db3e01b5..3a2e34e159d 100644 --- a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt +++ b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt @@ -15,6 +15,7 @@ import javax.ws.rs.HeaderParam import javax.ws.rs.Path import javax.ws.rs.PathParam import javax.ws.rs.Produces +import javax.ws.rs.QueryParam import javax.ws.rs.core.MediaType @Api(tags = ["OPENAPI_USER_MANAGEMENT_V4"], description = "OPENAPI-用户管理") @@ -37,6 +38,9 @@ interface ApigwUserManagementResourceV4 { apigwType: String?, @ApiParam("用户ID", required = true, defaultValue = AUTH_HEADER_USER_ID_DEFAULT_VALUE) @HeaderParam(AUTH_HEADER_USER_ID) - userId: String + userId: String, + @ApiParam("项目ID", required = true) + @QueryParam("projectCode") + projectCode: String ): Result } diff --git a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt index 51041eb473b..50d16f4ae98 100644 --- a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt +++ b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt @@ -17,11 +17,13 @@ class ApigwUserManagementResourceV4Impl @Autowired constructor( override fun getUserInfo( appCode: String?, apigwType: String?, - userId: String + userId: String, + projectCode: String ): Result { logger.info("OPENAPI_GET_USER_INFO_V4|$appCode|$userId") return client.get(ServiceDeptResource::class).getUserInfoAndWaterMark( - userId = userId + userId = userId, + projectCode = projectCode ) } From 92387a76b07c000f5850575a73f016510b1fd566 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 14 Nov 2023 14:31:15 +0800 Subject: [PATCH 53/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt index b7a90ee0556..171913b784f 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/UserAndDeptInfoVo.kt @@ -23,5 +23,5 @@ data class UserAndDeptInfoVo( @ApiModelProperty("水印信息") val waterMark: String? = null, @ApiModelProperty("是否是项目成员") - val belongProjectMember: Boolean? = null, + val belongProjectMember: Boolean? = null ) From 46158eae7fb29fbd33631e5afb6b78499ac2eaab Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 14 Nov 2023 14:50:09 +0800 Subject: [PATCH 54/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/devops/auth/service/oauth2/Oauth2Config.kt | 2 +- .../service/oauth2/grant/AuthorizationCodeTokenGranter.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt index fe6b66f9a41..1e3b730930e 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2Config.kt @@ -38,7 +38,7 @@ class Oauth2Config constructor( } private fun getDefaultTokenGranters(): List { - val tokenGranters = ArrayList() + val tokenGranters = mutableListOf() tokenGranters.add(clientCredentialsTokenGranter) tokenGranters.add(authorizationCodeTokenGranter) tokenGranters.add(refreshTokenGranter) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt index ba52dafe65f..8e080517c77 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/grant/AuthorizationCodeTokenGranter.kt @@ -52,7 +52,7 @@ class AuthorizationCodeTokenGranter constructor( ) } - fun handleAuthorizationCode( + private fun handleAuthorizationCode( code: String?, clientId: String ): TAuthOauth2CodeRecord { @@ -68,7 +68,7 @@ class AuthorizationCodeTokenGranter constructor( return codeDetails } - fun generateRefreshToken( + private fun generateRefreshToken( clientId: String, clientDetails: ClientDetailsInfo, accessTokenInfo: TAuthOauth2AccessTokenRecord? From b501a7e62ef80ef21712996b5fb860a054eee57d Mon Sep 17 00:00:00 2001 From: greysonfang Date: Tue, 14 Nov 2023 14:51:35 +0800 Subject: [PATCH 55/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/service/AuthDeptServiceImplTest.kt | 171 ------------------ 1 file changed, 171 deletions(-) delete mode 100644 src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt deleted file mode 100644 index 069932cfce0..00000000000 --- a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImplTest.kt +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. - * - * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. - * - * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. - * - * A copy of the MIT License is included in this file. - * - * - * Terms of the MIT License: - * --------------------------------------------------- - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of - * the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT - * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package com.tencent.devops.auth.service - -import com.tencent.devops.common.test.BkCiAbstractTest -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Test - -class AuthDeptServiceImplTest : BkCiAbstractTest() { - private val authDeptServiceImpl = AuthDeptServiceImpl(redisOperation, objectMapper) - - @Test - fun test() { - val response = "{\n" + - " \"count\": 162,\n" + - " \"results\": [\n" + - " {\n" + - " \"status\": \"NORMAL\",\n" + - " \"domain\": \"XXX.com\",\n" + - " \"telephone\": \"XXX\",\n" + - " \"create_time\": \"2021-04-27T15:33:59.000000Z\",\n" + - " \"country_code\": \"86\",\n" + - " \"logo\": null,\n" + - " \"iso_code\": \"CN\",\n" + - " \"id\": 173169,\n" + - " \"display_name\": \"abc\",\n" + - " \"leader\": [\n" + - " {\n" + - " \"username\": \"abcv\",\n" + - " \"display_name\": \"abc\",\n" + - " \"id\": 2435\n" + - " }\n" + - " ],\n" + - " \"username\": \"abc\",\n" + - " \"update_time\": \"2021-04-27T15:33:59.000000Z\",\n" + - " \"wx_userid\": \"\",\n" + - " \"staff_status\": \"IN\",\n" + - " \"password_valid_days\": -1,\n" + - " \"qq\": \"\",\n" + - " \"language\": \"zh-cn\",\n" + - " \"enabled\": true,\n" + - " \"time_zone\": \"Asia/Shanghai\",\n" + - " \"departments\": [\n" + - " {\n" + - " \"order\": 1,\n" + - " \"id\": 6580,\n" + - " \"full_name\": \"123/345\",\n" + - " \"name\": \"应用开发组\"\n" + - " }\n" + - " ],\n" + - " \"email\": \"abc@XXX.com\",\n" + - " \"extras\": {\n" + - " \"gender\": \"男\",\n" + - " \"postname\": \"应用开发组员工\"\n" + - " },\n" + - " \"position\": 0,\n" + - " \"category_id\": 2\n" + - " },\n" + - " {\n" + - " \"status\": \"NORMAL\",\n" + - " \"domain\": \"XXX.com\",\n" + - " \"telephone\": \"XXX\",\n" + - " \"create_time\": \"2021-04-27T15:33:59.000000Z\",\n" + - " \"country_code\": \"86\",\n" + - " \"logo\": null,\n" + - " \"iso_code\": \"CN\",\n" + - " \"id\": 173168,\n" + - " \"display_name\": \"abc\",\n" + - " \"leader\": [\n" + - " {\n" + - " \"username\": \"abc\",\n" + - " \"display_name\": \"abc\",\n" + - " \"id\": 2435\n" + - " }\n" + - " ],\n" + - " \"username\": \"def\",\n" + - " \"update_time\": \"2021-04-27T15:33:59.000000Z\",\n" + - " \"wx_userid\": \"\",\n" + - " \"staff_status\": \"IN\",\n" + - " \"password_valid_days\": -1,\n" + - " \"qq\": \"\",\n" + - " \"language\": \"zh-cn\",\n" + - " \"enabled\": true,\n" + - " \"time_zone\": \"Asia/Shanghai\",\n" + - " \"departments\": [\n" + - " {\n" + - " \"order\": 1,\n" + - " \"id\": 6580,\n" + - " \"full_name\": \"123/455\",\n" + - " \"name\": \"应用开发组\"\n" + - " }\n" + - " ],\n" + - " \"email\": \"XXX@126.com\",\n" + - " \"extras\": {\n" + - " \"gender\": \"男\",\n" + - " \"postname\": \"应用开发组员工\"\n" + - " },\n" + - " \"position\": 0,\n" + - " \"category_id\": 2\n" + - " }\n" + - " ]\n" + - " }" - val users = authDeptServiceImpl.findUserName(response) - val mockUsers = mutableListOf() - mockUsers.add("abc") - mockUsers.add("def") - Assertions.assertEquals(users, mockUsers) - } - - @Test - fun test1() { - val response = "[ {\n" + - " \"id\" : \"29510\",\n" + - " \"family\" : [ {\n" + - " \"order\" : 1,\n" + - " \"id\" : 123,\n" + - " \"full_name\" : \"XXX公司\",\n" + - " \"name\" : \"XXX公司\"\n" + - " }, {\n" + - " \"order\" : 1,\n" + - " \"id\" : 12345,\n" + - " \"full_name\" : \"XXX公司/XXX事业群\",\n" + - " \"name\" : \"XXX事业群\"\n" + - " }, {\n" + - " \"order\" : 1,\n" + - " \"id\" : 456,\n" + - " \"full_name\" : \"XXX公司/XXX事业群/XXX部\",\n" + - " \"name\" : \"XXX部\"\n" + - " }, {\n" + - " \"order\" : 1,\n" + - " \"id\" : 9878,\n" + - " \"full_name\" : \"XXX公司/XXX事业群/XXX部/XXX中心\",\n" + - " \"name\" : \"XXX中心\"\n" + - " } ],\n" + - " \"name\" : \"XXX组\"\n" + - "} ]" - val users = authDeptServiceImpl.getUserDeptTreeIds(response) - val mockUsers = mutableSetOf() - mockUsers.add("29510") - mockUsers.add("123") - mockUsers.add("12345") - mockUsers.add("456") - mockUsers.add("9878") - Assertions.assertEquals(users, mockUsers) - } -} From 13b46113a6e4b44a92cd850865842a3df7288978 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 15 Nov 2023 12:02:03 +0800 Subject: [PATCH 56/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuthorizationCodeTokenGranterTest.kt | 93 ++++++++++++ .../service/oauth2/Oauth2ClientServiceTest.kt | 133 ++++++++++++++++++ .../service/oauth2/Oauth2CodeServiceTest.kt | 77 ++++++++++ .../service/oauth2/RefreshTokenGranterTest.kt | 109 ++++++++++++++ 4 files changed, 412 insertions(+) create mode 100644 src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/AuthorizationCodeTokenGranterTest.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeServiceTest.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/RefreshTokenGranterTest.kt diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/AuthorizationCodeTokenGranterTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/AuthorizationCodeTokenGranterTest.kt new file mode 100644 index 00000000000..d6c2290d3b0 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/AuthorizationCodeTokenGranterTest.kt @@ -0,0 +1,93 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.pojo.ClientDetailsInfo +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.service.oauth2.grant.AuthorizationCodeTokenGranter +import com.tencent.devops.common.test.BkCiAbstractTest +import com.tencent.devops.model.auth.tables.records.TAuthOauth2AccessTokenRecord +import com.tencent.devops.model.auth.tables.records.TAuthOauth2RefreshTokenRecord +import io.mockk.every +import io.mockk.junit5.MockKExtension +import io.mockk.mockk +import io.mockk.spyk +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNotEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import java.time.LocalDateTime + +@ExtendWith(MockKExtension::class) +class AuthorizationCodeTokenGranterTest : BkCiAbstractTest() { + + private val codeService = mockk() + + private val accessTokenService = mockk() + + private val refreshTokenService = mockk() + + private val self: AuthorizationCodeTokenGranter = spyk( + AuthorizationCodeTokenGranter( + codeService = codeService, + accessTokenService = accessTokenService, + refreshTokenService = refreshTokenService + ), + recordPrivateCalls = true + ) + private val clientDetails = ClientDetailsInfo( + clientId = "testClientId", + clientSecret = "testClientSecret", + clientName = "testClientName", + authorizedGrantTypes = "testGrantTypes", + redirectUri = "testRedirectUri", + scope = "testScope", + accessTokenValidity = 3600, + refreshTokenValidity = 3600 + ) + + @Test + fun `generateRefreshToken should return existing refreshToken when accessToken is valid`() { + val accessTokenInfo = TAuthOauth2AccessTokenRecord( + "testAccessToken", + "testClientId", + "testUserName", + "testGrantType", + System.currentTimeMillis() / 1000 + 1000, + "testRefreshToken", + 1, + LocalDateTime.now() + ) + + val refreshToken = self.invokePrivate( + "generateRefreshToken", + clientDetails.clientId, + clientDetails, + accessTokenInfo + ) + + assertEquals(accessTokenInfo.refreshToken, refreshToken) + } + + @Test + fun `generateRefreshToken should return new refreshToken when accessToken is expired`() { + val expiredAccessTokenInfo = TAuthOauth2AccessTokenRecord( + "testAccessToken", + "testClientId", + "testUserName", + "testGrantType", + System.currentTimeMillis() / 1000 - 1000, + "testRefreshToken", + 1, + LocalDateTime.now() + ) + every { refreshTokenService.create(any(), any(), any()) } returns Unit + every { refreshTokenService.delete(any()) } returns Unit + + val refreshToken = self.invokePrivate( + "generateRefreshToken", + clientDetails.clientId, + clientDetails, + expiredAccessTokenInfo + ) + assertNotEquals(expiredAccessTokenInfo.refreshToken, refreshToken) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt new file mode 100644 index 00000000000..dff5818124a --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt @@ -0,0 +1,133 @@ +import com.tencent.devops.auth.constant.AuthMessageCode +import com.tencent.devops.auth.dao.AuthOauth2ClientDetailsDao +import com.tencent.devops.auth.pojo.ClientDetailsInfo +import com.tencent.devops.auth.service.oauth2.Oauth2ClientService +import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.common.test.BkCiAbstractTest +import io.mockk.mockk +import org.junit.jupiter.api.Assertions.assertArrayEquals +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class Oauth2ClientServiceTest : BkCiAbstractTest() { + + private val authOauth2ClientDetailsDao = mockk() + + private val oauth2ClientService = Oauth2ClientService( + dslContext = dslContext, + authOauth2ClientDetailsDao = authOauth2ClientDetailsDao + ) + + @Test + fun `test verifyClientInformation with invalid grant type`() { + val clientId = "testClient" + val clientDetails = ClientDetailsInfo( + clientId = clientId, + clientSecret = "testSecret", + clientName = "Test Client", + scope = "read,write", + authorizedGrantTypes = "authorization_code,refresh_token", + redirectUri = "http://example.com/callback", + accessTokenValidity = 3600, + refreshTokenValidity = 86400 + ) + + val invalidGrantType = "invalid_grant_type" + + val exception = assertThrows { + oauth2ClientService.verifyClientInformation( + clientId = clientId, + clientDetails = clientDetails, + grantType = invalidGrantType + ) + } + + assertEquals(AuthMessageCode.INVALID_AUTHORIZATION_TYPE, exception.errorCode) + assertArrayEquals(arrayOf(clientId), exception.params) + } + + @Test + fun `test verifyClientInformation with invalid redirect URI`() { + val clientId = "testClient" + val clientDetails = ClientDetailsInfo( + clientId = clientId, + clientSecret = "testSecret", + clientName = "Test Client", + scope = "read,write", + authorizedGrantTypes = "authorization_code", + redirectUri = "http://example.com/callback", + accessTokenValidity = 3600, + refreshTokenValidity = 86400 + ) + + val invalidRedirectUri = "http://invalid.com/callback" + + val exception = assertThrows { + oauth2ClientService.verifyClientInformation( + clientId = clientId, + clientDetails = clientDetails, + redirectUri = invalidRedirectUri + ) + } + + assertEquals(AuthMessageCode.INVALID_REDIRECT_URI, exception.errorCode) + assertArrayEquals(arrayOf(invalidRedirectUri), exception.params) + } + + @Test + fun `test verifyClientInformation with invalid client secret`() { + val clientId = "testClient" + val clientDetails = ClientDetailsInfo( + clientId = clientId, + clientSecret = "testSecret", + clientName = "Test Client", + scope = "read,write", + authorizedGrantTypes = "authorization_code", + redirectUri = "http://example.com/callback", + accessTokenValidity = 3600, + refreshTokenValidity = 86400 + ) + + val invalidClientSecret = "invalidSecret" + + val exception = assertThrows { + oauth2ClientService.verifyClientInformation( + clientId = clientId, + clientDetails = clientDetails, + clientSecret = invalidClientSecret + ) + } + + assertEquals(AuthMessageCode.INVALID_CLIENT_SECRET, exception.errorCode) + assertArrayEquals(arrayOf(clientId), exception.params) + } + + @Test + fun `test verifyClientInformation with invalid scope`() { + val clientId = "testClient" + val clientDetails = ClientDetailsInfo( + clientId = clientId, + clientSecret = "testSecret", + clientName = "Test Client", + scope = "read,write", + authorizedGrantTypes = "authorization_code", + redirectUri = "http://example.com/callback", + accessTokenValidity = 3600, + refreshTokenValidity = 86400 + ) + + val invalidScope = listOf("invalidScope") + + val exception = assertThrows { + oauth2ClientService.verifyClientInformation( + clientId = clientId, + clientDetails = clientDetails, + scope = invalidScope + ) + } + + assertEquals(AuthMessageCode.INVALID_SCOPE, exception.errorCode) + assertArrayEquals(arrayOf(clientId), exception.params) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeServiceTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeServiceTest.kt new file mode 100644 index 00000000000..2f4c33dd32a --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2CodeServiceTest.kt @@ -0,0 +1,77 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.constant.AuthMessageCode +import com.tencent.devops.auth.dao.AuthOauth2CodeDao +import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.common.test.BkCiAbstractTest +import com.tencent.devops.model.auth.tables.records.TAuthOauth2CodeRecord +import io.mockk.mockk +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.time.LocalDateTime + +class Oauth2CodeServiceTest : BkCiAbstractTest() { + private val authOauth2CodeDao = mockk() + private val oauth2CodeService = Oauth2CodeService( + dslContext = dslContext, + authOauth2CodeDao = authOauth2CodeDao + ) + + @Test + fun `test verifyCode with valid code`() { + val clientId = "testClient" + val codeDetails = TAuthOauth2CodeRecord( + clientId, + "testCode", + "testUser", + System.currentTimeMillis() / 1000 + 1000L, + 1, + LocalDateTime.now() + ) + + val result = oauth2CodeService.verifyCode(clientId, codeDetails) + + assertTrue(result) + } + + @Test + fun `test verifyCode with invalid client id`() { + val clientId = "testClient" + val invalidClientId = "invalidClient" + val codeDetails = TAuthOauth2CodeRecord( + clientId, + "testCode", + "testUser", + System.currentTimeMillis() / 1000 + 1000L, + 1, + LocalDateTime.now() + ) + + assertThrows { + oauth2CodeService.verifyCode(invalidClientId, codeDetails) + }.apply { + assertEquals(AuthMessageCode.INVALID_AUTHORIZATION_CODE, errorCode) + } + } + + @Test + fun `test verifyCode with expired code`() { + val clientId = "testClient" + val codeDetails = TAuthOauth2CodeRecord( + clientId, + "testCode", + "testUser", + System.currentTimeMillis() / 1000 - 1000L, + 1, + LocalDateTime.now() + ) + + assertThrows { + oauth2CodeService.verifyCode(clientId, codeDetails) + }.apply { + assertEquals(AuthMessageCode.INVALID_AUTHORIZATION_EXPIRED, errorCode) + } + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/RefreshTokenGranterTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/RefreshTokenGranterTest.kt new file mode 100644 index 00000000000..3fb5c361760 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/RefreshTokenGranterTest.kt @@ -0,0 +1,109 @@ +package com.tencent.devops.auth.service.oauth2 + +import com.tencent.devops.auth.constant.AuthMessageCode.ERROR_REFRESH_TOKEN_EXPIRED +import com.tencent.devops.auth.pojo.ClientDetailsInfo +import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest +import com.tencent.devops.auth.service.oauth2.grant.RefreshTokenGranter +import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.common.test.BkCiAbstractTest +import com.tencent.devops.model.auth.tables.records.TAuthOauth2AccessTokenRecord +import com.tencent.devops.model.auth.tables.records.TAuthOauth2RefreshTokenRecord +import io.mockk.every +import io.mockk.mockk +import io.mockk.spyk +import io.mockk.verify +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.time.LocalDateTime + +class RefreshTokenGranterTest : BkCiAbstractTest() { + private val accessTokenService = mockk() + + private val refreshTokenService = mockk() + + private val self: RefreshTokenGranter = spyk( + RefreshTokenGranter( + accessTokenService = accessTokenService, + refreshTokenService = refreshTokenService + ), + recordPrivateCalls = true + ) + private val clientDetails = ClientDetailsInfo( + clientId = "testClientId", + clientSecret = "testClientSecret", + clientName = "testClientName", + authorizedGrantTypes = "testGrantTypes", + redirectUri = "testRedirectUri", + scope = "testScope", + accessTokenValidity = 3600, + refreshTokenValidity = 3600 + ) + + private val accessTokenInfo = TAuthOauth2AccessTokenRecord( + "testAccessToken", + "testClientId", + "testUserName", + "testGrantType", + System.currentTimeMillis() / 1000 + 1000, + "testRefreshToken", + 1, + LocalDateTime.now() + ) + + private val accessTokenRequest = Oauth2AccessTokenRequest( + refreshToken = "testRefreshToken", + grantType = "testGrantType" + ) + + @Test + fun `getAccessToken should return valid Oauth2AccessTokenDTO`() { + val refreshTokenInfo = TAuthOauth2RefreshTokenRecord( + "testRefreshToken", + "testClientId", + System.currentTimeMillis() / 1000 + 1000, + LocalDateTime.now() + ) + every { refreshTokenService.get(any()) } returns refreshTokenInfo + every { accessTokenService.get(any(), any(), any(), any()) } returns accessTokenInfo + every { accessTokenService.delete(any()) } returns Unit + + val accessTokenDto = self.getAccessToken( + accessTokenRequest = accessTokenRequest, + clientDetails = clientDetails + ) + + assertEquals(accessTokenInfo.userName, accessTokenDto.userName) + assertEquals(accessTokenInfo.refreshToken, accessTokenDto.refreshToken) + assertEquals(accessTokenInfo.scopeId, accessTokenDto.scopeId) + + verify { refreshTokenService.get(accessTokenRequest.refreshToken) } + verify { accessTokenService.get(clientDetails.clientId, refreshToken = accessTokenRequest.refreshToken) } + verify { accessTokenService.delete(accessTokenInfo.accessToken) } + } + + @Test + fun `getAccessToken should throw ErrorCodeException when refreshToken is expired`() { + val expiredRefreshTokenInfo = TAuthOauth2RefreshTokenRecord( + "testRefreshToken", + "testClientId", + System.currentTimeMillis() / 1000 - 1000, + LocalDateTime.now() + ) + every { refreshTokenService.get(any()) } returns expiredRefreshTokenInfo + every { accessTokenService.get(clientId = any(), refreshToken = any()) } returns accessTokenInfo + every { refreshTokenService.delete(any()) } returns Unit + every { accessTokenService.delete(any()) } returns Unit + + val exception = assertThrows { + self.getAccessToken( + accessTokenRequest = accessTokenRequest, + clientDetails = clientDetails + ) + } + + assertEquals(ERROR_REFRESH_TOKEN_EXPIRED, exception.errorCode) + verify { refreshTokenService.get(accessTokenRequest.refreshToken) } + verify { refreshTokenService.delete(expiredRefreshTokenInfo.refreshToken) } + } +} From 6b90a7b6d83f267d89f481dfced9a36e8ad56bee Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 15 Nov 2023 17:14:31 +0800 Subject: [PATCH 57/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/pojo/ClientDetailsInfo.kt | 4 +++- .../auth/pojo/vo/Oauth2AuthorizationInfoVo.kt | 2 ++ .../auth/service/oauth2/Oauth2ClientService.kt | 3 ++- .../auth/service/oauth2/Oauth2EndpointService.kt | 3 ++- support-files/sql/1001_ci_auth_ddl_mysql.sql | 13 +++++++------ 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt index 9a04a5a5600..8e0433b8fc4 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/ClientDetailsInfo.kt @@ -20,5 +20,7 @@ data class ClientDetailsInfo( @ApiModelProperty("accessToken有效期", required = true) val accessTokenValidity: Long, @ApiModelProperty("refreshToken有效期", required = true) - val refreshTokenValidity: Long + val refreshTokenValidity: Long, + @ApiModelProperty("图标", required = true) + val icon: String ) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt index 72a9b2f30c6..79ad3bffaa5 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/vo/Oauth2AuthorizationInfoVo.kt @@ -9,6 +9,8 @@ data class Oauth2AuthorizationInfoVo( val userName: String, @ApiModelProperty("客户端名称", required = true) val clientName: String, + @ApiModelProperty("图标", required = true) + val icon: String, @ApiModelProperty("授权范围", required = true) val scope: Map ) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt index 1908e9d466e..4202d9ec109 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt @@ -39,7 +39,8 @@ class Oauth2ClientService constructor( authorizedGrantTypes = authorizedGrantTypes, redirectUri = webServerRedirectUri, accessTokenValidity = accessTokenValidity, - refreshTokenValidity = refreshTokenValidity + refreshTokenValidity = refreshTokenValidity, + icon = icon ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt index af86da36420..79bc961aedf 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2EndpointService.kt @@ -39,7 +39,8 @@ class Oauth2EndpointService constructor( return Oauth2AuthorizationInfoVo( userName = userId, clientName = clientDetails.clientName, - scope = scopeOperations.associateWith { scopeOperationService.get(it)!!.operationNameCn } + scope = scopeOperations.associateWith { scopeOperationService.get(it)!!.operationNameCn }, + icon = clientDetails.icon ) } diff --git a/support-files/sql/1001_ci_auth_ddl_mysql.sql b/support-files/sql/1001_ci_auth_ddl_mysql.sql index 9ccb397d263..c13871327e5 100644 --- a/support-files/sql/1001_ci_auth_ddl_mysql.sql +++ b/support-files/sql/1001_ci_auth_ddl_mysql.sql @@ -295,11 +295,12 @@ CREATE TABLE IF NOT EXISTS `T_AUTH_MONITOR_SPACE` ( PRIMARY KEY (`PROJECT_CODE`,`SPACE_BIZ_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT= '蓝盾监控空间权限表'; -CREATE TABLE `T_AUTH_OAUTH2_CLIENT_DETAILS` ( +CREATE TABLE IF NOT EXISTS `T_AUTH_OAUTH2_CLIENT_DETAILS` ( `CLIENT_ID` VARCHAR(32) NOT NULL COMMENT '客户端标识', `CLIENT_SECRET` VARCHAR(64) NOT NULL COMMENT '客户端秘钥', `CLIENT_NAME` VARCHAR(255) NOT NULL COMMENT '客户端名称', `SCOPE` MEDIUMTEXT DEFAULT NULL COMMENT '授权操作范围', + `ICON` MEDIUMTEXT DEFAULT NULL COMMENT '图标', `AUTHORIZED_GRANT_TYPES` VARCHAR(64) NOT NULL COMMENT '授权模式', `WEB_SERVER_REDIRECT_URI` VARCHAR(255) DEFAULT NULL COMMENT '跳转链接', `ACCESS_TOKEN_VALIDITY` BIGINT(20) NOT NULL COMMENT 'access_token有效时间', @@ -311,7 +312,7 @@ CREATE TABLE `T_AUTH_OAUTH2_CLIENT_DETAILS` ( PRIMARY KEY (`CLIENT_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户端信息表'; -CREATE TABLE `T_AUTH_OAUTH2_CODE` ( +CREATE TABLE IF NOT EXISTS `T_AUTH_OAUTH2_CODE` ( `CLIENT_ID` VARCHAR(32) NOT NULL COMMENT '客户端标识', `CODE` VARCHAR(64) NOT NULL COMMENT '授权码', `USER_NAME` VARCHAR(32) NOT NULL COMMENT '用户名', @@ -321,7 +322,7 @@ CREATE TABLE `T_AUTH_OAUTH2_CODE` ( INDEX `IDX_CODE` (`CODE`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='授权码表'; -CREATE TABLE `T_AUTH_OAUTH2_ACCESS_TOKEN` ( +CREATE TABLE IF NOT EXISTS `T_AUTH_OAUTH2_ACCESS_TOKEN` ( `ACCESS_TOKEN` VARCHAR(64) NOT NULL COMMENT 'ACCESS_TOKEN', `CLIENT_ID` VARCHAR(32) NOT NULL COMMENT '客户端ID', `USER_NAME` VARCHAR(32) DEFAULT NULL COMMENT '登录的用户名,客户端模式该值为空', @@ -333,7 +334,7 @@ CREATE TABLE `T_AUTH_OAUTH2_ACCESS_TOKEN` ( INDEX `IDX_CLIENT_ID_USER_NAME` (`ACCESS_TOKEN`) ) ENGINE=INNODB DEFAULT CHARSET=UTF8 COMMENT='ACCESS_TOKEN表'; -CREATE TABLE `T_AUTH_OAUTH2_REFRESH_TOKEN` ( +CREATE TABLE IF NOT EXISTS `T_AUTH_OAUTH2_REFRESH_TOKEN` ( `REFRESH_TOKEN` VARCHAR(64) NOT NULL COMMENT 'REFRESH_TOKEN', `CLIENT_ID` VARCHAR(32) NOT NULL COMMENT '客户端ID', `EXPIRED_TIME` BIGINT(20) NOT NULL COMMENT '过期时间', @@ -341,14 +342,14 @@ CREATE TABLE `T_AUTH_OAUTH2_REFRESH_TOKEN` ( INDEX `IDX_REFRESH_TOKEN` (`REFRESH_TOKEN`) ) ENGINE=INNODB DEFAULT CHARSET=UTF8 COMMENT='REFRESH_TOKEN表'; -CREATE TABLE `T_AUTH_OAUTH2_SCOPE` ( +CREATE TABLE IF NOT EXISTS `T_AUTH_OAUTH2_SCOPE` ( `ID` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主健ID', `SCOPE` MEDIUMTEXT NOT NULL COMMENT '授权范围', `CREATE_TIME` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`ID`) ) ENGINE=INNODB DEFAULT CHARSET=UTF8 COMMENT='授权范围表'; -CREATE TABLE `T_AUTH_OAUTH2_SCOPE_OPERATION` ( +CREATE TABLE IF NOT EXISTS `T_AUTH_OAUTH2_SCOPE_OPERATION` ( `ID` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主健ID', `OPERATION_ID` VARCHAR(64) NOT NULL COMMENT '授权操作ID', `OPERATION_NAME_CN` VARCHAR(64) NOT NULL COMMENT '授权操作中文名称', From 8b494cc1b1f74f166b68040a4d9d04d801a29e45 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Wed, 15 Nov 2023 17:33:48 +0800 Subject: [PATCH 58/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oauth2/AuthorizationCodeTokenGranterTest.kt | 5 ++--- .../auth/service/oauth2/Oauth2ClientServiceTest.kt | 12 ++++++++---- .../auth/service/oauth2/RefreshTokenGranterTest.kt | 3 ++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/AuthorizationCodeTokenGranterTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/AuthorizationCodeTokenGranterTest.kt index d6c2290d3b0..0c8e1bdb6f9 100644 --- a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/AuthorizationCodeTokenGranterTest.kt +++ b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/AuthorizationCodeTokenGranterTest.kt @@ -1,11 +1,9 @@ package com.tencent.devops.auth.service.oauth2 import com.tencent.devops.auth.pojo.ClientDetailsInfo -import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest import com.tencent.devops.auth.service.oauth2.grant.AuthorizationCodeTokenGranter import com.tencent.devops.common.test.BkCiAbstractTest import com.tencent.devops.model.auth.tables.records.TAuthOauth2AccessTokenRecord -import com.tencent.devops.model.auth.tables.records.TAuthOauth2RefreshTokenRecord import io.mockk.every import io.mockk.junit5.MockKExtension import io.mockk.mockk @@ -41,7 +39,8 @@ class AuthorizationCodeTokenGranterTest : BkCiAbstractTest() { redirectUri = "testRedirectUri", scope = "testScope", accessTokenValidity = 3600, - refreshTokenValidity = 3600 + refreshTokenValidity = 3600, + icon = "icon" ) @Test diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt index dff5818124a..e347c9c5495 100644 --- a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt +++ b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt @@ -30,7 +30,8 @@ class Oauth2ClientServiceTest : BkCiAbstractTest() { authorizedGrantTypes = "authorization_code,refresh_token", redirectUri = "http://example.com/callback", accessTokenValidity = 3600, - refreshTokenValidity = 86400 + refreshTokenValidity = 86400, + icon = "icon" ) val invalidGrantType = "invalid_grant_type" @@ -58,7 +59,8 @@ class Oauth2ClientServiceTest : BkCiAbstractTest() { authorizedGrantTypes = "authorization_code", redirectUri = "http://example.com/callback", accessTokenValidity = 3600, - refreshTokenValidity = 86400 + refreshTokenValidity = 86400, + icon = "icon" ) val invalidRedirectUri = "http://invalid.com/callback" @@ -86,7 +88,8 @@ class Oauth2ClientServiceTest : BkCiAbstractTest() { authorizedGrantTypes = "authorization_code", redirectUri = "http://example.com/callback", accessTokenValidity = 3600, - refreshTokenValidity = 86400 + refreshTokenValidity = 86400, + icon = "icon" ) val invalidClientSecret = "invalidSecret" @@ -114,7 +117,8 @@ class Oauth2ClientServiceTest : BkCiAbstractTest() { authorizedGrantTypes = "authorization_code", redirectUri = "http://example.com/callback", accessTokenValidity = 3600, - refreshTokenValidity = 86400 + refreshTokenValidity = 86400, + icon = "icon" ) val invalidScope = listOf("invalidScope") diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/RefreshTokenGranterTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/RefreshTokenGranterTest.kt index 3fb5c361760..9ad9ac1b2b2 100644 --- a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/RefreshTokenGranterTest.kt +++ b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/RefreshTokenGranterTest.kt @@ -37,7 +37,8 @@ class RefreshTokenGranterTest : BkCiAbstractTest() { redirectUri = "testRedirectUri", scope = "testScope", accessTokenValidity = 3600, - refreshTokenValidity = 3600 + refreshTokenValidity = 3600, + icon = "icon" ) private val accessTokenInfo = TAuthOauth2AccessTokenRecord( From 9ce98b0cd19b17a51e36bb0abee740c3242fdb19 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 16 Nov 2023 09:55:48 +0800 Subject: [PATCH 59/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/devops/auth/AuthConfiguration.kt | 6 ++++-- .../tencent/devops/auth/service/AuthDeptServiceImpl.kt | 10 ++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth-blueking/src/main/kotlin/com/tencent/devops/auth/AuthConfiguration.kt b/src/backend/ci/core/auth/biz-auth-blueking/src/main/kotlin/com/tencent/devops/auth/AuthConfiguration.kt index 5c82f82a3bf..25858b764c5 100644 --- a/src/backend/ci/core/auth/biz-auth-blueking/src/main/kotlin/com/tencent/devops/auth/AuthConfiguration.kt +++ b/src/backend/ci/core/auth/biz-auth-blueking/src/main/kotlin/com/tencent/devops/auth/AuthConfiguration.kt @@ -55,6 +55,7 @@ import com.tencent.devops.auth.service.iam.IamCacheService import com.tencent.devops.auth.service.iam.PermissionGradeService import com.tencent.devops.auth.service.iam.PermissionRoleMemberService import com.tencent.devops.auth.service.iam.PermissionRoleService +import com.tencent.devops.auth.service.secops.SecOpsService import com.tencent.devops.auth.service.stream.GithubStreamPermissionServiceImpl import com.tencent.devops.auth.service.stream.GitlabStreamPermissionServiceImpl import com.tencent.devops.auth.service.stream.StreamPermissionProjectServiceImpl @@ -117,8 +118,9 @@ class AuthConfiguration { @ConditionalOnProperty(prefix = "auth", name = ["idProvider"], havingValue = "bk_login") fun deptService( redisOperation: RedisOperation, - objectMapper: ObjectMapper - ) = AuthDeptServiceImpl(redisOperation, objectMapper) + objectMapper: ObjectMapper, + secOpsService: SecOpsService + ) = AuthDeptServiceImpl(redisOperation, objectMapper, secOpsService) @Bean @Primary diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt index dd3b887b88f..ce69f1e50f5 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt @@ -69,8 +69,7 @@ import java.util.concurrent.TimeUnit class AuthDeptServiceImpl @Autowired constructor( val redisOperation: RedisOperation, val objectMapper: ObjectMapper, - val secOpsService: SecOpsService, - val permissionProjectService: PermissionProjectService + val secOpsService: SecOpsService ) : DeptService { @Value("\${esb.code:#{null}}") @@ -280,11 +279,6 @@ class AuthDeptServiceImpl @Autowired constructor( defaultMessage = "user not exist!$userId" ) val userWaterMark = secOpsService.getUserWaterMark(userId = userId) - val belongProjectMember = permissionProjectService.isProjectUser( - userId = userId, - projectCode = projectCode, - group = null - ) return UserAndDeptInfoVo( id = userInfo.id, name = userInfo.name, @@ -293,7 +287,7 @@ class AuthDeptServiceImpl @Autowired constructor( deptInfo = userInfo.deptInfo, extras = userInfo.extras, waterMark = userWaterMark.data, - belongProjectMember = belongProjectMember + belongProjectMember = true ) } From 7f57e8eb911b9ce7d45a01ca85d86acaaa9b2c38 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 16 Nov 2023 10:00:38 +0800 Subject: [PATCH 60/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/devops/auth/service/AuthDeptServiceImpl.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt index ce69f1e50f5..c760fb45490 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt @@ -48,7 +48,6 @@ import com.tencent.devops.auth.entity.UserDeptTreeInfo import com.tencent.devops.auth.pojo.vo.BkUserInfoVo import com.tencent.devops.auth.pojo.vo.DeptInfoVo import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo -import com.tencent.devops.auth.service.iam.PermissionProjectService import com.tencent.devops.auth.service.secops.SecOpsService import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.common.api.exception.OperationException From 24ac2649c026147888e2a62046b2917d0fa21fc8 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 16 Nov 2023 10:45:16 +0800 Subject: [PATCH 61/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/service/ServiceDeptResource.kt | 11 ----- .../api/service/ServiceSecurityResource.kt | 28 +++++++++++ .../tencent/devops/auth/AuthConfiguration.kt | 6 +-- .../common/MockAuthCoreAutoConfiguration.kt | 14 ++++-- .../service/ServiceDeptResourceImpl.kt | 7 --- .../service/ServiceSecurityResourceImpl.kt | 47 ++++++++++++++++++ .../auth/service/AuthDeptServiceImpl.kt | 29 +---------- .../auth/service/DefaultDeptServiceImpl.kt | 9 ---- .../devops/auth/service/DeptService.kt | 2 - .../secops/DefaultSecOpsServiceImpl.kt | 12 ----- .../auth/service/secops/SecOpsService.kt | 13 ----- .../security/DefaultSecurityServiceImpl.kt | 17 +++++++ .../auth/service/security/SecurityService.kt | 49 +++++++++++++++++++ 13 files changed, 154 insertions(+), 90 deletions(-) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceSecurityResourceImpl.kt delete mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/DefaultSecOpsServiceImpl.kt delete mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/SecOpsService.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/security/DefaultSecurityServiceImpl.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/security/SecurityService.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt index 601cf9845f4..05f5473c2c6 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt @@ -80,15 +80,4 @@ interface ServiceDeptResource { name: String ): Result - @GET - @Path("/getUserInfoAndWaterMark") - @ApiOperation("获取单个用户信息和水印信息") - fun getUserInfoAndWaterMark( - @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) - @ApiParam("用户ID", required = true) - userId: String, - @ApiParam("项目ID", required = true) - @QueryParam("projectCode") - projectCode: String - ): Result } diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt new file mode 100644 index 00000000000..74bc6566b33 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt @@ -0,0 +1,28 @@ +package com.tencent.devops.auth.api.service + +import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo +import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID +import com.tencent.devops.common.api.pojo.Result +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam +import javax.ws.rs.GET +import javax.ws.rs.HeaderParam +import javax.ws.rs.Path +import javax.ws.rs.QueryParam + +@Api(tags = ["SERVICE_SECURITY"], description = "安全相关") +@Path("/service/security") +interface ServiceSecurityResource { + @GET + @Path("/getUserInfoAndWaterMark") + @ApiOperation("获取安全相关信息") + fun getUserSecurityInfo( + @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) + @ApiParam("用户ID", required = true) + userId: String, + @ApiParam("项目ID", required = true) + @QueryParam("projectCode") + projectCode: String + ): Result +} diff --git a/src/backend/ci/core/auth/biz-auth-blueking/src/main/kotlin/com/tencent/devops/auth/AuthConfiguration.kt b/src/backend/ci/core/auth/biz-auth-blueking/src/main/kotlin/com/tencent/devops/auth/AuthConfiguration.kt index 25858b764c5..5c82f82a3bf 100644 --- a/src/backend/ci/core/auth/biz-auth-blueking/src/main/kotlin/com/tencent/devops/auth/AuthConfiguration.kt +++ b/src/backend/ci/core/auth/biz-auth-blueking/src/main/kotlin/com/tencent/devops/auth/AuthConfiguration.kt @@ -55,7 +55,6 @@ import com.tencent.devops.auth.service.iam.IamCacheService import com.tencent.devops.auth.service.iam.PermissionGradeService import com.tencent.devops.auth.service.iam.PermissionRoleMemberService import com.tencent.devops.auth.service.iam.PermissionRoleService -import com.tencent.devops.auth.service.secops.SecOpsService import com.tencent.devops.auth.service.stream.GithubStreamPermissionServiceImpl import com.tencent.devops.auth.service.stream.GitlabStreamPermissionServiceImpl import com.tencent.devops.auth.service.stream.StreamPermissionProjectServiceImpl @@ -118,9 +117,8 @@ class AuthConfiguration { @ConditionalOnProperty(prefix = "auth", name = ["idProvider"], havingValue = "bk_login") fun deptService( redisOperation: RedisOperation, - objectMapper: ObjectMapper, - secOpsService: SecOpsService - ) = AuthDeptServiceImpl(redisOperation, objectMapper, secOpsService) + objectMapper: ObjectMapper + ) = AuthDeptServiceImpl(redisOperation, objectMapper) @Bean @Primary diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/MockAuthCoreAutoConfiguration.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/MockAuthCoreAutoConfiguration.kt index 9f7c38fca9f..4755e45574c 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/MockAuthCoreAutoConfiguration.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/common/MockAuthCoreAutoConfiguration.kt @@ -44,8 +44,8 @@ import com.tencent.devops.auth.service.sample.SamplePermissionRoleMemberService import com.tencent.devops.auth.service.sample.SamplePermissionRoleService import com.tencent.devops.auth.service.sample.SamplePermissionSuperManagerService import com.tencent.devops.auth.service.sample.SamplePermissionUrlServiceImpl -import com.tencent.devops.auth.service.secops.DefaultSecOpsServiceImpl -import com.tencent.devops.auth.service.secops.SecOpsService +import com.tencent.devops.auth.service.security.DefaultSecurityServiceImpl +import com.tencent.devops.auth.service.security.SecurityService import com.tencent.devops.common.client.Client import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.context.annotation.Bean @@ -145,6 +145,12 @@ class MockAuthCoreAutoConfiguration { fun sampleAuthMonitorSpaceService() = SampleAuthMonitorSpaceService() @Bean - @ConditionalOnMissingBean(SecOpsService::class) - fun defaultSecOpsServiceImpl() = DefaultSecOpsServiceImpl() + @ConditionalOnMissingBean(SecurityService::class) + fun defaultSecurityServiceImpl( + deptService: DeptService, + permissionProjectService: PermissionProjectService + ) = DefaultSecurityServiceImpl( + deptService = deptService, + permissionProjectService = permissionProjectService + ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt index 8e26a17b21a..5905d7483ae 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceDeptResourceImpl.kt @@ -50,11 +50,4 @@ class ServiceDeptResourceImpl @Autowired constructor( override fun getUserInfo(userId: String, name: String): Result { return Result(deptService.getUserInfo(userId, name)) } - - override fun getUserInfoAndWaterMark( - userId: String, - projectCode: String - ): Result { - return Result(deptService.getUserInfoAndWaterMark(userId, projectCode)) - } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceSecurityResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceSecurityResourceImpl.kt new file mode 100644 index 00000000000..ed24ccf2278 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/service/ServiceSecurityResourceImpl.kt @@ -0,0 +1,47 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.devops.auth.resources.service + +import com.tencent.devops.auth.api.service.ServiceSecurityResource +import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo +import com.tencent.devops.auth.service.security.SecurityService +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.common.web.RestResource +import org.springframework.beans.factory.annotation.Autowired + +@RestResource +class ServiceSecurityResourceImpl @Autowired constructor( + val securityService: SecurityService +) : ServiceSecurityResource { + override fun getUserSecurityInfo( + userId: String, + projectCode: String + ): Result { + return Result(securityService.getUserSecurityInfo(userId, projectCode)) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt index c760fb45490..8670904205e 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/AuthDeptServiceImpl.kt @@ -48,8 +48,6 @@ import com.tencent.devops.auth.entity.UserDeptTreeInfo import com.tencent.devops.auth.pojo.vo.BkUserInfoVo import com.tencent.devops.auth.pojo.vo.DeptInfoVo import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo -import com.tencent.devops.auth.service.secops.SecOpsService -import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.common.api.exception.OperationException import com.tencent.devops.common.api.util.JsonUtil import com.tencent.devops.common.api.util.OkhttpUtils @@ -67,8 +65,7 @@ import java.util.concurrent.TimeUnit class AuthDeptServiceImpl @Autowired constructor( val redisOperation: RedisOperation, - val objectMapper: ObjectMapper, - val secOpsService: SecOpsService + val objectMapper: ObjectMapper ) : DeptService { @Value("\${esb.code:#{null}}") @@ -266,30 +263,6 @@ class AuthDeptServiceImpl @Autowired constructor( return userInfoCache.getIfPresent(name)?.get() ?: getUserAndPutInCache(userId, name) } - override fun getUserInfoAndWaterMark( - userId: String, - projectCode: String - ): UserAndDeptInfoVo? { - val userInfo = getUserInfo( - userId = userId, - name = userId - ) ?: throw ErrorCodeException( - errorCode = AuthMessageCode.ERROR_USER_NOT_EXIST, - defaultMessage = "user not exist!$userId" - ) - val userWaterMark = secOpsService.getUserWaterMark(userId = userId) - return UserAndDeptInfoVo( - id = userInfo.id, - name = userInfo.name, - type = userInfo.type, - hasChild = userInfo.hasChild, - deptInfo = userInfo.deptInfo, - extras = userInfo.extras, - waterMark = userWaterMark.data, - belongProjectMember = true - ) - } - private fun getUserAndPutInCache(userId: String, name: String): UserAndDeptInfoVo? { return getUserAndDeptByName( name = name, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt index 6be0ef68091..df5bb01fddd 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DefaultDeptServiceImpl.kt @@ -73,13 +73,4 @@ class DefaultDeptServiceImpl : DeptService { name = name, type = ManagerScopesEnum.USER ) - - override fun getUserInfoAndWaterMark( - userId: String, - projectCode: String - ): UserAndDeptInfoVo? = UserAndDeptInfoVo( - id = 0, - name = userId, - type = ManagerScopesEnum.USER - ) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt index 6c5bea82488..ac49979a436 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/DeptService.kt @@ -55,6 +55,4 @@ interface DeptService { // 获取单个用户信息 fun getUserInfo(userId: String, name: String): UserAndDeptInfoVo? - - fun getUserInfoAndWaterMark(userId: String, projectCode: String): UserAndDeptInfoVo? } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/DefaultSecOpsServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/DefaultSecOpsServiceImpl.kt deleted file mode 100644 index 7e77d55b5e6..00000000000 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/DefaultSecOpsServiceImpl.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tencent.devops.auth.service.secops - -import com.tencent.devops.auth.pojo.vo.SecOpsWaterMarkInfoVo - -class DefaultSecOpsServiceImpl : SecOpsService { - override fun getUserWaterMark(userId: String): SecOpsWaterMarkInfoVo { - return SecOpsWaterMarkInfoVo( - type = "", - data = "" - ) - } -} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/SecOpsService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/SecOpsService.kt deleted file mode 100644 index 40344251a78..00000000000 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/secops/SecOpsService.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.tencent.devops.auth.service.secops - -import com.tencent.devops.auth.pojo.vo.SecOpsWaterMarkInfoVo - -/** - * 安全相关接口 - */ -interface SecOpsService { - /** - * 获取用户水印信息 - */ - fun getUserWaterMark(userId: String): SecOpsWaterMarkInfoVo -} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/security/DefaultSecurityServiceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/security/DefaultSecurityServiceImpl.kt new file mode 100644 index 00000000000..5f2263871ba --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/security/DefaultSecurityServiceImpl.kt @@ -0,0 +1,17 @@ +package com.tencent.devops.auth.service.security + +import com.tencent.devops.auth.pojo.vo.SecOpsWaterMarkInfoVo +import com.tencent.devops.auth.service.DeptService +import com.tencent.devops.auth.service.iam.PermissionProjectService + +class DefaultSecurityServiceImpl constructor( + deptService: DeptService, + permissionProjectService: PermissionProjectService +) : SecurityService(deptService, permissionProjectService) { + override fun getUserWaterMark(userId: String): SecOpsWaterMarkInfoVo { + return SecOpsWaterMarkInfoVo( + type = "", + data = "" + ) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/security/SecurityService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/security/SecurityService.kt new file mode 100644 index 00000000000..e350c14661b --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/security/SecurityService.kt @@ -0,0 +1,49 @@ +package com.tencent.devops.auth.service.security + +import com.tencent.devops.auth.constant.AuthMessageCode +import com.tencent.devops.auth.pojo.vo.SecOpsWaterMarkInfoVo +import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo +import com.tencent.devops.auth.service.DeptService +import com.tencent.devops.auth.service.iam.PermissionProjectService +import com.tencent.devops.common.api.exception.ErrorCodeException + +/** + * 安全相关接口 + */ +abstract class SecurityService( + val deptService: DeptService, + val permissionProjectService: PermissionProjectService +) { + fun getUserSecurityInfo( + userId: String, + projectCode: String + ): UserAndDeptInfoVo { + val userInfo = deptService.getUserInfo( + userId = userId, + name = userId + ) ?: throw ErrorCodeException( + errorCode = AuthMessageCode.ERROR_USER_NOT_EXIST, + defaultMessage = "user not exist!$userId" + ) + val belongProjectMember = permissionProjectService.getProjectUsers( + projectCode = projectCode, + group = null + ).contains(userId) + val userWaterMark = getUserWaterMark(userId = userId) + return UserAndDeptInfoVo( + id = userInfo.id, + name = userInfo.name, + type = userInfo.type, + hasChild = userInfo.hasChild, + deptInfo = userInfo.deptInfo, + extras = userInfo.extras, + waterMark = userWaterMark.data, + belongProjectMember = belongProjectMember + ) + } + + /** + * 获取用户水印信息 + */ + abstract fun getUserWaterMark(userId: String): SecOpsWaterMarkInfoVo +} From d3fbcdc5396878040c183d5bcacc430fd438e293 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 16 Nov 2023 10:52:46 +0800 Subject: [PATCH 62/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/devops/auth/api/service/ServiceDeptResource.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt index 05f5473c2c6..885c02b876b 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceDeptResource.kt @@ -79,5 +79,4 @@ interface ServiceDeptResource { @ApiParam("用户名称", required = true) name: String ): Result - } From 6e84a3f86560c02799687773554aea70e0554c58 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 16 Nov 2023 11:05:58 +0800 Subject: [PATCH 63/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/auth/api/service/ServiceSecurityResource.kt | 2 +- .../openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt | 6 +++--- .../apigw/v4/ApigwUserManagementResourceV4Impl.kt | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt index 74bc6566b33..ce4ebe844db 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt @@ -15,7 +15,7 @@ import javax.ws.rs.QueryParam @Path("/service/security") interface ServiceSecurityResource { @GET - @Path("/getUserInfoAndWaterMark") + @Path("/getUserSecurityInfo") @ApiOperation("获取安全相关信息") fun getUserSecurityInfo( @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) diff --git a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt index 3a2e34e159d..76485c73656 100644 --- a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt +++ b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt @@ -24,12 +24,12 @@ import javax.ws.rs.core.MediaType @Consumes(MediaType.APPLICATION_JSON) interface ApigwUserManagementResourceV4 { @GET - @Path("/getUserInfo") + @Path("/getUserSecurityInfo") @ApiOperation( - "获取用户信息", + "获取用户安全相关信息", tags = ["v4_app_user_info"] ) - fun getUserInfo( + fun getUserSecurityInfo( @ApiParam(value = "appCode", required = true, defaultValue = AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE) @HeaderParam(AUTH_HEADER_DEVOPS_APP_CODE) appCode: String?, diff --git a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt index 50d16f4ae98..de3a7e488c0 100644 --- a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt +++ b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt @@ -1,6 +1,7 @@ package com.tencent.devops.openapi.resources.apigw.v4 import com.tencent.devops.auth.api.service.ServiceDeptResource +import com.tencent.devops.auth.api.service.ServiceSecurityResource import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.client.Client @@ -14,14 +15,14 @@ class ApigwUserManagementResourceV4Impl @Autowired constructor( private val client: Client ) : ApigwUserManagementResourceV4 { - override fun getUserInfo( + override fun getUserSecurityInfo( appCode: String?, apigwType: String?, userId: String, projectCode: String ): Result { - logger.info("OPENAPI_GET_USER_INFO_V4|$appCode|$userId") - return client.get(ServiceDeptResource::class).getUserInfoAndWaterMark( + logger.info("OPENAPI_GET_USER_SECURITY_INFO_V4|$appCode|$userId") + return client.get(ServiceSecurityResource::class).getUserSecurityInfo( userId = userId, projectCode = projectCode ) From baf21328359622e6f493fb28623b0c3e6a25199e Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 16 Nov 2023 11:06:39 +0800 Subject: [PATCH 64/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt index de3a7e488c0..34cb1db89ac 100644 --- a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt +++ b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt @@ -1,6 +1,5 @@ package com.tencent.devops.openapi.resources.apigw.v4 -import com.tencent.devops.auth.api.service.ServiceDeptResource import com.tencent.devops.auth.api.service.ServiceSecurityResource import com.tencent.devops.auth.pojo.vo.UserAndDeptInfoVo import com.tencent.devops.common.api.pojo.Result From fb0df2249af5e4e03fb707d3a945e304a6172494 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 16 Nov 2023 11:58:28 +0800 Subject: [PATCH 65/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt | 2 +- .../resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt index 76485c73656..7c2cfb166d4 100644 --- a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt +++ b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwUserManagementResourceV4.kt @@ -42,5 +42,5 @@ interface ApigwUserManagementResourceV4 { @ApiParam("项目ID", required = true) @QueryParam("projectCode") projectCode: String - ): Result + ): Result } diff --git a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt index 34cb1db89ac..4c9f6849814 100644 --- a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt +++ b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwUserManagementResourceV4Impl.kt @@ -19,7 +19,7 @@ class ApigwUserManagementResourceV4Impl @Autowired constructor( apigwType: String?, userId: String, projectCode: String - ): Result { + ): Result { logger.info("OPENAPI_GET_USER_SECURITY_INFO_V4|$appCode|$userId") return client.get(ServiceSecurityResource::class).getUserSecurityInfo( userId = userId, From 43abdd97d96fb5c061976729efaa621bbc9afb2e Mon Sep 17 00:00:00 2001 From: greysonfang Date: Thu, 16 Nov 2023 15:34:26 +0800 Subject: [PATCH 66/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/auth/api/service/ServiceSecurityResource.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt index ce4ebe844db..9a6759c05ee 100644 --- a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/service/ServiceSecurityResource.kt @@ -6,13 +6,18 @@ import com.tencent.devops.common.api.pojo.Result import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam +import javax.ws.rs.Consumes import javax.ws.rs.GET import javax.ws.rs.HeaderParam import javax.ws.rs.Path +import javax.ws.rs.Produces import javax.ws.rs.QueryParam +import javax.ws.rs.core.MediaType @Api(tags = ["SERVICE_SECURITY"], description = "安全相关") @Path("/service/security") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) interface ServiceSecurityResource { @GET @Path("/getUserSecurityInfo") From cb2886e36fb37f973ae2a31945bf641339894f65 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 17 Nov 2023 12:18:32 +0800 Subject: [PATCH 67/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- support-files/sql/1001_ci_auth_ddl_mysql.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/sql/1001_ci_auth_ddl_mysql.sql b/support-files/sql/1001_ci_auth_ddl_mysql.sql index c13871327e5..16579e10997 100644 --- a/support-files/sql/1001_ci_auth_ddl_mysql.sql +++ b/support-files/sql/1001_ci_auth_ddl_mysql.sql @@ -301,7 +301,7 @@ CREATE TABLE IF NOT EXISTS `T_AUTH_OAUTH2_CLIENT_DETAILS` ( `CLIENT_NAME` VARCHAR(255) NOT NULL COMMENT '客户端名称', `SCOPE` MEDIUMTEXT DEFAULT NULL COMMENT '授权操作范围', `ICON` MEDIUMTEXT DEFAULT NULL COMMENT '图标', - `AUTHORIZED_GRANT_TYPES` VARCHAR(64) NOT NULL COMMENT '授权模式', + `AUTHORIZED_GRANT_TYPES` MEDIUMTEXT NOT NULL COMMENT '授权模式', `WEB_SERVER_REDIRECT_URI` VARCHAR(255) DEFAULT NULL COMMENT '跳转链接', `ACCESS_TOKEN_VALIDITY` BIGINT(20) NOT NULL COMMENT 'access_token有效时间', `REFRESH_TOKEN_VALIDITY` BIGINT(20) DEFAULT NULL COMMENT 'refresh_token有效时间', From 682fc522e358757eb96a01434df2a3e30cb52ad8 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 17 Nov 2023 12:19:06 +0800 Subject: [PATCH 68/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- support-files/sql/1001_ci_auth_ddl_mysql.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/support-files/sql/1001_ci_auth_ddl_mysql.sql b/support-files/sql/1001_ci_auth_ddl_mysql.sql index 16579e10997..b53d3cf0592 100644 --- a/support-files/sql/1001_ci_auth_ddl_mysql.sql +++ b/support-files/sql/1001_ci_auth_ddl_mysql.sql @@ -301,8 +301,8 @@ CREATE TABLE IF NOT EXISTS `T_AUTH_OAUTH2_CLIENT_DETAILS` ( `CLIENT_NAME` VARCHAR(255) NOT NULL COMMENT '客户端名称', `SCOPE` MEDIUMTEXT DEFAULT NULL COMMENT '授权操作范围', `ICON` MEDIUMTEXT DEFAULT NULL COMMENT '图标', - `AUTHORIZED_GRANT_TYPES` MEDIUMTEXT NOT NULL COMMENT '授权模式', - `WEB_SERVER_REDIRECT_URI` VARCHAR(255) DEFAULT NULL COMMENT '跳转链接', + `AUTHORIZED_GRANT_TYPES` VARCHAR(64) NOT NULL COMMENT '授权模式', + `WEB_SERVER_REDIRECT_URI` MEDIUMTEXT DEFAULT NULL COMMENT '跳转链接', `ACCESS_TOKEN_VALIDITY` BIGINT(20) NOT NULL COMMENT 'access_token有效时间', `REFRESH_TOKEN_VALIDITY` BIGINT(20) DEFAULT NULL COMMENT 'refresh_token有效时间', `CREATE_USER` VARCHAR(32) NOT NULL DEFAULT '""' COMMENT '创建人', From d2f406f4c5b88cc12c536731b0c5fcee7e150350 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 17 Nov 2023 12:23:19 +0800 Subject: [PATCH 69/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/auth/service/oauth2/Oauth2ClientService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt index 4202d9ec109..ad5fa404c57 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt @@ -62,7 +62,7 @@ class Oauth2ClientService constructor( defaultMessage = "The client($clientId) does not support $grantType type" ) } - if (redirectUri != null && redirectUri != clientDetails.redirectUri) { + if (redirectUri != null && !clientDetails.redirectUri.split(",").contains(redirectUri)) { logger.warn("The redirectUri is invalid|$clientId|$redirectUri") throw ErrorCodeException( errorCode = AuthMessageCode.INVALID_REDIRECT_URI, From 791c192080e462a2ef4cb5e3133adc1f5030c85f Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 17 Nov 2023 15:56:26 +0800 Subject: [PATCH 70/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/oauth2/Oauth2ClientServiceTest.kt | 65 ++++--------------- 1 file changed, 13 insertions(+), 52 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt index e347c9c5495..9244eb7defe 100644 --- a/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt +++ b/src/backend/ci/core/auth/biz-auth/src/test/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientServiceTest.kt @@ -18,22 +18,22 @@ class Oauth2ClientServiceTest : BkCiAbstractTest() { dslContext = dslContext, authOauth2ClientDetailsDao = authOauth2ClientDetailsDao ) + private val clientId = "testClient" + + private val clientDetails = ClientDetailsInfo( + clientId = "testClient", + clientSecret = "testSecret", + clientName = "Test Client", + scope = "read,write", + authorizedGrantTypes = "authorization_code,refresh_token", + redirectUri = "http://example.com/callback,http://example1.com/callback", + accessTokenValidity = 3600, + refreshTokenValidity = 86400, + icon = "icon" + ) @Test fun `test verifyClientInformation with invalid grant type`() { - val clientId = "testClient" - val clientDetails = ClientDetailsInfo( - clientId = clientId, - clientSecret = "testSecret", - clientName = "Test Client", - scope = "read,write", - authorizedGrantTypes = "authorization_code,refresh_token", - redirectUri = "http://example.com/callback", - accessTokenValidity = 3600, - refreshTokenValidity = 86400, - icon = "icon" - ) - val invalidGrantType = "invalid_grant_type" val exception = assertThrows { @@ -50,19 +50,6 @@ class Oauth2ClientServiceTest : BkCiAbstractTest() { @Test fun `test verifyClientInformation with invalid redirect URI`() { - val clientId = "testClient" - val clientDetails = ClientDetailsInfo( - clientId = clientId, - clientSecret = "testSecret", - clientName = "Test Client", - scope = "read,write", - authorizedGrantTypes = "authorization_code", - redirectUri = "http://example.com/callback", - accessTokenValidity = 3600, - refreshTokenValidity = 86400, - icon = "icon" - ) - val invalidRedirectUri = "http://invalid.com/callback" val exception = assertThrows { @@ -79,19 +66,6 @@ class Oauth2ClientServiceTest : BkCiAbstractTest() { @Test fun `test verifyClientInformation with invalid client secret`() { - val clientId = "testClient" - val clientDetails = ClientDetailsInfo( - clientId = clientId, - clientSecret = "testSecret", - clientName = "Test Client", - scope = "read,write", - authorizedGrantTypes = "authorization_code", - redirectUri = "http://example.com/callback", - accessTokenValidity = 3600, - refreshTokenValidity = 86400, - icon = "icon" - ) - val invalidClientSecret = "invalidSecret" val exception = assertThrows { @@ -108,19 +82,6 @@ class Oauth2ClientServiceTest : BkCiAbstractTest() { @Test fun `test verifyClientInformation with invalid scope`() { - val clientId = "testClient" - val clientDetails = ClientDetailsInfo( - clientId = clientId, - clientSecret = "testSecret", - clientName = "Test Client", - scope = "read,write", - authorizedGrantTypes = "authorization_code", - redirectUri = "http://example.com/callback", - accessTokenValidity = 3600, - refreshTokenValidity = 86400, - icon = "icon" - ) - val invalidScope = listOf("invalidScope") val exception = assertThrows { From 50c7334c8c80a69a347a08fcd0932c5796adccff Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 24 Nov 2023 11:08:37 +0800 Subject: [PATCH 71/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/oauth2/OpOauth2Resource.kt | 55 +++++++++++++++++++ .../devops/auth/pojo/dto/ClientDetailsDTO.kt | 30 ++++++++++ .../devops/auth/pojo/dto/ScopeOperationDTO.kt | 16 ++++++ .../auth/dao/AuthOauth2ClientDetailsDao.kt | 42 ++++++++++++++ .../auth/dao/AuthOauth2ScopeOperationDao.kt | 30 ++++++++++ .../auth/resources/OpOauth2ResourceImpl.kt | 31 +++++++++++ .../service/oauth2/Oauth2ClientService.kt | 17 ++++++ .../oauth2/Oauth2ScopeOperationService.kt | 25 +++++++-- 8 files changed, 242 insertions(+), 4 deletions(-) create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/OpOauth2Resource.kt create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/ClientDetailsDTO.kt create mode 100644 src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/ScopeOperationDTO.kt create mode 100644 src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/OpOauth2ResourceImpl.kt diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/OpOauth2Resource.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/OpOauth2Resource.kt new file mode 100644 index 00000000000..708c03b9c5b --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/api/oauth2/OpOauth2Resource.kt @@ -0,0 +1,55 @@ +package com.tencent.devops.auth.api.oauth2 + +import com.tencent.devops.auth.pojo.dto.ClientDetailsDTO +import com.tencent.devops.auth.pojo.dto.ScopeOperationDTO +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam +import javax.ws.rs.Consumes +import javax.ws.rs.DELETE +import javax.ws.rs.POST +import javax.ws.rs.Path +import javax.ws.rs.Produces +import javax.ws.rs.QueryParam +import javax.ws.rs.core.MediaType +import com.tencent.devops.common.api.pojo.Result + +@Api(tags = ["OP_OAUTH2"], description = "oauth2相关-op接口") +@Path("/op/oauth2/") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +interface OpOauth2Resource { + @POST + @Path("/createClientDetails") + @ApiOperation("新增Oauth2客户端信息") + fun createClientDetails( + @ApiParam("Oauth2客户端请求实体", required = true) + clientDetailsDTO: ClientDetailsDTO + ): Result + + @DELETE + @Path("/deleteClientDetails") + @ApiOperation("删除Oauth2客户端信息") + fun deleteClientDetails( + @ApiParam("客户端ID", required = true) + @QueryParam("clientId") + clientId: String + ): Result + + @POST + @Path("/createScopeOperation") + @ApiOperation("新增Oauth2授权操作信息") + fun createScopeOperation( + @ApiParam("Oauth2授权操作信息请求实体", required = true) + scopeOperationDTO: ScopeOperationDTO + ): Result + + @DELETE + @Path("/deleteScopeOperation") + @ApiOperation("删除Oauth2授权操作信息") + fun deleteScopeOperation( + @ApiParam("授权操作ID", required = true) + @QueryParam("operationId") + operationId: String + ): Result +} diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/ClientDetailsDTO.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/ClientDetailsDTO.kt new file mode 100644 index 00000000000..7ecace510c6 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/ClientDetailsDTO.kt @@ -0,0 +1,30 @@ +package com.tencent.devops.auth.pojo.dto + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("Oauth2客户端请求实体") +data class ClientDetailsDTO( + @ApiModelProperty("客户端ID") + val clientId: String, + @ApiModelProperty("客户端秘钥") + val clientSecret: String, + @ApiModelProperty("客户端名称") + val clientName: String, + @ApiModelProperty("授权操作范围") + val scope: String, + @ApiModelProperty("图标") + val icon: String, + @ApiModelProperty("授权模式") + val authorizedGrantTypes: String, + @ApiModelProperty("跳转链接") + val webServerRedirectUri: String, + @ApiModelProperty("access_token有效时间") + val accessTokenValidity: Long, + @ApiModelProperty("refresh_token有效时间") + val refreshTokenValidity: Long, + @ApiModelProperty("创建人") + val createUser: String? = null, + @ApiModelProperty("更新人") + val updateUser: String? = null +) diff --git a/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/ScopeOperationDTO.kt b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/ScopeOperationDTO.kt new file mode 100644 index 00000000000..00c40245ea6 --- /dev/null +++ b/src/backend/ci/core/auth/api-auth/src/main/kotlin/com/tencent/devops/auth/pojo/dto/ScopeOperationDTO.kt @@ -0,0 +1,16 @@ +package com.tencent.devops.auth.pojo.dto + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("Oauth2授权操作信息请求实体") +data class ScopeOperationDTO( + @ApiModelProperty("主键ID") + val id: Int, + @ApiModelProperty("授权操作ID") + val operationId: String, + @ApiModelProperty("授权操作中文名称") + val operationNameCn: String, + @ApiModelProperty("授权操作英文名称") + val operationNameEn: String +) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt index 818c0ebad9b..5d2e7cf3296 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt @@ -1,5 +1,6 @@ package com.tencent.devops.auth.dao +import com.tencent.devops.auth.pojo.dto.ClientDetailsDTO import com.tencent.devops.model.auth.tables.TAuthOauth2ClientDetails import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.jooq.DSLContext @@ -17,4 +18,45 @@ class AuthOauth2ClientDetailsDao { ) }.fetchOne() } + + fun create( + dslContext: DSLContext, + clientDetailsDTO: ClientDetailsDTO + ) { + with(TAuthOauth2ClientDetails.T_AUTH_OAUTH2_CLIENT_DETAILS) { + dslContext.insertInto( + this, + CLIENT_ID, + CLIENT_SECRET, + CLIENT_NAME, + SCOPE, + ICON, + AUTHORIZED_GRANT_TYPES, + WEB_SERVER_REDIRECT_URI, + ACCESS_TOKEN_VALIDITY, + REFRESH_TOKEN_VALIDITY, + CREATE_USER + ).values( + clientDetailsDTO.clientId, + clientDetailsDTO.clientSecret, + clientDetailsDTO.clientName, + clientDetailsDTO.scope, + clientDetailsDTO.icon, + clientDetailsDTO.authorizedGrantTypes, + clientDetailsDTO.webServerRedirectUri, + clientDetailsDTO.accessTokenValidity, + clientDetailsDTO.refreshTokenValidity, + clientDetailsDTO.createUser + ).execute() + } + } + + fun delete( + dslContext: DSLContext, + clientId: String + ) { + with(TAuthOauth2ClientDetails.T_AUTH_OAUTH2_CLIENT_DETAILS) { + dslContext.deleteFrom(this).where(CLIENT_ID.eq(clientId)) + } + } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt index 48471d9a40a..ebd4f3b481b 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt @@ -1,5 +1,6 @@ package com.tencent.devops.auth.dao +import com.tencent.devops.auth.pojo.dto.ScopeOperationDTO import com.tencent.devops.model.auth.tables.TAuthOauth2ScopeOperation import com.tencent.devops.model.auth.tables.records.TAuthOauth2ScopeOperationRecord import org.jooq.DSLContext @@ -16,4 +17,33 @@ class AuthOauth2ScopeOperationDao { .fetchOne() } } + + fun create( + dslContext: DSLContext, + scopeOperationDTO: ScopeOperationDTO + ) { + with(TAuthOauth2ScopeOperation.T_AUTH_OAUTH2_SCOPE_OPERATION) { + dslContext.insertInto( + this, + ID, + OPERATION_ID, + OPERATION_NAME_CN, + OPERATION_NAME_EN + ).values( + scopeOperationDTO.id, + scopeOperationDTO.operationId, + scopeOperationDTO.operationNameCn, + scopeOperationDTO.operationNameEn + ) + } + } + + fun delete( + dslContext: DSLContext, + operationId: String + ){ + with(TAuthOauth2ScopeOperation.T_AUTH_OAUTH2_SCOPE_OPERATION) { + dslContext.deleteFrom(this).where(OPERATION_ID.eq(operationId)) + } + } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/OpOauth2ResourceImpl.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/OpOauth2ResourceImpl.kt new file mode 100644 index 00000000000..cc5ae56a256 --- /dev/null +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/resources/OpOauth2ResourceImpl.kt @@ -0,0 +1,31 @@ +package com.tencent.devops.auth.resources + +import com.tencent.devops.auth.api.oauth2.OpOauth2Resource +import com.tencent.devops.auth.pojo.dto.ClientDetailsDTO +import com.tencent.devops.auth.pojo.dto.ScopeOperationDTO +import com.tencent.devops.auth.service.oauth2.Oauth2ClientService +import com.tencent.devops.auth.service.oauth2.Oauth2ScopeOperationService +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.common.web.RestResource + +@RestResource +class OpOauth2ResourceImpl constructor( + val clientService: Oauth2ClientService, + val scopeOperationService: Oauth2ScopeOperationService +) : OpOauth2Resource { + override fun createClientDetails(clientDetailsDTO: ClientDetailsDTO): Result { + return Result(clientService.createClientDetails(clientDetailsDTO = clientDetailsDTO)) + } + + override fun deleteClientDetails(clientId: String): Result { + return Result(clientService.deleteClientDetails(clientId = clientId)) + } + + override fun createScopeOperation(scopeOperationDTO: ScopeOperationDTO): Result { + return Result(scopeOperationService.create(scopeOperationDTO = scopeOperationDTO)) + } + + override fun deleteScopeOperation(operationId: String): Result { + return Result(scopeOperationService.delete(operationId = operationId)) + } +} diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt index ad5fa404c57..7423136fb39 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ClientService.kt @@ -3,6 +3,7 @@ package com.tencent.devops.auth.service.oauth2 import com.tencent.devops.auth.constant.AuthMessageCode import com.tencent.devops.auth.dao.AuthOauth2ClientDetailsDao import com.tencent.devops.auth.pojo.ClientDetailsInfo +import com.tencent.devops.auth.pojo.dto.ClientDetailsDTO import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.model.auth.tables.records.TAuthOauth2ClientDetailsRecord import org.jooq.DSLContext @@ -44,6 +45,22 @@ class Oauth2ClientService constructor( ) } + fun createClientDetails(clientDetailsDTO: ClientDetailsDTO): Boolean { + authOauth2ClientDetailsDao.create( + dslContext = dslContext, + clientDetailsDTO = clientDetailsDTO + ) + return true + } + + fun deleteClientDetails(clientId: String): Boolean { + authOauth2ClientDetailsDao.delete( + dslContext = dslContext, + clientId = clientId + ) + return true + } + @Suppress("ThrowsCount", "LongParameterList") fun verifyClientInformation( clientId: String, diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt index d3f8387c0fb..157a5a19048 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt @@ -1,21 +1,38 @@ package com.tencent.devops.auth.service.oauth2 import com.tencent.devops.auth.dao.AuthOauth2ScopeOperationDao +import com.tencent.devops.auth.pojo.dto.ScopeOperationDTO import com.tencent.devops.model.auth.tables.records.TAuthOauth2ScopeOperationRecord import org.jooq.DSLContext import org.springframework.stereotype.Service @Service class Oauth2ScopeOperationService constructor( - private val dslContext: DSLContext, - private val oauth2ScopeOperationDao: AuthOauth2ScopeOperationDao + private val dslContext: DSLContext, private val oauth2ScopeOperationDao: AuthOauth2ScopeOperationDao ) { fun get( operationId: String ): TAuthOauth2ScopeOperationRecord? { return oauth2ScopeOperationDao.get( - dslContext = dslContext, - operationId = operationId + dslContext = dslContext, operationId = operationId ) } + + fun create( + scopeOperationDTO: ScopeOperationDTO + ): Boolean { + oauth2ScopeOperationDao.create( + dslContext = dslContext, scopeOperationDTO = scopeOperationDTO + ) + return true + } + + fun delete( + operationId: String + ): Boolean { + oauth2ScopeOperationDao.delete( + dslContext = dslContext, operationId = operationId + ) + return true + } } From 184449cd3440e6f14c7e5621b0ba13c90bceaa29 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 24 Nov 2023 11:11:13 +0800 Subject: [PATCH 72/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt | 2 +- .../devops/auth/service/oauth2/Oauth2ScopeOperationService.kt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt index ebd4f3b481b..8d59f6439b7 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt @@ -41,7 +41,7 @@ class AuthOauth2ScopeOperationDao { fun delete( dslContext: DSLContext, operationId: String - ){ + ) { with(TAuthOauth2ScopeOperation.T_AUTH_OAUTH2_SCOPE_OPERATION) { dslContext.deleteFrom(this).where(OPERATION_ID.eq(operationId)) } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt index 157a5a19048..0159271a654 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/service/oauth2/Oauth2ScopeOperationService.kt @@ -8,7 +8,8 @@ import org.springframework.stereotype.Service @Service class Oauth2ScopeOperationService constructor( - private val dslContext: DSLContext, private val oauth2ScopeOperationDao: AuthOauth2ScopeOperationDao + private val dslContext: DSLContext, + private val oauth2ScopeOperationDao: AuthOauth2ScopeOperationDao ) { fun get( operationId: String From d747a47960bd34700aeb6da941ca1054361f1d40 Mon Sep 17 00:00:00 2001 From: greysonfang Date: Fri, 24 Nov 2023 12:16:47 +0800 Subject: [PATCH 73/73] =?UTF-8?q?feat=EF=BC=9A=E8=93=9D=E7=9B=BEAPP=20Oaut?= =?UTF-8?q?h2=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95=E5=AE=9E=E7=8E=B0=20#935?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt | 2 +- .../tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt index 5d2e7cf3296..0a5d0e6b0c9 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ClientDetailsDao.kt @@ -56,7 +56,7 @@ class AuthOauth2ClientDetailsDao { clientId: String ) { with(TAuthOauth2ClientDetails.T_AUTH_OAUTH2_CLIENT_DETAILS) { - dslContext.deleteFrom(this).where(CLIENT_ID.eq(clientId)) + dslContext.deleteFrom(this).where(CLIENT_ID.eq(clientId)).execute() } } } diff --git a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt index 8d59f6439b7..fb3ff2ad122 100644 --- a/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt +++ b/src/backend/ci/core/auth/biz-auth/src/main/kotlin/com/tencent/devops/auth/dao/AuthOauth2ScopeOperationDao.kt @@ -34,7 +34,7 @@ class AuthOauth2ScopeOperationDao { scopeOperationDTO.operationId, scopeOperationDTO.operationNameCn, scopeOperationDTO.operationNameEn - ) + ).execute() } } @@ -43,7 +43,7 @@ class AuthOauth2ScopeOperationDao { operationId: String ) { with(TAuthOauth2ScopeOperation.T_AUTH_OAUTH2_SCOPE_OPERATION) { - dslContext.deleteFrom(this).where(OPERATION_ID.eq(operationId)) + dslContext.deleteFrom(this).where(OPERATION_ID.eq(operationId)).execute() } } }