Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for opaque token #310

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
FROM bellsoft/liberica-openjdk-alpine-musl:21.0.1-16 AS build
WORKDIR /usr/src/app
# cache dependencies
COPY ./gradlew ./
COPY ./gradle.properties ./
COPY ./settings.gradle.kts ./
COPY ./gradle ./gradle/
COPY ./buildSrc/src ./buildSrc/src/
COPY ./buildSrc/*.gradle.kts ./buildSrc/
COPY ./server/build.gradle.kts ./server/
COPY ./server/web/build.gradle.kts ./server/web/
COPY ./server/service/build.gradle.kts ./server/service/
COPY ./server/data/build.gradle.kts ./server/data/
COPY ./server/model/build.gradle.kts ./server/model/
COPY ./server/common/build.gradle.kts ./server/common/
COPY ./gradlew ./
COPY ./gradle.properties ./
COPY ./settings.gradle.kts ./
COPY ./gradle ./gradle/
COPY ./buildSrc/src ./buildSrc/src/
COPY ./buildSrc/*.gradle.kts ./buildSrc/
COPY ./server/client/build.gradle.kts ./server/client/
COPY ./server/common/build.gradle.kts ./server/common/
COPY ./server/data/build.gradle.kts ./server/data/
COPY ./server/model/build.gradle.kts ./server/model/
COPY ./server/operation/build.gradle.kts ./server/operation/
COPY ./server/service/build.gradle.kts ./server/service/
COPY ./server/web/build.gradle.kts ./server/web/
COPY ./server/build.gradle.kts ./server/
RUN ./gradlew
# build
COPY ./buildSrc ./buildSrc
Expand Down
4 changes: 0 additions & 4 deletions buildSrc/src/main/kotlin/testing-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ plugins {

dependencies {
testImplementation("org.springframework.boot:spring-boot-starter-test")
// kotlin related dependencies should move to kotlin-testing-conventions
testImplementation("io.mockk:mockk-jvm:1.13.10")
testImplementation("com.ninja-squad:springmockk:4.0.2")
testImplementation("io.kotest:kotest-assertions-core-jvm:5.8.1")
}

tasks.test {
Expand Down
1 change: 1 addition & 0 deletions client/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ plugins {
dependencies {
api(project(":server:operation"))
implementation("org.springframework.cloud:spring-cloud-starter-openfeign")
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@ package hu.bsstudio.bssweb.config
import org.springframework.cloud.openfeign.EnableFeignClients

@EnableFeignClients("hu.bsstudio.bssweb.**.client", defaultConfiguration = [DefaultFeignConfig::class])
class BssFeignConfig
class BssFeignConfig constructor() {
init {
println("BssFeignConfig")
}
Comment on lines +6 to +9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace println with a logging framework to avoid cluttering the console output and to provide more flexible logging capabilities.

- println("BssFeignConfig")
+ logger.info("BssFeignConfig initialized")

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
class BssFeignConfig constructor() {
init {
println("BssFeignConfig")
}
class BssFeignConfig constructor() {
init {
logger.info("BssFeignConfig initialized")
}

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package hu.bsstudio.bssweb.config

import feign.auth.BasicAuthRequestInterceptor
import org.springframework.beans.factory.annotation.Value
import org.springframework.cloud.openfeign.security.OAuth2AccessTokenInterceptor
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class DefaultFeignConfig(
@Value("\${bss.client.username}") val username: String,
@Value("\${bss.client.password}") val password: String,
) {
@Bean
fun interceptor() = BasicAuthRequestInterceptor(this.username, this.password)
class DefaultFeignConfig {
// @Bean
// fun interceptor(oauth: OAuth2AccessTokenInterceptor) = oauth
Comment on lines +8 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complete the implementation of OAuth2AccessTokenInterceptor to ensure proper authentication handling.

- //    @Bean
- //    fun interceptor(oauth: OAuth2AccessTokenInterceptor) = oauth
+    @Bean
+    fun interceptor(oauth: OAuth2AccessTokenInterceptor) = oauth

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
class DefaultFeignConfig {
// @Bean
// fun interceptor(oauth: OAuth2AccessTokenInterceptor) = oauth
class DefaultFeignConfig {
@Bean
fun interceptor(oauth: OAuth2AccessTokenInterceptor) = oauth

}
2 changes: 1 addition & 1 deletion docker-compose.metrics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ services:
ports:
- "127.0.0.1:9090:9090"
volumes:
- "./docker/prometheus.yml:/etc/prometheus/prometheus.yml"
- "./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml"
healthcheck:
test: wget --tries=1 --no-verbose -qO- http://localhost:9090/-/ready | grep -q "Prometheus Server is Ready."
start_period: 5s
Expand Down
8 changes: 5 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ services:
- postgres
environment:
bss.file-api.url: "http://mock-file-api:8080"
spring.security.user.password: "password"
spring.security.oauth2.resourceserver.opaquetoken.introspection-uri: "http://authelia"
spring.security.oauth2.resourceserver.opaquetoken.client-id: "client_id"
spring.security.oauth2.resourceserver.opaquetoken.client-secret: "client_secret"
spring.datasource.url: "jdbc:postgresql://postgres:5432/bss?currentSchema=private"
spring.datasource.username: "user"
spring.datasource.password: "password"
Expand All @@ -37,7 +39,7 @@ services:
timeout: 5s
retries: 3
mock-file-api:
image: "wiremock/wiremock:2.35.0"
image: "wiremock/wiremock:2.35.1-1"
ports:
- "127.0.0.1:8888:8080"
healthcheck:
Expand All @@ -47,4 +49,4 @@ services:
timeout: 5s
retries: 3
volumes:
- "./stubs:/home/wiremock/mappings"
- "./docker/stubs:/home/wiremock/mappings"
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package hu.bsstudio.bssweb

import hu.bsstudio.bssweb.config.BssFeignConfig
import hu.bsstudio.bssweb.event.repository.DetailedEventRepository
import hu.bsstudio.bssweb.eventvideo.repository.EventVideoRepository
import hu.bsstudio.bssweb.label.repository.LabelRepository
Expand All @@ -12,16 +11,21 @@ import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.TestPropertySource
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig

@SpringJUnitConfig(classes = [BssFeignConfig::class, DataConfig::class])
@SpringJUnitConfig(classes = [DataConfig::class])
@TestPropertySource(
properties = [
"bss.client.url=http://localhost:8080",
"bss.client.username=user",
"bss.client.password=password",
"spring.flyway.enabled=false",
"spring.datasource.url=jdbc:postgresql://localhost:5432/bss?currentSchema=private",
"spring.datasource.username=user",
"spring.datasource.password=password",
"spring.cloud.openfeign.oauth2.enabled=true",
"spring.cloud.openfeign.client.config.event.url=http://localhost:8080",
"spring.security.oauth2.client.provider.authelia.issuer-uri=issuer-uri",
"spring.security.oauth2.client.registration.bss.provider=authelia",
"spring.security.oauth2.client.registration.bss.client-id=client-id",
"spring.security.oauth2.client.registration.bss.client-secret=client-secret",
"spring.cloud.openfeign.oauth2.clientRegistrationId=bss",
],
)
open class IntegrationTest {
Expand Down
1 change: 1 addition & 0 deletions server/web/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
implementation(libs.springdocOpenapiStarterWebmvcUi)
implementation("org.springframework.data:spring-data-commons")
testImplementation("org.springframework.security:spring-security-test")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@ package hu.bsstudio.bssweb.security.config

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.Customizer
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.web.SecurityFilterChain

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
class SecurityConfig {
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
return http
.authorizeHttpRequests {
it.requestMatchers("/api/**").authenticated()
it
.requestMatchers("/api/**").authenticated()
.anyRequest().permitAll()
}
.httpBasic(Customizer.withDefaults())
.oauth2ResourceServer {
it.opaqueToken {
// load settings from Spring Boot
// spring.security.oauth2.resourceserver.opaquetoken
}
}
.cors { it.disable() }
.csrf { it.disable() }
.build()
Expand Down
8 changes: 4 additions & 4 deletions server/web/src/main/resources/static/open-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -503,12 +503,12 @@ paths:
schema:
$ref: '#/components/schemas/BssMetrics'
security:
- basicAuth: []
- oidc: []
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
oidc:
type: openIdConnect
openIdConnectUrl: https://login.bsstudio.hu/.well-known/openid-configuration
parameters:
memberId:
name: memberId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.http.MediaType
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.opaqueToken
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.delete
import org.springframework.test.web.servlet.get
Expand All @@ -37,7 +37,7 @@ internal class EventControllerTest(
every { mockService.findAllEvent() } returns EVENT_LIST

mockMvc.get(BASE_URL) {
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
}.andExpect {
status { isOk() }
content { json(objectMapper.writeValueAsString(EVENT_LIST)) }
Expand All @@ -51,7 +51,7 @@ internal class EventControllerTest(
mockMvc.post(BASE_URL) {
contentType = MediaType.APPLICATION_JSON
content = objectMapper.writeValueAsString(CREATE_EVENT)
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
with(csrf())
}.andExpect {
status { isCreated() }
Expand All @@ -65,7 +65,7 @@ internal class EventControllerTest(
every { mockService.findEventById(EVENT_ID) } returns Optional.of(DETAILED_EVENT)

mockMvc.get("$BASE_URL/$EVENT_ID") {
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
}.andExpect {
status { isOk() }
content { json(objectMapper.writeValueAsString(DETAILED_EVENT)) }
Expand All @@ -77,7 +77,7 @@ internal class EventControllerTest(
every { mockService.findEventById(EVENT_ID) } returns Optional.empty()

mockMvc.get("$BASE_URL/$EVENT_ID") {
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
}.andExpect {
status { isNotFound() }
content { string("") }
Expand All @@ -91,7 +91,7 @@ internal class EventControllerTest(
mockMvc.put("$BASE_URL/$EVENT_ID") {
contentType = MediaType.APPLICATION_JSON
content = objectMapper.writeValueAsString(UPDATE_EVENT)
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
with(csrf())
}.andExpect {
status { isOk() }
Expand All @@ -106,7 +106,7 @@ internal class EventControllerTest(
mockMvc.put("$BASE_URL/$EVENT_ID") {
contentType = MediaType.APPLICATION_JSON
content = objectMapper.writeValueAsString(UPDATE_EVENT)
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
with(csrf())
}.andExpect {
status { isNotFound() }
Expand All @@ -119,7 +119,7 @@ internal class EventControllerTest(
every { mockService.removeEvent(EVENT_ID) } returns Unit

mockMvc.delete("$BASE_URL/$EVENT_ID") {
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
with(csrf())
}.andExpect {
status { isNoContent() }
Expand All @@ -129,8 +129,6 @@ internal class EventControllerTest(

private companion object {
private const val BASE_URL = "/api/v1/event"
private const val USERNAME = "user"
private const val PASSWORD = "password"
private const val URL = "url"
private const val TITLE = "title"
private const val DESCRIPTION = "description"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.opaqueToken
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.delete
import org.springframework.test.web.servlet.post
Expand All @@ -32,7 +32,7 @@ internal class EventVideoControllerTest(
mockMvc.post(BASE_URL) {
param("eventId", EVENT_ID.toString())
param("videoId", VIDEO_ID.toString())
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
with(csrf())
}.andExpectAll {
status { isOk() }
Expand All @@ -47,7 +47,7 @@ internal class EventVideoControllerTest(
mockMvc.delete(BASE_URL) {
param("eventId", EVENT_ID.toString())
param("videoId", VIDEO_ID.toString())
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
with(csrf())
}.andExpectAll {
status { isOk() }
Expand All @@ -57,8 +57,6 @@ internal class EventVideoControllerTest(

private companion object {
private const val BASE_URL = "/api/v1/eventVideo"
private const val USERNAME = "user"
private const val PASSWORD = "password"
private val EVENT_ID = UUID.randomUUID()
private val VIDEO_ID = UUID.randomUUID()
private val DETAILED_EVENT =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.http.MediaType
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.opaqueToken
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.delete
import org.springframework.test.web.servlet.get
Expand All @@ -31,7 +31,7 @@ internal class LabelControllerTest(
every { mockService.findAllLabels() } returns LABEL_LIST

mockMvc.get(BASE_URL) {
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
}.andExpectAll {
status { isOk() }
content { objectMapper.writeValueAsString(LABEL_LIST) }
Expand All @@ -45,7 +45,7 @@ internal class LabelControllerTest(
mockMvc.post(BASE_URL) {
contentType = MediaType.APPLICATION_JSON
content = objectMapper.writeValueAsString(CREATE_LABEL)
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
with(csrf())
}.andExpectAll {
status { isCreated() }
Expand All @@ -59,7 +59,7 @@ internal class LabelControllerTest(
every { mockService.removeLabel(LABEL_ID) } returns Unit

mockMvc.delete("$BASE_URL/$LABEL_ID") {
with(httpBasic(USERNAME, PASSWORD))
with(opaqueToken())
with(csrf())
}.andExpectAll {
status { isNoContent() }
Expand Down
Loading