以下の記事の内容を試してみました。
試す内容
以下のフローの⑦だけスキップしてそれ以外を実装しました。
言語はkotlinで実装しております。
Keycloakの設定
DockerでKeycloakを起動
以下のコマンドで自動でDockerイメージがダウンロードされる
docker run -d --name keycloak -p 8888:8080 \
-e KEYCLOAK_USER=spring \
-e KEYCLOAK_PASSWORD=spring123 \
jboss/keycloak
Clientの作成
以下のURLにアクセスする
http://localhost:8888/auth/admin/
Client Secretを取得
keycloak-without-test-scopeも同様に作成する。
Spring Bootのダウンロード
Spring InitializrからSpring Bootをダウンロードする
https://start.spring.io/
build.gradle.ktsの設定
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.5.2"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.5.20"
kotlin("plugin.spring") version "1.5.20"
}
group = "phoneappli.people"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
dependencyManagement {
imports {
mavenBom("org.springframework.cloud:spring-cloud-dependencies:2020.0.3")
}
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.springframework.cloud:spring-cloud-starter-gateway")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.security:spring-security-test")
implementation("org.springframework.security:spring-security-oauth2-resource-server")
implementation("org.springframework.security:spring-security-oauth2-jose")
implementation("org.springframework.security:spring-security-oauth2-client")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
application.ymlの設定
server.port: 8090
spring:
security:
oauth2:
client:
provider:
keycloak:
token-uri: http://127.0.0.1:8888/auth/realms/master/protocol/openid-connect/token
authorization-uri: http://127.0.0.1:8888/auth/realms/master/protocol/openid-connect/auth
userinfo-uri: http://127.0.0.1:8888/auth/realms/master/protocol/openid-connect/userinfo
user-name-attribute: preferred_username
registration:
keycloak-with-test-scope:
provider: keycloak
client-id: spring-with-test-scope
client-secret: f7fab54d-b766-4fc3-b3a2-fbcaf826e816
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/keycloak"
application:
name: callme
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://127.0.0.1:8888/auth/realms/master
cloud:
gateway:
default-filters: TokenRelay
routes:
- id: callme-service
uri: http://127.0.0.1:5000 #callmeサービスのURL
predicates:
- Path=/callme/**
filters:
- RemoveRequestHeader=Cookie #callmeサービスへ転送する時にCookieを削除
main:
web-application-type: reactive
allow-bean-definition-overriding: true
logging:
level:
org.springframework.security: DEBUG
Spring Securityの設定
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class SecurityConfig: WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http.authorizeHttpRequests {
authorize -> authorize.anyRequest().authenticated()
}.oauth2ResourceServer().jwt()
}
}
動作確認
callmeサービスはPython Flaskで文字列を返すだけのサービスを実装。
ブラウザで以下のURLにアクセス。
http://127.0.0.1:8090/callme/ping
以下の画面に自動でリダイレクトする。
「keycloak-with-test-scope」「keycloak-without-test-scope」のどちらかを選択するとログイン画面が表示されるので、ログインする。
認証URLはこのようになっている。(http://127.0.0.1:8888/auth/realms/master/protocol/openid-connect/auth?response_type=code&client_id=spring-with-test-scope&state=AnB-Pc1Mi6Uv3caMM59g5Sfs6ASz7wu4oMPN6aXpsvM%3D&redirect_uri=http://127.0.0.1:8090/login/oauth2/code/keycloak)
認証に成功するとcallmeサービスが返した内容が表示される。
http://127.0.0.1:8090/callme/ping
callmeサービスへ転送されたリクエストではcookieは削除されており、また以下の内容がheaderに付与されています。
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJaSlZqWmlHUzgybmVETVlpVUZaRW1QQjBJM0ItOXJSTmhzQWJMWnhnbmtjIn0.eyJleHAiOjE2MjU3MjQ4NDgsImlhdCI6MTYyNTcyNDc4OCwiYXV0aF90aW1lIjoxNjI1NzIzODUxLCJqdGkiOiI5MTU3YWE4Zi0xZGQ1LTQxYTMtYmJkYi0wMTIxNTgwNmZlM2YiLCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjg4ODgvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbIm1hc3Rlci1yZWFsbSIsImFjY291bnQiXSwic3ViIjoiY2M1MWIxNTQtMGQ2Mi00YjRhLWI5YWYtMWZkN2FjMmFmNDdhIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoic3ByaW5nLXdpdGgtdGVzdC1zY29wZSIsInNlc3Npb25fc3RhdGUiOiJjMGQxMWNmMi0wODllLTQzZWItYmYzMi1kNDVkYzM1N2EzNzQiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImNyZWF0ZS1yZWFsbSIsImRlZmF1bHQtcm9sZXMtbWFzdGVyIiwiU0NPUEVfVEVTVCIsIm9mZmxpbmVfYWNjZXNzIiwiYWRtaW4iLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7Im1hc3Rlci1yZWFsbSI6eyJyb2xlcyI6WyJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsInZpZXctcmVhbG0iLCJtYW5hZ2UtaWRlbnRpdHktcHJvdmlkZXJzIiwiaW1wZXJzb25hdGlvbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBURVNUIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InNwcmluZyJ9.CRKt9rGPsv-et1bWlLcVdgj46PSGRKSMmZmxzBusHxORjJK2OeyzSYRqFNlGWW_hZDtTp3zB4DU3VYnFSDo_zxAaBJnjA4efr3SnKhUKjdSa6Oiv95PVkU_xzStKKOeqC7VUB8WZpXWgh4GfcC7VFMnUhWJyjCUsE3kfUZA3z7WxuAhrU_9nz3elDIgtQt6Rj9CePk_a4HDfMrjhWLqYi1qjlnyWsMatHav44Iz0ygTpOQyd4k0awd-f7FEp916zfAxLOKFIo7tqsS8DEf46II_GBThTkTtmCNlOJoBHHTqL9VHaN1kWHUbm6BxTfoaqooLaIxTc7BIbkJPVp8Hhag
こちらはjwtになっており分解するとroleなどの情報が入っております。