Skip to content

Instantly share code, notes, and snippets.

@amrfarid140
Created January 23, 2020 12:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amrfarid140/3738bf4149a15dcd8a4ba9a9d8322334 to your computer and use it in GitHub Desktop.
Save amrfarid140/3738bf4149a15dcd8a4ba9a9d8322334 to your computer and use it in GitHub Desktop.
Example Token Manager
package me.amryousef.auth
import com.auth0.jwt.JWT
import com.auth0.jwt.JWTVerifier
import com.auth0.jwt.algorithms.Algorithm
import com.auth0.jwt.interfaces.Payload
import io.ktor.auth.Principal
import me.amryousef.model.TokenType
import me.amryousef.model.User
import me.amryousef.usecase.GetUserByIdUseCase
import java.util.*
import java.util.concurrent.TimeUnit
class JwtTokenManager(private val getUserByIdUseCase: GetUserByIdUseCase) {
private companion object {
private const val secret = "super-secret-stuff"
private const val issuer = "amryousef"
private val refreshTokenValidityInMs = TimeUnit.DAYS.toMillis(7)
private val accessTokenValidityInMs = TimeUnit.HOURS.toMillis(8)
private val algorithm = Algorithm.HMAC512(secret)
private const val ID_CLAIM_KEY = "id"
private const val ROLE_CLAIM_KEY = "role"
private const val AUTHENTICATION_SUBJECT = "Authentication"
private const val REFRESH_SUBJECT = "Refresh"
}
val verifier: JWTVerifier = JWT.require(algorithm).withIssuer(issuer).build()
fun createToken(user: User) =
TokenResult(
accessToken = JWT.create()
.withSubject(AUTHENTICATION_SUBJECT)
.withIssuer(issuer)
.withClaim(ID_CLAIM_KEY, user.id)
.withClaim(ROLE_CLAIM_KEY, user.roles.map { it::class.java.simpleName }.joinToString(", "))
.withExpiresAt(getExpiration(accessTokenValidityInMs))
.sign(algorithm),
refreshToken = JWT.create()
.withSubject(REFRESH_SUBJECT)
.withIssuer(issuer)
.withClaim(ID_CLAIM_KEY, user.id)
.withExpiresAt(getExpiration(refreshTokenValidityInMs))
.sign(algorithm)
)
fun isValidToken(token: Payload): TokenValidity {
if (token.expiresAt.before(Date())) {
return TokenValidity.NotValid
}
return token.claims["id"]?.asInt()?.let {
TokenValidity.Valid(
getUserByIdUseCase.execute(it),
token.subject.toTokenType()
)
} ?: TokenValidity.NotValid
}
@Throws(IllegalArgumentException::class)
private fun String.toTokenType() = when (this) {
AUTHENTICATION_SUBJECT -> TokenType.ACCESS
REFRESH_SUBJECT -> TokenType.REFRESH
else -> throw IllegalArgumentException()
}
private fun getExpiration(validityInMs: Long) = Date(System.currentTimeMillis() + validityInMs)
data class TokenResult(val accessToken: String, val refreshToken: String)
sealed class TokenValidity {
data class Valid(
val user: User,
val tokenType: TokenType
) : TokenValidity(), Principal
object NotValid : TokenValidity()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment