Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:Oauth token刷新保留原token #2822 #2824

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import com.tencent.bkrepo.auth.pojo.oauth.JsonWebKey
import com.tencent.bkrepo.auth.pojo.oauth.JsonWebKeySet
import com.tencent.bkrepo.auth.pojo.oauth.OauthToken
import com.tencent.bkrepo.auth.dao.repository.OauthTokenRepository
import com.tencent.bkrepo.auth.pojo.enums.ResourceType
import com.tencent.bkrepo.auth.pojo.oauth.OidcConfiguration
import com.tencent.bkrepo.auth.pojo.oauth.UserInfo
import com.tencent.bkrepo.auth.service.OauthAuthorizationService
Expand Down Expand Up @@ -146,17 +147,16 @@ class OauthAuthorizationServiceImpl(
with(generateTokenRequest) {
Preconditions.checkNotNull(clientId, this::clientId.name)
Preconditions.checkNotNull(refreshToken, this::refreshToken.name)
val token = oauthTokenRepository.findFirstByAccountIdAndRefreshToken(clientId!!, refreshToken!!)
var token = oauthTokenRepository.findFirstByAccountIdAndRefreshToken(clientId!!, refreshToken!!)
?: throw ErrorCodeException(CommonMessageCode.RESOURCE_NOT_FOUND, refreshToken!!)
val idToken = generateOpenIdToken(
clientId = clientId!!,
val client = accountDao.findById(clientId!!)
?: throw ErrorCodeException(CommonMessageCode.RESOURCE_NOT_FOUND, clientId!!)
token = buildOauthToken(
userId = token.userId,
nonce = OauthUtils.generateRandomString(10)
nonce = OauthUtils.generateRandomString(10),
client = client,
openId = token.idToken != null
)
token.accessToken = idToken.toJwtToken()
token.issuedAt = Instant.now(Clock.systemDefaultZone())
token.idToken?.let { token.idToken = idToken }
oauthTokenRepository.save(token)
responseToken(transfer(token))
}
}
Expand Down Expand Up @@ -201,7 +201,7 @@ class OauthAuthorizationServiceImpl(
): TOauthToken {
val idToken = generateOpenIdToken(client.id!!, userId, nonce)
val tOauthToken = TOauthToken(
accessToken = idToken.toJwtToken(),
accessToken = idToken.toJwtToken(client.scope),
refreshToken = OauthUtils.generateRefreshToken(),
expireSeconds = oauthProperties.expiredDuration.seconds,
type = "Bearer",
Expand Down Expand Up @@ -300,7 +300,7 @@ class OauthAuthorizationServiceImpl(
accessToken = tOauthToken.accessToken,
tokenType = tOauthToken.type,
scope = if (tOauthToken.scope == null) "" else tOauthToken.scope!!.joinToString(StringPool.COMMA),
idToken = tOauthToken.idToken?.toJwtToken(),
idToken = tOauthToken.idToken?.toJwtToken(tOauthToken.scope),
refreshToken = tOauthToken.refreshToken,
expiresIn = if (tOauthToken.expireSeconds == null) {
null
Expand All @@ -310,12 +310,15 @@ class OauthAuthorizationServiceImpl(
}
)

private fun IdToken.toJwtToken(): String {
private fun IdToken.toJwtToken(scope: Set<ResourceType>?): String {
val claims = mutableMapOf<String, Any>()
claims["scope"] = scope.orEmpty()
claims.putAll(JsonUtils.objectMapper.convertValue(this, jacksonTypeRef()))
return JwtUtils.generateToken(
signingKey = RsaUtils.stringToPrivateKey(cryptoProperties.privateKeyStr2048PKCS8),
expireDuration = oauthProperties.expiredDuration,
subject = sub,
claims = JsonUtils.objectMapper.convertValue(this, jacksonTypeRef()),
claims = claims,
header = mapOf(KEY_ID_NAME to KEY_ID_VALUE),
algorithm = SignatureAlgorithm.RS256
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class HttpAuthSecurityConfiguration(
)
}
if (httpAuthSecurity.oauthEnabled) {
httpAuthSecurity.addHttpAuthHandler(OauthAuthHandler(authenticationManager))
httpAuthSecurity.addHttpAuthHandler(OauthAuthHandler(authenticationManager, cryptoProperties))
}
if (httpAuthSecurity.temporaryTokenEnabled) {
httpAuthSecurity.addHttpAuthHandler(TemporaryTokenAuthHandler(authenticationManager))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,21 @@ package com.tencent.bkrepo.common.security.http.oauth
import com.tencent.bkrepo.common.api.constant.AUTHORITIES_KEY
import com.tencent.bkrepo.common.api.constant.HttpHeaders
import com.tencent.bkrepo.common.api.constant.OAUTH_AUTH_PREFIX
import com.tencent.bkrepo.common.security.crypto.CryptoProperties
import com.tencent.bkrepo.common.security.exception.AuthenticationException
import com.tencent.bkrepo.common.security.http.core.HttpAuthHandler
import com.tencent.bkrepo.common.security.http.credentials.AnonymousCredentials
import com.tencent.bkrepo.common.security.http.credentials.HttpAuthCredentials
import com.tencent.bkrepo.common.security.manager.AuthenticationManager
import com.tencent.bkrepo.common.security.util.JwtUtils
import com.tencent.bkrepo.common.security.util.RsaUtils
import org.slf4j.LoggerFactory
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

open class OauthAuthHandler(val authenticationManager: AuthenticationManager) : HttpAuthHandler {
open class OauthAuthHandler(
val authenticationManager: AuthenticationManager,
val cryptoProperties: CryptoProperties
) : HttpAuthHandler {
override fun extractAuthCredentials(request: HttpServletRequest): HttpAuthCredentials {
val authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION).orEmpty()
return if (authorizationHeader.startsWith(OAUTH_AUTH_PREFIX)) {
Expand All @@ -53,14 +59,24 @@ open class OauthAuthHandler(val authenticationManager: AuthenticationManager) :

override fun onAuthenticate(request: HttpServletRequest, authCredentials: HttpAuthCredentials): String {
require(authCredentials is OauthAuthCredentials)
return authenticationManager.checkOauthToken(authCredentials.token)
return try {
val claims = JwtUtils.validateToken(
signingKey = RsaUtils.stringToPrivateKey(cryptoProperties.privateKeyStr2048PKCS8),
token = authCredentials.token
)
val scopeList = claims.body["scope"] as? List<*>
val scope = scopeList?.joinToString(",")
?: authenticationManager.findOauthToken(authCredentials.token)?.scope
?: throw AuthenticationException("Invalid access token: $authCredentials.token")
request.setAttribute(AUTHORITIES_KEY, scope)
claims.body.subject
} catch (e: Exception) {
logger.info("invalid oauth token[${authCredentials.token}]: ${e.message}")
throw AuthenticationException("Invalid token")
}
}

override fun onAuthenticateSuccess(request: HttpServletRequest, response: HttpServletResponse, userId: String) {
val authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION).orEmpty()
val accessToken = authorizationHeader.removePrefix(OAUTH_AUTH_PREFIX).trim()
val oauthToken = authenticationManager.findOauthToken(accessToken)
?: throw AuthenticationException("Invalid access token")
request.setAttribute(AUTHORITIES_KEY, oauthToken.scope)
companion object {
private val logger = LoggerFactory.getLogger(OauthAuthHandler::class.java)
}
}
Loading