Commit b4c3b10d authored by Ghitha Dinan's avatar Ghitha Dinan

token interceptor fixing

parent 863081af
......@@ -90,6 +90,13 @@
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.10.00</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
......
package id.co.sangkuriang.inovasi.daerah.master.config
import id.co.sangkuriang.inovasi.daerah.master.constant.USER_ADMIN_ALLOWED_PATH
import id.co.sangkuriang.inovasi.daerah.master.constant.AUDIENCE_FILTER_PATH
import id.co.sangkuriang.inovasi.daerah.master.interceptor.TokenInterceptor
import org.springframework.boot.web.servlet.FilterRegistrationBean
import org.springframework.context.annotation.Bean
......@@ -24,9 +24,13 @@ class SpringWebConfig : WebMvcConfigurer {
fun tokenFilter(): FilterRegistrationBean<TokenInterceptor>? {
val registrationBean: FilterRegistrationBean<TokenInterceptor> =
FilterRegistrationBean<TokenInterceptor>()
USER_ADMIN_ALLOWED_PATH.forEach {
registrationBean.addUrlPatterns("/$it/*")
AUDIENCE_FILTER_PATH.forEach {
it.value.forEach {
registrationBean.addUrlPatterns(it)
}
}
registrationBean.filter = TokenInterceptor()
registrationBean.order = 1
return registrationBean
......
package id.co.sangkuriang.inovasi.daerah.master.constant
const val SECRET = "INOVASI-DAERAH"
const val TOKEN_PREFIX = "Bearer "
const val HEADER_STRING = "Authorization"
const val AUTH_URL = "https://auth.inovasi-daerah.spbe.sangkuriang.co.id/auth"
......
......@@ -9,3 +9,5 @@ const val VALIDATOR_MSG_HAS_USED = "sudah di pakai"
const val VALIDATOR_MSG_NOT_FOUND = "tidak di temukan"
const val VALIDATOR_MSG_DUPLICATE = "Data sudah ada di database"
const val VALIDATOR_MSG_NOT_HAVE_ACCESS = "tidak mempunyai hak akses"
package id.co.sangkuriang.inovasi.daerah.master.helpers
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import id.co.sangkuriang.inovasi.daerah.master.constant.HEADER_STRING
import id.co.sangkuriang.inovasi.daerah.master.model.response.ReturnData
import kong.unirest.Unirest
import org.apache.http.client.HttpClient
import org.apache.http.conn.ssl.NoopHostnameVerifier
import org.apache.http.conn.ssl.TrustSelfSignedStrategy
import org.apache.http.impl.client.HttpClients
import org.apache.http.ssl.SSLContextBuilder
import java.security.cert.X509Certificate
import javax.net.ssl.SSLContext
class RequestHelpers {
companion object {
private fun configHttpClient() {
val sslContext: SSLContext = SSLContextBuilder().loadTrustMaterial(
null,
object : TrustSelfSignedStrategy() {
override fun isTrusted(chain: Array<X509Certificate?>?, authType: String?): Boolean {
return true
}
}
).build()
val customHttpClient: HttpClient = HttpClients.custom().setSSLContext(sslContext)
.setSSLHostnameVerifier(NoopHostnameVerifier()).build()
Unirest.config().httpClient(customHttpClient)
}
fun authDetail(authUrl: String, bearer: String): ReturnData? {
return try {
configHttpClient()
val objectMapper = ObjectMapper()
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
val reqUrl = "$authUrl/detail"
val response = Unirest.get(reqUrl)
.header("Content-Type", "application/json")
.header(HEADER_STRING, bearer)
.asString()
objectMapper.readValue(response.body, ReturnData::class.java)
} catch (e: Exception) {
e.printStackTrace()
null
}
}
}
}
package id.co.sangkuriang.inovasi.daerah.master.interceptor
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import com.auth0.jwt.exceptions.JWTCreationException
import com.auth0.jwt.exceptions.JWTDecodeException
import com.auth0.jwt.exceptions.JWTVerificationException
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import id.co.sangkuriang.inovasi.daerah.master.constant.HEADER_STRING
import id.co.sangkuriang.inovasi.daerah.master.constant.SECRET
import id.co.sangkuriang.inovasi.daerah.master.constant.TOKEN_PREFIX
import id.co.sangkuriang.inovasi.daerah.master.constant.VALIDATOR_MSG_NOT_FOUND
import id.co.sangkuriang.inovasi.daerah.master.constant.*
import id.co.sangkuriang.inovasi.daerah.master.helpers.RequestHelpers
import id.co.sangkuriang.inovasi.daerah.master.model.response.ReturnData
import id.co.sangkuriang.inovasi.daerah.master.pojo.Users
import id.co.sangkuriang.inovasi.daerah.master.utility.getFullUrl
import id.co.sangkuriang.inovasi.daerah.master.utility.getPathUrl
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.web.util.ContentCachingRequestWrapper
import javax.servlet.Filter
......@@ -35,19 +33,15 @@ class TokenInterceptor : Filter {
// If header doesn't contain Bearer or is null will return nothing and exit
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
responseException(res, "Sorry, your provided token information not exists")
responseException(res, "Token $VALIDATOR_MSG_REQUIRED")
return
}
var authentication: UsernamePasswordAuthenticationToken? = null
var successAuth = true
try {
authentication = getAuthentication(req)
if (authentication == null) {
responseException(res, "User $VALIDATOR_MSG_NOT_FOUND")
}
} catch (e: JWTDecodeException) {
successAuth = false
responseException(res, e.message.toString())
......@@ -60,6 +54,9 @@ class TokenInterceptor : Filter {
} catch (e: IllegalArgumentException) {
successAuth = false
responseException(res, e.message.toString())
} catch (e: Exception) {
successAuth = false
responseException(res, e.message.toString())
}
SecurityContextHolder.getContext().authentication = authentication
......@@ -88,34 +85,56 @@ class TokenInterceptor : Filter {
JWTVerificationException::class,
IllegalArgumentException::class
)
private fun getAuthentication(request: HttpServletRequest): UsernamePasswordAuthenticationToken? {
val token = request.getHeader(HEADER_STRING)
if (token != null) {
// parse jwt token from request and validate it internal authentication
val jwt =
JWT.require(Algorithm.HMAC512(SECRET.toByteArray())).build().verify(token.replace(TOKEN_PREFIX, ""))
return if (jwt.subject != null) { // return principal username
val pathUrl = getPathUrl(request)
val audience = jwt.audience?.get(0)
println("pathUrl => $audience - ${request.method} - $pathUrl")
if (audience == "user") {
val tokenParse = token + System.currentTimeMillis()
JWT.require(Algorithm.HMAC512(SECRET.toByteArray())).build()
.verify(tokenParse.replace(TOKEN_PREFIX, ""))
try {
val token = request.getHeader(HEADER_STRING)
val reqAuthDetail: ReturnData =
RequestHelpers.authDetail(AUTH_URL, token) ?: throw Exception("User $VALIDATOR_MSG_NOT_FOUND")
reqAuthDetail.success?.let {
if (!it) {
throw Exception(reqAuthDetail.message)
}
}
val objectMapper = ObjectMapper()
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
val users: Users =
objectMapper.readValue(objectMapper.writeValueAsString(reqAuthDetail.data), Users::class.java)
var audience = "user-admin"
if (users.roleId == ROLE_USER_ID) {
audience = "user"
}
var isAllowed = false
AUDIENCE_FILTER_PATH[audience]?.forEach lambda@{
if (it.contains("/*")) {
if (getPathUrl(request).contains(it.replaceFirst("/", "").replace("/*", ""))) {
isAllowed = true
return@lambda
}
} else {
if (getFullUrl(request).contains(it)) {
isAllowed = true
return@lambda
}
}
}
return if (isAllowed) {
UsernamePasswordAuthenticationToken(
jwt.subject,
ObjectMapper().writeValueAsString(users),
audience,
ArrayList<GrantedAuthority>()
arrayListOf()
)
} else {
null
throw Exception("User $VALIDATOR_MSG_NOT_HAVE_ACCESS")
}
} catch (e: Exception) {
e.printStackTrace()
throw e
}
return null
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment