From fce161196907331332c1625500c3be6efa94c6d0 Mon Sep 17 00:00:00 2001 From: Sergey Okatov Date: Sat, 20 Jul 2024 12:33:38 +0500 Subject: [PATCH] M8l3 Auth --- deploy/keycloak-tokens.sh | 5 +- .../build.gradle.kts | 3 + .../src/commonMain/kotlin/JwtHelper.kt | 84 + .../kotlin/v2/ControllerHelperV2.kt | 3 + .../src/commonTest/kotlin/auth/AuthTest.kt | 47 + .../src/commonTest/kotlin/auth/addAuth.kt | 20 + .../kotlin/repo/V2AdRepoBaseTest.kt | 3 + .../jvmMain/kotlin/v1/ControllerHelperV1.kt | 3 + .../jvmTest/kotlin/repo/V1AdRepoBaseTest.kt | 3 + .../kotlin/controllers/AdControllerV1Fine.kt | 29 +- .../kotlin/controllers/AdControllerV2Fine.kt | 29 +- .../src/test/kotlin/repo/AdRepoBaseV1Test.kt | 19 +- .../src/test/kotlin/repo/AdRepoBaseV2Test.kt | 19 +- .../ok-marketplace-auth/build.gradle.kts | 26 + .../src/commonMain/kotlin/CheckPermitted.kt | 75 + .../kotlin/ResolveChainPermissionsTo.kt | 46 + .../kotlin/ResolveFrontPermissionsTo.kt | 59 + .../commonMain/kotlin/ResolveRelationsTo.kt | 16 + .../src/commonMain/kotlin/package.kt | 1 + .../ok-marketplace-biz/build.gradle.kts | 5 +- .../src/commonMain/kotlin/MkplAdProcessor.kt | 23 + .../kotlin/permissions/AccessValidation.kt | 37 + .../kotlin/permissions/ChainPermissions.kt | 21 + .../kotlin/permissions/FrontPermissions.kt | 34 + .../kotlin/permissions/SearchType.kt | 22 + .../kotlin/repo/AdRepoPrepareCreate.kt | 4 +- .../src/commonMain/kotlin/repo/InitRepo.kt | 2 + .../src/commonTest/kotlin/AddTestPrincipal.kt | 17 + .../kotlin/repo/BizRepoCreateTest.kt | 5 +- .../kotlin/repo/BizRepoDeleteTest.kt | 5 +- .../kotlin/repo/BizRepoOffersTest.kt | 5 +- .../commonTest/kotlin/repo/BizRepoReadTest.kt | 5 +- .../kotlin/repo/BizRepoSearchTest.kt | 5 +- .../kotlin/repo/BizRepoUpdateTest.kt | 5 +- .../commonTest/kotlin/repo/RepoByIdTests.kt | 2 + .../ValidateSearchStringLengthTest.kt | 5 + .../validation/ValidateTitleHasContentTest.kt | 4 + .../validation/ValidationBadDescription.kt | 5 + .../kotlin/validation/ValidationBadId.kt | 5 + .../kotlin/validation/ValidationBadLock.kt | 5 + .../kotlin/validation/ValidationBadTitle.kt | 5 + .../src/commonMain/kotlin/MkplContext.kt | 6 + .../kotlin/helpers/MkplErrorsHelpers.kt | 28 +- .../src/commonMain/kotlin/models/MkplAd.kt | 5 + .../commonMain/kotlin/models/MkplAdFilter.kt | 1 + .../kotlin/models/MkplSearchPermissions.kt | 7 + .../kotlin/permissions/MkplPrincipalModel.kt | 16 + .../permissions/MkplPrincipalRelations.kt | 10 + .../kotlin/permissions/MkplUserGroups.kt | 9 + .../kotlin/permissions/MkplUserPermissions.kt | 26 + .../src/commonMain/kotlin/MkplAdStubBolts.kt | 3 - ok-marketplace-be/settings.gradle.kts | 3 + .../ok-marketplace-e2e-be/build.gradle.kts | 6 +- .../docker-compose-ktor-keycloak-jvm.yml | 47 + .../docker-compose/volumes/envoy/envoy.yaml | 90 + .../volumes/keycloak/.gitignore | 3 + .../volumes/keycloak/import/master-realm.json | 1953 ++++++++++++++ .../keycloak/import/master-users-0.json | 23 + .../import/otus-marketplace-realm.json | 1830 ++++++++++++++ .../import/otus-marketplace-users-0.json | 24 + .../volumes/keycloak/realm-export.json | 2236 +++++++++++++++++ .../volumes/keycloak/standalone.xml | 12 + .../docker/KtorJvmKeycloakDockerCompose.kt | 21 + .../kotlin/fixture/client/RestAuthClient.kt | 81 + .../src/test/kotlin/test/AccRestTest.kt | 19 +- .../kotlin/test/action/v2/sendAndReceiveV2.kt | 2 - 66 files changed, 7104 insertions(+), 73 deletions(-) create mode 100644 ok-marketplace-be/ok-marketplace-app-common/src/commonMain/kotlin/JwtHelper.kt create mode 100644 ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/auth/AuthTest.kt create mode 100644 ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/auth/addAuth.kt create mode 100644 ok-marketplace-be/ok-marketplace-auth/build.gradle.kts create mode 100644 ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/CheckPermitted.kt create mode 100644 ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveChainPermissionsTo.kt create mode 100644 ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveFrontPermissionsTo.kt create mode 100644 ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveRelationsTo.kt create mode 100644 ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/package.kt create mode 100644 ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/AccessValidation.kt create mode 100644 ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/ChainPermissions.kt create mode 100644 ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/FrontPermissions.kt create mode 100644 ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/SearchType.kt create mode 100644 ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/AddTestPrincipal.kt create mode 100644 ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplSearchPermissions.kt create mode 100644 ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplPrincipalModel.kt create mode 100644 ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplPrincipalRelations.kt create mode 100644 ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplUserGroups.kt create mode 100644 ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplUserPermissions.kt create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/docker-compose-ktor-keycloak-jvm.yml create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/envoy/envoy.yaml create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/.gitignore create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/master-realm.json create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/master-users-0.json create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/otus-marketplace-realm.json create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/otus-marketplace-users-0.json create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/realm-export.json create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/standalone.xml create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/docker/KtorJvmKeycloakDockerCompose.kt create mode 100644 ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/fixture/client/RestAuthClient.kt diff --git a/deploy/keycloak-tokens.sh b/deploy/keycloak-tokens.sh index f1cbf16..fb0ae6e 100755 --- a/deploy/keycloak-tokens.sh +++ b/deploy/keycloak-tokens.sh @@ -1,6 +1,7 @@ #!/bin/bash -KCHOST=http://localhost:8080 +KCHOST=http://localhost:8081 +#KCHOST=http://localhost:32782 REALM=otus-marketplace CLIENT_ID=otus-marketplace-service UNAME=otus-test @@ -13,7 +14,7 @@ PASSWORD=otus # -d "grant_type=password" \ # "$KCHOST/auth/realms/$REALM/protocol/openid-connect/token" | jq -r '.access_token'` -ACCESS_TOKEN=`curl \ +ACCESS_TOKEN=`curl -XPOST \ -d "client_id=$CLIENT_ID" \ -d "username=$UNAME" \ -d "password=$PASSWORD" \ diff --git a/ok-marketplace-be/ok-marketplace-app-common/build.gradle.kts b/ok-marketplace-be/ok-marketplace-app-common/build.gradle.kts index e23dfd4..85ccbb5 100644 --- a/ok-marketplace-be/ok-marketplace-app-common/build.gradle.kts +++ b/ok-marketplace-be/ok-marketplace-app-common/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("build-kmp") + alias(libs.plugins.kotlinx.serialization) } kotlin { @@ -9,6 +10,8 @@ kotlin { dependencies { implementation(kotlin("stdlib-jdk8")) implementation(libs.coroutines.core) + implementation(libs.kotlinx.serialization.core) + implementation(libs.kotlinx.serialization.json) // transport models implementation(project(":ok-marketplace-common")) diff --git a/ok-marketplace-be/ok-marketplace-app-common/src/commonMain/kotlin/JwtHelper.kt b/ok-marketplace-be/ok-marketplace-app-common/src/commonMain/kotlin/JwtHelper.kt new file mode 100644 index 0000000..567582b --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-app-common/src/commonMain/kotlin/JwtHelper.kt @@ -0,0 +1,84 @@ +package ru.otus.otuskotlin.marketplace.app.common + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import ru.otus.otuskotlin.marketplace.common.models.MkplUserId +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalModel +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserGroups +import kotlin.io.encoding.Base64 +import kotlin.io.encoding.ExperimentalEncodingApi + +const val AUTH_HEADER: String = "x-jwt-payload" + +@OptIn(ExperimentalEncodingApi::class) +fun String?.jwt2principal(): MkplPrincipalModel = this?.let { jwtHeader -> + val jwtJson = Base64.decode(jwtHeader).decodeToString() + println("JWT JSON PAYLOAD: $jwtJson") + val jwtObj = jsMapper.decodeFromString(JwtPayload.serializer(), jwtJson) + jwtObj.toPrincipal() + } + ?: run { + println("No jwt found in headers") + MkplPrincipalModel.NONE + } + +@OptIn(ExperimentalEncodingApi::class) +fun MkplPrincipalModel.createJwtTestHeader(): String { + val jwtObj = fromPrincipal() + val jwtJson = jsMapper.encodeToString(JwtPayload.serializer(), jwtObj) + return Base64.encode(jwtJson.encodeToByteArray()) +} + +private val jsMapper = Json { + ignoreUnknownKeys = true +} + +@Serializable +private data class JwtPayload( + val aud: List? = null, + val sub: String? = null, + @SerialName("family_name") + val familyName: String? = null, + @SerialName("given_name") + val givenName: String? = null, + @SerialName("middle_name") + val middleName: String? = null, + val groups: List? = null, +) + +private fun JwtPayload.toPrincipal(): MkplPrincipalModel = MkplPrincipalModel( + id = sub?.let { MkplUserId(it) } ?: MkplUserId.NONE, + fname = givenName ?: "", + mname = middleName ?: "", + lname = familyName ?: "", + groups = groups?.mapNotNull { it.toPrincipalGroup() }?.toSet() ?: emptySet(), +) + +private fun MkplPrincipalModel.fromPrincipal(): JwtPayload = JwtPayload( + sub = id.takeIf { it != MkplUserId.NONE }?.asString(), + givenName = fname.takeIf { it.isNotBlank() }, + middleName = mname.takeIf { it.isNotBlank() }, + familyName = lname.takeIf { it.isNotBlank() }, + groups = groups.mapNotNull { it.fromPrincipalGroup() }.toList().takeIf { it.isNotEmpty() } ?: emptyList(), +) + +private fun String?.toPrincipalGroup(): MkplUserGroups? = when (this?.uppercase()) { + "USER" -> MkplUserGroups.USER + "ADMIN_AD" -> MkplUserGroups.ADMIN_AD + "MODERATOR_MP" -> MkplUserGroups.MODERATOR_MP + "TEST" -> MkplUserGroups.TEST + "BAN_AD" -> MkplUserGroups.BAN_AD + // TODO сделать обработку ошибок + else -> null +} + +private fun MkplUserGroups?.fromPrincipalGroup(): String? = when (this) { + MkplUserGroups.USER -> "USER" + MkplUserGroups.ADMIN_AD -> "ADMIN_AD" + MkplUserGroups.MODERATOR_MP -> "MODERATOR_MP" + MkplUserGroups.TEST -> "TEST" + MkplUserGroups.BAN_AD -> "BAN_AD" + // TODO сделать обработку ошибок + else -> null +} diff --git a/ok-marketplace-be/ok-marketplace-app-ktor/src/commonMain/kotlin/v2/ControllerHelperV2.kt b/ok-marketplace-be/ok-marketplace-app-ktor/src/commonMain/kotlin/v2/ControllerHelperV2.kt index a459ee0..0205e85 100644 --- a/ok-marketplace-be/ok-marketplace-app-ktor/src/commonMain/kotlin/v2/ControllerHelperV2.kt +++ b/ok-marketplace-be/ok-marketplace-app-ktor/src/commonMain/kotlin/v2/ControllerHelperV2.kt @@ -7,7 +7,9 @@ import ru.otus.otuskotlin.marketplace.api.v2.mappers.fromTransport import ru.otus.otuskotlin.marketplace.api.v2.mappers.toTransportAd import ru.otus.otuskotlin.marketplace.api.v2.models.IRequest import ru.otus.otuskotlin.marketplace.api.v2.models.IResponse +import ru.otus.otuskotlin.marketplace.app.common.AUTH_HEADER import ru.otus.otuskotlin.marketplace.app.common.controllerHelper +import ru.otus.otuskotlin.marketplace.app.common.jwt2principal import ru.otus.otuskotlin.marketplace.app.ktor.MkplAppSettings import kotlin.reflect.KClass @@ -17,6 +19,7 @@ suspend inline fun ()) }, { this@processV2.respond(toTransportAd() as R) }, diff --git a/ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/auth/AuthTest.kt b/ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/auth/AuthTest.kt new file mode 100644 index 0000000..897f258 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/auth/AuthTest.kt @@ -0,0 +1,47 @@ +package ru.otus.otuskotlin.marketplace.app.ktor.auth + +import io.ktor.client.call.* +import io.ktor.client.plugins.contentnegotiation.* +import io.ktor.client.request.* +import io.ktor.http.* +import io.ktor.serialization.kotlinx.json.* +import io.ktor.server.testing.* +import ru.otus.otuskotlin.marketplace.api.v2.apiV2Mapper +import ru.otus.otuskotlin.marketplace.api.v2.models.* +import ru.otus.otuskotlin.marketplace.app.ktor.MkplAppSettings +import ru.otus.otuskotlin.marketplace.app.ktor.module +import ru.otus.otuskotlin.marketplace.common.MkplCorSettings +import ru.otus.otuskotlin.marketplace.repo.inmemory.AdRepoInMemory +import kotlin.test.Test +import kotlin.test.assertEquals + +class AuthTest { + @Test + fun invalidAudience() = testApplication { + val client = createClient { + install(ContentNegotiation) { + json(apiV2Mapper) + } + } + application { module(MkplAppSettings(corSettings = MkplCorSettings(repoTest = AdRepoInMemory()))) } + val response = client.post("/v2/ad/create") { + addAuth(groups = emptyList()) + contentType(ContentType.Application.Json) + setBody( + AdCreateRequest( + ad = AdCreateObject( + title = "xxsdgff", + description = "dfgdfg", + adType = DealSide.SUPPLY, + visibility = AdVisibility.PUBLIC, + ), + debug = AdDebug(mode = AdRequestDebugMode.TEST) + ) + ) + } + val adObj = response.body() + assertEquals(200, response.status.value) + assertEquals(ResponseResult.ERROR, adObj.result) + assertEquals("access-create", adObj.errors?.first()?.code) + } +} diff --git a/ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/auth/addAuth.kt b/ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/auth/addAuth.kt new file mode 100644 index 0000000..db41011 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/auth/addAuth.kt @@ -0,0 +1,20 @@ +package ru.otus.otuskotlin.marketplace.app.ktor.auth + +import io.ktor.client.request.* +import ru.otus.otuskotlin.marketplace.app.common.AUTH_HEADER +import ru.otus.otuskotlin.marketplace.app.common.createJwtTestHeader +import ru.otus.otuskotlin.marketplace.common.models.MkplUserId +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalModel +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserGroups +import ru.otus.otuskotlin.marketplace.stubs.MkplAdStubBolts.AD_DEMAND_BOLT1 + +fun HttpRequestBuilder.addAuth(principal: MkplPrincipalModel) { + header(AUTH_HEADER, principal.createJwtTestHeader()) +} + +fun HttpRequestBuilder.addAuth( + id: MkplUserId = AD_DEMAND_BOLT1.ownerId, + groups: Collection = listOf(MkplUserGroups.TEST, MkplUserGroups.USER), +) { + addAuth(MkplPrincipalModel(id, groups = groups.toSet())) +} diff --git a/ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/repo/V2AdRepoBaseTest.kt b/ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/repo/V2AdRepoBaseTest.kt index f3108c1..e0645f8 100644 --- a/ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/repo/V2AdRepoBaseTest.kt +++ b/ok-marketplace-be/ok-marketplace-app-ktor/src/commonTest/kotlin/repo/V2AdRepoBaseTest.kt @@ -14,10 +14,12 @@ import ru.otus.otuskotlin.marketplace.api.v2.mappers.toTransportRead import ru.otus.otuskotlin.marketplace.api.v2.mappers.toTransportUpdate import ru.otus.otuskotlin.marketplace.api.v2.models.* import ru.otus.otuskotlin.marketplace.app.ktor.MkplAppSettings +import ru.otus.otuskotlin.marketplace.app.ktor.auth.addAuth import ru.otus.otuskotlin.marketplace.app.ktor.module import ru.otus.otuskotlin.marketplace.common.models.MkplAdId import ru.otus.otuskotlin.marketplace.common.models.MkplAdLock import ru.otus.otuskotlin.marketplace.common.models.MkplDealSide +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserGroups import ru.otus.otuskotlin.marketplace.stubs.MkplAdStub import kotlin.test.Test import kotlin.test.assertEquals @@ -167,6 +169,7 @@ abstract class V2AdRepoBaseTest { val response = client.post("/v2/ad/$func") { contentType(ContentType.Application.Json) header("X-Trace-Id", "12345") + addAuth(groups = listOf(MkplUserGroups.USER)) setBody(request) } function(response) diff --git a/ok-marketplace-be/ok-marketplace-app-ktor/src/jvmMain/kotlin/v1/ControllerHelperV1.kt b/ok-marketplace-be/ok-marketplace-app-ktor/src/jvmMain/kotlin/v1/ControllerHelperV1.kt index fbfc337..a3f0232 100644 --- a/ok-marketplace-be/ok-marketplace-app-ktor/src/jvmMain/kotlin/v1/ControllerHelperV1.kt +++ b/ok-marketplace-be/ok-marketplace-app-ktor/src/jvmMain/kotlin/v1/ControllerHelperV1.kt @@ -5,7 +5,9 @@ import io.ktor.server.request.* import io.ktor.server.response.* import ru.otus.otuskotlin.marketplace.api.v1.models.IRequest import ru.otus.otuskotlin.marketplace.api.v1.models.IResponse +import ru.otus.otuskotlin.marketplace.app.common.AUTH_HEADER import ru.otus.otuskotlin.marketplace.app.common.controllerHelper +import ru.otus.otuskotlin.marketplace.app.common.jwt2principal import ru.otus.otuskotlin.marketplace.app.ktor.MkplAppSettings import ru.otus.otuskotlin.marketplace.mappers.v1.fromTransport import ru.otus.otuskotlin.marketplace.mappers.v1.toTransportAd @@ -17,6 +19,7 @@ suspend inline fun ()) }, { respond(toTransportAd()) }, diff --git a/ok-marketplace-be/ok-marketplace-app-ktor/src/jvmTest/kotlin/repo/V1AdRepoBaseTest.kt b/ok-marketplace-be/ok-marketplace-app-ktor/src/jvmTest/kotlin/repo/V1AdRepoBaseTest.kt index 44a31e9..908d3f7 100644 --- a/ok-marketplace-be/ok-marketplace-app-ktor/src/jvmTest/kotlin/repo/V1AdRepoBaseTest.kt +++ b/ok-marketplace-be/ok-marketplace-app-ktor/src/jvmTest/kotlin/repo/V1AdRepoBaseTest.kt @@ -9,10 +9,12 @@ import io.ktor.serialization.jackson.* import io.ktor.server.testing.* import ru.otus.otuskotlin.marketplace.api.v1.models.* import ru.otus.otuskotlin.marketplace.app.ktor.MkplAppSettings +import ru.otus.otuskotlin.marketplace.app.ktor.auth.addAuth import ru.otus.otuskotlin.marketplace.app.ktor.moduleJvm import ru.otus.otuskotlin.marketplace.common.models.MkplAdId import ru.otus.otuskotlin.marketplace.common.models.MkplAdLock import ru.otus.otuskotlin.marketplace.common.models.MkplDealSide +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserGroups import ru.otus.otuskotlin.marketplace.mappers.v1.toTransportCreate import ru.otus.otuskotlin.marketplace.mappers.v1.toTransportDelete import ru.otus.otuskotlin.marketplace.mappers.v1.toTransportRead @@ -164,6 +166,7 @@ abstract class V1AdRepoBaseTest { val response = client.post("/v1/ad/$func") { contentType(ContentType.Application.Json) header("X-Trace-Id", "12345") + addAuth(groups = listOf(MkplUserGroups.USER)) setBody(request) } function(response) diff --git a/ok-marketplace-be/ok-marketplace-app-spring/src/main/kotlin/controllers/AdControllerV1Fine.kt b/ok-marketplace-be/ok-marketplace-app-spring/src/main/kotlin/controllers/AdControllerV1Fine.kt index 25d34bd..31b433a 100644 --- a/ok-marketplace-be/ok-marketplace-app-spring/src/main/kotlin/controllers/AdControllerV1Fine.kt +++ b/ok-marketplace-be/ok-marketplace-app-spring/src/main/kotlin/controllers/AdControllerV1Fine.kt @@ -1,9 +1,12 @@ package ru.otus.otuskotlin.markeplace.app.spring.controllers +import org.springframework.http.HttpHeaders import org.springframework.web.bind.annotation.* import ru.otus.otuskotlin.markeplace.app.spring.base.MkplAppSettings import ru.otus.otuskotlin.marketplace.api.v1.models.* +import ru.otus.otuskotlin.marketplace.app.common.AUTH_HEADER import ru.otus.otuskotlin.marketplace.app.common.controllerHelper +import ru.otus.otuskotlin.marketplace.app.common.jwt2principal import ru.otus.otuskotlin.marketplace.mappers.v1.fromTransport import ru.otus.otuskotlin.marketplace.mappers.v1.toTransportAd import kotlin.reflect.KClass @@ -16,37 +19,39 @@ class AdControllerV1Fine( ) { @PostMapping("create") - suspend fun create(@RequestBody request: AdCreateRequest): AdCreateResponse = - process(appSettings, request = request, this::class, "create") + suspend fun create(@RequestBody request: AdCreateRequest, @RequestHeader headers: HttpHeaders): AdCreateResponse = + process(appSettings, request = request, headers = headers, this::class, "create") @PostMapping("read") - suspend fun read(@RequestBody request: AdReadRequest): AdReadResponse = - process(appSettings, request = request, this::class, "read") + suspend fun read(@RequestBody request: AdReadRequest, @RequestHeader headers: HttpHeaders): AdReadResponse = + process(appSettings, request = request, headers = headers, this::class, "read") @RequestMapping("update", method = [RequestMethod.POST]) - suspend fun update(@RequestBody request: AdUpdateRequest): AdUpdateResponse = - process(appSettings, request = request, this::class, "update") + suspend fun update(@RequestBody request: AdUpdateRequest, @RequestHeader headers: HttpHeaders): AdUpdateResponse = + process(appSettings, request = request, headers = headers, this::class, "update") @PostMapping("delete") - suspend fun delete(@RequestBody request: AdDeleteRequest): AdDeleteResponse = - process(appSettings, request = request, this::class, "delete") + suspend fun delete(@RequestBody request: AdDeleteRequest, @RequestHeader headers: HttpHeaders): AdDeleteResponse = + process(appSettings, request = request, headers = headers, this::class, "delete") @PostMapping("search") - suspend fun search(@RequestBody request: AdSearchRequest): AdSearchResponse = - process(appSettings, request = request, this::class, "search") + suspend fun search(@RequestBody request: AdSearchRequest, @RequestHeader headers: HttpHeaders): AdSearchResponse = + process(appSettings, request = request, headers = headers, this::class, "search") @PostMapping("offers") - suspend fun offers(@RequestBody request: AdOffersRequest): AdOffersResponse = - process(appSettings, request = request, this::class, "offers") + suspend fun offers(@RequestBody request: AdOffersRequest, @RequestHeader headers: HttpHeaders): AdOffersResponse = + process(appSettings, request = request, headers = headers, this::class, "offers") companion object { suspend inline fun process( appSettings: MkplAppSettings, request: Q, + headers: HttpHeaders, clazz: KClass<*>, logId: String, ): R = appSettings.controllerHelper( { + principal = headers[AUTH_HEADER]?.first().jwt2principal() fromTransport(request) }, { toTransportAd() as R }, diff --git a/ok-marketplace-be/ok-marketplace-app-spring/src/main/kotlin/controllers/AdControllerV2Fine.kt b/ok-marketplace-be/ok-marketplace-app-spring/src/main/kotlin/controllers/AdControllerV2Fine.kt index b1e48bc..cc528d3 100644 --- a/ok-marketplace-be/ok-marketplace-app-spring/src/main/kotlin/controllers/AdControllerV2Fine.kt +++ b/ok-marketplace-be/ok-marketplace-app-spring/src/main/kotlin/controllers/AdControllerV2Fine.kt @@ -1,10 +1,13 @@ package ru.otus.otuskotlin.markeplace.app.spring.controllers +import org.springframework.http.HttpHeaders import org.springframework.web.bind.annotation.* import ru.otus.otuskotlin.markeplace.app.spring.base.MkplAppSettings import ru.otus.otuskotlin.marketplace.api.v2.mappers.* import ru.otus.otuskotlin.marketplace.api.v2.models.* +import ru.otus.otuskotlin.marketplace.app.common.AUTH_HEADER import ru.otus.otuskotlin.marketplace.app.common.controllerHelper +import ru.otus.otuskotlin.marketplace.app.common.jwt2principal import kotlin.reflect.KClass @Suppress("unused") @@ -13,37 +16,39 @@ import kotlin.reflect.KClass class AdControllerV2Fine(private val appSettings: MkplAppSettings) { @PostMapping("create") - suspend fun create(@RequestBody request: AdCreateRequest): AdCreateResponse = - process(appSettings, request = request, this::class, "create") + suspend fun create(@RequestBody request: AdCreateRequest, @RequestHeader headers: HttpHeaders): AdCreateResponse = + process(appSettings, request = request, headers = headers, this::class, "create") @PostMapping("read") - suspend fun read(@RequestBody request: AdReadRequest): AdReadResponse = - process(appSettings, request = request, this::class, "read") + suspend fun read(@RequestBody request: AdReadRequest, @RequestHeader headers: HttpHeaders): AdReadResponse = + process(appSettings, request = request, headers = headers, this::class, "read") @RequestMapping("update", method = [RequestMethod.POST]) - suspend fun update(@RequestBody request: AdUpdateRequest): AdUpdateResponse = - process(appSettings, request = request, this::class, "update") + suspend fun update(@RequestBody request: AdUpdateRequest, @RequestHeader headers: HttpHeaders): AdUpdateResponse = + process(appSettings, request = request, headers = headers, this::class, "update") @PostMapping("delete") - suspend fun delete(@RequestBody request: AdDeleteRequest): AdDeleteResponse = - process(appSettings, request = request, this::class, "delete") + suspend fun delete(@RequestBody request: AdDeleteRequest, @RequestHeader headers: HttpHeaders): AdDeleteResponse = + process(appSettings, request = request, headers = headers, this::class, "delete") @PostMapping("search") - suspend fun search(@RequestBody request: AdSearchRequest): AdSearchResponse = - process(appSettings, request = request, this::class, "search") + suspend fun search(@RequestBody request: AdSearchRequest, @RequestHeader headers: HttpHeaders): AdSearchResponse = + process(appSettings, request = request, headers = headers, this::class, "search") @PostMapping("offers") - suspend fun offers(@RequestBody request: AdOffersRequest): AdOffersResponse = - process(appSettings, request = request, this::class, "offers") + suspend fun offers(@RequestBody request: AdOffersRequest, @RequestHeader headers: HttpHeaders): AdOffersResponse = + process(appSettings, request = request, headers = headers, this::class, "offers") companion object { suspend inline fun process( appSettings: MkplAppSettings, request: Q, + headers: HttpHeaders, clazz: KClass<*>, logId: String, ): R = appSettings.controllerHelper( { + principal = headers[AUTH_HEADER]?.first().jwt2principal() fromTransport(request) }, { toTransportAd() as R }, diff --git a/ok-marketplace-be/ok-marketplace-app-spring/src/test/kotlin/repo/AdRepoBaseV1Test.kt b/ok-marketplace-be/ok-marketplace-app-spring/src/test/kotlin/repo/AdRepoBaseV1Test.kt index adbe5eb..fdd7438 100644 --- a/ok-marketplace-be/ok-marketplace-app-spring/src/test/kotlin/repo/AdRepoBaseV1Test.kt +++ b/ok-marketplace-be/ok-marketplace-app-spring/src/test/kotlin/repo/AdRepoBaseV1Test.kt @@ -5,10 +5,15 @@ import org.springframework.http.MediaType import org.springframework.test.web.reactive.server.WebTestClient import org.springframework.web.reactive.function.BodyInserters import ru.otus.otuskotlin.marketplace.api.v1.models.* +import ru.otus.otuskotlin.marketplace.app.common.AUTH_HEADER +import ru.otus.otuskotlin.marketplace.app.common.createJwtTestHeader import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.models.* +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalModel +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserGroups import ru.otus.otuskotlin.marketplace.mappers.v1.* import ru.otus.otuskotlin.marketplace.stubs.MkplAdStub +import ru.otus.otuskotlin.marketplace.stubs.MkplAdStubBolts import kotlin.test.Test internal abstract class AdRepoBaseV1Test { @@ -76,7 +81,6 @@ internal abstract class AdRepoBaseV1Test { MkplContext( state = MkplState.RUNNING, adsResponse = MkplAdStub.prepareSearchList("xx", MkplDealSide.SUPPLY) - .onEach { it.permissionsClient.clear() } .sortedBy { it.id.asString() } .toMutableList() ) @@ -92,9 +96,8 @@ internal abstract class AdRepoBaseV1Test { ), MkplContext( state = MkplState.RUNNING, - adResponse = MkplAdStub.prepareResult { permissionsClient.clear() }, + adResponse = MkplAdStub.get(), adsResponse = MkplAdStub.prepareSearchList("xx", MkplDealSide.SUPPLY) - .onEach { it.permissionsClient.clear() } .sortedBy { it.id.asString() } .toMutableList() ) @@ -103,21 +106,23 @@ internal abstract class AdRepoBaseV1Test { private fun prepareCtx(ad: MkplAd) = MkplContext( state = MkplState.RUNNING, - adResponse = ad.apply { - // Пока не реализована эта функциональность - permissionsClient.clear() - }, + adResponse = ad, ) private inline fun testRepoAd( url: String, requestObj: Req, expectObj: Res, + principal: MkplPrincipalModel = MkplPrincipalModel( + id = MkplAdStubBolts.AD_DEMAND_BOLT1.ownerId, + groups = setOf(MkplUserGroups.TEST, MkplUserGroups.USER) + ) ) { webClient .post() .uri("/v1/ad/$url") .contentType(MediaType.APPLICATION_JSON) + .header(AUTH_HEADER, principal.createJwtTestHeader()) .body(BodyInserters.fromValue(requestObj)) .exchange() .expectStatus().isOk diff --git a/ok-marketplace-be/ok-marketplace-app-spring/src/test/kotlin/repo/AdRepoBaseV2Test.kt b/ok-marketplace-be/ok-marketplace-app-spring/src/test/kotlin/repo/AdRepoBaseV2Test.kt index b1d67d4..2ec0830 100644 --- a/ok-marketplace-be/ok-marketplace-app-spring/src/test/kotlin/repo/AdRepoBaseV2Test.kt +++ b/ok-marketplace-be/ok-marketplace-app-spring/src/test/kotlin/repo/AdRepoBaseV2Test.kt @@ -6,9 +6,14 @@ import org.springframework.test.web.reactive.server.WebTestClient import org.springframework.web.reactive.function.BodyInserters import ru.otus.otuskotlin.marketplace.api.v2.mappers.* import ru.otus.otuskotlin.marketplace.api.v2.models.* +import ru.otus.otuskotlin.marketplace.app.common.AUTH_HEADER +import ru.otus.otuskotlin.marketplace.app.common.createJwtTestHeader import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.models.* +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalModel +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserGroups import ru.otus.otuskotlin.marketplace.stubs.MkplAdStub +import ru.otus.otuskotlin.marketplace.stubs.MkplAdStubBolts import kotlin.test.Test internal abstract class AdRepoBaseV2Test { @@ -76,7 +81,6 @@ internal abstract class AdRepoBaseV2Test { MkplContext( state = MkplState.RUNNING, adsResponse = MkplAdStub.prepareSearchList("xx", MkplDealSide.SUPPLY) - .onEach { it.permissionsClient.clear() } .sortedBy { it.id.asString() } .toMutableList() ) @@ -92,9 +96,8 @@ internal abstract class AdRepoBaseV2Test { ), MkplContext( state = MkplState.RUNNING, - adResponse = MkplAdStub.prepareResult { permissionsClient.clear() }, + adResponse = MkplAdStub.get(), adsResponse = MkplAdStub.prepareSearchList("xx", MkplDealSide.SUPPLY) - .onEach { it.permissionsClient.clear() } .sortedBy { it.id.asString() } .toMutableList() ) @@ -103,21 +106,23 @@ internal abstract class AdRepoBaseV2Test { private fun prepareCtx(ad: MkplAd) = MkplContext( state = MkplState.RUNNING, - adResponse = ad.apply { - // Пока не реализована эта функциональность - permissionsClient.clear() - }, + adResponse = ad, ) private inline fun testRepoAd( url: String, requestObj: Req, expectObj: Res, + principal: MkplPrincipalModel = MkplPrincipalModel( + id = MkplAdStubBolts.AD_DEMAND_BOLT1.ownerId, + groups = setOf(MkplUserGroups.TEST, MkplUserGroups.USER) + ) ) { webClient .post() .uri("/v2/ad/$url") .contentType(MediaType.APPLICATION_JSON) + .header(AUTH_HEADER, principal.createJwtTestHeader()) .body(BodyInserters.fromValue(requestObj)) .exchange() .expectStatus().isOk diff --git a/ok-marketplace-be/ok-marketplace-auth/build.gradle.kts b/ok-marketplace-be/ok-marketplace-auth/build.gradle.kts new file mode 100644 index 0000000..bd38cb2 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-auth/build.gradle.kts @@ -0,0 +1,26 @@ +plugins { + id("build-kmp") +} + +kotlin { + sourceSets { + val datetimeVersion: String by project + val coroutinesVersion: String by project + + val commonMain by getting { + dependencies { + implementation(kotlin("stdlib-common")) + + api(libs.coroutines.core) + api(libs.kotlinx.datetime) + implementation(projects.okMarketplaceCommon) + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + } + } +} diff --git a/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/CheckPermitted.kt b/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/CheckPermitted.kt new file mode 100644 index 0000000..e388d92 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/CheckPermitted.kt @@ -0,0 +1,75 @@ +package ru.otus.otuskotlin.marketplace.auth + +import ru.otus.otuskotlin.marketplace.common.models.MkplCommand +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalRelations +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserPermissions + +/** + * Вычисляет доступность выполнения операции. + * Здесь происходит сравнение доступных прав (пермишинов) и фактических отношений принципала к объекту, с которым работаем + */ +fun checkPermitted( + command: MkplCommand, + relations: Iterable, + permissions: Iterable, +) = + relations.asSequence().flatMap { relation -> + permissions.map { permission -> + AccessTableConditions( + command = command, + permission = permission, + relation = relation, + ) + } + }.any { + accessTable[it] != null + } + // Дополнительно можно сделать проверку на отсутствие в результатах false + +private data class AccessTableConditions( + val command: MkplCommand, + val permission: MkplUserPermissions, + val relation: MkplPrincipalRelations +) + +private val accessTable = mapOf( + // Create + AccessTableConditions( + command = MkplCommand.CREATE, + permission = MkplUserPermissions.CREATE_OWN, + relation = MkplPrincipalRelations.NEW, + ) to true, + + // Read + AccessTableConditions( + command = MkplCommand.READ, + permission = MkplUserPermissions.READ_OWN, + relation = MkplPrincipalRelations.OWN, + ) to true, + AccessTableConditions( + command = MkplCommand.READ, + permission = MkplUserPermissions.READ_PUBLIC, + relation = MkplPrincipalRelations.PUBLIC, + ) to true, + + // Update + AccessTableConditions( + command = MkplCommand.UPDATE, + permission = MkplUserPermissions.UPDATE_OWN, + relation = MkplPrincipalRelations.OWN, + ) to true, + + // Delete + AccessTableConditions( + command = MkplCommand.DELETE, + permission = MkplUserPermissions.DELETE_OWN, + relation = MkplPrincipalRelations.OWN, + ) to true, + + // Offers + AccessTableConditions( + command = MkplCommand.OFFERS, + permission = MkplUserPermissions.OFFER_FOR_OWN, + relation = MkplPrincipalRelations.OWN, + ) to true, +) diff --git a/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveChainPermissionsTo.kt b/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveChainPermissionsTo.kt new file mode 100644 index 0000000..7473da0 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveChainPermissionsTo.kt @@ -0,0 +1,46 @@ +package ru.otus.otuskotlin.marketplace.auth + +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserGroups +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserPermissions + +/** + * На вход подаем группы/роли из JWT, на выход получаем пермишины, соответствующие этим группам/ролям + */ +fun resolveChainPermissions( + groups: Iterable, +) = mutableSetOf() + .apply { + // Группы, добавляющие права (пермишины) + addAll(groups.flatMap { groupPermissionsAdmits[it] ?: emptySet() }) + // Группы, запрещающие права (пермишины) + removeAll(groups.flatMap { groupPermissionsDenys[it] ?: emptySet() }.toSet()) + } + .toSet() + +// +private val groupPermissionsAdmits = mapOf( + MkplUserGroups.USER to setOf( + MkplUserPermissions.READ_OWN, + MkplUserPermissions.READ_PUBLIC, + MkplUserPermissions.CREATE_OWN, + MkplUserPermissions.UPDATE_OWN, + MkplUserPermissions.DELETE_OWN, + MkplUserPermissions.OFFER_FOR_OWN, + ), + MkplUserGroups.MODERATOR_MP to setOf(), + MkplUserGroups.ADMIN_AD to setOf(), + MkplUserGroups.TEST to setOf(), + MkplUserGroups.BAN_AD to setOf(), +) + +private val groupPermissionsDenys = mapOf( + MkplUserGroups.USER to setOf(), + MkplUserGroups.MODERATOR_MP to setOf(), + MkplUserGroups.ADMIN_AD to setOf(), + MkplUserGroups.TEST to setOf(), + MkplUserGroups.BAN_AD to setOf( + MkplUserPermissions.UPDATE_OWN, + MkplUserPermissions.CREATE_OWN, + MkplUserPermissions.DELETE_OWN, + ), +) diff --git a/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveFrontPermissionsTo.kt b/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveFrontPermissionsTo.kt new file mode 100644 index 0000000..1f24267 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveFrontPermissionsTo.kt @@ -0,0 +1,59 @@ +package ru.otus.otuskotlin.marketplace.auth + +import ru.otus.otuskotlin.marketplace.common.models.MkplAdPermissionClient +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalRelations +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserPermissions + +fun resolveFrontPermissions( + permissions: Iterable, + relations: Iterable, +) = mutableSetOf() + .apply { + for (permission in permissions) { + for (relation in relations) { + accessTable[permission]?.get(relation)?.let { this@apply.add(it) } + } + } + } + .toSet() + +/** + * Это трехмерная таблица пермишин в бэкенде->отношение к объявлению->пермишин на фронте + */ +private val accessTable = mapOf( + // READ + MkplUserPermissions.READ_OWN to mapOf( + MkplPrincipalRelations.OWN to MkplAdPermissionClient.READ + ), + MkplUserPermissions.READ_GROUP to mapOf( + MkplPrincipalRelations.GROUP to MkplAdPermissionClient.READ + ), + MkplUserPermissions.READ_PUBLIC to mapOf( + MkplPrincipalRelations.PUBLIC to MkplAdPermissionClient.READ + ), + MkplUserPermissions.READ_CANDIDATE to mapOf( + MkplPrincipalRelations.MODERATABLE to MkplAdPermissionClient.READ + ), + + // UPDATE + MkplUserPermissions.UPDATE_OWN to mapOf( + MkplPrincipalRelations.OWN to MkplAdPermissionClient.UPDATE + ), + MkplUserPermissions.UPDATE_PUBLIC to mapOf( + MkplPrincipalRelations.MODERATABLE to MkplAdPermissionClient.UPDATE + ), + MkplUserPermissions.UPDATE_CANDIDATE to mapOf( + MkplPrincipalRelations.MODERATABLE to MkplAdPermissionClient.UPDATE + ), + + // DELETE + MkplUserPermissions.DELETE_OWN to mapOf( + MkplPrincipalRelations.OWN to MkplAdPermissionClient.DELETE + ), + MkplUserPermissions.DELETE_PUBLIC to mapOf( + MkplPrincipalRelations.MODERATABLE to MkplAdPermissionClient.DELETE + ), + MkplUserPermissions.DELETE_CANDIDATE to mapOf( + MkplPrincipalRelations.MODERATABLE to MkplAdPermissionClient.DELETE + ), +) diff --git a/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveRelationsTo.kt b/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveRelationsTo.kt new file mode 100644 index 0000000..265a3d6 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/ResolveRelationsTo.kt @@ -0,0 +1,16 @@ +package ru.otus.otuskotlin.marketplace.auth + +import ru.otus.otuskotlin.marketplace.common.models.MkplAd +import ru.otus.otuskotlin.marketplace.common.models.MkplAdId +import ru.otus.otuskotlin.marketplace.common.models.MkplVisibility +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalModel +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalRelations + +fun MkplAd.resolveRelationsTo(principal: MkplPrincipalModel): Set = setOfNotNull( + MkplPrincipalRelations.NONE, + // Используется при создании нового объявления + MkplPrincipalRelations.NEW.takeIf { id == MkplAdId.NONE }, + MkplPrincipalRelations.OWN.takeIf { principal.id == ownerId }, + MkplPrincipalRelations.MODERATABLE.takeIf { visibility != MkplVisibility.VISIBLE_TO_OWNER }, + MkplPrincipalRelations.PUBLIC.takeIf { visibility == MkplVisibility.VISIBLE_PUBLIC }, +) diff --git a/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/package.kt b/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/package.kt new file mode 100644 index 0000000..71d94a7 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-auth/src/commonMain/kotlin/package.kt @@ -0,0 +1 @@ +package ru.otus.otuskotlin.marketplace.auth diff --git a/ok-marketplace-be/ok-marketplace-biz/build.gradle.kts b/ok-marketplace-be/ok-marketplace-biz/build.gradle.kts index ab4ccef..335a5fc 100644 --- a/ok-marketplace-be/ok-marketplace-biz/build.gradle.kts +++ b/ok-marketplace-be/ok-marketplace-biz/build.gradle.kts @@ -13,8 +13,9 @@ kotlin { implementation(libs.mkpl.cor) implementation(libs.mkpl.state.common) - implementation(project(":ok-marketplace-common")) - implementation(project(":ok-marketplace-stubs")) + implementation(projects.okMarketplaceCommon) + implementation(projects.okMarketplaceStubs) + implementation(projects.okMarketplaceAuth) } } commonTest { diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/MkplAdProcessor.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/MkplAdProcessor.kt index 90a7225..9f4c855 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/MkplAdProcessor.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/MkplAdProcessor.kt @@ -4,6 +4,10 @@ import ru.otus.otuskotlin.marketplace.biz.general.getAdState import ru.otus.otuskotlin.marketplace.biz.general.getAdStates import ru.otus.otuskotlin.marketplace.biz.general.initStatus import ru.otus.otuskotlin.marketplace.biz.general.operation +import ru.otus.otuskotlin.marketplace.biz.permissions.accessValidation +import ru.otus.otuskotlin.marketplace.biz.permissions.chainPermissions +import ru.otus.otuskotlin.marketplace.biz.permissions.frontPermissions +import ru.otus.otuskotlin.marketplace.biz.permissions.searchTypes import ru.otus.otuskotlin.marketplace.biz.repo.* import ru.otus.otuskotlin.marketplace.biz.stubs.* import ru.otus.otuskotlin.marketplace.biz.validation.* @@ -34,6 +38,7 @@ class MkplAdProcessor( stubDbError("Имитация ошибки работы с БД") stubNoCase("Ошибка: запрошенный стаб недопустим") } + chainPermissions("Вычисление разрешений для пользователя") validation { worker("Копируем поля в adValidating") { adValidating = adRequest.deepCopy() } worker("Очистка id") { adValidating.id = MkplAdId.NONE } @@ -49,8 +54,10 @@ class MkplAdProcessor( chain { title = "Логика сохранения" repoPrepareCreate("Подготовка объекта для сохранения") + accessValidation("Вычисление прав доступа") repoCreate("Создание объявления в БД") } + frontPermissions("Вычисление пользовательских разрешений для фронтенда") getAdState("Вычисление состояния объявления") prepareResult("Подготовка ответа") } @@ -61,6 +68,7 @@ class MkplAdProcessor( stubDbError("Имитация ошибки работы с БД") stubNoCase("Ошибка: запрошенный стаб недопустим") } + chainPermissions("Вычисление разрешений для пользователя") validation { worker("Копируем поля в adValidating") { adValidating = adRequest.deepCopy() } worker("Очистка id") { adValidating.id = MkplAdId(adValidating.id.asString().trim()) } @@ -72,12 +80,14 @@ class MkplAdProcessor( chain { title = "Логика чтения" repoRead("Чтение объявления из БД") + accessValidation("Вычисление прав доступа") worker { title = "Подготовка ответа для Read" on { state == MkplState.RUNNING } handle { adRepoDone = adRepoRead } } } + frontPermissions("Вычисление пользовательских разрешений для фронтенда") getAdState("Вычисление состояния объявления") prepareResult("Подготовка ответа") } @@ -90,6 +100,7 @@ class MkplAdProcessor( stubDbError("Имитация ошибки работы с БД") stubNoCase("Ошибка: запрошенный стаб недопустим") } + chainPermissions("Вычисление разрешений для пользователя") validation { worker("Копируем поля в adValidating") { adValidating = adRequest.deepCopy() } worker("Очистка id") { adValidating.id = MkplAdId(adValidating.id.asString().trim()) } @@ -110,10 +121,12 @@ class MkplAdProcessor( chain { title = "Логика сохранения" repoRead("Чтение объявления из БД") + accessValidation("Вычисление прав доступа") checkLock("Проверяем консистентность по оптимистичной блокировке") repoPrepareUpdate("Подготовка объекта для обновления") repoUpdate("Обновление объявления в БД") } + frontPermissions("Вычисление пользовательских разрешений для фронтенда") getAdState("Вычисление состояния объявления") prepareResult("Подготовка ответа") } @@ -124,6 +137,7 @@ class MkplAdProcessor( stubDbError("Имитация ошибки работы с БД") stubNoCase("Ошибка: запрошенный стаб недопустим") } + chainPermissions("Вычисление разрешений для пользователя") validation { worker("Копируем поля в adValidating") { adValidating = adRequest.deepCopy() @@ -139,10 +153,12 @@ class MkplAdProcessor( chain { title = "Логика удаления" repoRead("Чтение объявления из БД") + accessValidation("Вычисление прав доступа") checkLock("Проверяем консистентность по оптимистичной блокировке") repoPrepareDelete("Подготовка объекта для удаления") repoDelete("Удаление объявления из БД") } + frontPermissions("Вычисление пользовательских разрешений для фронтенда") getAdState("Вычисление состояния объявления") prepareResult("Подготовка ответа") } @@ -153,13 +169,17 @@ class MkplAdProcessor( stubDbError("Имитация ошибки работы с БД") stubNoCase("Ошибка: запрошенный стаб недопустим") } + chainPermissions("Вычисление разрешений для пользователя") validation { worker("Копируем поля в adFilterValidating") { adFilterValidating = adFilterRequest.deepCopy() } validateSearchStringLength("Валидация длины строки поиска в фильтре") finishAdFilterValidation("Успешное завершение процедуры валидации") } + searchTypes("Подготовка поискового запроса") + repoSearch("Поиск объявления в БД по фильтру") + frontPermissions("Вычисление пользовательских разрешений для фронтенда") getAdStates("Вычисление состояния объявления") prepareResult("Подготовка ответа") } @@ -170,6 +190,7 @@ class MkplAdProcessor( stubDbError("Имитация ошибки работы с БД") stubNoCase("Ошибка: запрошенный стаб недопустим") } + chainPermissions("Вычисление разрешений для пользователя") validation { worker("Копируем поля в adValidating") { adValidating = adRequest.deepCopy() } worker("Очистка id") { adValidating.id = MkplAdId(adValidating.id.asString().trim()) } @@ -181,9 +202,11 @@ class MkplAdProcessor( chain { title = "Логика поиска в БД" repoRead("Чтение объявления из БД") + accessValidation("Вычисление прав доступа") repoPrepareOffers("Подготовка данных для поиска предложений") repoOffers("Поиск предложений для объявления в БД") } + frontPermissions("Вычисление пользовательских разрешений для фронтенда") getAdStates("Вычисление состояния объявления") prepareResult("Подготовка ответа") } diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/AccessValidation.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/AccessValidation.kt new file mode 100644 index 0000000..9825c5b --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/AccessValidation.kt @@ -0,0 +1,37 @@ +package ru.otus.otuskotlin.marketplace.biz.permissions + +import ru.otus.otuskotlin.marketplace.auth.checkPermitted +import ru.otus.otuskotlin.marketplace.auth.resolveRelationsTo +import ru.otus.otuskotlin.marketplace.common.MkplContext +import ru.otus.otuskotlin.marketplace.common.helpers.accessViolation +import ru.otus.otuskotlin.marketplace.common.helpers.fail +import ru.otus.otuskotlin.marketplace.common.models.MkplState +import ru.otus.otuskotlin.marketplace.cor.ICorChainDsl +import ru.otus.otuskotlin.marketplace.cor.chain +import ru.otus.otuskotlin.marketplace.cor.worker + +fun ICorChainDsl.accessValidation(title: String) = chain { + this.title = title + description = "Вычисление прав доступа по группе принципала и таблице прав доступа" + on { state == MkplState.RUNNING } + worker("Вычисление отношения объявления к принципалу") { + adRepoRead.principalRelations = adRepoRead.resolveRelationsTo(principal) + } + worker("Вычисление доступа к объявлению") { + permitted = checkPermitted(command, adRepoRead.principalRelations, permissionsChain) + } + worker { + this.title = "Валидация прав доступа" + description = "Проверка наличия прав для выполнения операции" + on { !permitted } + handle { + fail( + accessViolation( + principal = principal, + operation = command, + adId = adRepoRead.id, + ) + ) + } + } +} diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/ChainPermissions.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/ChainPermissions.kt new file mode 100644 index 0000000..657738b --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/ChainPermissions.kt @@ -0,0 +1,21 @@ +package ru.otus.otuskotlin.marketplace.biz.permissions + +import ru.otus.otuskotlin.marketplace.auth.resolveChainPermissions +import ru.otus.otuskotlin.marketplace.common.MkplContext +import ru.otus.otuskotlin.marketplace.common.models.MkplState +import ru.otus.otuskotlin.marketplace.cor.ICorChainDsl +import ru.otus.otuskotlin.marketplace.cor.worker + + +fun ICorChainDsl.chainPermissions(title: String) = worker { + this.title = title + description = "Вычисление прав доступа для групп пользователей" + + on { state == MkplState.RUNNING } + + handle { + permissionsChain.addAll(resolveChainPermissions(principal.groups)) + println("PRINCIPAL: $principal") + println("PERMISSIONS: $permissionsChain") + } +} diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/FrontPermissions.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/FrontPermissions.kt new file mode 100644 index 0000000..502cf65 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/FrontPermissions.kt @@ -0,0 +1,34 @@ +package ru.otus.otuskotlin.marketplace.biz.permissions + +import ru.otus.otuskotlin.marketplace.auth.resolveFrontPermissions +import ru.otus.otuskotlin.marketplace.auth.resolveRelationsTo +import ru.otus.otuskotlin.marketplace.common.MkplContext +import ru.otus.otuskotlin.marketplace.common.models.MkplState +import ru.otus.otuskotlin.marketplace.cor.ICorChainDsl +import ru.otus.otuskotlin.marketplace.cor.worker + +fun ICorChainDsl.frontPermissions(title: String) = worker { + this.title = title + description = "Вычисление разрешений пользователей для фронтенда" + + on { state == MkplState.RUNNING } + + handle { + adRepoDone.permissionsClient.addAll( + resolveFrontPermissions( + permissionsChain, + // Повторно вычисляем отношения, поскольку они могли измениться при выполении операции + adRepoDone.resolveRelationsTo(principal) + ) + ) + + for (ad in adsRepoDone) { + ad.permissionsClient.addAll( + resolveFrontPermissions( + permissionsChain, + ad.resolveRelationsTo(principal) + ) + ) + } + } +} diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/SearchType.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/SearchType.kt new file mode 100644 index 0000000..44fa73f --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/permissions/SearchType.kt @@ -0,0 +1,22 @@ +package ru.otus.otuskotlin.marketplace.biz.permissions + +import ru.otus.otuskotlin.marketplace.common.MkplContext +import ru.otus.otuskotlin.marketplace.common.models.MkplSearchPermissions +import ru.otus.otuskotlin.marketplace.common.models.MkplState +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserPermissions +import ru.otus.otuskotlin.marketplace.cor.ICorChainDsl +import ru.otus.otuskotlin.marketplace.cor.chain +import ru.otus.otuskotlin.marketplace.cor.worker + +fun ICorChainDsl.searchTypes(title: String) = chain { + this.title = title + description = "Добавление ограничений в поисковый запрос согласно правам доступа и др. политикам" + on { state == MkplState.RUNNING } + worker("Определение типа поиска") { + adFilterValidated.searchPermissions = setOfNotNull( + MkplSearchPermissions.OWN.takeIf { permissionsChain.contains(MkplUserPermissions.SEARCH_OWN) }, + MkplSearchPermissions.PUBLIC.takeIf { permissionsChain.contains(MkplUserPermissions.SEARCH_PUBLIC) }, + MkplSearchPermissions.REGISTERED.takeIf { permissionsChain.contains(MkplUserPermissions.SEARCH_REGISTERED) }, + ).toMutableSet() + } +} diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/repo/AdRepoPrepareCreate.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/repo/AdRepoPrepareCreate.kt index 7a18cbf..7950adc 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/repo/AdRepoPrepareCreate.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/repo/AdRepoPrepareCreate.kt @@ -4,7 +4,6 @@ import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.models.MkplState import ru.otus.otuskotlin.marketplace.cor.ICorChainDsl import ru.otus.otuskotlin.marketplace.cor.worker -import ru.otus.otuskotlin.marketplace.stubs.MkplAdStub fun ICorChainDsl.repoPrepareCreate(title: String) = worker { this.title = title @@ -12,7 +11,6 @@ fun ICorChainDsl.repoPrepareCreate(title: String) = worker { on { state == MkplState.RUNNING } handle { adRepoPrepare = adValidated.deepCopy() - // TODO будет реализовано в занятии по управлению пользвателями - adRepoPrepare.ownerId = MkplAdStub.get().ownerId + adRepoPrepare.ownerId = principal.id } } diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/repo/InitRepo.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/repo/InitRepo.kt index a3b7f41..21536e6 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/repo/InitRepo.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonMain/kotlin/repo/InitRepo.kt @@ -5,6 +5,7 @@ import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.helpers.errorSystem import ru.otus.otuskotlin.marketplace.common.helpers.fail import ru.otus.otuskotlin.marketplace.common.models.MkplWorkMode +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserGroups import ru.otus.otuskotlin.marketplace.common.repo.IRepoAd import ru.otus.otuskotlin.marketplace.cor.ICorChainDsl import ru.otus.otuskotlin.marketplace.cor.worker @@ -18,6 +19,7 @@ fun ICorChainDsl.initRepo(title: String) = worker { adRepo = when { workMode == MkplWorkMode.TEST -> corSettings.repoTest workMode == MkplWorkMode.STUB -> corSettings.repoStub + principal.groups.contains(MkplUserGroups.TEST) -> corSettings.repoTest else -> corSettings.repoProd } if (workMode != MkplWorkMode.STUB && adRepo == IRepoAd.NONE) fail( diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/AddTestPrincipal.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/AddTestPrincipal.kt new file mode 100644 index 0000000..fab4325 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/AddTestPrincipal.kt @@ -0,0 +1,17 @@ +package ru.otus.otuskotlin.marketplace.biz + +import ru.otus.otuskotlin.marketplace.common.MkplContext +import ru.otus.otuskotlin.marketplace.common.models.MkplUserId +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalModel +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserGroups +import ru.otus.otuskotlin.marketplace.stubs.MkplAdStubBolts + +fun MkplContext.addTestPrincipal(userId: MkplUserId = MkplAdStubBolts.AD_DEMAND_BOLT1.ownerId) { + principal = MkplPrincipalModel( + id = userId, + groups = setOf( + MkplUserGroups.USER, + MkplUserGroups.TEST, + ) + ) +} diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoCreateTest.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoCreateTest.kt index ab79cfa..1f68d57 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoCreateTest.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoCreateTest.kt @@ -3,17 +3,19 @@ package ru.otus.otuskotlin.marketplace.biz.repo import kotlinx.coroutines.test.runTest import ru.otus.otuskotlin.marketplace.backend.repo.tests.AdRepositoryMock import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.MkplCorSettings import ru.otus.otuskotlin.marketplace.common.models.* import ru.otus.otuskotlin.marketplace.common.repo.DbAdResponseOk +import ru.otus.otuskotlin.marketplace.stubs.MkplAdStubBolts import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotEquals class BizRepoCreateTest { - private val userId = MkplUserId("321") + private val userId = MkplAdStubBolts.AD_DEMAND_BOLT1.ownerId private val command = MkplCommand.CREATE private val uuid = "10000000-0000-0000-0000-000000000001" private val repo = AdRepositoryMock( @@ -48,6 +50,7 @@ class BizRepoCreateTest { visibility = MkplVisibility.VISIBLE_PUBLIC, ), ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(MkplState.FINISHING, ctx.state) assertNotEquals(MkplAdId.NONE, ctx.adResponse.id) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoDeleteTest.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoDeleteTest.kt index 8db1a15..28a7e50 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoDeleteTest.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoDeleteTest.kt @@ -4,18 +4,20 @@ import kotlinx.coroutines.test.runTest import repo.repoNotFoundTest import ru.otus.otuskotlin.marketplace.backend.repo.tests.AdRepositoryMock import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.MkplCorSettings import ru.otus.otuskotlin.marketplace.common.models.* import ru.otus.otuskotlin.marketplace.common.repo.DbAdResponseErr import ru.otus.otuskotlin.marketplace.common.repo.DbAdResponseOk +import ru.otus.otuskotlin.marketplace.stubs.MkplAdStubBolts import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue class BizRepoDeleteTest { - private val userId = MkplUserId("321") + private val userId = MkplAdStubBolts.AD_DEMAND_BOLT1.ownerId private val command = MkplCommand.DELETE private val initAd = MkplAd( id = MkplAdId("123"), @@ -59,6 +61,7 @@ class BizRepoDeleteTest { workMode = MkplWorkMode.TEST, adRequest = adToUpdate, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(MkplState.FINISHING, ctx.state) assertTrue { ctx.errors.isEmpty() } diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoOffersTest.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoOffersTest.kt index d58fd97..a9196b8 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoOffersTest.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoOffersTest.kt @@ -4,17 +4,19 @@ import kotlinx.coroutines.test.runTest import repo.repoNotFoundTest import ru.otus.otuskotlin.marketplace.backend.repo.tests.AdRepositoryMock import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.MkplCorSettings import ru.otus.otuskotlin.marketplace.common.models.* import ru.otus.otuskotlin.marketplace.common.repo.DbAdResponseOk import ru.otus.otuskotlin.marketplace.common.repo.DbAdsResponseOk +import ru.otus.otuskotlin.marketplace.stubs.MkplAdStubBolts import kotlin.test.Test import kotlin.test.assertEquals class BizRepoOffersTest { - private val userId = MkplUserId("321") + private val userId = MkplAdStubBolts.AD_DEMAND_BOLT1.ownerId private val command = MkplCommand.OFFERS private val initAd = MkplAd( id = MkplAdId("123"), @@ -58,6 +60,7 @@ class BizRepoOffersTest { id = MkplAdId("123"), ), ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(MkplState.FINISHING, ctx.state) assertEquals(1, ctx.adsResponse.size) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoReadTest.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoReadTest.kt index 0791718..cf55816 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoReadTest.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoReadTest.kt @@ -4,16 +4,18 @@ import kotlinx.coroutines.test.runTest import repo.repoNotFoundTest import ru.otus.otuskotlin.marketplace.backend.repo.tests.AdRepositoryMock import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.MkplCorSettings import ru.otus.otuskotlin.marketplace.common.models.* import ru.otus.otuskotlin.marketplace.common.repo.DbAdResponseOk +import ru.otus.otuskotlin.marketplace.stubs.MkplAdStubBolts import kotlin.test.Test import kotlin.test.assertEquals class BizRepoReadTest { - private val userId = MkplUserId("321") + private val userId = MkplAdStubBolts.AD_DEMAND_BOLT1.ownerId private val command = MkplCommand.READ private val initAd = MkplAd( id = MkplAdId("123"), @@ -43,6 +45,7 @@ class BizRepoReadTest { id = MkplAdId("123"), ), ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(MkplState.FINISHING, ctx.state) assertEquals(initAd.id, ctx.adResponse.id) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoSearchTest.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoSearchTest.kt index a5fb7db..4ebdce6 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoSearchTest.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoSearchTest.kt @@ -3,16 +3,18 @@ package ru.otus.otuskotlin.marketplace.biz.repo import kotlinx.coroutines.test.runTest import ru.otus.otuskotlin.marketplace.backend.repo.tests.AdRepositoryMock import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.MkplCorSettings import ru.otus.otuskotlin.marketplace.common.models.* import ru.otus.otuskotlin.marketplace.common.repo.DbAdsResponseOk +import ru.otus.otuskotlin.marketplace.stubs.MkplAdStubBolts import kotlin.test.Test import kotlin.test.assertEquals class BizRepoSearchTest { - private val userId = MkplUserId("321") + private val userId = MkplAdStubBolts.AD_DEMAND_BOLT1.ownerId private val command = MkplCommand.SEARCH private val initAd = MkplAd( id = MkplAdId("123"), @@ -43,6 +45,7 @@ class BizRepoSearchTest { dealSide = MkplDealSide.DEMAND ), ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(MkplState.FINISHING, ctx.state) assertEquals(1, ctx.adsResponse.size) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoUpdateTest.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoUpdateTest.kt index 097af20..4aef381 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoUpdateTest.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/BizRepoUpdateTest.kt @@ -4,16 +4,18 @@ import kotlinx.coroutines.test.runTest import repo.repoNotFoundTest import ru.otus.otuskotlin.marketplace.backend.repo.tests.AdRepositoryMock import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.MkplCorSettings import ru.otus.otuskotlin.marketplace.common.models.* import ru.otus.otuskotlin.marketplace.common.repo.DbAdResponseOk +import ru.otus.otuskotlin.marketplace.stubs.MkplAdStubBolts import kotlin.test.Test import kotlin.test.assertEquals class BizRepoUpdateTest { - private val userId = MkplUserId("321") + private val userId = MkplAdStubBolts.AD_DEMAND_BOLT1.ownerId private val command = MkplCommand.UPDATE private val initAd = MkplAd( id = MkplAdId("123"), @@ -62,6 +64,7 @@ class BizRepoUpdateTest { workMode = MkplWorkMode.TEST, adRequest = adToUpdate, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(MkplState.FINISHING, ctx.state) assertEquals(adToUpdate.id, ctx.adResponse.id) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/RepoByIdTests.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/RepoByIdTests.kt index 046230f..b5dd139 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/RepoByIdTests.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/repo/RepoByIdTests.kt @@ -3,6 +3,7 @@ package repo import kotlinx.coroutines.test.runTest import ru.otus.otuskotlin.marketplace.backend.repo.tests.AdRepositoryMock import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.MkplCorSettings import ru.otus.otuskotlin.marketplace.common.models.* @@ -44,6 +45,7 @@ fun repoNotFoundTest(command: MkplCommand) = runTest { lock = MkplAdLock("123-234-abc-ABC"), ), ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(MkplState.FAILING, ctx.state) assertEquals(MkplAd(), ctx.adResponse) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidateSearchStringLengthTest.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidateSearchStringLengthTest.kt index 1198328..49bab22 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidateSearchStringLengthTest.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidateSearchStringLengthTest.kt @@ -1,5 +1,6 @@ package ru.otus.otuskotlin.marketplace.biz.validation +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.models.MkplAdFilter import ru.otus.otuskotlin.marketplace.common.models.MkplState @@ -19,6 +20,7 @@ class ValidateSearchStringLengthTest { @Test fun blankString() = runBizTest { val ctx = MkplContext(state = MkplState.RUNNING, adFilterValidating = MkplAdFilter(searchString = " ")) + ctx.addTestPrincipal() chain.exec(ctx) assertEquals(MkplState.RUNNING, ctx.state) assertEquals(0, ctx.errors.size) @@ -27,6 +29,7 @@ class ValidateSearchStringLengthTest { @Test fun shortString() = runBizTest { val ctx = MkplContext(state = MkplState.RUNNING, adFilterValidating = MkplAdFilter(searchString = "12")) + ctx.addTestPrincipal() chain.exec(ctx) assertEquals(MkplState.FAILING, ctx.state) assertEquals(1, ctx.errors.size) @@ -36,6 +39,7 @@ class ValidateSearchStringLengthTest { @Test fun normalString() = runBizTest { val ctx = MkplContext(state = MkplState.RUNNING, adFilterValidating = MkplAdFilter(searchString = "123")) + ctx.addTestPrincipal() chain.exec(ctx) assertEquals(MkplState.RUNNING, ctx.state) assertEquals(0, ctx.errors.size) @@ -44,6 +48,7 @@ class ValidateSearchStringLengthTest { @Test fun longString() = runBizTest { val ctx = MkplContext(state = MkplState.RUNNING, adFilterValidating = MkplAdFilter(searchString = "12".repeat(51))) + ctx.addTestPrincipal() chain.exec(ctx) assertEquals(MkplState.FAILING, ctx.state) assertEquals(1, ctx.errors.size) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidateTitleHasContentTest.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidateTitleHasContentTest.kt index 11408f9..db4f52b 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidateTitleHasContentTest.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidateTitleHasContentTest.kt @@ -1,5 +1,6 @@ package ru.otus.otuskotlin.marketplace.biz.validation +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.models.MkplAd import ru.otus.otuskotlin.marketplace.common.models.MkplAdFilter @@ -12,6 +13,7 @@ class ValidateTitleHasContentTest { @Test fun emptyString() = runBizTest { val ctx = MkplContext(state = MkplState.RUNNING, adValidating = MkplAd(title = "")) + ctx.addTestPrincipal() chain.exec(ctx) assertEquals(MkplState.RUNNING, ctx.state) assertEquals(0, ctx.errors.size) @@ -20,6 +22,7 @@ class ValidateTitleHasContentTest { @Test fun noContent() = runBizTest { val ctx = MkplContext(state = MkplState.RUNNING, adValidating = MkplAd(title = "12!@#$%^&*()_+-=")) + ctx.addTestPrincipal() chain.exec(ctx) assertEquals(MkplState.FAILING, ctx.state) assertEquals(1, ctx.errors.size) @@ -29,6 +32,7 @@ class ValidateTitleHasContentTest { @Test fun normalString() = runBizTest { val ctx = MkplContext(state = MkplState.RUNNING, adFilterValidating = MkplAdFilter(searchString = "Ж")) + ctx.addTestPrincipal() chain.exec(ctx) assertEquals(MkplState.RUNNING, ctx.state) assertEquals(0, ctx.errors.size) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadDescription.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadDescription.kt index 5dc8163..eaf3766 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadDescription.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadDescription.kt @@ -1,6 +1,7 @@ package ru.otus.otuskotlin.marketplace.biz.validation import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.models.MkplCommand import ru.otus.otuskotlin.marketplace.common.models.MkplState @@ -17,6 +18,7 @@ fun validationDescriptionCorrect(command: MkplCommand, processor: MkplAdProcesso workMode = MkplWorkMode.TEST, adRequest = MkplAdStub.get(), ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(0, ctx.errors.size) assertNotEquals(MkplState.FAILING, ctx.state) @@ -32,6 +34,7 @@ fun validationDescriptionTrim(command: MkplCommand, processor: MkplAdProcessor) description = " \n\tabc \n\t" }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(0, ctx.errors.size) assertNotEquals(MkplState.FAILING, ctx.state) @@ -47,6 +50,7 @@ fun validationDescriptionEmpty(command: MkplCommand, processor: MkplAdProcessor) description = "" }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(1, ctx.errors.size) assertEquals(MkplState.FAILING, ctx.state) @@ -64,6 +68,7 @@ fun validationDescriptionSymbols(command: MkplCommand, processor: MkplAdProcesso description = "!@#$%^&*(),.{}" }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(1, ctx.errors.size) assertEquals(MkplState.FAILING, ctx.state) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadId.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadId.kt index d6fb823..2d95a31 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadId.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadId.kt @@ -1,6 +1,7 @@ package ru.otus.otuskotlin.marketplace.biz.validation import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.models.MkplAdId import ru.otus.otuskotlin.marketplace.common.models.MkplCommand @@ -18,6 +19,7 @@ fun validationIdCorrect(command: MkplCommand, processor: MkplAdProcessor) = runB workMode = MkplWorkMode.TEST, adRequest = MkplAdStub.get(), ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(0, ctx.errors.size) assertNotEquals(MkplState.FAILING, ctx.state) @@ -32,6 +34,7 @@ fun validationIdTrim(command: MkplCommand, processor: MkplAdProcessor) = runBizT id = MkplAdId(" \n\t ${id.asString()} \n\t ") }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(0, ctx.errors.size) assertNotEquals(MkplState.FAILING, ctx.state) @@ -46,6 +49,7 @@ fun validationIdEmpty(command: MkplCommand, processor: MkplAdProcessor) = runBiz id = MkplAdId("") }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(1, ctx.errors.size) assertEquals(MkplState.FAILING, ctx.state) @@ -63,6 +67,7 @@ fun validationIdFormat(command: MkplCommand, processor: MkplAdProcessor) = runBi id = MkplAdId("!@#\$%^&*(),.{}") }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(1, ctx.errors.size) assertEquals(MkplState.FAILING, ctx.state) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadLock.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadLock.kt index c8caf14..1775d45 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadLock.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadLock.kt @@ -1,6 +1,7 @@ package validation import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.biz.validation.runBizTest import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.models.MkplAdLock @@ -19,6 +20,7 @@ fun validationLockCorrect(command: MkplCommand, processor: MkplAdProcessor) = ru workMode = MkplWorkMode.TEST, adRequest = MkplAdStub.get(), ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(0, ctx.errors.size) assertNotEquals(MkplState.FAILING, ctx.state) @@ -33,6 +35,7 @@ fun validationLockTrim(command: MkplCommand, processor: MkplAdProcessor) = runBi lock = MkplAdLock(" \n\t 123-234-abc-ABC \n\t ") }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(0, ctx.errors.size) assertNotEquals(MkplState.FAILING, ctx.state) @@ -47,6 +50,7 @@ fun validationLockEmpty(command: MkplCommand, processor: MkplAdProcessor) = runB lock = MkplAdLock("") }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(1, ctx.errors.size) assertEquals(MkplState.FAILING, ctx.state) @@ -64,6 +68,7 @@ fun validationLockFormat(command: MkplCommand, processor: MkplAdProcessor) = run lock = MkplAdLock("!@#\$%^&*(),.{}") }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(1, ctx.errors.size) assertEquals(MkplState.FAILING, ctx.state) diff --git a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadTitle.kt b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadTitle.kt index e95c729..716aba9 100644 --- a/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadTitle.kt +++ b/ok-marketplace-be/ok-marketplace-biz/src/commonTest/kotlin/validation/ValidationBadTitle.kt @@ -1,6 +1,7 @@ package ru.otus.otuskotlin.marketplace.biz.validation import ru.otus.otuskotlin.marketplace.biz.MkplAdProcessor +import ru.otus.otuskotlin.marketplace.biz.addTestPrincipal import ru.otus.otuskotlin.marketplace.common.MkplContext import ru.otus.otuskotlin.marketplace.common.models.MkplCommand import ru.otus.otuskotlin.marketplace.common.models.MkplState @@ -19,6 +20,7 @@ fun validationTitleCorrect(command: MkplCommand, processor: MkplAdProcessor) = r title = "abc" }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(0, ctx.errors.size) assertNotEquals(MkplState.FAILING, ctx.state) @@ -34,6 +36,7 @@ fun validationTitleTrim(command: MkplCommand, processor: MkplAdProcessor) = runB title = " \n\t abc \t\n " }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(0, ctx.errors.size) assertNotEquals(MkplState.FAILING, ctx.state) @@ -49,6 +52,7 @@ fun validationTitleEmpty(command: MkplCommand, processor: MkplAdProcessor) = run title = "" }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(1, ctx.errors.size) assertEquals(MkplState.FAILING, ctx.state) @@ -66,6 +70,7 @@ fun validationTitleSymbols(command: MkplCommand, processor: MkplAdProcessor) = r title = "!@#$%^&*(),.{}" }, ) + ctx.addTestPrincipal() processor.exec(ctx) assertEquals(1, ctx.errors.size) assertEquals(MkplState.FAILING, ctx.state) diff --git a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/MkplContext.kt b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/MkplContext.kt index 1520a0d..e2a7720 100644 --- a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/MkplContext.kt +++ b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/MkplContext.kt @@ -2,6 +2,8 @@ package ru.otus.otuskotlin.marketplace.common import kotlinx.datetime.Instant import ru.otus.otuskotlin.marketplace.common.models.* +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalModel +import ru.otus.otuskotlin.marketplace.common.permissions.MkplUserPermissions import ru.otus.otuskotlin.marketplace.common.repo.IRepoAd import ru.otus.otuskotlin.marketplace.common.stubs.MkplStubs import ru.otus.otuskotlin.marketplace.common.ws.IMkplWsSession @@ -17,6 +19,10 @@ data class MkplContext( var stubCase: MkplStubs = MkplStubs.NONE, var wsSession: IMkplWsSession = IMkplWsSession.NONE, + var principal: MkplPrincipalModel = MkplPrincipalModel.NONE, + val permissionsChain: MutableSet = mutableSetOf(), + var permitted: Boolean = false, + var requestId: MkplRequestId = MkplRequestId.NONE, var timeStart: Instant = Instant.NONE, var adRequest: MkplAd = MkplAd(), diff --git a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/helpers/MkplErrorsHelpers.kt b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/helpers/MkplErrorsHelpers.kt index 1b00166..25555b6 100644 --- a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/helpers/MkplErrorsHelpers.kt +++ b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/helpers/MkplErrorsHelpers.kt @@ -1,8 +1,8 @@ package ru.otus.otuskotlin.marketplace.common.helpers import ru.otus.otuskotlin.marketplace.common.MkplContext -import ru.otus.otuskotlin.marketplace.common.models.MkplError -import ru.otus.otuskotlin.marketplace.common.models.MkplState +import ru.otus.otuskotlin.marketplace.common.models.* +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalModel import ru.otus.otuskotlin.marketplace.logging.common.LogLevel fun Throwable.asMkplError( @@ -17,20 +17,20 @@ fun Throwable.asMkplError( exception = this, ) -inline fun MkplContext.addError(error: MkplError) = errors.add(error) -inline fun MkplContext.addErrors(error: Collection) = errors.addAll(error) +fun MkplContext.addError(error: MkplError) = errors.add(error) +fun MkplContext.addErrors(error: Collection) = errors.addAll(error) -inline fun MkplContext.fail(error: MkplError) { +fun MkplContext.fail(error: MkplError) { addError(error) state = MkplState.FAILING } -inline fun MkplContext.fail(errors: Collection) { +fun MkplContext.fail(errors: Collection) { addErrors(errors) state = MkplState.FAILING } -inline fun errorValidation( +fun errorValidation( field: String, /** * Код, характеризующий ошибку. Не должен включать имя поля или указание на валидацию. @@ -47,7 +47,7 @@ inline fun errorValidation( level = level, ) -inline fun errorSystem( +fun errorSystem( violationCode: String, level: LogLevel = LogLevel.ERROR, e: Throwable, @@ -58,3 +58,15 @@ inline fun errorSystem( level = level, exception = e, ) + +fun accessViolation( + principal: MkplPrincipalModel, + operation: MkplCommand, + adId: MkplAdId = MkplAdId.NONE, +) = MkplError( + code = "access-${operation.name.lowercase()}", + group = "access", + message = "User ${principal.genericName()} (${principal.id.asString()}) is not allowed to perform operation ${operation.name}" + + if (adId != MkplAdId.NONE) " on ad ${adId.asString()}" else "", + level = LogLevel.ERROR, +) diff --git a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplAd.kt b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplAd.kt index 9dc0efe..85f0342 100644 --- a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplAd.kt +++ b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplAd.kt @@ -1,5 +1,6 @@ package ru.otus.otuskotlin.marketplace.common.models +import ru.otus.otuskotlin.marketplace.common.permissions.MkplPrincipalRelations import ru.otus.otuskotlin.marketplace.states.common.statemachine.SMAdStates data class MkplAd( @@ -11,6 +12,10 @@ data class MkplAd( var visibility: MkplVisibility = MkplVisibility.NONE, var productId: MkplProductId = MkplProductId.NONE, var lock: MkplAdLock = MkplAdLock.NONE, + + // Результат вычисления отношений текущего пользователя (который сделал запрос) к текущему объявлению + var principalRelations: Set = emptySet(), + // Набор пермишинов, которые отдадим во фронтенд val permissionsClient: MutableSet = mutableSetOf(), var adState: SMAdStates = SMAdStates.NONE, diff --git a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplAdFilter.kt b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplAdFilter.kt index ccb155b..6d71a92 100644 --- a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplAdFilter.kt +++ b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplAdFilter.kt @@ -4,6 +4,7 @@ data class MkplAdFilter( var searchString: String = "", var ownerId: MkplUserId = MkplUserId.NONE, var dealSide: MkplDealSide = MkplDealSide.NONE, + var searchPermissions: MutableSet = mutableSetOf(), ) { fun deepCopy(): MkplAdFilter = copy() diff --git a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplSearchPermissions.kt b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplSearchPermissions.kt new file mode 100644 index 0000000..675fbd9 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/models/MkplSearchPermissions.kt @@ -0,0 +1,7 @@ +package ru.otus.otuskotlin.marketplace.common.models + +enum class MkplSearchPermissions { + OWN, + PUBLIC, + REGISTERED, +} diff --git a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplPrincipalModel.kt b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplPrincipalModel.kt new file mode 100644 index 0000000..56b6a0a --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplPrincipalModel.kt @@ -0,0 +1,16 @@ +package ru.otus.otuskotlin.marketplace.common.permissions + +import ru.otus.otuskotlin.marketplace.common.models.MkplUserId + +data class MkplPrincipalModel( + val id: MkplUserId = MkplUserId.NONE, + val fname: String = "", + val mname: String = "", + val lname: String = "", + val groups: Set = emptySet() +) { + fun genericName() = "$fname $mname $lname" + companion object { + val NONE = MkplPrincipalModel() + } +} diff --git a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplPrincipalRelations.kt b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplPrincipalRelations.kt new file mode 100644 index 0000000..5e77fb5 --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplPrincipalRelations.kt @@ -0,0 +1,10 @@ +package ru.otus.otuskotlin.marketplace.common.permissions + +enum class MkplPrincipalRelations { + NONE, + NEW, + OWN, + GROUP, + PUBLIC, + MODERATABLE, +} diff --git a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplUserGroups.kt b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplUserGroups.kt new file mode 100644 index 0000000..fab09ea --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplUserGroups.kt @@ -0,0 +1,9 @@ +package ru.otus.otuskotlin.marketplace.common.permissions + +enum class MkplUserGroups { + USER, + ADMIN_AD, + MODERATOR_MP, + TEST, + BAN_AD +} diff --git a/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplUserPermissions.kt b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplUserPermissions.kt new file mode 100644 index 0000000..aca34be --- /dev/null +++ b/ok-marketplace-be/ok-marketplace-common/src/commonMain/kotlin/permissions/MkplUserPermissions.kt @@ -0,0 +1,26 @@ +package ru.otus.otuskotlin.marketplace.common.permissions + +@Suppress("unused") +enum class MkplUserPermissions { + CREATE_OWN, + + READ_OWN, + READ_GROUP, + READ_PUBLIC, + READ_CANDIDATE, + + UPDATE_OWN, + UPDATE_CANDIDATE, + UPDATE_PUBLIC, + + DELETE_OWN, + DELETE_CANDIDATE, + DELETE_PUBLIC, + + SEARCH_OWN, + SEARCH_PUBLIC, + SEARCH_REGISTERED, + SEARCH_DRAFTS, + + OFFER_FOR_OWN, +} diff --git a/ok-marketplace-be/ok-marketplace-stubs/src/commonMain/kotlin/MkplAdStubBolts.kt b/ok-marketplace-be/ok-marketplace-stubs/src/commonMain/kotlin/MkplAdStubBolts.kt index 6549ca0..4ab25c4 100644 --- a/ok-marketplace-be/ok-marketplace-stubs/src/commonMain/kotlin/MkplAdStubBolts.kt +++ b/ok-marketplace-be/ok-marketplace-stubs/src/commonMain/kotlin/MkplAdStubBolts.kt @@ -16,9 +16,6 @@ object MkplAdStubBolts { MkplAdPermissionClient.READ, MkplAdPermissionClient.UPDATE, MkplAdPermissionClient.DELETE, - MkplAdPermissionClient.MAKE_VISIBLE_PUBLIC, - MkplAdPermissionClient.MAKE_VISIBLE_GROUP, - MkplAdPermissionClient.MAKE_VISIBLE_OWNER, ) ) val AD_SUPPLY_BOLT1 = AD_DEMAND_BOLT1.copy(adType = MkplDealSide.SUPPLY) diff --git a/ok-marketplace-be/settings.gradle.kts b/ok-marketplace-be/settings.gradle.kts index 1bf5c7c..0b67bb0 100644 --- a/ok-marketplace-be/settings.gradle.kts +++ b/ok-marketplace-be/settings.gradle.kts @@ -53,3 +53,6 @@ include(":ok-marketplace-repo-postgres") include(":ok-marketplace-repo-cassandra") include(":ok-marketplace-repo-gremlin") +// Auth +include(":ok-marketplace-auth") + diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/build.gradle.kts b/ok-marketplace-tests/ok-marketplace-e2e-be/build.gradle.kts index f7cbeed..dc93dd0 100644 --- a/ok-marketplace-tests/ok-marketplace-e2e-be/build.gradle.kts +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("build-jvm") + alias(libs.plugins.kotlinx.serialization) } dependencies { @@ -21,9 +22,8 @@ dependencies { testImplementation(libs.ktor.client.core) testImplementation(libs.ktor.client.okhttp) -// testImplementation("io.ktor:ktor-client-core:$ktorVersion") -// testImplementation("io.ktor:ktor-client-okhttp:$ktorVersion") -// testImplementation("io.ktor:ktor-client-okhttp-jvm:$ktorVersion") + testImplementation(libs.kotlinx.serialization.core) + testImplementation(libs.kotlinx.serialization.json) } var severity: String = "MINOR" diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/docker-compose-ktor-keycloak-jvm.yml b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/docker-compose-ktor-keycloak-jvm.yml new file mode 100644 index 0000000..a0588df --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/docker-compose-ktor-keycloak-jvm.yml @@ -0,0 +1,47 @@ +services: + app: + image: ok-marketplace-app-ktor-x64:0.0.1 + environment: + DB_TYPE_PROD: "mem" + + envoy: + image: envoyproxy/envoy:v1.29.0 # Use the official Envoy proxy image + volumes: + - ./volumes/envoy/envoy.yaml:/etc/envoy/envoy.yaml # Mount your Envoy configuration file + # - ./envoy/certs:/etc/envoy/certs # Mount your TLS certificates + ports: + - "8080:8080" + depends_on: + keycloak: + condition: service_healthy + + keycloak: + image: quay.io/keycloak/keycloak:24.0.4 +# ports: +# - "8081:8080" + volumes: + # - ./keycloak:/tmp + - ./volumes/keycloak/import:/opt/keycloak/data/import + # - ./keycloak/standalone.xml:/opt/jboss/keycloak/standalone/configuration/standalone.xml + # - ./keycloak/certs/keycloak.jks:/etc/x509/https/keystore # Mount your Keycloak keystore + environment: + KEYCLOAK_USER: otus + KEYCLOAK_PASSWORD: otus + KEYCLOAK_ADMIN: admin + KEYCLOAK_ADMIN_PASSWORD: admin + KEYCLOAK_IMPORT: "/tmp/realm-export.json" + KC_HEALTH_ENABLED: "true" + KC_HOSTNAME_URL: "http://localhost:8080/" + healthcheck: + test: [ "CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/8080;echo -e \"GET /health/ready HTTP/1.1\r\nhost: http://localhost\r\nConnection: close\r\n\r\n\" >&3;grep \"HTTP/1.1 200 OK\" <&3"] + interval: 10s + timeout: 5s + retries: 5 + command: + - start-dev + # - --features admin-fine-grained-authz + - --hostname-port=8081 + - --import-realm +# - --proxy edge + - --proxy-headers=forwarded + - --hostname-strict=false diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/envoy/envoy.yaml b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/envoy/envoy.yaml new file mode 100644 index 0000000..7ce9ec1 --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/envoy/envoy.yaml @@ -0,0 +1,90 @@ +admin: + access_log_path: /tmp/admin_access.log + address: + socket_address: + address: 0.0.0.0 + port_value: 15001 + +static_resources: + listeners: + - name: listener_app + address: + socket_address: + address: 0.0.0.0 + port_value: 8080 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: [ "*" ] + routes: + - match: { path: "/" } + route: { cluster: app } + - match: { prefix: "/v1/ad/" } + route: { cluster: app } + - match: { prefix: "/v2/ad/" } + route: { cluster: app } + - match: { prefix: "/realms/" } + route: { cluster: keycloak } + - match: { prefix: "/resources/" } + route: { cluster: keycloak } + http_filters: + - name: envoy.filters.http.jwt_authn + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication + providers: + keycloak_provider: + issuer: "http://localhost:8080/realms/otus-marketplace" + remote_jwks: + http_uri: + uri: http://keycloak:8080/realms/otus-marketplace/protocol/openid-connect/certs + cluster: keycloak + timeout: 5s + cache_duration: + seconds: 300 + # Пробрасываем JWT в заголовок запроса + forward: true + forward_payload_header: x-jwt-payload + rules: + - match: { prefix: /v1/ad/ } + requires: { provider_name: keycloak_provider } + - match: { prefix: /v2/ad/ } + requires: { provider_name: keycloak_provider } + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + clusters: + - name: app + connect_timeout: 30s + type: LOGICAL_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: app + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: app + port_value: 8080 + + - name: keycloak + connect_timeout: 0.25s + type: LOGICAL_DNS + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: keycloak + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: keycloak + port_value: 8080 diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/.gitignore b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/.gitignore new file mode 100644 index 0000000..2cb7f86 --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/.gitignore @@ -0,0 +1,3 @@ +/hsperfdata_*/ +/certs/ +/vertx-cache/ diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/master-realm.json b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/master-realm.json new file mode 100644 index 0000000..fa6425d --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/master-realm.json @@ -0,0 +1,1953 @@ +{ + "id" : "7f8cfc97-2875-4eb4-9868-090cd03d39ce", + "realm" : "master", + "displayName" : "Keycloak", + "displayNameHtml" : "
Keycloak
", + "notBefore" : 0, + "defaultSignatureAlgorithm" : "RS256", + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 60, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 1800, + "ssoSessionMaxLifespan" : 36000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "clientSessionIdleTimeout" : 0, + "clientSessionMaxLifespan" : 0, + "clientOfflineSessionIdleTimeout" : 0, + "clientOfflineSessionMaxLifespan" : 0, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "oauth2DeviceCodeLifespan" : 600, + "oauth2DevicePollingInterval" : 5, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "a7c7fc13-0b30-4d39-9037-bfd7b8251952", + "name" : "admin", + "description" : "${role_admin}", + "composite" : true, + "composites" : { + "realm" : [ "create-realm" ], + "client" : { + "otus-marketplace-realm" : [ "manage-clients", "impersonation", "query-users", "view-authorization", "view-clients", "view-events", "query-groups", "manage-events", "view-users", "manage-users", "manage-authorization", "view-identity-providers", "manage-identity-providers", "manage-realm", "query-realms", "create-client", "query-clients", "view-realm" ], + "master-realm" : [ "create-client", "manage-realm", "manage-users", "view-clients", "view-realm", "manage-clients", "view-authorization", "query-groups", "manage-identity-providers", "view-users", "manage-authorization", "view-identity-providers", "impersonation", "query-users", "view-events", "query-realms", "query-clients", "manage-events" ] + } + }, + "clientRole" : false, + "containerId" : "7f8cfc97-2875-4eb4-9868-090cd03d39ce", + "attributes" : { } + }, { + "id" : "8388cf9b-7682-43b4-ab30-f1ab7de66eef", + "name" : "default-roles-master", + "description" : "${role_default-roles}", + "composite" : true, + "composites" : { + "realm" : [ "offline_access", "uma_authorization" ], + "client" : { + "account" : [ "manage-account", "view-profile" ] + } + }, + "clientRole" : false, + "containerId" : "7f8cfc97-2875-4eb4-9868-090cd03d39ce", + "attributes" : { } + }, { + "id" : "cf16f949-516e-40a6-94b8-6b83bdb2f40c", + "name" : "create-realm", + "description" : "${role_create-realm}", + "composite" : false, + "clientRole" : false, + "containerId" : "7f8cfc97-2875-4eb4-9868-090cd03d39ce", + "attributes" : { } + }, { + "id" : "f7ec1ca9-753c-4b4b-a90a-ea51397aa878", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "7f8cfc97-2875-4eb4-9868-090cd03d39ce", + "attributes" : { } + }, { + "id" : "42a49ea2-5c39-4785-ab2d-b353ab4a998b", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "7f8cfc97-2875-4eb4-9868-090cd03d39ce", + "attributes" : { } + } ], + "client" : { + "security-admin-console" : [ ], + "otus-marketplace-realm" : [ { + "id" : "5eee687b-e738-46b6-89e2-35be4ced4571", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "c6c5f707-70b9-4d2e-8c14-a5e2a8d874c9", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "58c6e24c-974e-424d-ba2a-226cbefbd53e", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "4a3e45f8-0063-4583-93a5-392d3e1e077a", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "d81c195d-ba79-4039-a28c-52f63b691531", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "9e81328b-8c54-40a8-b097-6fdd731cc118", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "otus-marketplace-realm" : [ "query-groups", "query-users" ] + } + }, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "c36ffae0-1a8f-466c-824b-c8fe4779807c", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "3769b8cc-8b04-4cf0-b9b4-35b196e049de", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "ecc55a5f-fcad-4be3-9d12-5fa4eb9e8fad", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "fd11aa26-f415-4a30-a592-0a4cb3f8a145", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "e39c1dc3-c991-4f81-b124-2f649d23298a", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "d985caf7-6e35-48bc-bae3-8bb1f42345bb", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "d23944ff-1a82-46e2-b3dd-59d00bb9f399", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "otus-marketplace-realm" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "ff39faa8-8773-4270-b646-b3870bb56cd2", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "709a4de3-138d-46f1-9a68-859b88bb930d", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "b965f47f-15ea-4ca8-bd77-2bb0d89501b2", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "a97a5256-f3e4-405f-b62b-70365b71db93", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + }, { + "id" : "8aa9dce6-f419-42f2-8c9e-25a68faee799", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "attributes" : { } + } ], + "admin-cli" : [ ], + "account-console" : [ ], + "broker" : [ { + "id" : "0f3e4ec6-92ce-4f03-9c03-2c4c8b8f67da", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "a303d9ea-209a-466d-82cf-1916d6c0b0dc", + "attributes" : { } + } ], + "master-realm" : [ { + "id" : "42928f22-20ea-463f-93e6-a1479ad0625a", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "bdde852c-3d46-4d61-879f-005dd6b2bcee", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "aeac2961-709a-479a-816e-f268eeae9c55", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "master-realm" : [ "query-users", "query-groups" ] + } + }, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "6a7e1ae7-fd49-440d-abb0-92eb17314818", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "d30c7ec3-c5a2-40b4-9d73-c447482aaecd", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "08bd69ec-3471-4b41-89cc-d95933d69e33", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "41063bd8-5087-47da-8e57-238ad1a2f758", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "0cde41a8-c7fe-4795-88ea-4fa6dce883bd", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "f4126086-f35d-47a7-9c04-ed5a2f589af4", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "a35f6b95-bd5c-4e1f-95a5-b1609012df02", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "a5aabb0a-4c6a-4113-8663-87ea8e353e5b", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "2b7c728c-0747-4b33-857d-52c4cfbc3220", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "master-realm" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "80db49a0-0b82-40eb-9008-5e40ef29fc00", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "fde4c263-982d-4dc1-8faf-b7df5bbad4c3", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "d574dae0-9249-4866-aa46-4ff6016c8543", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "9d466a94-704f-4041-9843-f08b519cbfe9", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "7c7a10ba-6952-49be-8361-ba8de3168356", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + }, { + "id" : "9227ffc5-9a02-46d5-8ebc-3021209fbe80", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "attributes" : { } + } ], + "account" : [ { + "id" : "48bea54f-f979-4fb6-ac15-715265976ca0", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "d3782eab-764d-4eee-bb6b-5f93014fa62c", + "attributes" : { } + }, { + "id" : "3d7ac2e0-f7b4-47f9-bdce-08576f75a8f9", + "name" : "delete-account", + "description" : "${role_delete-account}", + "composite" : false, + "clientRole" : true, + "containerId" : "d3782eab-764d-4eee-bb6b-5f93014fa62c", + "attributes" : { } + }, { + "id" : "6897e4fb-edf2-4a99-857d-515502e44726", + "name" : "manage-consent", + "description" : "${role_manage-consent}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "view-consent" ] + } + }, + "clientRole" : true, + "containerId" : "d3782eab-764d-4eee-bb6b-5f93014fa62c", + "attributes" : { } + }, { + "id" : "cfe739ad-deb0-46d4-af20-200133942b45", + "name" : "view-consent", + "description" : "${role_view-consent}", + "composite" : false, + "clientRole" : true, + "containerId" : "d3782eab-764d-4eee-bb6b-5f93014fa62c", + "attributes" : { } + }, { + "id" : "1323b804-c291-4adf-bec2-17a439480fd3", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } + }, + "clientRole" : true, + "containerId" : "d3782eab-764d-4eee-bb6b-5f93014fa62c", + "attributes" : { } + }, { + "id" : "50165505-262b-4a3e-a292-55fad4109934", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "d3782eab-764d-4eee-bb6b-5f93014fa62c", + "attributes" : { } + }, { + "id" : "c7c85106-abbe-4f95-ba72-0b11650e6b33", + "name" : "view-groups", + "description" : "${role_view-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "d3782eab-764d-4eee-bb6b-5f93014fa62c", + "attributes" : { } + }, { + "id" : "340e77d1-0cdf-41cc-a756-e69e51ca17c3", + "name" : "view-applications", + "description" : "${role_view-applications}", + "composite" : false, + "clientRole" : true, + "containerId" : "d3782eab-764d-4eee-bb6b-5f93014fa62c", + "attributes" : { } + } ] + } + }, + "groups" : [ ], + "defaultRole" : { + "id" : "8388cf9b-7682-43b4-ab30-f1ab7de66eef", + "name" : "default-roles-master", + "description" : "${role_default-roles}", + "composite" : true, + "clientRole" : false, + "containerId" : "7f8cfc97-2875-4eb4-9868-090cd03d39ce" + }, + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpPolicyCodeReusable" : false, + "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], + "localizationTexts" : { }, + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyExtraOrigins" : [ ], + "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessRpId" : "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessCreateTimeout" : 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessExtraOrigins" : [ ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + } ], + "clientScopeMappings" : { + "account" : [ { + "client" : "account-console", + "roles" : [ "manage-account", "view-groups" ] + } ] + }, + "clients" : [ { + "id" : "d3782eab-764d-4eee-bb6b-5f93014fa62c", + "clientId" : "account", + "name" : "${client_account}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/master/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/master/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "9ecfcb5b-7f75-4241-9775-1ea0b4ea8f3e", + "clientId" : "account-console", + "name" : "${client_account-console}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/master/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/master/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "c447b387-dc6a-4a18-a59b-fc27ab70718e", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "b182e249-72ed-4b07-bae5-5b6b4d4ba13f", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "a303d9ea-209a-466d-82cf-1916d6c0b0dc", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "2ba419c2-2a52-4309-87bb-84efa408e224", + "clientId" : "master-realm", + "name" : "master Realm", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "9a920f1e-547d-4bb4-bd36-315abd1a342c", + "clientId" : "otus-marketplace-realm", + "name" : "otus-marketplace Realm", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ ], + "optionalClientScopes" : [ ] + }, { + "id" : "744ae759-2228-4997-8726-9eda96bf3c88", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "rootUrl" : "${authAdminUrl}", + "baseUrl" : "/admin/master/console/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/admin/master/console/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "3bf60d1f-d730-47dc-9a69-073473a8f74e", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + } ], + "clientScopes" : [ { + "id" : "a88c3225-6482-48a8-a1c8-12a297a94d16", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "b20857f3-b57f-4d08-8dfb-86a4da07f023", + "name" : "acr loa level", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-acr-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "73db4979-7a1e-4d74-b73c-f26868d3a5d9", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${profileScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "a9b045a4-4002-47dd-b51a-1377af79834b", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + }, { + "id" : "3714fc92-7391-4494-9627-508fca22c0a6", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "long" + } + }, { + "id" : "40e92d0b-9ffe-406b-aaf3-e47bc6979151", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "44ff333b-1978-40f7-8c9c-dd5367179bd7", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + }, { + "id" : "bffccc43-2451-4a1a-aca1-57b49500cb2f", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + }, { + "id" : "a7a41532-2d09-40a0-b011-baccabab86dd", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "6f27582a-a855-4145-8cbe-d0af967296ed", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + }, { + "id" : "9244442e-e8cb-4066-98e8-e77e2d157f9e", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + }, { + "id" : "4fffd2ab-e7ad-4877-a99a-741188e2a9bb", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "833a612b-3abe-446f-8a32-7aff15db6c46", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + }, { + "id" : "4bd8134f-3a5f-4a91-b9a6-e58c229ae1bf", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "64609011-ddc5-4c97-bb86-f3fe5ad2d654", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + }, { + "id" : "85456521-eac6-41e7-a42d-030bcecbf46c", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "ce395b22-7a89-4781-b0ed-226413d909bf", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + } ] + }, { + "id" : "902c9119-5936-49e3-983c-ac26bd99c440", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${phoneScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "c7ac5a48-2732-44b5-aaab-9c1ff0389950", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + }, { + "id" : "4f9c027e-13d4-4889-8911-bffe9cd29519", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "0553f997-3fa5-45b1-a7a6-0c72f69ce41f", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "a24c55fb-fff7-47c6-9e06-bff97e8518dc", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "af095b32-d235-4d23-a622-367667d81804", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "e6c5b194-087b-4765-8a76-fe6ab3cc4f52", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + }, { + "id" : "b6c78b2f-1e85-4aa6-947c-e3f59820c322", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "5ed0d5c3-80f9-456c-8c76-0ceb5efaa73f", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${rolesScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "01b327ee-4640-4736-b56f-46039bf636b9", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String" + } + }, { + "id" : "5c6a3fc9-fdf8-4692-ae00-c459ff2f99dd", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + }, { + "id" : "941cf8ec-7ee6-4b11-9532-6e581fc089ac", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "060ab5b6-9048-49b0-b798-c9ee8b741969", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${addressScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "84291eac-1370-43a5-8272-d730b6b2518c", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "introspection.token.claim" : "true", + "user.attribute.postal_code" : "postal_code", + "userinfo.token.claim" : "true", + "user.attribute.street" : "street", + "id.token.claim" : "true", + "user.attribute.region" : "region", + "access.token.claim" : "true", + "user.attribute.locality" : "locality" + } + } ] + }, { + "id" : "4b5ed663-f258-4f15-832e-2f030601f1c8", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "470d06ae-653b-4f81-aa67-d3d0849140af", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "2c429e7d-368a-4379-b08c-f8145e002a24", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${emailScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "ae857120-3202-4090-931e-70d9523650e1", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + }, { + "id" : "672414e3-2542-4e8c-a79a-c2270af1ea8c", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "5640bd6a-5d51-4a9e-b7f9-54c14e3d6f8a", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + } ], + "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins", "acr" ], + "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "referrerPolicy" : "no-referrer", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "xXSSProtection" : "1; mode=block", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { }, + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "identityProviders" : [ ], + "identityProviderMappers" : [ ], + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "7ed484b9-a3c6-4e71-bbc6-71441c6d25fc", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "4d25aaa6-ca19-4edc-8bee-0bcafcef28ce", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "saml-user-property-mapper", "oidc-usermodel-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper" ] + } + }, { + "id" : "5e013fac-b9db-4c24-a5f7-1cf9f9c11433", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] + } + }, { + "id" : "69a7577f-c222-414f-a543-70f6cdbce5d1", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "9f115bac-3011-4658-b206-01540e8dd383", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "8f5966f8-0641-48aa-a2b8-0e8ee93fd59c", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper", "saml-user-property-mapper" ] + } + }, { + "id" : "d8a7aedd-4039-49b2-b359-c661286fb3c4", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "79868463-e96a-4200-9348-3b5cd841b913", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + } ], + "org.keycloak.keys.KeyProvider" : [ { + "id" : "e983b625-e640-4937-9afd-f36322ef7096", + "name" : "rsa-generated", + "providerId" : "rsa-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEowIBAAKCAQEAqV8a9UdyMXd7o+iC4MTSh/TZYOH1tI2QurwoP2gn+MErjeeoszArega8o9B709nndt4hZA0/f1hGssDhJoTELwN4F85B1yx7UEZYMmVjEY99vsQKHqHgKCVrPthnDHioTDsdwD71J4Wvy7zvucLDFM2PXOqX6m7vMUGZMgLjKbfwloGZn2sB9bWPl94GbBcHejNCkj+AFKGIPY3dSZkd0Wbah6yc6DGGsPzkfEkddUy8VwA6Qsw0LeIp8Mqfc5YWmD7FxzXsN+0uuJGT/G8/MyFFQUw2HajYrm7bVWanDDNQ3vWV1z/3/1E4KKoUAQCDw1O58ERIvK9b0Ehs/OZHPwIDAQABAoIBAB8EfclhljYc7ZWs5RsIsI2Zd53Yg8jXDCRGhRBnoLpblgBc5nY6Yhvs0+skKSk5BLyuHWtXScOmhPwDerg1JEB/4CRr737adJLU7x37l1MF9j9TY48MkiKIB8Xwl56fEiMzyFUGsprUTsd/CF/6nQNYSeL4S23xdviMTOPtx3BCJJgtDXy+C8Yf2suhHoUf2r96qYccj0Jhhh2nGs7B5vzBSYEpcb13/RcaXtWPgOhDnI8lqBZ0o2WnWFpM82gVe/UwHIo1g+zzBozJuSPyOhNC3LnChj3IAejgL0X3g2fHTltMjIRkWkkrrs8LEcqu+0ioDwCPyTwpvoMY0RvTzRECgYEA6VA8J+Hitdbu7pyJmyHXe+t1bZeiM/sl3YrNTag075Ue1josfCZtw6eUFjTOleDJZRNlLbQB4rArkm4w1KDx6nquqA+0CzPTyVNpjcBDMyen0tF6mhfl4q7sls+Fo7ydJ+7XXSlXD+1ed2PsNEmNaDuWBrFuxiETeMxKmYwD9lMCgYEAudcxfJ93pivAmB6cbNz9NlaHYHsEkXGkx66Au4ex9FUac2valvJx7c0OwLcGsu1coY+T5ginNnBNZKri39T39G4wI0xjVPRsQGnM57KmsVyM2353jhvlhZJBdvF+A3Q3SDy3Hf8+Ng/bzXcwcI0Se/3AWjOj8bHFYVAGcFQ9deUCgYAAvnnCoszHSa0vY55ouT3nrkOMmuwwgD+JqlSnR78LeI1Fn5/esXyuIA2v2HFENxhNUzeCYs2SvH8XE3TiaLT8y3FdJdesJXkqbjKq+g78zcaSPIrIjQT1qRsmC/lgIUzbAL79FBGsAlTHyrDJJebmizIaSVySEy7ttrESNkkY8wKBgQC4yd+tOavxkaPKHvYP0ZX+x/+I0gnyzXu6Cix7TCyI9W59woryeVULzlCTE+sXU6o+A9RecdBC81whc0JwqwV7CW3YS4ah3QEe85UJ9ryFs69kOdaLefW54Xoy2WIh8RdfPvAeZcToYNCA97k00THGFMWFa7/i/o9zee1NGJaceQKBgE8ntPmQV78ctTrleoFkqR94TnLHEycylSsSvFZ1t25Ig4x+jEX3h+tXgUdioX8cOHdaYLanf0TSNvSBluU4mhk0vpwyRZLYEotxO37V34mvnh+s5jZt6bA+ahdNF9iy+T0sYi7bBFzyKFiy8dqaRSlfeK9Pvk1+bL3f+WyCMJDu" ], + "keyUse" : [ "SIG" ], + "certificate" : [ "MIICmzCCAYMCBgGNbwMEVjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjQwMjAzMTI0NjI1WhcNMzQwMjAzMTI0ODA1WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpXxr1R3Ixd3uj6ILgxNKH9Nlg4fW0jZC6vCg/aCf4wSuN56izMCt6Bryj0HvT2ed23iFkDT9/WEaywOEmhMQvA3gXzkHXLHtQRlgyZWMRj32+xAoeoeAoJWs+2GcMeKhMOx3APvUnha/LvO+5wsMUzY9c6pfqbu8xQZkyAuMpt/CWgZmfawH1tY+X3gZsFwd6M0KSP4AUoYg9jd1JmR3RZtqHrJzoMYaw/OR8SR11TLxXADpCzDQt4inwyp9zlhaYPsXHNew37S64kZP8bz8zIUVBTDYdqNiubttVZqcMM1De9ZXXP/f/UTgoqhQBAIPDU7nwREi8r1vQSGz85kc/AgMBAAEwDQYJKoZIhvcNAQELBQADggEBADvEuhI6BfHI5zMFMZG0r3JgxMIi6maZJ+98Z6NZ3mjimEIKdbqOjMxY93YLpn1WD5rJpXBxYH6da59qKPG/qkmgbjTBhcocrV+4QUee4del0gBE+wImS2jMxwsFpXiLCyvIXfOo4ar9LdZh6dVGYSrjZRDAhaf0WUyZS2zzt7IdlAswV4WtqrnpN/WGvEGob4S6IgM3Al0oCfDAYkg1sW2L+FDo+QBHxScl1oBzp7ood6iTwV0XicT8vJlkvyzYTP+50GdXEXCS4TuPzZsOnE5FH9W6bEXDEVU3FERLNqtEQG0cbHCZRLzc1cm51GtmhvZyGmQpJf+WZaKAKONedD8=" ], + "priority" : [ "100" ] + } + }, { + "id" : "08192352-797f-4a39-bd47-f3f79186b311", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEowIBAAKCAQEAut/gryCkntm7aTjsNHS8PWlD/+scbZX4/Oo09jS14Wosrs+MvTUIQLlB97lJ/MkmAHED3SgbAj1HeYqNQpav1QOH3nHNhKEZmgBc5nSHfMch7KHWb7SJpuGiD/V5u4md/ZGxkjYE8b2VAbfqabasElct2zXhZWX4oIwG4JiFIJat3qna0s0m2JzEn+U9wcIdHu4wRQSz0h9C0RN0UqgedOKdBZ72qjkomdHVa5hMJXYnIDZkxG6/qYgZd1aR52pUYbrqVT9NYUAO3rS5KGn3X4S0uumUrXGyLtugti60B669LyJ75rrQHWxE373xrEZvnJ8YzYRJr7VEluPFagGuCwIDAQABAoIBACiY6WlyWIEQAShnTt1IfPqEa1rmG1ttSNW9FbtlERxC4ikp+sPCCSRyerPUA5BQrJpM8w9xHoj6ghQT9wM/1DwdE7/ODl1hWDv+FzCToTmI00RilkDXQk5IV1pLNGJ7D6EeLSr75FAWJRBmAZ1sq24ilVo5ltld8UkDkpzpVYaSBZINuE/SX7VgENy67gAA3/6eTPAvLVMLdByCUbOEfNPjiB94NizhAOXRWQ6OKcMOGVEOm1iozPnKnMGtZnX+A/Jtd2eSdktVZ2K8/zCTLwhj1fRI3SK14HL9X9VTzMOraOZoGEJky81zgfzbIUtzJy7t743mVX053wATKniCB/kCgYEA+qPhFfF/Dm/VUG3KRUrqdkE0RJmY6JId92qGmml1/HsAPl5OTGVONH7m3Y7gRVObJeVd5tmTuNFm+TOyjbxbhnLHReMRAEfHPdDRGYRdyiiZ+fvX96FeHi0YJ7AnYqKgE3EEOQqJxLV/490WUIUOTklr5a0h5kFn0vscD3WoxhMCgYEAvt7qbB4hYHitl+i2QbEX0y38mdb8d2SivYQDRvd6ZBD7pDGgIM4kpglGPYxOJpHYxL1zIvB4zghaHW1TenJzWDJoZyh9Su++g8noAx4e5s0DVr6fX+cLh2ei5RoQz2LOetD9MRPSpHZLF+Kn81CDSXu+ipQZ3YTFmskGiNHg1ykCgYAFEEJ/2v0iIYhBs7YeaEEMWozfxeqc6DbKxNArVm4Xx7RdjjIuwO0vilDHsRc+z02XGmcnPsYJOdHGvxCgZGnE8ZStCMVTKCASU6GlzlLGvsM9laTrT8tC+M5AHwLsrzRksCfRrzDRVIlc5R6KSeXcFwejADhrGm8qiAAtH8dlGQKBgF7BXZFVF+7DmjJa5fgQyaoeH1PkJavD+wKogdP+UfVRdQubU0pV7F29JvCxMa72Iq3w+zKyPNbT0KDhQFr+bIKxa6Eiuai1Alh8qMC7eE3OI0UyFv7OPav36CdiXEwIWkcgb0Go/J6G11rBO+2P381gMEStp3WQT2U7PRI5VyyZAoGBAOpTNGIyJcug/JQXRiOhXealSu1VXIPVf4tY3REkTT3yYZnHjGZuD9DG9+lwTMY0ASWe8nxq8QVM3OFrzyUqbBnSbqxfFjrrBVy25lNMGl2F3MaUwA402WJHKbyzz7AmomyHzkUJaAPct9MRUoswD7LPNr+n9f3gf+B6fQP9r4XK" ], + "keyUse" : [ "ENC" ], + "certificate" : [ "MIICmzCCAYMCBgGNbwMGwTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjQwMjAzMTI0NjI1WhcNMzQwMjAzMTI0ODA1WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC63+CvIKSe2btpOOw0dLw9aUP/6xxtlfj86jT2NLXhaiyuz4y9NQhAuUH3uUn8ySYAcQPdKBsCPUd5io1Clq/VA4fecc2EoRmaAFzmdId8xyHsodZvtImm4aIP9Xm7iZ39kbGSNgTxvZUBt+pptqwSVy3bNeFlZfigjAbgmIUglq3eqdrSzSbYnMSf5T3Bwh0e7jBFBLPSH0LRE3RSqB504p0FnvaqOSiZ0dVrmEwldicgNmTEbr+piBl3VpHnalRhuupVP01hQA7etLkoafdfhLS66ZStcbIu26C2LrQHrr0vInvmutAdbETfvfGsRm+cnxjNhEmvtUSW48VqAa4LAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFEJalckgftLXhXG8VMMIAVtuM1Kvn6Ha6us6hwKAgOpLfrlhDvbq6i4ZdTNa+GrBre1fTFnotCd2a7F8u47BRI07ETE/6luQ0vPLTnmC5Q5t5X4iW2uQgqpjgIMPTPF/9P/PkwblLKU5KbU+P1r4Kulc7FhC0eptHA53uICZvhYq9grMz6W5FwTv6xwB6OqXjqx+b2G9iv2XcGZJdxfqKBn7Hp/+bIfSPcXqvBCZfV8fWRLd9FJ+Y/S97zsfewaYoPiKqQg8wRkBLBf9fTTTfT+KhF8M8vYHu37TsU/xOeFF0J2Z1oF650/Rb86GwMxD6ceKSPITfn1MyTuVQfKTb0=" ], + "priority" : [ "100" ], + "algorithm" : [ "RSA-OAEP" ] + } + }, { + "id" : "17f968b0-a4ca-43f4-98b9-72728036fce7", + "name" : "hmac-generated", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "2eb77ac4-ea11-4401-af58-2d7e5408235c" ], + "secret" : [ "vWE1Sg97wX-v6mhXzQ2hNGBJ1g5flYnpSIpgv72_BiZvM3IdhBbT91c65L5LWI-5nk-rsESfNc3sCbmxY9HXlQ" ], + "priority" : [ "100" ], + "algorithm" : [ "HS256" ] + } + }, { + "id" : "72e764f1-73e4-4d49-9622-2a7bdbe790fc", + "name" : "aes-generated", + "providerId" : "aes-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "89edffde-fa48-49ac-86ec-688808db8d51" ], + "secret" : [ "YVlkLCpJMzPDkK-isLzCig" ], + "priority" : [ "100" ] + } + } ] + }, + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "authenticationFlows" : [ { + "id" : "1fe345c3-5961-47ac-a2fc-77c556010249", + "alias" : "Account verification options", + "description" : "Method with which to verity the existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-email-verification", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false + } ] + }, { + "id" : "91daca8a-9a3d-406a-bd60-569312febcdd", + "alias" : "Browser - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "104c4b07-beeb-47f5-909b-e3348d99a5bb", + "alias" : "Direct Grant - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "faa0890b-1320-4152-8671-92d582244dae", + "alias" : "First broker login - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "61f1fcca-a987-43ef-ad4c-8b56c7a04839", + "alias" : "Handle Existing Account", + "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Account verification options", + "userSetupAllowed" : false + } ] + }, { + "id" : "447a192c-07c9-423f-a963-5e7459e1ece0", + "alias" : "Reset - Conditional OTP", + "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "3865e9fe-eba3-4a2a-8f69-585f4ef533c1", + "alias" : "User creation or linking", + "description" : "Flow for the existing/non-existing user alternatives", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false + } ] + }, { + "id" : "7d5291b8-4462-43bf-8080-82f55ec6dc83", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "First broker login - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "5792673a-7ec8-4d07-b0f9-ed78a750fcfd", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "identity-provider-redirector", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 25, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "forms", + "userSetupAllowed" : false + } ] + }, { + "id" : "745f8d22-3b64-41bd-8932-cde1477a0b50", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-secret-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-x509", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "7949df80-e593-443b-b35d-b25ddf24b333", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "Direct Grant - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "21d4e98a-abd9-49ca-b6c5-6420e2b4ef26", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "e5aa7210-0d6c-4e14-964f-a5d27fe617f4", + "alias" : "first broker login", + "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "User creation or linking", + "userSetupAllowed" : false + } ] + }, { + "id" : "fd757866-5d3c-46f7-9be0-e4591cc28f56", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "130b86a8-fa1e-41a7-8309-8bb365cf0e0e", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "registration form", + "userSetupAllowed" : false + } ] + }, { + "id" : "6262f75d-03f1-484d-934a-24695b2d7a76", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-password-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-recaptcha-action", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 60, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-terms-and-conditions", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 70, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "aeed0b9e-532b-4b3b-aa9e-70450576adfa", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-credential-email", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 40, + "autheticatorFlow" : true, + "flowAlias" : "Reset - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "b7a8ea5d-f130-4153-9718-d33fcec47cf4", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "522e2d61-2249-4eef-a7b5-7bd32f77bd62", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "id" : "a0493d20-9043-42fe-ab2a-b77f68630035", + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + } ], + "requiredActions" : [ { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 10, + "config" : { } + }, { + "alias" : "TERMS_AND_CONDITIONS", + "name" : "Terms and Conditions", + "providerId" : "TERMS_AND_CONDITIONS", + "enabled" : false, + "defaultAction" : false, + "priority" : 20, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : true, + "defaultAction" : false, + "priority" : 30, + "config" : { } + }, { + "alias" : "UPDATE_PROFILE", + "name" : "Update Profile", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 50, + "config" : { } + }, { + "alias" : "delete_account", + "name" : "Delete Account", + "providerId" : "delete_account", + "enabled" : false, + "defaultAction" : false, + "priority" : 60, + "config" : { } + }, { + "alias" : "webauthn-register", + "name" : "Webauthn Register", + "providerId" : "webauthn-register", + "enabled" : true, + "defaultAction" : false, + "priority" : 70, + "config" : { } + }, { + "alias" : "webauthn-register-passwordless", + "name" : "Webauthn Register Passwordless", + "providerId" : "webauthn-register-passwordless", + "enabled" : true, + "defaultAction" : false, + "priority" : 80, + "config" : { } + }, { + "alias" : "update_user_locale", + "name" : "Update User Locale", + "providerId" : "update_user_locale", + "enabled" : true, + "defaultAction" : false, + "priority" : 1000, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "attributes" : { + "cibaBackchannelTokenDeliveryMode" : "poll", + "cibaExpiresIn" : "120", + "cibaAuthRequestedUserHint" : "login_hint", + "parRequestUriLifespan" : "60", + "cibaInterval" : "5", + "realmReusableOtpCode" : "false" + }, + "keycloakVersion" : "23.0.6", + "userManagedAccessAllowed" : false, + "clientProfiles" : { + "profiles" : [ ] + }, + "clientPolicies" : { + "policies" : [ ] + } +} \ No newline at end of file diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/master-users-0.json b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/master-users-0.json new file mode 100644 index 0000000..bbe1b2c --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/master-users-0.json @@ -0,0 +1,23 @@ +{ + "realm" : "master", + "users" : [ { + "id" : "56f51ff0-bb64-446f-a2ed-632741dc6661", + "createdTimestamp" : 1706964489216, + "username" : "admin", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "924ddccd-ae33-4b6a-97c0-d0dbe5a0461e", + "type" : "password", + "createdDate" : 1706964489365, + "secretData" : "{\"value\":\"qRb/AHkE5KTSp9gYciONPr5BrbOs8Q0EVGbiQbVJOj4=\",\"salt\":\"ygl/E/tCOa6IFzDTG0wd6Q==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "admin", "default-roles-master" ], + "notBefore" : 0, + "groups" : [ ] + } ] +} \ No newline at end of file diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/otus-marketplace-realm.json b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/otus-marketplace-realm.json new file mode 100644 index 0000000..9b223b0 --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/otus-marketplace-realm.json @@ -0,0 +1,1830 @@ +{ + "id" : "otus-marketplace", + "realm" : "otus-marketplace", + "displayName" : "Otus Marketplace", + "notBefore" : 0, + "defaultSignatureAlgorithm" : "RS256", + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 300, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 1800, + "ssoSessionMaxLifespan" : 36000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "clientSessionIdleTimeout" : 0, + "clientSessionMaxLifespan" : 0, + "clientOfflineSessionIdleTimeout" : 0, + "clientOfflineSessionMaxLifespan" : 0, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "oauth2DeviceCodeLifespan" : 600, + "oauth2DevicePollingInterval" : 5, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "ec06542b-8c8a-4fa1-a605-1594b17250b4", + "name" : "default-roles-otus-marketplace", + "description" : "${role_default-roles}", + "composite" : true, + "composites" : { + "realm" : [ "offline_access", "uma_authorization" ], + "client" : { + "account" : [ "view-profile", "manage-account" ] + } + }, + "clientRole" : false, + "containerId" : "otus-marketplace", + "attributes" : { } + }, { + "id" : "e0ed7ba1-870a-443d-bd59-470a22a336ec", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "otus-marketplace", + "attributes" : { } + }, { + "id" : "faaa28ab-a7db-4336-a16f-32f55bb16112", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "otus-marketplace", + "attributes" : { } + } ], + "client" : { + "otus-marketplace-service" : [ { + "id" : "f7e5668b-1f4d-4dff-aa98-9e5225b43e7d", + "name" : "USER", + "composite" : false, + "clientRole" : true, + "containerId" : "96b7d5f3-b04b-4460-9f7a-faf964c583a5", + "attributes" : { } + } ], + "realm-management" : [ { + "id" : "442bfc5f-0a32-423f-83b8-8dedec745bf9", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "c6ad5c1d-72a1-46d3-8404-b037d86e4ebf", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "a0e86a5b-323e-4c45-9252-e8352a3250dd", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "c4cc9153-950f-4dd1-86bf-fbdb90cd5c7d", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "c5eadc9c-7a0c-4a84-81c4-75a7160bca09", + "name" : "realm-admin", + "description" : "${role_realm-admin}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "view-realm", "view-clients", "manage-users", "impersonation", "view-events", "query-realms", "manage-realm", "query-groups", "manage-identity-providers", "query-clients", "create-client", "view-authorization", "manage-events", "manage-clients", "manage-authorization", "query-users", "view-identity-providers", "view-users" ] + } + }, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "43d1944b-8b96-4b14-9f03-cbf4d7747a0e", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "cde7483f-a6c9-4885-b638-830bd208cf09", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "b375162f-fd21-4034-ab47-e622d8a390aa", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "fd1bc1bb-fe38-486c-8906-3e93d3b6c8ba", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "62a7a36c-b52f-42d1-aff6-b463d671a966", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "db9fde48-20bf-4516-881d-46fd4b94e88d", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "eb863476-fe0a-4e38-a385-56976bbfb851", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "cb748ce9-eab9-4bc5-a1e5-ff0672ac34db", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "a0e0453d-aeb4-4f4d-a871-3dd039584456", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "36d59481-fe9f-46ee-8d33-cd46b1f4d307", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "29a41fe2-3499-4261-af17-36602a14647f", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "ddb597c6-cb7f-45ea-8b6c-4e5ab66b2106", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "bba1df94-d44c-4584-8373-6ca8dd3c86be", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + }, { + "id" : "c9b4a403-9b28-4c25-8c88-49e5ff848cd5", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-groups", "query-users" ] + } + }, + "clientRole" : true, + "containerId" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes" : { } + } ], + "security-admin-console" : [ ], + "admin-cli" : [ ], + "account-console" : [ ], + "broker" : [ { + "id" : "52b5daaf-81fa-4d59-8f3d-2cab429a0341", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "7f5a6b99-d4fc-4276-82e0-93642fbc2f60", + "attributes" : { } + } ], + "account" : [ { + "id" : "08b328ca-8d45-4098-807a-d97b13e931e4", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes" : { } + }, { + "id" : "bb8e8f91-8a19-488b-afd0-69dfc3e38ef0", + "name" : "view-groups", + "description" : "${role_view-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes" : { } + }, { + "id" : "a8ab93f6-5b15-4f98-a328-c833f2815826", + "name" : "manage-consent", + "description" : "${role_manage-consent}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "view-consent" ] + } + }, + "clientRole" : true, + "containerId" : "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes" : { } + }, { + "id" : "76a2152c-d06c-4bbe-bc51-1a86c38684ba", + "name" : "view-consent", + "description" : "${role_view-consent}", + "composite" : false, + "clientRole" : true, + "containerId" : "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes" : { } + }, { + "id" : "4e37e74b-ec6c-4245-a277-b82bc057fb8e", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } + }, + "clientRole" : true, + "containerId" : "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes" : { } + }, { + "id" : "3b76c415-6a54-4719-a2b8-44bd2aedef97", + "name" : "view-applications", + "description" : "${role_view-applications}", + "composite" : false, + "clientRole" : true, + "containerId" : "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes" : { } + }, { + "id" : "557663b6-1e42-4697-89b3-279272467349", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes" : { } + }, { + "id" : "744ee6f8-0c20-4848-b34d-3d1f7a05a6bf", + "name" : "delete-account", + "description" : "${role_delete-account}", + "composite" : false, + "clientRole" : true, + "containerId" : "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes" : { } + } ] + } + }, + "groups" : [ { + "id" : "8711b426-3d18-4842-832d-c277d5414ee8", + "name" : "USER", + "path" : "/USER", + "subGroups" : [ ], + "attributes" : { }, + "realmRoles" : [ "default-roles-otus-marketplace" ], + "clientRoles" : { } + } ], + "defaultRole" : { + "id" : "ec06542b-8c8a-4fa1-a605-1594b17250b4", + "name" : "default-roles-otus-marketplace", + "description" : "${role_default-roles}", + "composite" : true, + "clientRole" : false, + "containerId" : "otus-marketplace" + }, + "defaultGroups" : [ "/USER" ], + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpPolicyCodeReusable" : false, + "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], + "localizationTexts" : { }, + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyExtraOrigins" : [ ], + "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessRpId" : "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessCreateTimeout" : 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessExtraOrigins" : [ ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + }, { + "clientScope" : "otus-marketplace", + "roles" : [ "default-roles-otus-marketplace" ] + } ], + "clientScopeMappings" : { + "account" : [ { + "client" : "account-console", + "roles" : [ "manage-account", "view-groups" ] + } ] + }, + "clients" : [ { + "id" : "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "clientId" : "account", + "name" : "${client_account}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/otus-marketplace/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/otus-marketplace/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "8380c41e-f906-4c01-8685-dce56e853ee3", + "clientId" : "account-console", + "name" : "${client_account-console}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/otus-marketplace/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/otus-marketplace/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "9046a1dc-cd8c-4812-b3b7-5e1f342a479d", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + } ], + "defaultClientScopes" : [ "web-origins", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "1ea1031a-c029-46fd-9477-2867783adc93", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "7f5a6b99-d4fc-4276-82e0-93642fbc2f60", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "96b7d5f3-b04b-4460-9f7a-faf964c583a5", + "clientId" : "otus-marketplace-service", + "rootUrl" : "http://localhost:8080", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "saml.force.post.binding" : "false", + "saml.multivalued.roles" : "false", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false", + "saml.server.signature.keyinfo.ext" : "false", + "use.refresh.tokens" : "true", + "jwt.credential.certificate" : "MIICvzCCAacCBgGEayQGdzANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhvdHVzLW1hcmtldHBsYWNlLXNlcnZpY2UwHhcNMjIxMTEyMDkxODUzWhcNMzIxMTEyMDkyMDMzWjAjMSEwHwYDVQQDDBhvdHVzLW1hcmtldHBsYWNlLXNlcnZpY2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIxAetegY1Yl8GD0zCUboJVflioxgkU65nbHOZtHUJDNlv4hk4YKGcELPZr226tz/468xFfPVeSWmzMVRnZYa5Ure54M27jh/sPfne0Wqy5YwD2XJy34CU3tFdn5dGuC4WOFcxkd8fbOKLLu3yi25tKR9VYXHDXQ6vuGvras5Rpn+HjHUs+1kSsNEvaBrEeG/MvxI44jbqYz4srD+ZniHB5R9rfluyewADx1/3/HUEtzp1m34oWKXXMP8NccYDqf8U2IQrjxV0hruQDirEp3W2iAox2N5pcLXCMVD3DYFkOf15Pp3zDPVRcbD4+LhvT5cDLFtwPosf+8xcQVOaM7aRAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADR5bl0/TWpgPsCS8ug/HaX2w5SFnQggdlfOoALgXzcNFsVmt1apz81uOfjC2+mDLeaUufGVC7DEwxHG/y6QXhmeYua9cxb3Lbqv93eTolkPBB44nkHI3g/afdOoQH4feHsJt4nmhGRr5APFazPHRgngEpk+soTgUrmQponohCskH/D/Gt69fo9T6jq9kwQ67FIKhXy/KgDZB1yJj3Rh6TrGxns/g/uw/mPLjuzDOpVBbH7fD83SMhMsKJwxeapHGnj7Voj04iprv9UfEXdwrsCOPD5XyjAwqyiqvOFA5nBQrDOv1Ii8CzK+XerP+d5ZVbzlyur6mGWHVumE5/UUeb8=", + "oidc.ciba.grant.enabled" : "false", + "backchannel.logout.session.required" : "true", + "client_credentials.use_refresh_token" : "false", + "require.pushed.authorization.requests" : "false", + "saml.client.signature" : "false", + "id.token.as.detached.signature" : "false", + "saml.assertion.signature" : "false", + "saml.encrypt" : "false", + "saml.server.signature" : "false", + "exclude.session.state.from.auth.response" : "false", + "saml.artifact.binding" : "false", + "saml_force_name_id_format" : "false", + "tls.client.certificate.bound.access.tokens" : "false", + "saml.authnstatement" : "false", + "display.on.consent.screen" : "false", + "saml.onetimeuse.condition" : "false" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "protocolMappers" : [ { + "id" : "e6d885c8-4c3a-40a6-87bb-5ee2e6ee835f", + "name" : "aud", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-hardcoded-claim-mapper", + "consentRequired" : false, + "config" : { + "claim.value" : "ad-users", + "userinfo.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "aud", + "access.tokenResponse.claim" : "false" + } + }, { + "id" : "10524baa-10b6-49ee-a18e-cb5242c0fa13", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-group-membership-mapper", + "consentRequired" : false, + "config" : { + "full.path" : "false", + "id.token.claim" : "false", + "access.token.claim" : "true", + "claim.name" : "groups", + "userinfo.token.claim" : "false" + } + } ], + "defaultClientScopes" : [ "web-origins", "roles" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "clientId" : "realm-management", + "name" : "${client_realm-management}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "d829107c-dcfe-416e-82cb-a36b76f33009", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "rootUrl" : "${authAdminUrl}", + "baseUrl" : "/admin/otus-marketplace/console/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/admin/otus-marketplace/console/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "a3c28e64-eef9-4e9f-9a72-6814545b84d3", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + } ], + "clientScopes" : [ { + "id" : "73de5776-9807-46ac-a040-601d07722400", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${addressScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "0457b8bb-54ee-4583-8c02-df7dac6f28d5", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "user.attribute.postal_code" : "postal_code", + "userinfo.token.claim" : "true", + "user.attribute.street" : "street", + "id.token.claim" : "true", + "user.attribute.region" : "region", + "access.token.claim" : "true", + "user.attribute.locality" : "locality" + } + } ] + }, { + "id" : "6779cf1c-a895-4330-a94c-36d607635fb3", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "6905b9fa-1f2b-4276-9538-885728d81c6e", + "name" : "acr loa level", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-acr-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "a782e4d5-7389-4d90-9627-10ea2911a33e", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "c936ab6c-b7df-4f18-81cb-f9b4599f259b", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "d610fd5c-e9f0-4c75-bada-deaa38a44f93", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${phoneScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "678d741b-72da-4dcc-a866-1554b656c3a3", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + }, { + "id" : "1ce17405-221a-4702-b39b-35eeae432681", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "85f25644-ae19-46b6-b8b2-7fb4c4fd0a56", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "58a55003-399f-4ad8-aaac-8547f0b57e78", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { } + } ] + }, { + "id" : "1e91dc51-1c7b-42fb-a146-10acc4b7f0e6", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${emailScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "67a034c1-1995-4322-b61d-3dc731256172", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + }, { + "id" : "a70613bb-3d0b-4e1f-a7d1-97806ef4fb49", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "d01d7158-4bc5-438f-b426-1b75858f1fa8", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${profileScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "45951871-317f-426a-afba-aff445ea1d1c", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + }, { + "id" : "b0f80249-5325-4120-9fba-2c80fb167dae", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + }, { + "id" : "b58b57ff-3251-423a-9fa8-792de8e4fefd", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "faf0444a-4437-437a-a4e8-639c10febb0d", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + }, { + "id" : "ee5ccaae-cdde-40f7-9912-6d05c32d021d", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + }, { + "id" : "3f92e080-d77f-4cd8-a1d0-95864b714e67", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + }, { + "id" : "628747d4-9a19-46ba-ae31-844cb03614b5", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + }, { + "id" : "ff254cad-f6bc-43f5-b826-99300f1e5ccd", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + }, { + "id" : "fec69fa9-0ca2-4cd8-a9c3-cd1f46b7f125", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "9917ec30-6547-44b4-ac7e-4063bb6aa450", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "fb56dbeb-1e95-4ebb-a664-6bb0f646578d", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "fc776024-878e-4ffc-bcba-811df52fefea", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "6a6c50b6-7dc7-4176-b4d0-0e66362612ca", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "String" + } + }, { + "id" : "b2dccd64-15d5-4327-8cd1-27c17e171db3", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + } ] + }, { + "id" : "c5393ba9-51ad-4439-9a3a-e3d50fc90db8", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${rolesScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "c501f064-accb-4a04-a6ce-6a56a9f4c20b", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + }, { + "id" : "cc56ea3e-e440-4124-b71f-51f74d253a91", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + }, { + "id" : "3028fb30-d025-4666-a016-75c69132fe0a", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + } ] + }, { + "id" : "d826541e-37d1-42ac-94e6-c9ace735e12e", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + }, { + "id" : "d51fdf5d-d297-4b3b-ac78-f002c8517398", + "name" : "otus-marketplace", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true" + } + }, { + "id" : "7e017fb9-185f-4540-9061-8d8fa0ef9559", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "fa2c8da1-9068-4bf1-8efa-bce9169af279", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + }, { + "id" : "30a7a411-f1de-4b4a-804c-7ebad85dbc0f", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "multivalued" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + } ] + } ], + "defaultDefaultClientScopes" : [ "email", "web-origins", "role_list", "roles", "profile", "acr" ], + "defaultOptionalClientScopes" : [ "address", "microprofile-jwt", "phone", "offline_access" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "referrerPolicy" : "no-referrer", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection" : "1; mode=block", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { }, + "loginTheme" : "keycloak", + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "identityProviders" : [ ], + "identityProviderMappers" : [ ], + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "aa142c07-2a15-4b0d-af81-cb9a13107a47", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] + } + }, { + "id" : "35c7b09b-9043-4337-ae7d-4455a2daa14c", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "3b2dee13-e36e-4545-8307-0b970e70ab5d", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "9bc37677-45b4-4d50-afcc-9ee741f77a5e", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper" ] + } + }, { + "id" : "3f10a26e-c3c1-4fd6-9ce4-909088438d97", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "oidc-full-name-mapper" ] + } + }, { + "id" : "9f1597f1-7492-4e37-879a-3010278305a6", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "c62fbee8-d4b6-42d3-bf33-a969143be74c", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "11e3a6d8-fc57-4ac1-a74f-aa8bc4b4ec23", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + } ], + "org.keycloak.keys.KeyProvider" : [ { + "id" : "2ee7e882-a94f-44cd-8dfd-23ddf6574d0f", + "name" : "rsa-generated", + "providerId" : "rsa-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEpAIBAAKCAQEAs7hga43ufKQbT7X8V92NDy/za3ZmMUYcaVaNGw+kPqvpwJPMwHfnWrQxKTHOjrzgq777c+DOuad/9DSaFegpzjQUZ4zd8DXRuCNv2k1zM7iTgIyntA12FCw/yIR42yru36RAuZ6btlAuoj3K6eQrhmAyjJjoQMVG7ogxk+iIolqeMncRuk1H3E4rOy4mxVR5UPDyuXTDp3B+UTFlGtKtbSMS7WOwMVO5C4OXTChnfZnwNvXxKAx3ux1U5PooRlUiR4oZmU6W62NyOaFjPyUT24Bsyg5AoSk4jG/8NmVPpCXSHZSw8+yQSYMnVGflmSbZDTSJ35RrPTTQ+FzU841LAQIDAQABAoIBAE/G2wozTTeH01XNZ1ALmTeyJeBAhPl/cVIzKNzn0xU807z3/s47C3hAf4gVQ2cqIaMrWkxkcO+JkmtxRCrQTWpqxNn4dnZQNaGDHX4uniJJ3zQTe8gZp54pzEByyYEkbDfbHh4ncWB69FBxlJbBga6bGiU+JO7Hg4aT70oEUU6boTisJ6YnOobJ8OM42faqq227+jBuE0BQR7rhrdmvQjub2YQMHpM/luK0ZX32w85KWIlR4TGfngSCPnS5boS1HJCCBrY/g2zO6Z46F8mYijjkO+WvNFWIrLglfGhU4ia8wa0qqEYsUWFcCZ3SGx8W/yPhIP1nh9mKtuDsIOBN/ucCgYEA+7wauVi6299qkC0NZq/Uu53X1/jLXRFg5CJT1gtTP4xB6z2fK7B7hTWX17h4FdBhTvi19d+8Vg85GJ2o0x0demN9dZsmisVIIswwEtCS+exsPh9GCIiAsQ22k1EAG708b7v36EVDJtziFDi1sYsIucY3XKFZKMyBFXQdlq2Vc1sCgYEAtsPpBVABEtdSq8ugJepUjhfp/s4fhOXsZxFgyLxbKVZ5poKxmw7zj1jGsel512TS4Qk38nytkjl19NeHuONeIFHZLWQLDg9bLhVxS+TZwoV/vE4sASlNmBayA1Wkri7poIa8ZvY1ORA39gNIj97qFRjU3+xU1F8Ws0vd1LzWVdMCgYBfnOaZl3YBpS4YbMQ2SHqIeD9PLJQxWTRv8gndtpd7/43aB6G5OmLwCZcOvGYAAxGyqQyTwtMJ7OZGzzscVGap4bf5P2C4PI5ViTCJNOdePcovHjm/a/lVRlweQBnGb23REpfqhMQosqS8AX4hXSmHRh4o9K+kq2gr+dpzLKMjGQKBgQCd+HvC0cH7zQ1x3FESNJbdMqJYUUVBE5LgC09CcjvBYTNIzxJAWg3/StaDFLDxkf4L8HHhMA6+otfnxxtSnYPQH6694wkDIBbJoFMLLEVkMwuTcWXrow2kdYlsBGyQ+Y+J5quVux2JsxELnQ7s+9oMXigxXA5+eaofU2Xr6UTBbQKBgQDuGUFm+RFi4P+tI2ZbSN2OjbpXIAMijVcKneaiyN0asUMMPra+gKI8X7Pa0FuBoIRoj/YrFlZmkkS0n/fR/0bg9V2PoP74Hb4cU5jA/2zPp0kqQG5u6MWtDhc678Yody6+yqvggZeQ0zZvd1gtY1TsxbkRM4kN+pHpnK06AQ4TUw==" ], + "certificate" : [ "MIICrzCCAZcCBgGNbwMRXjANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBBvdHVzLW1hcmtldHBsYWNlMB4XDTI0MDIwMzEyNDYyOFoXDTM0MDIwMzEyNDgwOFowGzEZMBcGA1UEAwwQb3R1cy1tYXJrZXRwbGFjZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALO4YGuN7nykG0+1/FfdjQ8v82t2ZjFGHGlWjRsPpD6r6cCTzMB351q0MSkxzo684Ku++3Pgzrmnf/Q0mhXoKc40FGeM3fA10bgjb9pNczO4k4CMp7QNdhQsP8iEeNsq7t+kQLmem7ZQLqI9yunkK4ZgMoyY6EDFRu6IMZPoiKJanjJ3EbpNR9xOKzsuJsVUeVDw8rl0w6dwflExZRrSrW0jEu1jsDFTuQuDl0woZ32Z8Db18SgMd7sdVOT6KEZVIkeKGZlOlutjcjmhYz8lE9uAbMoOQKEpOIxv/DZlT6Ql0h2UsPPskEmDJ1Rn5Zkm2Q00id+Uaz000Phc1PONSwECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAEUs9kI9Ho3eFRzDxHTCY6CPJJZW4HYkvhn630NxK0SCa7NHOKnXFZMEsmRE8sSNDASTeripTHXfJ7I0YLsbxeBrgLm8YWto7/4Dd1duzwWBp53WYSZ1sl61kewDJFoYCyKWFJB73egGDrA6rvvOvXE7s/DYMQ3J2R1xYtOJDhzj8AjQnrc5mN/FWKNPjYkJg2SC1cHgXvLxAAtIFXE9E6333BFcN13b+KN9BoVb2dOm6m3SAuKuH0cay0q6oo1VRrz2RAyorfM61ot5ViOz70BaFkiXct31KUr0gi+cP/QAi707Ev2kBdqKQj79UM148NV7ADE1ZXgtUhOGPF3A4/Q==" ], + "priority" : [ "100" ] + } + }, { + "id" : "af4bd03c-bb9b-4861-b69d-b8f69a241968", + "name" : "aes-generated", + "providerId" : "aes-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "fff43362-ca3b-4b85-bc29-bf632fb00255" ], + "secret" : [ "nsWH9ORgLvzJeZHDbNr4Kw" ], + "priority" : [ "100" ] + } + }, { + "id" : "7888065d-47a7-43db-85e1-9ae9a8664d4e", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEogIBAAKCAQEAn0yGgdbE+sh203AMpy3p3gVwUxPmU4VOTN0IW44FtA6okIXaaQdUVsAdmc3U/KOPT7KOw8JeuJr2CaBcLWpNya4//atDJTR+3mLe0I4kwghX8q1S8n+PawW7U9ZSLql2gntQc8UHqLCliWNKhCOe6Jk7eRUoWuf3UC6u0lfSnmfcfFJRIyg7guK5W7H+GPlNFoCBIQzhwNz7M91V52xLIAhDhNc8ZqBn/UwHzEFRaIMQ9IwMHk4xnNzLPCyA9UDUYB9nXXvekObz7g1Az3qA48C2gSIVWuFNA8vFtjn/v81wAxZciLUswE9kKOvmY/rP5x/KCzqXB3Ohxi/WaIVN6QIDAQABAoIBAAMaxXNR2XhuwDwaLrDyaOCqF/iShnZhvncqhp9sKunJsFjStwE9gpQHPfxxocFDuccKmpQvnVN5N6rT3IAJFpeD5RzfQdl/hqp0YFXNs2MxsO8amCeAO24RSEeXwXXF2TitSRHciOvtd2hwTjM5k38Cf4F6W1U8OJpwMnmIeyMZqLNzW5GCz0m/Fv3dxdKNlZap9YGb3cktUrovH1Oyz0kRAs8b1GKywnday6lhrKLgMELQibifIp1OIWAbTib9yyWtljup1glnAmiRL00yOac0cntiwcsR7hGKmRSBuYxlESRfgCVToULtDeAVgWPfek+Vze1HVQjpvSC0qFSvNvUCgYEA2BZHdZTP88Uxe1a05hXUCalHXzNi3xXpFzehkeAUSMoyqEmXGBnQsoTl0JxPC5wqktJSYKiJczYMcFQQNnFhT4k41pU3AYJzbg8Y3DcqH9kK2CFlKHzOT+g7DWUoTMO+19Vb8pQ1sMH0C35zx1ApjeLyctVtOE8TnLuR1xUKKT0CgYEAvLkCSRFM8jIqwXXtrEQA6C5UG0Ad4WM6D3ovIusbFNmO4RuOAp9CbCPQsOnUGrITBB71Xak1MChuTu79OPfVROhkNAhxa1B74POHvFt6WXCCUg5QtPtkfG/c9aChC80u6A/vhjNHGHf0dw20zpQrajCmTFH1/p1cwSgfnllvSh0CgYAnT+5SOu+WRtLYwI6KqX/4/f4JGN0s/tx4J9vSITUvhPGwYisF7HRmdf0ldbp/vzqTmYX5JdBT0Ip0ySZl8Tyl7q4Tg/QM50G+zSpVrgeQ4biyV2kC86nJKdPMfRHW3WnT9HIU8NfPv4l5qdjAcxoMQTSgpamILALCafF/csl1dQKBgBRkBPwyE1dD1lzKyiBHxLVRdCLxnYjhuL89W2RxdJ6fFxH5cTGVVY7rm7vRt+oefXF/itFQ2/9VDv4WUmPaWz+zwEfi9aY7rvbSOUM/uwt43YvSIiQ72VKcn4omjeABjmTie+XLGo5pP4+xemyrk7lIgl9Sp7qX9BKmrCvmy+B9AoGAb4LVupSZYnp6ESYG8HznzF0OjKdTJhfUDsdPd0f27mGpjxyksRuwLoX+1Xd96Bko9mbKA/FzS2W6RJH030umhAze9/BIvTPtbs3cyl/szIhnxtskLZ2UAvODA5lgfb3mG8qgh59kIk/ASq3x0wXJ40dgcZFNEye6A40Yjp6vYGk=" ], + "certificate" : [ "MIICrzCCAZcCBgGNbwMRwTANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBBvdHVzLW1hcmtldHBsYWNlMB4XDTI0MDIwMzEyNDYyOFoXDTM0MDIwMzEyNDgwOFowGzEZMBcGA1UEAwwQb3R1cy1tYXJrZXRwbGFjZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ9MhoHWxPrIdtNwDKct6d4FcFMT5lOFTkzdCFuOBbQOqJCF2mkHVFbAHZnN1Pyjj0+yjsPCXria9gmgXC1qTcmuP/2rQyU0ft5i3tCOJMIIV/KtUvJ/j2sFu1PWUi6pdoJ7UHPFB6iwpYljSoQjnuiZO3kVKFrn91AurtJX0p5n3HxSUSMoO4LiuVux/hj5TRaAgSEM4cDc+zPdVedsSyAIQ4TXPGagZ/1MB8xBUWiDEPSMDB5OMZzcyzwsgPVA1GAfZ1173pDm8+4NQM96gOPAtoEiFVrhTQPLxbY5/7/NcAMWXIi1LMBPZCjr5mP6z+cfygs6lwdzocYv1miFTekCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAvQnpO+F+FnzCcpARXQFApZyNDQNJ+AvSReCNWT++f7hbNj8A4g7r7R8ddusizWgoxUr92dy5ThERABCngiG3v6AsTYiLAI/wImaTgkSIM0LcgJCWnV9JKuzfMl+FVbp6DB8sBVQAUVIAUffv0c4d5SFXm8OuQvcsm4tOjJ+YaaOdO3NDYTEphwPH3BOifTgcL1vi6YZ7FdDqCt0bmTBmMaPcqWTZATPlrLC+Z47z2Q7cj2XCOWCibRWff9V/WV0DEBhvzO1monsyf8yKzGZ6O3lCIl+hdx+xdt/3PpvfuheRy6lcahUshg9T9QZTWHFvrUZzShklwmX2e1DAW3K+g==" ], + "priority" : [ "100" ], + "algorithm" : [ "RSA-OAEP" ] + } + }, { + "id" : "3d06a085-40da-40ef-bad4-398447b62ecf", + "name" : "hmac-generated", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "917b5e68-5ab5-45e0-9c6e-8b457b0de579" ], + "secret" : [ "JWRhYMWjb9zugMKBuh-WBW_X8J6KU-XSiiGD9_mXrxFTZkmtvMGDLMEZVfXOOWRIPJXWG-MaGDEXEaHByQ9y-w" ], + "priority" : [ "100" ], + "algorithm" : [ "HS256" ] + } + } ] + }, + "internationalizationEnabled" : false, + "supportedLocales" : [ "" ], + "authenticationFlows" : [ { + "id" : "913f1273-2755-4ed6-9d43-7451fc7f46f6", + "alias" : "Account verification options", + "description" : "Method with which to verity the existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-email-verification", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false + } ] + }, { + "id" : "7fde02a6-6252-41f7-8de7-f8e963ed3721", + "alias" : "Browser - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "00d4700a-3554-4372-af15-8aafdd1e0a6b", + "alias" : "Direct Grant - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "5f6b4205-7374-4e62-8c3a-7f343c05fc4c", + "alias" : "First broker login - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "84ee15fa-f04b-43fd-879a-3d464ad4d0ce", + "alias" : "Handle Existing Account", + "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Account verification options", + "userSetupAllowed" : false + } ] + }, { + "id" : "f78faeb8-9b19-4863-a67e-f4b3071521b8", + "alias" : "Reset - Conditional OTP", + "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "f6a32408-74f1-4c37-b5f1-0f45dabcdcfc", + "alias" : "User creation or linking", + "description" : "Flow for the existing/non-existing user alternatives", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false + } ] + }, { + "id" : "781f4946-073c-49bf-ab5c-9dcc30f7bacd", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "First broker login - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "14c0cae3-23fb-4bc2-aaf5-b00e6b28d690", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "identity-provider-redirector", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 25, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "forms", + "userSetupAllowed" : false + } ] + }, { + "id" : "787889ec-0399-4381-9e5c-c81e41dc34a1", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-secret-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-x509", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "a36e5912-620c-4d7a-a9f0-956bbeefbd5b", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "Direct Grant - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "9ded7328-5509-4224-a823-59d84a7eff38", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "b8439ff4-0f9d-49d8-bf1e-293fca6011d8", + "alias" : "first broker login", + "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "User creation or linking", + "userSetupAllowed" : false + } ] + }, { + "id" : "b8ac79f8-ffb5-4716-b29e-b508bbe8c204", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "449cc526-f2e1-4b0e-ae06-c914eac81443", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "registration form", + "userSetupAllowed" : false + } ] + }, { + "id" : "69dd4fa9-de4d-4dbf-b77a-11599d485930", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-password-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-recaptcha-action", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 60, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "cea3fde8-217b-49cc-b33e-b639adbf5a12", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-credential-email", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 40, + "autheticatorFlow" : true, + "flowAlias" : "Reset - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "82506382-c8fc-46f0-84ee-acacb2cf16cc", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "085caece-781c-45ae-9c4d-b9920563f657", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "id" : "a28287da-7d00-46f5-be37-32d3bb4b267f", + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + } ], + "requiredActions" : [ { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 10, + "config" : { } + }, { + "alias" : "TERMS_AND_CONDITIONS", + "name" : "Terms and Conditions", + "providerId" : "TERMS_AND_CONDITIONS", + "enabled" : false, + "defaultAction" : false, + "priority" : 20, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : true, + "defaultAction" : false, + "priority" : 30, + "config" : { } + }, { + "alias" : "UPDATE_PROFILE", + "name" : "Update Profile", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 50, + "config" : { } + }, { + "alias" : "delete_account", + "name" : "Delete Account", + "providerId" : "delete_account", + "enabled" : false, + "defaultAction" : false, + "priority" : 60, + "config" : { } + }, { + "alias" : "update_user_locale", + "name" : "Update User Locale", + "providerId" : "update_user_locale", + "enabled" : true, + "defaultAction" : false, + "priority" : 1000, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "attributes" : { + "cibaBackchannelTokenDeliveryMode" : "poll", + "cibaAuthRequestedUserHint" : "login_hint", + "clientOfflineSessionMaxLifespan" : "0", + "oauth2DevicePollingInterval" : "5", + "clientSessionIdleTimeout" : "0", + "userProfileEnabled" : "false", + "clientOfflineSessionIdleTimeout" : "0", + "cibaInterval" : "5", + "realmReusableOtpCode" : "false", + "cibaExpiresIn" : "120", + "oauth2DeviceCodeLifespan" : "600", + "parRequestUriLifespan" : "60", + "clientSessionMaxLifespan" : "0" + }, + "keycloakVersion" : "23.0.6", + "userManagedAccessAllowed" : false, + "clientProfiles" : { + "profiles" : [ ] + }, + "clientPolicies" : { + "policies" : [ ] + } +} \ No newline at end of file diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/otus-marketplace-users-0.json b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/otus-marketplace-users-0.json new file mode 100644 index 0000000..fc9688c --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/import/otus-marketplace-users-0.json @@ -0,0 +1,24 @@ +{ + "realm" : "otus-marketplace", + "users" : [ { + "id" : "638647df-d9e4-4759-8748-6f99ac220d11", + "createdTimestamp" : 1706964619142, + "username" : "otus-test", + "enabled" : true, + "totp" : false, + "emailVerified" : true, + "credentials" : [ { + "id" : "56beee96-cf26-4f6e-83db-8138530e0148", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1706964634548, + "secretData" : "{\"value\":\"CBy36ufg5bdAyXTLX9gMYyxw4QXKiAkNox6NFYi8FuQ=\",\"salt\":\"wasUxUctTzzm0c5HTyy7Sw==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-otus-marketplace" ], + "notBefore" : 0, + "groups" : [ "/USER" ] + } ] +} \ No newline at end of file diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/realm-export.json b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/realm-export.json new file mode 100644 index 0000000..4a37337 --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/realm-export.json @@ -0,0 +1,2236 @@ +{ + "id": "otus-marketplace", + "realm": "otus-marketplace", + "displayName": "Otus Marketplace", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "ec06542b-8c8a-4fa1-a605-1594b17250b4", + "name": "default-roles-otus-marketplace", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "view-profile", + "manage-account" + ] + } + }, + "clientRole": false, + "containerId": "otus-marketplace", + "attributes": {} + }, + { + "id": "e0ed7ba1-870a-443d-bd59-470a22a336ec", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "otus-marketplace", + "attributes": {} + }, + { + "id": "faaa28ab-a7db-4336-a16f-32f55bb16112", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "otus-marketplace", + "attributes": {} + } + ], + "client": { + "otus-marketplace-service": [ + { + "id": "f7e5668b-1f4d-4dff-aa98-9e5225b43e7d", + "name": "USER", + "composite": false, + "clientRole": true, + "containerId": "96b7d5f3-b04b-4460-9f7a-faf964c583a5", + "attributes": {} + } + ], + "realm-management": [ + { + "id": "442bfc5f-0a32-423f-83b8-8dedec745bf9", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "c6ad5c1d-72a1-46d3-8404-b037d86e4ebf", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "a0e86a5b-323e-4c45-9252-e8352a3250dd", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "c4cc9153-950f-4dd1-86bf-fbdb90cd5c7d", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "c5eadc9c-7a0c-4a84-81c4-75a7160bca09", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "view-realm", + "view-clients", + "manage-users", + "impersonation", + "view-events", + "query-realms", + "manage-realm", + "query-groups", + "manage-identity-providers", + "query-clients", + "create-client", + "view-authorization", + "manage-events", + "manage-clients", + "manage-authorization", + "query-users", + "view-identity-providers", + "view-users" + ] + } + }, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "43d1944b-8b96-4b14-9f03-cbf4d7747a0e", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "cde7483f-a6c9-4885-b638-830bd208cf09", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "b375162f-fd21-4034-ab47-e622d8a390aa", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "fd1bc1bb-fe38-486c-8906-3e93d3b6c8ba", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "62a7a36c-b52f-42d1-aff6-b463d671a966", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "db9fde48-20bf-4516-881d-46fd4b94e88d", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "eb863476-fe0a-4e38-a385-56976bbfb851", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "cb748ce9-eab9-4bc5-a1e5-ff0672ac34db", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "a0e0453d-aeb4-4f4d-a871-3dd039584456", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "36d59481-fe9f-46ee-8d33-cd46b1f4d307", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "29a41fe2-3499-4261-af17-36602a14647f", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "ddb597c6-cb7f-45ea-8b6c-4e5ab66b2106", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "bba1df94-d44c-4584-8373-6ca8dd3c86be", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + }, + { + "id": "c9b4a403-9b28-4c25-8c88-49e5ff848cd5", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-groups", + "query-users" + ] + } + }, + "clientRole": true, + "containerId": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "52b5daaf-81fa-4d59-8f3d-2cab429a0341", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "7f5a6b99-d4fc-4276-82e0-93642fbc2f60", + "attributes": {} + } + ], + "account": [ + { + "id": "08b328ca-8d45-4098-807a-d97b13e931e4", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes": {} + }, + { + "id": "a8ab93f6-5b15-4f98-a328-c833f2815826", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes": {} + }, + { + "id": "76a2152c-d06c-4bbe-bc51-1a86c38684ba", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes": {} + }, + { + "id": "4e37e74b-ec6c-4245-a277-b82bc057fb8e", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes": {} + }, + { + "id": "3b76c415-6a54-4719-a2b8-44bd2aedef97", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes": {} + }, + { + "id": "557663b6-1e42-4697-89b3-279272467349", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes": {} + }, + { + "id": "744ee6f8-0c20-4848-b34d-3d1f7a05a6bf", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "attributes": {} + } + ] + } + }, + "groups": [ + { + "id": "8711b426-3d18-4842-832d-c277d5414ee8", + "name": "USER", + "path": "/USER", + "attributes": {}, + "realmRoles": [ + "default-roles-otus-marketplace" + ], + "clientRoles": {}, + "subGroups": [] + } + ], + "defaultRole": { + "id": "ec06542b-8c8a-4fa1-a605-1594b17250b4", + "name": "default-roles-otus-marketplace", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "otus-marketplace" + }, + "defaultGroups": [ + "/USER" + ], + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + }, + { + "clientScope": "otus-marketplace", + "roles": [ + "default-roles-otus-marketplace" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account" + ] + } + ] + }, + "clients": [ + { + "id": "ba10e1e9-e7dd-4260-b412-60a9a4a2b6a0", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/otus-marketplace/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/otus-marketplace/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "8380c41e-f906-4c01-8685-dce56e853ee3", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/otus-marketplace/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/otus-marketplace/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "9046a1dc-cd8c-4812-b3b7-5e1f342a479d", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "1ea1031a-c029-46fd-9477-2867783adc93", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "7f5a6b99-d4fc-4276-82e0-93642fbc2f60", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "96b7d5f3-b04b-4460-9f7a-faf964c583a5", + "clientId": "otus-marketplace-service", + "rootUrl": "http://localhost:8080", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "id.token.as.detached.signature": "false", + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "use.refresh.tokens": "true", + "exclude.session.state.from.auth.response": "false", + "jwt.credential.certificate": "MIICvzCCAacCBgGEayQGdzANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhvdHVzLW1hcmtldHBsYWNlLXNlcnZpY2UwHhcNMjIxMTEyMDkxODUzWhcNMzIxMTEyMDkyMDMzWjAjMSEwHwYDVQQDDBhvdHVzLW1hcmtldHBsYWNlLXNlcnZpY2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIxAetegY1Yl8GD0zCUboJVflioxgkU65nbHOZtHUJDNlv4hk4YKGcELPZr226tz/468xFfPVeSWmzMVRnZYa5Ure54M27jh/sPfne0Wqy5YwD2XJy34CU3tFdn5dGuC4WOFcxkd8fbOKLLu3yi25tKR9VYXHDXQ6vuGvras5Rpn+HjHUs+1kSsNEvaBrEeG/MvxI44jbqYz4srD+ZniHB5R9rfluyewADx1/3/HUEtzp1m34oWKXXMP8NccYDqf8U2IQrjxV0hruQDirEp3W2iAox2N5pcLXCMVD3DYFkOf15Pp3zDPVRcbD4+LhvT5cDLFtwPosf+8xcQVOaM7aRAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADR5bl0/TWpgPsCS8ug/HaX2w5SFnQggdlfOoALgXzcNFsVmt1apz81uOfjC2+mDLeaUufGVC7DEwxHG/y6QXhmeYua9cxb3Lbqv93eTolkPBB44nkHI3g/afdOoQH4feHsJt4nmhGRr5APFazPHRgngEpk+soTgUrmQponohCskH/D/Gt69fo9T6jq9kwQ67FIKhXy/KgDZB1yJj3Rh6TrGxns/g/uw/mPLjuzDOpVBbH7fD83SMhMsKJwxeapHGnj7Voj04iprv9UfEXdwrsCOPD5XyjAwqyiqvOFA5nBQrDOv1Ii8CzK+XerP+d5ZVbzlyur6mGWHVumE5/UUeb8=", + "oidc.ciba.grant.enabled": "false", + "saml.artifact.binding": "false", + "backchannel.logout.session.required": "true", + "client_credentials.use_refresh_token": "false", + "saml_force_name_id_format": "false", + "require.pushed.authorization.requests": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "e6d885c8-4c3a-40a6-87bb-5ee2e6ee835f", + "name": "aud", + "protocol": "openid-connect", + "protocolMapper": "oidc-hardcoded-claim-mapper", + "consentRequired": false, + "config": { + "claim.value": "ad-users", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "aud", + "access.tokenResponse.claim": "false" + } + }, + { + "id": "10524baa-10b6-49ee-a18e-cb5242c0fa13", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-group-membership-mapper", + "consentRequired": false, + "config": { + "full.path": "false", + "id.token.claim": "false", + "access.token.claim": "true", + "claim.name": "groups", + "userinfo.token.claim": "false" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "roles" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "6d21188b-8942-4c23-99ca-ddbd534f0dc3", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "d829107c-dcfe-416e-82cb-a36b76f33009", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/otus-marketplace/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/admin/otus-marketplace/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "a3c28e64-eef9-4e9f-9a72-6814545b84d3", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "73de5776-9807-46ac-a040-601d07722400", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "0457b8bb-54ee-4583-8c02-df7dac6f28d5", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "a782e4d5-7389-4d90-9627-10ea2911a33e", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "c936ab6c-b7df-4f18-81cb-f9b4599f259b", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "d610fd5c-e9f0-4c75-bada-deaa38a44f93", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "678d741b-72da-4dcc-a866-1554b656c3a3", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "1ce17405-221a-4702-b39b-35eeae432681", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "85f25644-ae19-46b6-b8b2-7fb4c4fd0a56", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "58a55003-399f-4ad8-aaac-8547f0b57e78", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "1e91dc51-1c7b-42fb-a146-10acc4b7f0e6", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "67a034c1-1995-4322-b61d-3dc731256172", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "a70613bb-3d0b-4e1f-a7d1-97806ef4fb49", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "d01d7158-4bc5-438f-b426-1b75858f1fa8", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "45951871-317f-426a-afba-aff445ea1d1c", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "b0f80249-5325-4120-9fba-2c80fb167dae", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "b58b57ff-3251-423a-9fa8-792de8e4fefd", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "faf0444a-4437-437a-a4e8-639c10febb0d", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "ee5ccaae-cdde-40f7-9912-6d05c32d021d", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "3f92e080-d77f-4cd8-a1d0-95864b714e67", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "628747d4-9a19-46ba-ae31-844cb03614b5", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "ff254cad-f6bc-43f5-b826-99300f1e5ccd", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "fec69fa9-0ca2-4cd8-a9c3-cd1f46b7f125", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "9917ec30-6547-44b4-ac7e-4063bb6aa450", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "fb56dbeb-1e95-4ebb-a664-6bb0f646578d", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "fc776024-878e-4ffc-bcba-811df52fefea", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "6a6c50b6-7dc7-4176-b4d0-0e66362612ca", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + }, + { + "id": "b2dccd64-15d5-4327-8cd1-27c17e171db3", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + } + ] + }, + { + "id": "c5393ba9-51ad-4439-9a3a-e3d50fc90db8", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "c501f064-accb-4a04-a6ce-6a56a9f4c20b", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "cc56ea3e-e440-4124-b71f-51f74d253a91", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + }, + { + "id": "3028fb30-d025-4666-a016-75c69132fe0a", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "id": "d826541e-37d1-42ac-94e6-c9ace735e12e", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "d51fdf5d-d297-4b3b-ac78-f002c8517398", + "name": "otus-marketplace", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" + } + }, + { + "id": "7e017fb9-185f-4540-9061-8d8fa0ef9559", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "fa2c8da1-9068-4bf1-8efa-bce9169af279", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "30a7a411-f1de-4b4a-804c-7ebad85dbc0f", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "email", + "web-origins", + "role_list", + "roles", + "profile" + ], + "defaultOptionalClientScopes": [ + "address", + "microprofile-jwt", + "phone", + "offline_access" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "loginTheme": "keycloak", + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "aa142c07-2a15-4b0d-af81-cb9a13107a47", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "35c7b09b-9043-4337-ae7d-4455a2daa14c", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "3f10a26e-c3c1-4fd6-9ce4-909088438d97", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-sha256-pairwise-sub-mapper", + "saml-user-property-mapper", + "saml-user-attribute-mapper", + "saml-role-list-mapper", + "oidc-address-mapper", + "oidc-usermodel-property-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-full-name-mapper" + ] + } + }, + { + "id": "9f1597f1-7492-4e37-879a-3010278305a6", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "c62fbee8-d4b6-42d3-bf33-a969143be74c", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "3b2dee13-e36e-4545-8307-0b970e70ab5d", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "9bc37677-45b4-4d50-afcc-9ee741f77a5e", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-attribute-mapper", + "saml-user-property-mapper", + "oidc-usermodel-property-mapper", + "oidc-full-name-mapper", + "oidc-address-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "saml-user-attribute-mapper" + ] + } + }, + { + "id": "11e3a6d8-fc57-4ac1-a74f-aa8bc4b4ec23", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "2ee7e882-a94f-44cd-8dfd-23ddf6574d0f", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "af4bd03c-bb9b-4861-b69d-b8f69a241968", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "7888065d-47a7-43db-85e1-9ae9a8664d4e", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "RSA-OAEP" + ] + } + }, + { + "id": "3d06a085-40da-40ef-bad4-398447b62ecf", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS256" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [ + "" + ], + "authenticationFlows": [ + { + "id": "913f1273-2755-4ed6-9d43-7451fc7f46f6", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "477f74be-da81-46d0-a70e-218d3789de01", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth-otp", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "7fde02a6-6252-41f7-8de7-f8e963ed3721", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "00d4700a-3554-4372-af15-8aafdd1e0a6b", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "5f6b4205-7374-4e62-8c3a-7f343c05fc4c", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "84ee15fa-f04b-43fd-879a-3d464ad4d0ce", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Account verification options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "f78faeb8-9b19-4863-a67e-f4b3071521b8", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "f6a32408-74f1-4c37-b5f1-0f45dabcdcfc", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "781f4946-073c-49bf-ab5c-9dcc30f7bacd", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "14c0cae3-23fb-4bc2-aaf5-b00e6b28d690", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "787889ec-0399-4381-9e5c-c81e41dc34a1", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "a36e5912-620c-4d7a-a9f0-956bbeefbd5b", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "9ded7328-5509-4224-a823-59d84a7eff38", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "b8439ff4-0f9d-49d8-bf1e-293fca6011d8", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "User creation or linking", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "b8ac79f8-ffb5-4716-b29e-b508bbe8c204", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "517ab002-0767-464a-a2b2-d4d01b7efe87", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Authentication Options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "449cc526-f2e1-4b0e-ae06-c914eac81443", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "69dd4fa9-de4d-4dbf-b77a-11599d485930", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "cea3fde8-217b-49cc-b33e-b639adbf5a12", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "82506382-c8fc-46f0-84ee-acacb2cf16cc", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "085caece-781c-45ae-9c4d-b9920563f657", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "a28287da-7d00-46f5-be37-32d3bb4b267f", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaExpiresIn": "120", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DeviceCodeLifespan": "600", + "clientOfflineSessionMaxLifespan": "0", + "oauth2DevicePollingInterval": "5", + "clientSessionIdleTimeout": "0", + "userProfileEnabled": "false", + "parRequestUriLifespan": "60", + "clientSessionMaxLifespan": "0", + "clientOfflineSessionIdleTimeout": "0", + "cibaInterval": "5" + }, + "keycloakVersion": "16.1.1", + "userManagedAccessAllowed": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } +} \ No newline at end of file diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/standalone.xml b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/standalone.xml new file mode 100644 index 0000000..4d9f245 --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/docker-compose/volumes/keycloak/standalone.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/docker/KtorJvmKeycloakDockerCompose.kt b/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/docker/KtorJvmKeycloakDockerCompose.kt new file mode 100644 index 0000000..720c748 --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/docker/KtorJvmKeycloakDockerCompose.kt @@ -0,0 +1,21 @@ +package ru.otus.otuskotlin.marketplace.e2e.be.docker + +import ru.otus.otuskotlin.marketplace.e2e.be.fixture.docker.AbstractDockerCompose + +object KtorJvmKeycloakDockerCompose : AbstractDockerCompose( + "envoy_1", 8080, "docker-compose-ktor-keycloak-jvm.yml" +) +//object KtorJvmKeycloakDockerCompose : DockerCompose { +// override fun start() { +// } +// +// override fun stop() { +// } +// +// override fun clearDb() { +// +// } +// +// override val inputUrl: URLBuilder +// get() = URLBuilder("http://localhost:8080/") +//} diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/fixture/client/RestAuthClient.kt b/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/fixture/client/RestAuthClient.kt new file mode 100644 index 0000000..87ba75e --- /dev/null +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/fixture/client/RestAuthClient.kt @@ -0,0 +1,81 @@ +package ru.otus.otuskotlin.marketplace.e2e.be.fixture.client + +import co.touchlab.kermit.Logger +import io.ktor.client.* +import io.ktor.client.call.* +import io.ktor.client.engine.okhttp.* +import io.ktor.client.request.* +import io.ktor.client.request.forms.* +import io.ktor.http.* +import kotlinx.coroutines.runBlocking +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import ru.otus.otuskotlin.marketplace.blackbox.fixture.docker.DockerCompose + +/** + * Отправка запросов по http/rest + */ +class RestAuthClient(dockerCompose: DockerCompose) : Client { + private val log = Logger + private val urlBuilder by lazy { dockerCompose.inputUrl } + private val client = HttpClient(OkHttp) + private val token by lazy { runBlocking { getToken() } } + override suspend fun sendAndReceive(version: String, path: String, request: String): String { + val url = urlBuilder.apply { + path("$version/$path") + }.build() + + val resp = client.post { + url(url) + headers { + append(HttpHeaders.ContentType, ContentType.Application.Json) + append(HttpHeaders.Authorization, token) + } + accept(ContentType.Application.Json) + setBody(request) + + }.call + + return resp.body() + } + + private suspend fun getToken(): String { + val url = urlBuilder.apply { + path("/realms/otus-marketplace/protocol/openid-connect/token") + }.build() + val response = client.post(url) { + setBody( + FormDataContent(Parameters.build { + append("client_id", "otus-marketplace-service") + append("grant_type", "password") + append("username", "otus-test") + append("password", "otus") + }) + ) + } + val tokenObj: TokenApi = Json.decodeFromString(response.body()) + log.i { "TOKEN: ${tokenObj.accessToken}" } + return "${tokenObj.tokenType} ${tokenObj.accessToken}" + } + + @Serializable + data class TokenApi( + @SerialName("access_token") + val accessToken: String = "", + @SerialName("expires_in") + val expiresIn: Int = 0, + @SerialName("refresh_expires_in") + val refreshExpiresIn: Int = 0, + @SerialName("refresh_token") + val refreshToken: String = "", + @SerialName("token_type") + val tokenType: String = "", + @SerialName("not-before-policy") + val notBeforePolicty: Int = 0, + @SerialName("session_state") + val sessionState: String = "", + @SerialName("scope") + val scope: String = "", + ) +} diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/test/AccRestTest.kt b/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/test/AccRestTest.kt index 30c3182..9bda6c5 100644 --- a/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/test/AccRestTest.kt +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/test/AccRestTest.kt @@ -1,11 +1,10 @@ package ru.otus.otuskotlin.marketplace.e2e.be.test import io.kotest.core.annotation.Ignored -import ru.otus.otuskotlin.marketplace.blackbox.fixture.docker.DockerCompose -import ru.otus.otuskotlin.marketplace.e2e.be.docker.KtorJvmPGDockerCompose -import ru.otus.otuskotlin.marketplace.e2e.be.docker.KtorLinuxPGDockerCompose -import ru.otus.otuskotlin.marketplace.e2e.be.docker.WiremockDockerCompose import ru.otus.otuskotlin.marketplace.e2e.be.fixture.BaseFunSpec +import ru.otus.otuskotlin.marketplace.blackbox.fixture.docker.DockerCompose +import ru.otus.otuskotlin.marketplace.e2e.be.docker.* +import ru.otus.otuskotlin.marketplace.e2e.be.fixture.client.RestAuthClient import ru.otus.otuskotlin.marketplace.e2e.be.fixture.client.RestClient import ru.otus.otuskotlin.marketplace.e2e.be.test.action.v1.toV1 import ru.otus.otuskotlin.marketplace.e2e.be.test.action.v2.toV2 @@ -22,6 +21,7 @@ open class AccRestTestBaseFull(dockerCompose: DockerCompose, debug: TestDebug = testApiV1(restClient, prefix = "rest ", debug = debug.toV1()) testApiV2(restClient, prefix = "rest ", debug = debug.toV2()) }) + @Ignored open class AccRestTestBaseShort(dockerCompose: DockerCompose, debug: TestDebug = TestDebug.STUB) : BaseFunSpec(dockerCompose, { val restClient = RestClient(dockerCompose) @@ -31,5 +31,12 @@ open class AccRestTestBaseShort(dockerCompose: DockerCompose, debug: TestDebug = class AccRestWiremockTest : AccRestTestBaseFull(WiremockDockerCompose) //class AccRestSpringTest : AccRestTestBaseFull(SpringDockerCompose, debug = TestDebug.PROD) -class AccRestKtorPgJvmTest : AccRestTestBaseFull(KtorJvmPGDockerCompose, debug = TestDebug.PROD) -class AccRestKtorPgLinuxTest : AccRestTestBaseShort(KtorLinuxPGDockerCompose, debug = TestDebug.PROD) +//class AccRestKtorPgJvmTest : AccRestTestBaseFull(KtorJvmPGDockerCompose, debug = TestDebug.PROD) +//class AccRestKtorPgLinuxTest : AccRestTestBaseShort(KtorLinuxPGDockerCompose, debug = TestDebug.PROD) + +class AccRestKtorKeycloakJvmTest : BaseFunSpec(KtorJvmKeycloakDockerCompose, { + val restClient = RestAuthClient(KtorJvmKeycloakDockerCompose) + val debug = TestDebug.TEST +// testApiV1(restClient, prefix = "rest ", debug = debug.toV1()) + testApiV2(restClient, prefix = "rest ", debug = debug.toV2()) +}) diff --git a/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/test/action/v2/sendAndReceiveV2.kt b/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/test/action/v2/sendAndReceiveV2.kt index 8efcdc5..09f4721 100644 --- a/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/test/action/v2/sendAndReceiveV2.kt +++ b/ok-marketplace-tests/ok-marketplace-e2e-be/src/test/kotlin/test/action/v2/sendAndReceiveV2.kt @@ -11,12 +11,10 @@ import ru.otus.otuskotlin.marketplace.e2e.be.fixture.client.Client suspend inline fun Client.sendAndReceive(path: String, request: Rq): Rs { val log = Logger val requestBody = apiV2RequestSimpleSerialize(request) -// val requestBody = apiV2RequestSerialize(request) log.w { "Send to v2/$path\n$requestBody" } val responseBody = sendAndReceive("v2", path, requestBody) log.w { "Received\n$responseBody" } -// return apiV2ResponseDeserialize(responseBody) return apiV2ResponseSimpleDeserialize(responseBody) }