From 60f25e15087fca70fe90bc158c8baddaa0410fa1 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Mon, 9 Sep 2024 11:28:46 +0300 Subject: [PATCH 01/16] Creating new Authentication jwt --- build.gradle.kts | 5 +++++ .../academy/filters/AuthenticationFilter.kt | 15 +++++++++++++ .../academy/resource/AutenticationResourse.kt | 6 +++++ .../hibob/academy/service/SessionService.kt | 22 +++++++++++++++++++ .../kotlin/com/hibob/jwt/jwtClassExercise.kt | 2 ++ 5 files changed, 50 insertions(+) create mode 100644 src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt create mode 100644 src/main/kotlin/com/hibob/academy/resource/AutenticationResourse.kt create mode 100644 src/main/kotlin/com/hibob/academy/service/SessionService.kt create mode 100644 src/main/kotlin/com/hibob/jwt/jwtClassExercise.kt diff --git a/build.gradle.kts b/build.gradle.kts index ac5dec817..fd312ece3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -35,6 +35,11 @@ dependencies { implementation("org.jooq:jooq:3.16.9") implementation("org.slf4j:slf4j-api") + //JWT + implementation("io.jsonwebtoken:jjwt-api:0.11.5") + runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5") + runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.5") + implementation("org.postgresql:postgresql") testImplementation("org.junit.jupiter:junit-jupiter") diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt new file mode 100644 index 000000000..48f226774 --- /dev/null +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -0,0 +1,15 @@ +package com.hibob.academy.filters +import jakarta.ws.rs.container.ContainerRequestContext +import jakarta.ws.rs.container.ContainerRequestFilter +import org.springframework.stereotype.Component + + +@Component +class AuthenticationFilter : ContainerRequestFilter { + override fun filter(requestContext: ContainerRequestContext?) { + if (requestContext.uriInfo.path == "To be implement") return + + //here we need to verify the JWT token + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/hibob/academy/resource/AutenticationResourse.kt b/src/main/kotlin/com/hibob/academy/resource/AutenticationResourse.kt new file mode 100644 index 000000000..ae08d80a4 --- /dev/null +++ b/src/main/kotlin/com/hibob/academy/resource/AutenticationResourse.kt @@ -0,0 +1,6 @@ +package com.hibob.academy.resource + +import jakarta.ws.rs.Path + + +@Path("/jwt.io") diff --git a/src/main/kotlin/com/hibob/academy/service/SessionService.kt b/src/main/kotlin/com/hibob/academy/service/SessionService.kt new file mode 100644 index 000000000..e02514c42 --- /dev/null +++ b/src/main/kotlin/com/hibob/academy/service/SessionService.kt @@ -0,0 +1,22 @@ +package com.hibob.academy.service +import io.jsonwebtoken.Jwts +import io.jsonwebtoken.SignatureAlgorithm +import org.springframework.stereotype.Component +import java.util.Date +import javax.xml.crypto.dsig.SignatureMethod.HMAC_SHA256 + +@Component +class SessionService { + private val secretKey = "secret" + + fun createJWTToken(): String { + return Jwts.builder() + .setHeaderParam("typ", "JWT") + .claim("email", "hibob@hibob.academy") + .claim("username", "ronAzar") + .claim("isAdmin", true) + .setExpiration(Date(Date().time + 24 * 60 * 60 * 1000)) + .signWith(SignatureAlgorithm.HS512, HMAC_SHA256) + .compact() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/hibob/jwt/jwtClassExercise.kt b/src/main/kotlin/com/hibob/jwt/jwtClassExercise.kt new file mode 100644 index 000000000..5b3630c2d --- /dev/null +++ b/src/main/kotlin/com/hibob/jwt/jwtClassExercise.kt @@ -0,0 +1,2 @@ +package com.hibob.jwt + From bc174181ee6e5e7c5a4c087cf44fc1fdba1c7d30 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Mon, 9 Sep 2024 11:29:13 +0300 Subject: [PATCH 02/16] Creating new Authentication jwt --- .../{AutenticationResourse.kt => AuthenticationResourse.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/kotlin/com/hibob/academy/resource/{AutenticationResourse.kt => AuthenticationResourse.kt} (100%) diff --git a/src/main/kotlin/com/hibob/academy/resource/AutenticationResourse.kt b/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt similarity index 100% rename from src/main/kotlin/com/hibob/academy/resource/AutenticationResourse.kt rename to src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt From 49a0890e0eda03c3bd7a6fc39fabe43c13584d18 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Mon, 9 Sep 2024 12:29:22 +0300 Subject: [PATCH 03/16] Few changes --- .../academy/filters/AuthenticationFilter.kt | 2 +- .../resource/AuthenticationResourse.kt | 21 ++++++++++++++++++- .../hibob/academy/service/SessionService.kt | 13 ++++++------ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index 48f226774..0666311a2 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -6,7 +6,7 @@ import org.springframework.stereotype.Component @Component class AuthenticationFilter : ContainerRequestFilter { - override fun filter(requestContext: ContainerRequestContext?) { + override fun filter(requestContext: ContainerRequestContext) { if (requestContext.uriInfo.path == "To be implement") return //here we need to verify the JWT token diff --git a/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt b/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt index ae08d80a4..49862f6cd 100644 --- a/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt +++ b/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt @@ -1,6 +1,25 @@ package com.hibob.academy.resource +import jakarta.ws.rs.POST import jakarta.ws.rs.Path +import jakarta.ws.rs.core.Response +import com.hibob.academy.service.SessionService +import jakarta.ws.rs.Consumes +import jakarta.ws.rs.Produces +import jakarta.ws.rs.core.MediaType +import org.springframework.stereotype.Controller +data class User(val email: String,val name: String, val isAdmin: Boolean) -@Path("/jwt.io") +@Controller +@Path("/users") +class AuthenticationResourse(private val service: SessionService) { + @Path("/Login") + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + fun addNewUser(newUser: User): Response { + val session = SessionService() + val afterJwt = session.createJWTToken(newUser) // Assuming createJWTToken returns a JWT + return Response.status(Response.Status.CREATED).entity(afterJwt).build() } +} \ No newline at end of file diff --git a/src/main/kotlin/com/hibob/academy/service/SessionService.kt b/src/main/kotlin/com/hibob/academy/service/SessionService.kt index e02514c42..3f4a4d9d1 100644 --- a/src/main/kotlin/com/hibob/academy/service/SessionService.kt +++ b/src/main/kotlin/com/hibob/academy/service/SessionService.kt @@ -4,19 +4,20 @@ import io.jsonwebtoken.SignatureAlgorithm import org.springframework.stereotype.Component import java.util.Date import javax.xml.crypto.dsig.SignatureMethod.HMAC_SHA256 +import com.hibob.academy.resource.User @Component class SessionService { - private val secretKey = "secret" + private val secretKey = "secretsdfghjkjhghjhghjhjkjhghjkjhgfghjhgfcvhj" - fun createJWTToken(): String { + fun createJWTToken(user: User): String { return Jwts.builder() .setHeaderParam("typ", "JWT") - .claim("email", "hibob@hibob.academy") - .claim("username", "ronAzar") - .claim("isAdmin", true) + .claim("email", user.email) + .claim("username", user.name) + .claim("isAdmin", user.isAdmin) .setExpiration(Date(Date().time + 24 * 60 * 60 * 1000)) - .signWith(SignatureAlgorithm.HS512, HMAC_SHA256) + .signWith(SignatureAlgorithm.HS512, secretKey) .compact() } } \ No newline at end of file From 58da6036ffd27135b7d38e4d3bd13a8c828b8e42 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Mon, 9 Sep 2024 13:33:40 +0300 Subject: [PATCH 04/16] Need to add string as key at SessionService --- .../kotlin/com/hibob/academy/service/SessionService.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/hibob/academy/service/SessionService.kt b/src/main/kotlin/com/hibob/academy/service/SessionService.kt index 3f4a4d9d1..3a04fda65 100644 --- a/src/main/kotlin/com/hibob/academy/service/SessionService.kt +++ b/src/main/kotlin/com/hibob/academy/service/SessionService.kt @@ -3,12 +3,13 @@ import io.jsonwebtoken.Jwts import io.jsonwebtoken.SignatureAlgorithm import org.springframework.stereotype.Component import java.util.Date -import javax.xml.crypto.dsig.SignatureMethod.HMAC_SHA256 +import io.jsonwebtoken.security.Keys +import java.security.Key import com.hibob.academy.resource.User @Component class SessionService { - private val secretKey = "secretsdfghjkjhghjhghjhjkjhghjkjhgfghjhgfcvhj" + private val secretKey: Key = Keys.secretKeyFor(SignatureAlgorithm.HS512) fun createJWTToken(user: User): String { return Jwts.builder() @@ -17,7 +18,7 @@ class SessionService { .claim("username", user.name) .claim("isAdmin", user.isAdmin) .setExpiration(Date(Date().time + 24 * 60 * 60 * 1000)) - .signWith(SignatureAlgorithm.HS512, secretKey) + .signWith(secretKey) .compact() } } \ No newline at end of file From 06d414d9ede72b5dbeac8d1ca4917cbe717a9dff Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Mon, 9 Sep 2024 13:46:34 +0300 Subject: [PATCH 05/16] Need to add string as key at SessionService --- src/main/kotlin/com/hibob/academy/service/SessionService.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/com/hibob/academy/service/SessionService.kt b/src/main/kotlin/com/hibob/academy/service/SessionService.kt index 3a04fda65..7014988ae 100644 --- a/src/main/kotlin/com/hibob/academy/service/SessionService.kt +++ b/src/main/kotlin/com/hibob/academy/service/SessionService.kt @@ -3,13 +3,11 @@ import io.jsonwebtoken.Jwts import io.jsonwebtoken.SignatureAlgorithm import org.springframework.stereotype.Component import java.util.Date -import io.jsonwebtoken.security.Keys -import java.security.Key import com.hibob.academy.resource.User @Component class SessionService { - private val secretKey: Key = Keys.secretKeyFor(SignatureAlgorithm.HS512) + private val secretKey = "secretsdfghjkjhghjhghjhjkjhghjkjhgfghjhg21243e5wredwedywe5te4343tewqawsertyusdfghjkerftgyhujdfgxdewefcvhj" fun createJWTToken(user: User): String { return Jwts.builder() @@ -18,7 +16,7 @@ class SessionService { .claim("username", user.name) .claim("isAdmin", user.isAdmin) .setExpiration(Date(Date().time + 24 * 60 * 60 * 1000)) - .signWith(secretKey) + .signWith(SignatureAlgorithm.HS512, secretKey) .compact() } } \ No newline at end of file From 76338c4c852c932aba87bec3422ca283a0afe843 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Mon, 9 Sep 2024 15:14:40 +0300 Subject: [PATCH 06/16] Not done yet --- .../hibob/academy/filters/AuthenticationFilter.kt | 14 +++++++++++++- .../academy/resource/AuthenticationResourse.kt | 2 +- .../com/hibob/academy/service/SessionService.kt | 5 ++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index 0666311a2..2f54b4ce0 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -1,7 +1,11 @@ package com.hibob.academy.filters +import io.jsonwebtoken.Claims +import io.jsonwebtoken.Jws +import io.jsonwebtoken.Jwts import jakarta.ws.rs.container.ContainerRequestContext import jakarta.ws.rs.container.ContainerRequestFilter import org.springframework.stereotype.Component +import com.hibob.academy.service.SessionService @Component @@ -10,6 +14,14 @@ class AuthenticationFilter : ContainerRequestFilter { if (requestContext.uriInfo.path == "To be implement") return //here we need to verify the JWT token - } + } + fun verify(cookie: String?): Jws? = + cookie?.let { + try { + Jwts.parser().setSigningKey(SessionService.secretKey).parseClaimsJws(it) + } catch (ex: Exception) { + null + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt b/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt index 49862f6cd..dce103bfe 100644 --- a/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt +++ b/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt @@ -12,11 +12,11 @@ import org.springframework.stereotype.Controller data class User(val email: String,val name: String, val isAdmin: Boolean) @Controller +@Produces(MediaType.APPLICATION_JSON) @Path("/users") class AuthenticationResourse(private val service: SessionService) { @Path("/Login") @POST - @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) fun addNewUser(newUser: User): Response { val session = SessionService() diff --git a/src/main/kotlin/com/hibob/academy/service/SessionService.kt b/src/main/kotlin/com/hibob/academy/service/SessionService.kt index 7014988ae..370695697 100644 --- a/src/main/kotlin/com/hibob/academy/service/SessionService.kt +++ b/src/main/kotlin/com/hibob/academy/service/SessionService.kt @@ -7,7 +7,10 @@ import com.hibob.academy.resource.User @Component class SessionService { - private val secretKey = "secretsdfghjkjhghjhghjhjkjhghjkjhgfghjhg21243e5wredwedywe5te4343tewqawsertyusdfghjkerftgyhujdfgxdewefcvhj" + companion object { + val secretKey = + "secretsdfghjkjhghjhghjhjkjhghjkjhgfghjhg21243e5wredwedywe5te4343tewqawsertyusdfghjkerftgyhujdfgxdewefcvhj" + } fun createJWTToken(user: User): String { return Jwts.builder() From ee166a47b8ec20da210597ce8096422ee5840a35 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Mon, 9 Sep 2024 17:35:33 +0300 Subject: [PATCH 07/16] Completed --- .../academy/filters/AuthenticationFilter.kt | 18 ++++++++++++---- .../resource/AuthenticationResourse.kt | 21 ++++++++++++++----- .../hibob/academy/service/SessionService.kt | 2 +- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index 2f54b4ce0..50ff5a98f 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -5,21 +5,31 @@ import io.jsonwebtoken.Jwts import jakarta.ws.rs.container.ContainerRequestContext import jakarta.ws.rs.container.ContainerRequestFilter import org.springframework.stereotype.Component -import com.hibob.academy.service.SessionService +import com.hibob.academy.service.SessionService.Companion.secretKey +import jakarta.ws.rs.core.Response +import jakarta.ws.rs.ext.Provider @Component +@Provider class AuthenticationFilter : ContainerRequestFilter { override fun filter(requestContext: ContainerRequestContext) { - if (requestContext.uriInfo.path == "To be implement") return + if (requestContext.uriInfo.path == "jwt/users/login") return - //here we need to verify the JWT token + // Verify the JWT token from the cookie + val cookie = requestContext.cookies + val jwtClaims = verify(cookie["ron_cookie_name"]?.value) + if (jwtClaims == null) { + requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Invalid or expired token").build()) + } } + private val jwtParser = Jwts.parser().setSigningKey(secretKey) + fun verify(cookie: String?): Jws? = cookie?.let { try { - Jwts.parser().setSigningKey(SessionService.secretKey).parseClaimsJws(it) + jwtParser.parseClaimsJws(it) } catch (ex: Exception) { null } diff --git a/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt b/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt index dce103bfe..9880e8bed 100644 --- a/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt +++ b/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt @@ -5,21 +5,32 @@ import jakarta.ws.rs.Path import jakarta.ws.rs.core.Response import com.hibob.academy.service.SessionService import jakarta.ws.rs.Consumes +import jakarta.ws.rs.GET import jakarta.ws.rs.Produces import jakarta.ws.rs.core.MediaType +import jakarta.ws.rs.core.NewCookie import org.springframework.stereotype.Controller data class User(val email: String,val name: String, val isAdmin: Boolean) @Controller @Produces(MediaType.APPLICATION_JSON) -@Path("/users") +@Path("/jwt/users") class AuthenticationResourse(private val service: SessionService) { - @Path("/Login") + + @Path("/login") @POST @Consumes(MediaType.APPLICATION_JSON) fun addNewUser(newUser: User): Response { - val session = SessionService() - val afterJwt = session.createJWTToken(newUser) // Assuming createJWTToken returns a JWT - return Response.status(Response.Status.CREATED).entity(afterJwt).build() } + val tokenJwt = service.createJWTToken(newUser) // Assuming createJWTToken returns a JWT + val cookie = NewCookie.Builder("ron_cookie_name").value(tokenJwt).build()//Creating new cookie + return Response.ok().cookie(cookie).build() + } + + @Path("/getAllUsers") + @GET + @Consumes(MediaType.APPLICATION_JSON) + fun getAllUsers(): Response { + return Response.ok().entity("Yessssss").build() + } } \ No newline at end of file diff --git a/src/main/kotlin/com/hibob/academy/service/SessionService.kt b/src/main/kotlin/com/hibob/academy/service/SessionService.kt index 370695697..a6eb2a663 100644 --- a/src/main/kotlin/com/hibob/academy/service/SessionService.kt +++ b/src/main/kotlin/com/hibob/academy/service/SessionService.kt @@ -8,7 +8,7 @@ import com.hibob.academy.resource.User @Component class SessionService { companion object { - val secretKey = + const val secretKey = "secretsdfghjkjhghjhghjhjkjhghjkjhgfghjhg21243e5wredwedywe5te4343tewqawsertyusdfghjkerftgyhujdfgxdewefcvhj" } From 15a61414ffbd6a297d8823aa1f157e31f2640792 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Mon, 9 Sep 2024 18:21:12 +0300 Subject: [PATCH 08/16] Make Secret key const with capital letters --- .../kotlin/com/hibob/academy/filters/AuthenticationFilter.kt | 4 ++-- src/main/kotlin/com/hibob/academy/service/SessionService.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index 50ff5a98f..977253095 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -5,7 +5,7 @@ import io.jsonwebtoken.Jwts import jakarta.ws.rs.container.ContainerRequestContext import jakarta.ws.rs.container.ContainerRequestFilter import org.springframework.stereotype.Component -import com.hibob.academy.service.SessionService.Companion.secretKey +import com.hibob.academy.service.SessionService.Companion.SECRET_KEY import jakarta.ws.rs.core.Response import jakarta.ws.rs.ext.Provider @@ -24,7 +24,7 @@ class AuthenticationFilter : ContainerRequestFilter { requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Invalid or expired token").build()) } } - private val jwtParser = Jwts.parser().setSigningKey(secretKey) + private val jwtParser = Jwts.parser().setSigningKey(SECRET_KEY) fun verify(cookie: String?): Jws? = cookie?.let { diff --git a/src/main/kotlin/com/hibob/academy/service/SessionService.kt b/src/main/kotlin/com/hibob/academy/service/SessionService.kt index a6eb2a663..fe9203d03 100644 --- a/src/main/kotlin/com/hibob/academy/service/SessionService.kt +++ b/src/main/kotlin/com/hibob/academy/service/SessionService.kt @@ -8,7 +8,7 @@ import com.hibob.academy.resource.User @Component class SessionService { companion object { - const val secretKey = + const val SECRET_KEY = "secretsdfghjkjhghjhghjhjkjhghjkjhgfghjhg21243e5wredwedywe5te4343tewqawsertyusdfghjkerftgyhujdfgxdewefcvhj" } @@ -19,7 +19,7 @@ class SessionService { .claim("username", user.name) .claim("isAdmin", user.isAdmin) .setExpiration(Date(Date().time + 24 * 60 * 60 * 1000)) - .signWith(SignatureAlgorithm.HS512, secretKey) + .signWith(SignatureAlgorithm.HS512, SECRET_KEY) .compact() } } \ No newline at end of file From f140a7181f3310843d21e2b6339d20ef0ddd9f1c Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Wed, 11 Sep 2024 09:36:02 +0300 Subject: [PATCH 09/16] DUMMY --- .../kotlin/com/hibob/academy/filters/AuthenticationFilter.kt | 3 ++- src/main/kotlin/com/hibob/academy/service/SessionService.kt | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index 977253095..9121b6308 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -13,8 +13,9 @@ import jakarta.ws.rs.ext.Provider @Component @Provider class AuthenticationFilter : ContainerRequestFilter { + override fun filter(requestContext: ContainerRequestContext) { - if (requestContext.uriInfo.path == "jwt/users/login") return + if (requestContext.uriInfo.path == JWT_TOKEN_URL) return // Verify the JWT token from the cookie val cookie = requestContext.cookies diff --git a/src/main/kotlin/com/hibob/academy/service/SessionService.kt b/src/main/kotlin/com/hibob/academy/service/SessionService.kt index fe9203d03..088e53299 100644 --- a/src/main/kotlin/com/hibob/academy/service/SessionService.kt +++ b/src/main/kotlin/com/hibob/academy/service/SessionService.kt @@ -11,6 +11,9 @@ class SessionService { const val SECRET_KEY = "secretsdfghjkjhghjhghjhjkjhghjkjhgfghjhg21243e5wredwedywe5te4343tewqawsertyusdfghjkerftgyhujdfgxdewefcvhj" } + companion object{ + const val JWT_TOKEN_URL = "jwt/users/login" + } fun createJWTToken(user: User): String { return Jwts.builder() From 59625f3adab0e72f21a22006443634b0ffe0fa67 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Thu, 12 Sep 2024 09:22:26 +0300 Subject: [PATCH 10/16] consider making "jwt/users/login" a const --- .../com/hibob/academy/filters/AuthenticationFilter.kt | 8 ++++++-- .../kotlin/com/hibob/academy/service/SessionService.kt | 3 --- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index 9121b6308..f9cdf9d53 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -13,13 +13,17 @@ import jakarta.ws.rs.ext.Provider @Component @Provider class AuthenticationFilter : ContainerRequestFilter { + companion object { + private const val LOGIN_PATH = "/jwt/users/login" + private const val COOKIE_NAME = "ron_cookie_name" // Replace with actual cookie name + } override fun filter(requestContext: ContainerRequestContext) { - if (requestContext.uriInfo.path == JWT_TOKEN_URL) return + if (requestContext.uriInfo.path == LOGIN_PATH) return // Verify the JWT token from the cookie val cookie = requestContext.cookies - val jwtClaims = verify(cookie["ron_cookie_name"]?.value) + val jwtClaims = verify(cookie[COOKIE_NAME]?.value) if (jwtClaims == null) { requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Invalid or expired token").build()) diff --git a/src/main/kotlin/com/hibob/academy/service/SessionService.kt b/src/main/kotlin/com/hibob/academy/service/SessionService.kt index 088e53299..fe9203d03 100644 --- a/src/main/kotlin/com/hibob/academy/service/SessionService.kt +++ b/src/main/kotlin/com/hibob/academy/service/SessionService.kt @@ -11,9 +11,6 @@ class SessionService { const val SECRET_KEY = "secretsdfghjkjhghjhghjhjkjhghjkjhgfghjhg21243e5wredwedywe5te4343tewqawsertyusdfghjkerftgyhujdfgxdewefcvhj" } - companion object{ - const val JWT_TOKEN_URL = "jwt/users/login" - } fun createJWTToken(user: User): String { return Jwts.builder() From 14beceb8d596f59b512aa8d1442154acdaf50ae1 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Thu, 12 Sep 2024 09:29:08 +0300 Subject: [PATCH 11/16] handle this in the catch --- .../com/hibob/academy/filters/AuthenticationFilter.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index f9cdf9d53..cebdc88b9 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -22,10 +22,12 @@ class AuthenticationFilter : ContainerRequestFilter { if (requestContext.uriInfo.path == LOGIN_PATH) return // Verify the JWT token from the cookie - val cookie = requestContext.cookies - val jwtClaims = verify(cookie[COOKIE_NAME]?.value) + val cookie = requestContext.cookies[COOKIE_NAME]?.value - if (jwtClaims == null) { + try { + val jwtClaims = verify(cookie) ?: throw Exception("Invalid or expired token") // If claims are null, throw an exception + } catch (e: Exception) { + // Catch any exceptions (including null or verification failure) and abort with UNAUTHORIZED status requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Invalid or expired token").build()) } } From f6c550978336fd47035c18c67327495e3f93061d Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Thu, 12 Sep 2024 09:41:48 +0300 Subject: [PATCH 12/16] handle this in the catch --- .../kotlin/com/hibob/academy/filters/AuthenticationFilter.kt | 2 +- .../com/hibob/academy/resource/AuthenticationResourse.kt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index cebdc88b9..fdcc4a228 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -15,7 +15,7 @@ import jakarta.ws.rs.ext.Provider class AuthenticationFilter : ContainerRequestFilter { companion object { private const val LOGIN_PATH = "/jwt/users/login" - private const val COOKIE_NAME = "ron_cookie_name" // Replace with actual cookie name + const val COOKIE_NAME = "ron_cookie_name" // Replace with actual cookie name } override fun filter(requestContext: ContainerRequestContext) { diff --git a/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt b/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt index 9880e8bed..7f9af9803 100644 --- a/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt +++ b/src/main/kotlin/com/hibob/academy/resource/AuthenticationResourse.kt @@ -10,6 +10,7 @@ import jakarta.ws.rs.Produces import jakarta.ws.rs.core.MediaType import jakarta.ws.rs.core.NewCookie import org.springframework.stereotype.Controller +import com.hibob.academy.filters.AuthenticationFilter.Companion.COOKIE_NAME data class User(val email: String,val name: String, val isAdmin: Boolean) @@ -23,7 +24,7 @@ class AuthenticationResourse(private val service: SessionService) { @Consumes(MediaType.APPLICATION_JSON) fun addNewUser(newUser: User): Response { val tokenJwt = service.createJWTToken(newUser) // Assuming createJWTToken returns a JWT - val cookie = NewCookie.Builder("ron_cookie_name").value(tokenJwt).build()//Creating new cookie + val cookie = NewCookie.Builder(COOKIE_NAME).value(tokenJwt).build()//Creating new cookie return Response.ok().cookie(cookie).build() } From e2ae958d6247a7cb05af163f8f27af3d7fb86361 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Thu, 12 Sep 2024 10:13:02 +0300 Subject: [PATCH 13/16] handle this in the catch --- .../kotlin/com/hibob/academy/filters/AuthenticationFilter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index fdcc4a228..fe15e91b9 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -14,7 +14,7 @@ import jakarta.ws.rs.ext.Provider @Provider class AuthenticationFilter : ContainerRequestFilter { companion object { - private const val LOGIN_PATH = "/jwt/users/login" + private const val LOGIN_PATH = "jwt/users/login" const val COOKIE_NAME = "ron_cookie_name" // Replace with actual cookie name } From 189dcb9b0579616f2814553110b32b9c373a81c1 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Sun, 15 Sep 2024 11:56:52 +0300 Subject: [PATCH 14/16] you already have an exception being thrown in the verify method? no need to throw a new exception here. just handle the null case in the verify method --- .../kotlin/com/hibob/academy/filters/AuthenticationFilter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index fe15e91b9..2e6b41214 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -25,7 +25,7 @@ class AuthenticationFilter : ContainerRequestFilter { val cookie = requestContext.cookies[COOKIE_NAME]?.value try { - val jwtClaims = verify(cookie) ?: throw Exception("Invalid or expired token") // If claims are null, throw an exception + val jwtClaims = verify(cookie) // If claims are null, throw an exception } catch (e: Exception) { // Catch any exceptions (including null or verification failure) and abort with UNAUTHORIZED status requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Invalid or expired token").build()) From cf3055d8859898aaf2bbf855cea0a692679ad231 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Mon, 16 Sep 2024 18:51:11 +0300 Subject: [PATCH 15/16] Added authentication filter to validate JWT token from cookies and reject unauthenticated requests with 401 status. --- .../kotlin/com/hibob/academy/filters/AuthenticationFilter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index 2e6b41214..f9ce6a3ce 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -25,7 +25,7 @@ class AuthenticationFilter : ContainerRequestFilter { val cookie = requestContext.cookies[COOKIE_NAME]?.value try { - val jwtClaims = verify(cookie) // If claims are null, throw an exception + val jwtClaims = verify(cookie) ?: throw Exception("Invalid token") } catch (e: Exception) { // Catch any exceptions (including null or verification failure) and abort with UNAUTHORIZED status requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Invalid or expired token").build()) From 6353923b5f684d5f0df7e66a1280c2800e82fae5 Mon Sep 17 00:00:00 2001 From: Ron Azar Date: Tue, 17 Sep 2024 08:58:11 +0300 Subject: [PATCH 16/16] Refactored authentication filter to move cookie handling into verify method for cleaner separation of concerns. --- .../academy/filters/AuthenticationFilter.kt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt index f9ce6a3ce..24e28ea1e 100644 --- a/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt +++ b/src/main/kotlin/com/hibob/academy/filters/AuthenticationFilter.kt @@ -13,6 +13,7 @@ import jakarta.ws.rs.ext.Provider @Component @Provider class AuthenticationFilter : ContainerRequestFilter { + companion object { private const val LOGIN_PATH = "jwt/users/login" const val COOKIE_NAME = "ron_cookie_name" // Replace with actual cookie name @@ -21,24 +22,23 @@ class AuthenticationFilter : ContainerRequestFilter { override fun filter(requestContext: ContainerRequestContext) { if (requestContext.uriInfo.path == LOGIN_PATH) return - // Verify the JWT token from the cookie val cookie = requestContext.cookies[COOKIE_NAME]?.value - try { - val jwtClaims = verify(cookie) ?: throw Exception("Invalid token") - } catch (e: Exception) { - // Catch any exceptions (including null or verification failure) and abort with UNAUTHORIZED status + if (!verify(cookie)) { requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Invalid or expired token").build()) } } - private val jwtParser = Jwts.parser().setSigningKey(SECRET_KEY) - fun verify(cookie: String?): Jws? = - cookie?.let { + private val jwtParser = Jwts.parserBuilder().setSigningKey(SECRET_KEY).build() + + fun verify(cookie: String?): Boolean { + return cookie?.let { try { jwtParser.parseClaimsJws(it) + true } catch (ex: Exception) { - null + false } - } + } ?: false + } } \ No newline at end of file