diff --git a/oauth2-server-jwt/pom.xml b/oauth2-server-jwt/pom.xml new file mode 100644 index 0000000..9ccd3bd --- /dev/null +++ b/oauth2-server-jwt/pom.xml @@ -0,0 +1,27 @@ + + + + kotlin-oauth2-server + nl.myndocs + 0.3.2-SNAPSHOT + + 4.0.0 + + oauth2-server-jwt + + + + nl.myndocs + oauth2-server-core + ${project.version} + provided + + + com.auth0 + java-jwt + 3.5.0 + + + \ No newline at end of file diff --git a/oauth2-server-jwt/src/main/java/nl/myndocs/convert/DefaultJwtBuilder.kt b/oauth2-server-jwt/src/main/java/nl/myndocs/convert/DefaultJwtBuilder.kt new file mode 100644 index 0000000..2b44c1e --- /dev/null +++ b/oauth2-server-jwt/src/main/java/nl/myndocs/convert/DefaultJwtBuilder.kt @@ -0,0 +1,20 @@ +package nl.myndocs.convert + +import com.auth0.jwt.JWT +import java.time.Instant +import java.util.* + +object DefaultJwtBuilder : JwtBuilder { + override fun buildJwt(username: String?, clientId: String, requestedScopes: Set, expiresInSeconds: Long) = + JWT.create() + .withIssuedAt(Date.from(Instant.now())) + .withExpiresAt( + Date.from( + Instant.now() + .plusSeconds(expiresInSeconds) + ) + ) + .withClaim("client_id", clientId) + .withArrayClaim("scopes", requestedScopes.toTypedArray()) + .let { withBuilder -> if (username != null) withBuilder.withClaim("username", username) else withBuilder } +} \ No newline at end of file diff --git a/oauth2-server-jwt/src/main/java/nl/myndocs/convert/JwtAccessTokenConverter.kt b/oauth2-server-jwt/src/main/java/nl/myndocs/convert/JwtAccessTokenConverter.kt new file mode 100644 index 0000000..a794724 --- /dev/null +++ b/oauth2-server-jwt/src/main/java/nl/myndocs/convert/JwtAccessTokenConverter.kt @@ -0,0 +1,32 @@ +package nl.myndocs.convert + +import com.auth0.jwt.algorithms.Algorithm +import nl.myndocs.oauth2.token.AccessToken +import nl.myndocs.oauth2.token.RefreshToken +import nl.myndocs.oauth2.token.converter.AccessTokenConverter +import java.time.Instant + +class JwtAccessTokenConverter( + private val algorithm: Algorithm, + private val accessTokenExpireInSeconds: Int = 3600, + private val jwtBuilder: JwtBuilder = DefaultJwtBuilder +) : AccessTokenConverter { + override fun convertToToken(username: String?, clientId: String, requestedScopes: Set, refreshToken: RefreshToken?): AccessToken { + val jwtBuilder = jwtBuilder.buildJwt( + username, + clientId, + requestedScopes, + accessTokenExpireInSeconds.toLong() + ) + + return AccessToken( + jwtBuilder.sign(algorithm), + "bearer", + Instant.now().plusSeconds(accessTokenExpireInSeconds.toLong()), + username, + clientId, + requestedScopes, + refreshToken + ) + } +} \ No newline at end of file diff --git a/oauth2-server-jwt/src/main/java/nl/myndocs/convert/JwtBuilder.kt b/oauth2-server-jwt/src/main/java/nl/myndocs/convert/JwtBuilder.kt new file mode 100644 index 0000000..800b09b --- /dev/null +++ b/oauth2-server-jwt/src/main/java/nl/myndocs/convert/JwtBuilder.kt @@ -0,0 +1,7 @@ +package nl.myndocs.convert + +import com.auth0.jwt.JWTCreator + +interface JwtBuilder { + fun buildJwt(username: String?, clientId: String, requestedScopes: Set, expiresInSeconds: Long): JWTCreator.Builder +} \ No newline at end of file diff --git a/oauth2-server-jwt/src/main/java/nl/myndocs/convert/JwtRefreshTokenConverter.kt b/oauth2-server-jwt/src/main/java/nl/myndocs/convert/JwtRefreshTokenConverter.kt new file mode 100644 index 0000000..e633fb8 --- /dev/null +++ b/oauth2-server-jwt/src/main/java/nl/myndocs/convert/JwtRefreshTokenConverter.kt @@ -0,0 +1,29 @@ +package nl.myndocs.convert + +import com.auth0.jwt.algorithms.Algorithm +import nl.myndocs.oauth2.token.RefreshToken +import nl.myndocs.oauth2.token.converter.RefreshTokenConverter +import java.time.Instant + +class JwtRefreshTokenConverter( + private val algorithm: Algorithm, + private val refreshTokenExpireInSeconds: Int = 86400, + private val jwtBuilder: JwtBuilder = DefaultJwtBuilder +) : RefreshTokenConverter { + override fun convertToToken(username: String?, clientId: String, requestedScopes: Set): RefreshToken { + val jwtBuilder = jwtBuilder.buildJwt( + username, + clientId, + requestedScopes, + refreshTokenExpireInSeconds.toLong() + ) + + return RefreshToken( + jwtBuilder.sign(algorithm), + Instant.now().plusSeconds(refreshTokenExpireInSeconds.toLong()), + username, + clientId, + requestedScopes + ) + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index d3bd6c0..61c237b 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,7 @@ oauth2-server-javalin oauth2-server-sparkjava oauth2-server-http4k + oauth2-server-jwt