Skip to content

Commit 366d600

Browse files
committed
Application Wallet Api call request timeout
1 parent 6c9f407 commit 366d600

10 files changed

Lines changed: 39 additions & 48 deletions

File tree

src/main/kotlin/io/openfuture/api/component/state/DefaultStateApi.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class DefaultStateApi(private val stateRestTemplate: RestTemplate) : StateApi {
1616
}
1717

1818
override fun deleteWallet(address: String, blockchain: Blockchain) {
19-
val url = "/wallets/blockchain/${blockchain}/address/${address}"
19+
val url = "/wallets/blockchain/${blockchain.getValue()}/address/${address}"
2020
stateRestTemplate.delete(url)
2121
}
2222

src/main/kotlin/io/openfuture/api/config/SecurityConfig.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class SecurityConfig(
4747

4848
.addFilterAfter(AuthorizationFilter(properties, keyService), OAuth2LoginAuthenticationFilter::class.java)
4949
.addFilterAfter(ApiAuthorizationFilter(mapper), AuthorizationFilter::class.java)
50-
.addFilterAfter(PublicApiAuthorizationFilter(applicationService), AuthorizationFilter::class.java)
50+
.addFilterAfter(PublicApiAuthorizationFilter(applicationService, mapper, properties), AuthorizationFilter::class.java)
5151
.sessionManagement().sessionCreationPolicy(STATELESS)
5252

5353
.and()

src/main/kotlin/io/openfuture/api/config/filter/PublicApiAuthorizationFilter.kt

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,26 @@ package io.openfuture.api.config.filter
22

33
import com.fasterxml.jackson.databind.ObjectMapper
44
import io.openfuture.api.config.propety.AuthorizationProperties
5+
import org.springframework.http.HttpStatus.UNAUTHORIZED
6+
import io.openfuture.api.domain.exception.ExceptionResponse
57
import io.openfuture.api.domain.key.WalletApiCreateRequest
68
import io.openfuture.api.service.ApplicationService
79
import io.openfuture.api.util.CustomHttpRequestWrapper
810
import io.openfuture.api.util.KeyGeneratorUtils
11+
import io.openfuture.api.util.currentEpochs
912
import io.openfuture.api.util.differenceEpochs
10-
import org.springframework.http.HttpHeaders
1113
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
1214
import org.springframework.security.core.authority.SimpleGrantedAuthority
1315
import org.springframework.security.core.context.SecurityContextHolder
1416
import javax.servlet.*
1517
import javax.servlet.http.HttpServletRequest
18+
import javax.servlet.http.HttpServletResponse
1619

1720

1821
class PublicApiAuthorizationFilter(
19-
private val applicationService: ApplicationService
22+
private val applicationService: ApplicationService,
23+
private val mapper: ObjectMapper,
24+
private val properties: AuthorizationProperties
2025
): Filter {
2126

2227
override fun init(filterConfig: FilterConfig?) {
@@ -25,29 +30,35 @@ class PublicApiAuthorizationFilter(
2530

2631
override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
2732
request as HttpServletRequest
33+
response as HttpServletResponse
2834

29-
if (request.requestURI.startsWith("/public") && null == SecurityContextHolder.getContext().authentication && request.getHeader("X-API-KEY") != null) {
35+
if (request.requestURI.startsWith("/public") && request.getHeader("X-API-KEY") != null) {
3036

3137
val accessKey = request.getHeader("X-API-KEY")
3238
val signature = request.getHeader("X-API-SIGNATURE")
39+
val expirePeriod = 10L;
3340

3441
val requestWrapper = CustomHttpRequestWrapper(request)
35-
val walletApiCreateRequest = ObjectMapper().readValue(requestWrapper.bodyInStringFormat, WalletApiCreateRequest::class.java)
42+
val walletApiCreateRequest = mapper.readValue(requestWrapper.bodyInStringFormat, WalletApiCreateRequest::class.java)
3643

37-
val diffMinutes = differenceEpochs(System.currentTimeMillis() / 1000L, walletApiCreateRequest.timestamp.toLong())
44+
val diffMinutes = differenceEpochs(currentEpochs(), walletApiCreateRequest.timestamp.toLong())
3845

3946
val application = applicationService.getByAccessKey(accessKey)
4047

4148
val hmacSha256 = application.let {
4249
KeyGeneratorUtils.calcHmacSha256(it.apiSecretKey, walletApiCreateRequest.toString())
4350
}
4451

45-
if (hmacSha256 == signature && diffMinutes < 10){
46-
val token = UsernamePasswordAuthenticationToken(application.user, null,
47-
application.user.roles.map { SimpleGrantedAuthority("ROLE_APPLICATION") })
48-
SecurityContextHolder.getContext().authentication = token
52+
if (hmacSha256 != signature || diffMinutes > expirePeriod) {
53+
val exceptionResponse = ExceptionResponse(UNAUTHORIZED.value(), "Signature mismatch or request timeout")
54+
response.status = exceptionResponse.status
55+
response.writer.write(mapper.writeValueAsString(exceptionResponse))
56+
return
4957
}
5058

59+
val token = UsernamePasswordAuthenticationToken(application.user, null, listOf(SimpleGrantedAuthority("ROLE_APPLICATION")))
60+
SecurityContextHolder.getContext().authentication = token
61+
5162
chain.doFilter(requestWrapper, response);
5263
return
5364
}

src/main/kotlin/io/openfuture/api/config/propety/AuthorizationProperties.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ import javax.validation.constraints.NotEmpty
99
@Validated
1010
@Component
1111
class AuthorizationProperties(
12-
@field:NotEmpty var cookieName: String? = null
12+
@field:NotEmpty var cookieName: String? = null,
13+
var expireApi: Long? = 10
1314
)

src/main/kotlin/io/openfuture/api/controller/api/WalletApiController.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@ class WalletApiController(
1919
) {
2020

2121
@PreAuthorize(value = "hasAnyRole('ROLE_APPLICATION')")
22-
@PostMapping(path = ["/generate"], consumes = [MediaType.APPLICATION_FORM_URLENCODED_VALUE])
23-
fun generateWallet(@RequestParam paramMap: MutableMap<String, Any>, httpServletRequest: HttpServletRequest): KeyWalletDto? {
24-
return service.generateWallet(paramMap, httpServletRequest)
25-
}
26-
27-
@PostMapping("/gen")
22+
@PostMapping("/generate")
2823
fun generateWallet(@RequestBody walletApiCreateRequest: WalletApiCreateRequest, @RequestHeader("X-API-KEY") accessKey: String, @CurrentUser user: User): KeyWalletDto? {
2924

3025
val application = applicationService.getByAccessKey(accessKey)

src/main/kotlin/io/openfuture/api/service/DefaultApplicationWalletService.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ class DefaultApplicationWalletService(
3232
}
3333

3434
override fun deleteWallet(applicationId: String, address: String) {
35+
// Delete from Open Key
3536
keyApi.deleteAllKeysByApplicationAddress(applicationId, address)
37+
// Delete from Open State
3638
stateApi.deleteWallet(address, Blockchain.Ethereum)
3739
}
3840
}

src/main/kotlin/io/openfuture/api/service/DefaultWalletApiService.kt

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,37 +13,17 @@ import javax.servlet.http.HttpServletRequest
1313

1414
@Service
1515
class DefaultWalletApiService(
16-
private val applicationWalletService: ApplicationWalletService,
17-
private val applicationService: ApplicationService
16+
private val applicationWalletService: ApplicationWalletService
1817
) : WalletApiService{
1918

2019
override fun generateWallet(
2120
walletApiCreateRequest: WalletApiCreateRequest,
2221
application: Application,
2322
user: User
2423
): KeyWalletDto {
25-
return applicationWalletService.generateWallet(GenerateWalletRequest(application.id.toString(), application.webHook!!, walletApiCreateRequest.blockchain), user)
26-
}
27-
28-
override fun generateWallet(
29-
paramMap: MutableMap<String, Any>,
30-
httpServletRequest: HttpServletRequest
31-
): KeyWalletDto {
32-
val accessKey = httpServletRequest.getHeader("X-API-KEY")
33-
val signature = httpServletRequest.getHeader("X-API-SIGNATURE")
34-
35-
val joinedParams = paramMap.entries.joinToString(separator = "&") { (key, value) ->
36-
"${key}=${value}"
37-
}
38-
val application = applicationService.getByAccessKey(accessKey)
39-
40-
val hmacSha256 = KeyGeneratorUtils.calcHmacSha256(application.apiSecretKey, joinedParams)
41-
42-
43-
if (hmacSha256 == signature){
44-
return applicationWalletService.generateWallet(GenerateWalletRequest(application.id.toString(), application.webHook!!, BlockchainType.valueOf(
45-
paramMap["blockchain"].toString())), application.user)
46-
}
47-
throw NotFoundException("Signature does not match")
24+
return applicationWalletService.generateWallet(
25+
GenerateWalletRequest(application.id.toString(), application.webHook!!, walletApiCreateRequest.blockchain),
26+
user
27+
)
4828
}
4929
}

src/main/kotlin/io/openfuture/api/service/Service.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,4 @@ interface WalletApiService {
138138

139139
fun generateWallet(walletApiCreateRequest: WalletApiCreateRequest, application: Application, user: User): KeyWalletDto
140140

141-
fun generateWallet(paramMap: MutableMap<String, Any>, httpServletRequest: HttpServletRequest): KeyWalletDto
142-
143141
}

src/main/kotlin/io/openfuture/api/util/DateUtils.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fun LocalDateTime.toEpochMillis(): Long {
3131
}
3232

3333
fun differenceEpochs(startTime: Long, endTime: Long): Long{
34-
return TimeUnit.MILLISECONDS.toMinutes(kotlin.math.abs(
35-
endTime - startTime
36-
))
34+
return kotlin.math.abs(endTime - startTime)/60
3735
}
36+
37+
fun currentEpochs(): Long = System.currentTimeMillis() / 1000L

src/main/resources/application.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@ ethereum.event-subscription=${EVENT_SUBSCRIPTION}
1919

2020
# AUTH
2121
auth.cookie-name=open_key
22+
auth.expire-api=10
2223

2324
# WIDGET
2425
widget.host=${WIDGET_HOST}
2526

2627
# STATE
2728
state.base-url=${OPEN_STATE_URL}
29+
30+
# KEY
31+
key.base-url=${OPEN_KEY_URL}

0 commit comments

Comments
 (0)