Rework token invalidation (#307)

This commit is contained in:
KirillPamPam
2023-09-25 16:02:36 +04:00
committed by GitHub
parent 109fb97e0a
commit 8e26d4a8cf
8 changed files with 51 additions and 104 deletions

View File

@@ -17,9 +17,13 @@ import java.io.StringReader
import java.nio.file.Files
import java.nio.file.Paths
import java.security.KeyFactory
import java.security.PrivateKey
import java.security.PublicKey
import java.security.interfaces.RSAPrivateKey
import java.security.interfaces.RSAPublicKey
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec
import java.time.Instant
class AuthProcessorV1Test {
private val processor = AuthProcessorV1(
@@ -31,12 +35,13 @@ class AuthProcessorV1Test {
)
private val rsaKeyReader = RsaKeyReader()
private val privProviderPath = ResourceUtils.getFile("classpath:keys/priv.p8.key").path
private val privDrpcPath = ResourceUtils.getFile("classpath:keys/priv-drpc.p8.key").path
private val publicDrpcPath = ResourceUtils.getFile("classpath:keys/public-drpc.pem").path
private val token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkcnBjIiwiaWF0IjoxNjkyMTg1OTMxLCJ2ZXJzaW9uI" +
"joiVjEifQ.BZILN0GQ7JzXGFz-GZIbFTT9E5L-miB4Nga0v4o_cQThk8gbDelBRzEfdsqxCq_ppPr3v_Own8M-vR9yQElx5nEdlI4xe5QAMdIvr3g" +
"12fMckydX9IsW4sVQ1kJJY8RrHb-WL-uI0WSWqoMSwf-Psb-UyiEHAjc3oK7fA72lBaGT4waPHOxRBPvezwg7N934vCZvZMAftFfVgmeEtbCeD7bF" +
"umEr0uEmkIKPTg4QwP-VMvqoLBYpMiJVzP_Ipg_wRHJ7fUN0BGEPjjMvhQ_6TWByiQUBz1kTMd0Ebf_kEuXFQeiwA-FXHJpWczzh66CbbmmWAWsi" +
"ehKw3KPZeBj0oQ"
private val token = JWT.create()
.withIssuedAt(Instant.now())
.withIssuer("drpc")
.withClaim(VERSION, AuthVersion.V1.toString())
.sign(Algorithm.RSA256(generatePrivateKey(privDrpcPath) as RSAPrivateKey))
private val keyPair = rsaKeyReader.getKeyPair(privProviderPath, publicDrpcPath)
@Test
@@ -88,4 +93,14 @@ class AuthProcessorV1Test {
return KeyFactory.getInstance("RSA").generatePublic(publicKeySpec)
}
private fun generatePrivateKey(path: String): PrivateKey {
val privateKeyReader = StringReader(Files.readString(Paths.get(path)))
val privatePem = PEMParser(privateKeyReader).readPemObject()
val privateKeySpec = PKCS8EncodedKeySpec(privatePem.content)
return KeyFactory.getInstance("RSA").generatePrivate(privateKeySpec)
}
}

View File

@@ -1,53 +0,0 @@
package io.emeraldpay.dshackle.auth.processor
import io.emeraldpay.dshackle.auth.AuthContext
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.time.Instant
import java.time.temporal.ChronoUnit
class TokenProcessorTest {
private val tokenProcessor = TokenProcessor()
@BeforeEach
fun removeSessions() {
AuthContext.sessions.clear()
}
@Test
fun `invalidate all tokens`() {
AuthContext.putTokenInContext(
AuthContext.TokenWrapper("token", Instant.now().minus(1, ChronoUnit.HOURS), "session1")
)
AuthContext.putTokenInContext(
AuthContext.TokenWrapper("token", Instant.now().minus(1, ChronoUnit.HOURS), "session2")
)
AuthContext.putTokenInContext(
AuthContext.TokenWrapper("token", Instant.now().minus(1, ChronoUnit.HOURS), "session3")
)
tokenProcessor.invalidateTokens()
assertTrue(AuthContext.sessions.isEmpty())
}
@Test
fun `tokens are still in the context after invalidation`() {
val token1 = AuthContext.TokenWrapper("token", Instant.now().minus(30, ChronoUnit.MINUTES), "session1")
val token2 = AuthContext.TokenWrapper("token", Instant.now().minus(30, ChronoUnit.MINUTES), "session2")
val token3 = AuthContext.TokenWrapper("token", Instant.now().minus(30, ChronoUnit.MINUTES), "session3")
AuthContext.putTokenInContext(token1)
AuthContext.putTokenInContext(token2)
AuthContext.putTokenInContext(token3)
tokenProcessor.invalidateTokens()
assertEquals(3, AuthContext.sessions.size)
assertEquals(
mapOf(token1.sessionId to token1, token2.sessionId to token2, token3.sessionId to token3),
AuthContext.sessions
)
}
}

View File

@@ -21,6 +21,7 @@ import java.util.concurrent.CompletableFuture
class AuthServiceTest {
private val rsaKeyReader = mock(KeyReader::class.java)
private val mockV1Processor = mock(AuthProcessor::class.java)
private val authContext = AuthContext()
private val factory = AuthProcessorResolver(mockV1Processor)
private val token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkcnBjIiwiaWF0IjoxNjkyMTg1OTMxLCJ2ZXJzaW9uI" +
@@ -31,7 +32,7 @@ class AuthServiceTest {
@Test
fun `unimplemented error if auth is disabled`() {
val authService = AuthService(AuthorizationConfig.default(), rsaKeyReader, factory)
val authService = AuthService(AuthorizationConfig.default(), rsaKeyReader, factory, authContext)
val e = assertThrows(StatusException::class.java) { authService.authenticate("") }
assertEquals("UNIMPLEMENTED: Authentication process is not enabled", e.message)
@@ -48,7 +49,7 @@ class AuthServiceTest {
AuthorizationConfig.ServerConfig("privPath", "pubPath"),
AuthorizationConfig.ClientConfig.default()
),
rsaKeyReader, factory
rsaKeyReader, factory, authContext
)
val pair = KeyReader.Keys(mock(PrivateKey::class.java), mock(PublicKey::class.java))
@@ -59,7 +60,7 @@ class AuthServiceTest {
authService.authenticate(token)
verify(rsaKeyReader).getKeyPair("privPath", "pubPath")
verify(mockV1Processor).process(pair, token)
assertTrue(AuthContext.sessions.containsKey(tokenWrapper.sessionId))
assertTrue(authContext.containsSession(tokenWrapper.sessionId))
}
@Test
@@ -77,7 +78,7 @@ class AuthServiceTest {
AuthorizationConfig.ServerConfig("privPath", "pubPath"),
AuthorizationConfig.ClientConfig.default()
),
rsaKeyReader, factory
rsaKeyReader, factory, authContext
)
`when`(rsaKeyReader.getKeyPair("privPath", "pubPath")).thenReturn(pair)
@@ -93,7 +94,7 @@ class AuthServiceTest {
verify(rsaKeyReader, times(2)).getKeyPair("privPath", "pubPath")
verify(mockV1Processor, times(2)).process(pair, token)
assertTrue(AuthContext.sessions.containsKey(tokenWrapper.sessionId))
assertTrue(AuthContext.sessions.containsKey(tokenWrapper1.sessionId))
assertTrue(authContext.containsSession(tokenWrapper.sessionId))
assertTrue(authContext.containsSession(tokenWrapper1.sessionId))
}
}