API 및 웹 페이지에 대한 액세스를 보호하려고 합니다. HTTPS를 사용하여 API에 대한 외부 액세스를 도청하지 못하도록 보호하는 방법과 OAuth 2.0
및 OpenID Connect
를 사용하여 API에 액세스하도록 사용자 및 클라이언트 앱을 인증하고 권한을 부여합니다. 마지막으로 HTTP 기본 인증을 사용하여 검색 서버인 Netflix Eureka
에 대한 액세스를 보호합니다.
이 장에서 다룰 주제는 다음과 같습니다.
OAuth 2.0
및 OpenID Connect
Netflix Eureka
접근 보안OAuth 2.0
및 OpenID Connect
의 API 인증 및 권한 부여OpenID Connect
제공업체인 Auth0
로 테스트인증은 사용자의 자격 증명을 확인하여 사용자를 식별하는 것입니다. 권한 부여는 API에 대한 액세스 권한을 인증된 사용자에게 부여하는 것입니다.
OAuth 2.0
은 권한 위임을 위한 개방형 표준이며 OpenID Connect
는 OAuth 2.0의 추가 기능으로 클라이언트 앱이 권한 서버에서 수행한 인증을 기반으로 사용자의 신원을 확인할 수 있도록 합니다.
OAuth 2.0
은 사용자가 제3자 클라이언트 앱이 사용자 이름으로 보호된 리소스에 액세스하는 데 동의할 수 있도록 하는 승인을 위해 널리 허용되는 공개 표준입니다. API 호출과 같이 타사 클라이언트 앱에 사용자 이름으로 작업할 수 있는 권한을 부여하는 것을 권한 위임이라고 합니다.
So, what does this mean?
Let's start by sorting out the concepts used:
인증 서버에 클라이언트가 등록되면 client_id와 secret이 부여됩니다. 클라이언트는 또한 사용자 인증 후 클라이언트 앱에 다시 발행된 인증 코드와 토큰을 보낸 후 인증 서버가 사용할 허용된 리디렉션 URI에 등록됩니다.
예를 들어, 사용자가 타사 클라이언트 앱에 액세스하고 클라이언트 앱이 사용자에게 서비스를 제공하기 위해 보호된 API를 호출하려고 한다고 가정해 보겠습니다. 이러한 API에 액세스할 수 있으려면 클라이언트 앱이 사용자 이름으로 작동하고 있음을 API에 알리는 방법이 필요합니다. 사용자가 인증을 위해 자신의 자격 증명을 클라이언트 앱과 공유해야 하는 솔루션을 피하기 위해 클라이언트 앱에 사용자 이름으로 선택된 API에 대한 제한된 액세스 권한을 부여하는 권한 부여 서버에서 액세스 토큰을 발행합니다.
즉, 사용자는 클라이언트 앱에 자격 증명을 공개할 필요가 없습니다. 사용자는 사용자를 대신하여 특정 API에 액세스하기 위해 클라이언트 앱에 동의할 수도 있습니다.
The OAuth 2.0 specification defines four authorization grant flows for issuing access tokens, explained as follows:
인증 코드 부여 방식
This is the safest, but also the most complex, grant flow. This grant flow requires that the user interacts with the authorization server using a web browser for authentication and giving consent to the client application, as illustrated by the following diagram:
Figure 11.1: OAuth 2.0
– 인증코드 부여 방식
Here's what's going on in this diagram:
클라이언트 앱은 사용자를 웹 브라우저의 인증 서버로 보내 승인 흐름을 시작합니다.
인증 서버는 사용자를 인증하고 사용자의 동의를 요청합니다.
인증 서버는 인증 코드를 사용하여 사용자를 클라이언트 앱으로 다시 리디렉션합니다. 인증 서버는 1단계에서 클라이언트가 지정한 리디렉션 URI를 사용하여 인증 코드를 보낼 위치를 파악합니다. 인증 코드는 웹 브라우저를 통해 클라이언트 앱으로 다시 전달되기 때문에, 즉 악성 자바스크립트 코드가 잠재적으로 인증 코드를 받을 수 있는 비보안 환경으로 짧은 시간 동안 한 번만 사용할 수 있습니다.
액세스 토큰에 대한 인증 코드를 교환하기 위해 클라이언트 앱은 인증 서버를 다시 호출해야 합니다. 클라이언트 앱은 인증 서버에 대한 인증 코드와 함께 클라이언트 ID와 암호를 제시해야 합니다.
인증 서버는 액세스 토큰을 발행하고 이를 클라이언트 앱으로 다시 보냅니다. 권한 부여 서버는 선택적으로 리프레시 토큰을 발행하고 반환할 수도 있습니다.
클라이언트는 액세스 토큰을 사용하여 리소스 서버에서 노출된 보호된 API에 요청을 보낼 수 있습니다.
리소스 서버는 액세스 토큰의 유효성을 검사하여 처리합니다. 액세스 토큰이 유효한 한 6단계와 7단계를 반복할 수 있습니다. 토큰 수명이 만료되면 클라이언트는 리프레시 토큰을 사용하여 새 토큰을 얻을 수 있습니다.
클라이언트 자격증명 방식
특정 사용자와 관계없는 API를 호출하는 클라이언트가 있을 경우 client_id와 secret을 사용하여 액세스 토큰을 얻을 수 있습니다.
OAuth 2.1의 가장 중요한 개선은 다음과 같습니다.
보안을 개선하기 위해 퍼블릭 클라이언트는 PKCE
를 사용해야 합니다. 인증 서버가 자신의 자격 증명을 확인할 수 있는 프라이빗 클라이언트의 경우 PKCE
를 사용할 필요가 없으며 권장됩니다.
암시적 방식과 암호 방식은 더 이상 사용되지 않습니다.
앞으로 인증코드 방식과 클라이언트 자격증명 방식만 사용할 것입니다.
OAuth 2.0으로 보호되는 API에 대한 테스트 자동화와 관련하여 클라이언트 자격 증명 부여 흐름은 웹 브라우저를 사용한 수동 상호 작용이 필요하지 않기 때문에 매우 편리합니다. 이 장의 뒷부분에서 테스트 스크립트와 함께 이 승인 흐름을 사용할 것입니다. 테스트 스크립트 섹션의 변경 사항을 참조하십시오.
OpenID Connect
는 클라이언트가 사용자의 신원을 확인할 수 있는 OAuth 2.0
의 추가 기능입니다. OpenID Connect
는 승인이 완료된 후 클라이언트가 인증 서버에서 받는 ID 토큰
을 추가합니다.
ID 토큰
은 JWT로 인코딩되며 사용자 ID, 이메일 주소 같은 클레임이 포함되며 JWS로 서명됩니다. 이렇게 하면 클라이언트는 인증 서버의 공개 키를 사용하여 서명의 유효성을 검사하여 토큰 정보를 신뢰할 수 있습니다.
ID 토큰
과 동일한 방식으로 인코딩 및 서명될 수 있습니다.OpenID Connect
는 인증 코드 및 토큰 요청 또는 서명된 JWT를 확인하기 위한 공개 키 가져오기와 엔드포인트를 정의합니다. 이 책에서는
OpenID Connect
사양을 준수하는 인증 서버만 사용합니다. 이렇게 하면 검색 끝점을 사용하여 리소스 서버의 구성을 단순화할 수 있습니다. 또한 디지털 서명된 JWT 액세스 토큰에 대한 선택적 지원을 사용하여 리소스 서버가 액세스 토큰의 신뢰성을 확인할 수 있는 방법을 단순화합니다. 아래 Edge 서버 및Product-composite
서비스 섹션의 변경 사항을 참조하십시오.
시스템 환경을 보호하기 위해 다음 단계를 수행합니다.
HTTPS를 사용하여 외부 API에 대한 외부 요청 및 응답을 암호화
OAuth 2.0
및 OpenID Connect
로 API에 액세스하는 사용자 및 클라이언트 인증 및 권한 부여
HTTP 기본 인증으로 Eureka에 대한 보안 액세스
시스템 내부에서는 HTTP를 사용하고 외부에 노출되는 에지 서버에는 HTTPS를 적용합니다.
"18장 서비스 Mesh를 사용하여 관찰 가능성 및 관리 개선"에서 서비스 Mesh 제품으로 HTTPS를 자동으로 프로비저닝하여 내부 통신을 보호하는 방법을 볼 수 있습니다.
테스트를 위해 시스템에 로컬 OAuth 2.0
인증 서버를 추가합니다. 인증 서버와의 모든 외부 통신은 에지 서버를 통해 라우팅됩니다. 에지 서버와 product-composite
서비스는 리소스 서버로 작동합니다.
액세스 토큰 유효성 검사의 오버헤드를 최소화하기 위해 액세스 토큰이 서명된 JWT로 인코딩되고 인증 서버는 리소스 서버가 서명을 확인하는데 필요한 공개 키를 액세스 할 엔드포인트를 노출합니다.
시스템 환경은 다음과 같습니다.
Figure 11.2: 시스템 환경에 인증서버 추가
From the preceding diagram, we can note that:
시스템 내부에서는 http를 사용합니다.
로컬 OAuth 2.0
인증 서버는 에지 서버를 통해 액세스됩니다.
리소스인 에지 서버와 product-composite
서비스는 액세스 토큰을 서명된 JWT로 검증합니다.
리소스 서비스는 jwk-set
엔드포인트에서 인증 서버의 공개키를 가져와 액세스 토큰의 서명을 확인합니다.
HTTPS를 사용하려면 다음을 수행해야 합니다.
자체 서명된 인증서를 생성합니다.
keytool -genkeypair -alias localhost -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore edge.p12 -validity 3650
소스코드에 인증서 파일 샘플이 있으므로 다음의 예제를 실행하기 위해 이 명령을 실행할 필요는 없습니다.
The command will ask for a number of parameters. When asked for a password, I entered roouty
. For the rest of the parameters, I simply entered an empty value to accept the default value.
인증서 edge.p12
는 spring-cloud/gateway
프로로젝트의 /src/main/resources/keystore
에 놓이므로 빌드 시 .jar
파일에 포함됩니다.
개발 중에는 클래스 경로를 사용하여 인증서를 제공해도 되지만 프로덕션 환경에서는 적용할 수 없습니다. 런타임 시 인증서를 외부 인증서로 교체하는 방법은 아래 런타임 시 자체 서명 인증서 교체 섹션을 참조하십시오!
에지 서버가 인증서와 https를 사용하도록 gateway
프로젝트의 application.yml
에 다음과 같이 설정합니다.
server.port: 8443
server.ssl:
key-store-type: PKCS12
key-store: classpath:keystore/edge.p12
key-store-password: roouty
key-alias: localhost
다음 파일에서도 포트를 8443
으로 수정합니다.
docker-compose*.yml
test-em-all.bash
자체 서명 인증서를 .jar
파일에 배치하는 것은 개발 환경에서만 유용합니다. 테스트 또는 프로덕션과 같은 런타임 환경에서 작동하는 솔루션의 경우 인증된 CA에서 서명한 인증서를 사용할 수 있어야 합니다.
또한 .jar
파일을 다시 빌드할 필요 없이 런타임 중에 사용할 인증서를 지정할 수 있어야 하며 Docker를 사용할 때 .jar
파일이 포함된 Docker 이미지를 지정할 수 있어야 합니다. Compose를 사용하여 Docker 컨테이너를 관리할 때 Docker 컨테이너의 볼륨을 Docker 호스트에 있는 인증서에 매핑할 수 있습니다. Docker 볼륨의 외부 인증서를 가리키는 Docker 컨테이너에 대한 환경 변수를 설정할 수도 있습니다.
"15장, Kubernetes 소개"에서는 클러스터에서 Docker 컨테이너를 실행하는 데 적합한 인증서와 같은 시크릿을 처리하는 방법에 대한 보다 강력한 솔루션을 볼 수 있습니다. 즉, 컨테이너가 단일 Docker 호스트가 아닌 Docker 호스트 그룹에서 예약되는 경우입니다.
이 주제의 변경 사항은 git 소스에는 반영되지 않았으므로 직접 만들어야 합니다!
.jar
파일에 패키지된 인증서를 교체하려면 다음 단계를 수행하십시오.
testtest
로 입력합니다:mkdir keystore
keytool -genkeypair -alias localhost -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore/edge-test.p12 -validity 3650
docker-compose.yml
에 새 인증서가 저장된 폴더에 매핑하는 위치, 패스워드, 볼륨에 대한 환경 변수를 갱신합니다:gateway:
environment:
- SPRING_PROFILES_ACTIVE=docker
- SERVER_SSL_KEY_STORE=file:/keystore/edge-test.p12
- SERVER_SSL_KEY_STORE_PASSWORD=testtest
volumes:
- $PWD/keystore:/keystore
build: spring-cloud/gateway
mem_limit: 512m
ports:
- "8443:8443"
에지 서버를 올리고 실행하면 다음 명령을 재시작이 필요합니다:
docker-compose up -d --scale gateway=0
docker-compose up -d --scale gateway=1
도커 서비스 재시작은
docker-compose restart
명령이 합당해 보이지만 docker-compose.yml의 변경을 고려하지 않으므로 여기에 적당하지 않습니다.
이제 새 인증서를 사용합니다.
이제는 http basic 인증을 사용하여 API 액세스와 Eureka 서버의 웹 페이지 접근을 제한합니다. 사용자는 username
과 password
를 제출하여야 액세스가 허용됩니다.
SecurityConfig
클래스에 설정을 추가합니다:
사용자는 다음과 같이 정의합니다.
public void configure(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser(username).password(password)
.authorities("USER");
}
SecurityConfig의 생성자에 username
와 password
를 주입합니다.
@Autowired
public SecurityConfig(
@Value("${app.eureka-username}") String user,
@Value("${app.eureka-password}") String passwd
) {
this.username = user;
this.password = passwd;
}
다음 정의에 의해 모든 API와 웹 페이지들은 HTTP 기본 인증으로 보호됩니다.
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
자격증명은 application.yml
파일에 기록합니다 :
app:
eureka-username: user
eureka-password: passwd
Finally, the test class, EurekaServerApplicationTests
, uses the credentials from the configuration file when testing the APIs of the Eureka server:
@Value("${app.eureka-username}")
private String user;
@Value("${app.eureka-password}")
private String passwd;
@Autowired
public void setTestRestTemplate(TestRestTemplate temp) {
this.template = temp.withBasicAuth(user, passwd);
}
Eureka 서버의 API 및 웹페이지 접근을 제한하기 위해 필요한 단계입니다.
마지막 단계는 Eureka 클라이언트를 설정하여 Eureka 서버를 액세스 할 때 자격증명을 건네도록 수정합니다.
Eureka 클라이언트에서 자격증명은 Eureka 서버에 대한 컨넥션 URL에서 지정할 수 있습니다. 클라이언트의 application.yml
에서 지정합니다.
app:
eureka-username: user
eureka-password: passwd
eureka:
client:
serviceUrl:
defaultZone: "http://${app.eureka-username}:${app.eureka-password}@${app.eureka-server}:8761/eureka/"
Eureka 서버 테스트 섹션에서 테스트를 실행하여 액세스가 보호되는지 확인합니다.
OAuth 2.0 및 OID Connect를 사용하여 보호되는 API를 사용하여 로컬에서 자동화된 테스트를 실행할 수 있도록 인증 서버를 시스템 환경에 추가합니다.
Spring Security는 불행히도 인증 서버를 즉시 제공하지 않습니다. 하지만 2020년 4월, Spring Security 팀이 주도하는 커뮤니티 주도 프로젝트인 Spring Authorization Server
가 인증 서버 제공을 목표로 발표되었습니다.
Spring Authorization Server 는 OID Connect 디스커버리 엔드포인트의 사용과 액세스 토큰의 디지털 서명을 모두 지원합니다. 또한 토큰의 서명을 확인하기 위한 키를 얻기 위해 디스커버리 정보를 사용하여 액세스할 수 있는 엔드포인트를 제공합니다.
로컬 및 자동화 테스트에서 인증 서버로 사용할 수 있습니다.
샘플 프로젝트를 다음과 같이 수정하였습니다.
9999
actuator
의 엔드포인트의 공개 접근을 허용WARNING: actuator의 엔드포인트에 대한 공개 액세스를 허용하는 것은 개발 중에 매우 유용하지만 프로덕션 시스템의 액츄에이터 엔드포인트에서 너무 많은 정보를 공개하는 것은 보안 문제가 될 수 있습니다. 따라서 생산 시 actuator 엔드포인트에서 노출되는 정보를 최소화하도록 계획하십시오!
OIDC 명세에 따라 주요 엔드포인트 액세스를 검증하는 단위 테스트가 추가됩니다.
한 사용자의 username
과 password
는 "user" and "passwd"입니다.
두 OAuth 클라이언트를 등록합니다. reader
클라이언트에게는 product:read
scope를 부여하고 writer
클라이언트는 product:read
와 product:write
scope를 부여합니다. 두 클라이언트 모두 client secret
이 secret
으로 지정합니다.
클라이언트에게 허용된 리다이렉트 URIs는 https://my.redirect.uri
와 https://localhost:8443/webjars/swagger-ui/oauth2-redirect.html
으로 지정합니다. 하나는 테스트 용이고 다른 하나는 Swagger UI
컴포넌트에서 사용합니다.
인증 서버를 시스템 환경에 붙이기 위해 다음 파일들이 수정됩니다.
settings.gradle
에 인증 서버를 추가합니다docker-compose*.yml
에 추가합니다spring-cloud/gateway
에서HealthCheckConfiguration
에 인증 서버 추가/oauth
, /login
, /error
로 시작하는 인증 서버로 향하는 URI를 application.yml
에 추가SecurityConfig
에서 모든 요청 허가로 설정합니다.인증 서버로 에지 서버와 product-composite
서비스를 리소스 서버로 개선할 수 있으므로 유효한 액세스 토큰이 필요합니다. 에지 서버는 인증 서버에서 제공한 서명을 사용하여 확인할 수 있는 모든 액세스 토큰을 수락하도록 구성됩니다. product-composite
서비스에는 scope를 포함하는 액세스 토큰도 필요합니다.
product:read
scope: read-only APIs 액세스product:write
scope: create and delete APIs 액세스product-composite
서비스는 Swagger UI
구성 요소가 인증 서버로부터 액세스 토큰을 발급할 수 있도록 하는 구성으로 개선됩니다.
test-em-all.bash
를 개선하여 액세스 토큰을 획득하고 테스트를 수행할 때 사용할 수 있도록 해야 합니다.
The following changes have been applied in the source code to both the edge server and the product-composite
service:
SecurityConfig
를 추가합니다.@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
SecurityWebFilterChain springSecurityFilterChain(
ServerHttpSecurity http) {
http
.authorizeExchange()
.pathMatchers("/actuator/**").permitAll()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
}
Be careful about which URLs are exposed unprotected. For example, the
actuator
endpoints should be protected before going to production.
anyExchange().authenticated()
: 나머지 모든 URL은 인증이 필요
oauth2ResourceServer().jwt()
: 인증이 액세스 토큰 방식으로 이루어짐
인증 서버의 OIDC 디스커버리 엔드포인트는 application.yml
에 등록합니다:
app.auth-server: localhost
spring.security.oauth2.resourceserver.jwt.issuer-uri: http://${app.auth-server}:9999
---
spring.config.activate.on-profile: docker
app.auth-server: auth-server
시스템 환경이 시작되면 디스커버리 엔드포인트를 테스트할 수 있습니다. 예를 들어 다음 명령을 사용하여 토큰의 서명을 확인하는 데 필요한 키를 반환하는 엔드포인트를 찾을 수 있습니다.
docker-compose exec auth-server curl localhost:9999/.well-known/openid-configuration -s | jq -r .jwks_uri
응답은
http://auth-server:9999/oauth2/jwks
SecurityConfig 클래스의 보안 구성은 액세스를 허용하기 위해 액세스 토큰에 'OAuth 2.0' scope를 요구하여 개선되었습니다.
.pathMatchers(POST, "/product-composite/**")
.hasAuthority("SCOPE_product:write")
.pathMatchers(DELETE, "/product-composite/**")
.hasAuthority("SCOPE_product:write")
.pathMatchers(GET, "/product-composite/**")
.hasAuthority("SCOPE_product:read")
Spring Security에서는 권한 앞에
SCOPE_
를 붙여야 합니다.
Swagger UI
가 액세스 토큰을 받도록 수정
To allow access to the protected APIs from the Swagger UI
component, the following changes have been applied in the product-composite
service:
Swagger UI
컴포넌트가 노출하는 API 접근을 모두에게 허용합니다. .pathMatchers("/openapi/**").permitAll()
.pathMatchers("/webjars/**").permitAll()
security_auth
가 적용되도록 API의 OAS를 개선합니다.The following line has been added to the definition of the interface ProductCompositeService
in the API project:
@SecurityRequirement(name = "security_auth")
security_auth
의 시멘틱을 정의하기 위해 product-composite
프로젝트에 OpenApiConfig
를 추가합니다.@SecurityScheme(
name = "security_auth", type = SecuritySchemeType.OAUTH2,
flows = @OAuthFlows(
authorizationCode = @OAuthFlow(
authorizationUrl = "${springdoc.oAuthFlow.
authorizationUrl}",
tokenUrl = "${springdoc.oAuthFlow.tokenUrl}",
scopes = {
@OAuthScope(name = "product:read", description =
"read scope"),
@OAuthScope(name = "product:write", description =
"write scope")
}
)))
public class OpenApiConfig {}
OAuth 2.0
기반의 시큐리티 스키마 적용
인증 코드 부여 방식을 사용
인증 코드와 액세스 토큰을 받기 위한 URL을 설정 파일에서 제공
scope 목록(product:read
and product:write
)
끝으로 application.yml
에 몇가지 설정을 추가합니다.
swagger-ui:
oauth2-redirect-url: https://localhost:8443/ webjars/swagger-ui/oauth2-redirect.html
oauth:
clientId: writer
clientSecret: secret
useBasicAuthenticationWithAccessCodeGrant: true
oAuthFlow:
authorizationUrl: https://localhost:8443/oauth2/authorize
tokenUrl: https://localhost:8443/oauth2/token
1. Swagger UI가 인증 코드를 받는데 사용할 리다이렉트 URL
2. client ID and client secret.
3. 인증서버에 대해 자신을 인증할 때 기본 인증을 사용함.
4. 위에서 설명한 OpenApiConfig 클래스에서 사용하는 `authorizationUrl` 및 `tokenUrl` 파라미터의 값입니다. 이 URL은 product-composite 서비스 자체가 아니라 웹 브라우저에서 확인할 수 있어야 합니다.
Swagger UI' 웹 페이지에 대한 보호되지 않은 액세스를 허용하기 위해 Swagger UI 구성 요소로 라우팅되는 URL에 대한 무제한 액세스를 허용하도록 에지 서버도 구성되었습니다.
The following is added to the edge server's `SecurityConfig` class:
```java
.pathMatchers("/openapi/**").permitAll()
.pathMatchers("/webjars/**").permitAll()
이러한 변경 사항이 적용되면 에지 서버와 product-composite 서비스가 모두 'OAuth 2.0' 리소스 서버로 작동할 수 있고 Swagger UI 구성요소는 OAuth 클라이언트로 작동할 수 있습니다.
마지막 단계는 테스트 스크립트를 업데이트하는 것이므로 액세스 토큰을 획득하고 테스트를 실행할 때 사용합니다.
헬스 체크 API를 제외한 나머지 API를 호출하기 전에 액세스 토큰이 필요합니다. 클라이언트 자격증명을 사용하여 액세스 토큰을 획득합니다.
ACCESS_TOKEN=$(curl -k https://writer:secret@$HOST:$PORT/oauth2/token -d grant_type=client_credentials -s | jq .access_token -r)
From the preceding command, we can see that it uses HTTP Basic
authentication, passing its client ID
and client secret
as writer:secret@
before the hostname
.
scope 기반 인증이 작동하는지 확인하는 두 개의 테스트를 추가합니다.
# Verify that a request without access token fails on 401, Unauthorized
assertCurl 401 "curl -k https://$HOST:$PORT/product-composite/$PROD_ID_REVS_RECS -s"
# Verify that the reader client with only read scope can call the read API but not delete API
READER_ACCESS_TOKEN=$(curl -k https://reader:secret@$HOST:$PORT/oauth2/token -d grant_type=client_credentials -s | jq .access_token -r)
READER_AUTH="-H \"Authorization: Bearer $READER_ACCESS_TOKEN\""
assertCurl 200 "curl -k https://$HOST:$PORT/product-composite/$PROD_ID_REVS_RECS $READER_AUTH -s"
assertCurl 403 "curl -k https://$HOST:$PORT/product-composite/$PROD_ID_REVS_RECS $READER_AUTH -X DELETE -s"
테스트 스크립트는 reader 클라이언트의 자격 증명을 사용하여 액세스 토큰을 획득합니다.
첫 번째 테스트는 액세스 토큰을 제공하지 않고 API를 호출합니다. API는 '401 Unauthorized' HTTP 상태를 반환합니다.
두 번째 테스트는 reader 클라이언트가 read-only API를 호출할 수 있는지 확인합니다.
마지막 테스트는 읽기 범위만 부여된 reader 클라이언트를 사용하여 업데이트 API를 호출합니다. 삭제 API로 전송된 요청은 '403 Forbidden' HTTP 상태를 반환할 것으로 예상됩니다.
For the full source code, see test-em-all.bash
.
With the test script updated to acquire and use OAuth 2.0 access tokens, we are ready to try it out in the next section!
모든 시큐리티 컴포넌트를 함께 테스트합니다. 로컬 인증서버를 사용하여 액세스 토큰을 발행합니다.
소스를 빌드하고 테스트 스크립트를 실행하여 모든 것을 함께 부합하는지 테스트 합니다.
보호된 디스커버리 서버의 API와 웹 페이지를 테스트 합니다
클라이언트 자격증명과 인증코드 부여 방식을 사용하여 액세스 토큰을 얻는 방법을 배웁니다.
발행한 토큰으로 API를 테스트 합니다. 또한 reader 클라이언트가 업데이트 API를 호출할 수 없는지는 태스트 합니다.
Verify that Swagger UI can issue access tokens and call the APIs.
To build and run automated tests, we perform the following steps:
cd $BOOK_HOME/Chapter11
./gradlew build && docker-compose build
./test-em-all.bash start
네거티브 테스트 끝에서는 인증이 안된 경우 401 Unauthorized
코드를 받으며 권한이 없는 경우는 403 Forbidden
코드를 얻는지 확인합니다.
보호된 서버인 Eureka가 실행 중이므로 API 및 웹 페이지에 액세스할 수 있도록 유효한 자격 증명을 제공해야 합니다.
예를 들어 Eureka 서버에게 등록된 인스턴스를 요청입니다. 여기서 URL에 username과 password를 직접 제공합니다.
curl -H "accept:application/json" https://u:p@localhost:8443/eureka/api/apps -ks | jq -r
응답은
{
"applications": {
"versions__delta": "1",
"apps__hashcode": "UP_6_",
"application": [
{
"name": "GATEWAY",
"instance": [
{
"instanceId": "7299660fd99d:gateway:8443",
"hostName": "7299660fd99d",
"app": "GATEWAY",
"ipAddr": "172.23.0.7",
"status": "UP",
"overriddenStatus": "UNKNOWN",
"port": {
"$": 8443,
"@enabled": "true"
...
https://localhost:8443/eureka/web
의 웹 페이지에 액세스할 때 인증서가 자체 서명되어 있으므로 먼저 안전하지 않은 연결을 수락해야 하고 다음으로 지정된 대로 유효한 자격 증명을 제공해야 합니다.
클라이언트 자격증명 방식
writer에 대한 액세스 토큰을 얻어 옵니다:
curl -k https://writer:secret@localhost:8443/oauth2/token -d grant_type=client_credentials -s | jq .
client ID
, writer
, and its client secret
, secret
.{
"access_token": "eyJraWQiOiI3Nj...",
"scope": "product:write openid product:read",
"token_type": "Bearer",
"expires_in": "3599"
}
이번에는, reader를 위한 액세스 토큰을 받아옵니다.
curl -k https://reader:secret@localhost:8443/oauth2/token -d grant_type=client_credentials -s | jq .
{
"access_token": "eyJraWQiOiI3NjAyYTFiN...",
"scope": "openid product:read",
"token_type": "Bearer",
"expires_in": "3599"
}
인증 코드 부여 방식으로 액세스 토큰 얻어오기
인증코드 부여 방식은 웹 브라우저가 필요합니다.
첫 번째 안전하지 않은 단계에서는 웹 브라우저를 사용하여 액세스 토큰으로 교환할 수 있는 한 번만 사용할 수 있는 인증 코드를 획득합니다. 인증 코드는 웹 브라우저에서 보안 계층(예: 서버 측 코드)으로 전달되며, 이 계층은 인증 서버에 액세스 토큰에 대한 인증 코드를 교환하기 위해 새로운 요청을 할 수 있습니다. 이 보안 교환에서 서버는 해당 ID를 확인하기 위해 클라이언트 암호를 제공해야 합니다.
인증 코드 부여 흐름을 실행하려면 다음 단계를 수행하십시오.
curl "https://localhost:8443/oauth2/authorize?response_type=code&client_id=reader&redirect_uri=https://my.redirect.uri&scope=product:read&state=35725"
그림 11.7: 인증 코드 부여 흐름 시도하기
다음으로 reader 클라이언트가 우리 이름으로 API를 호출하는 데 동의해야 합니다.
동의 제출 버튼을 클릭하면 다음과 같은 응답을 받게 됩니다.
언뜻 보기에는 다소 실망스러울 수 있습니다. 인증 서버가 웹 브라우저로 다시 보낸 URL은 초기 요청에서 클라이언트가 지정한 리디렉션 URI를 기반으로 합니다. URL을 텍스트 편집기에 복사하면 다음과 유사한 내용을 찾을 수 있습니다.
https://my.redirect.uri/?code=Yyr...X0Q&state=35725
코드 요청 매개변수의 리디렉션 URL에서 인증 코드를 찾을 수 있습니다. code 파라미터에서 인증 코드를 추출하고 해당 값으로 환경 변수 CODE를 정의합니다.
CODE=Yyr...X0Q
curl -k https://reader:secret@localhost:8443/oauth2/token \
-d grant_type=authorization_code \
-d client_id=reader \
-d redirect_uri=https://my.redirect.uri \
-d code=$CODE -s | jq .
스크린샷에서 다음 예외를 제외하고 클라이언트 자격 증명 흐름에서 얻은 것과 유사한 정보가 응답에 있음을 알 수 있습니다.
더 안전한 승인 흐름을 사용했기 때문에 리프레시 토큰도 발급되었습니다.
reader 클라이언트에 대한 액세스 토큰을 요청했기 때문에 product:read
범위만 얻었습니다.
https://localhost:8443/oauth2/authorize?response_type=code&client_id=writer&redirect_uri=https://my.redirect.uri&scope=product:read+product :writer&state=72489.
curl -k https://writer:secret@localhost:8443/oauth2/token \
-d grant_type=authorization_code \
-d client_id=writer \
-d redirect_uri=https://my.redirect.uri \
-d code=$CODE -s | jq .
Verify that the response now also contains the product:write scope!
OAuth 2.0
액세스 토큰은 앞에 Bearer
를 붙여 표준 HTTP authorization header로 보내집니다.
Run the following commands to call the protected APIs:
composite product
without a valid access token:ACCESS_TOKEN=an-invalid-token
curl https://localhost:8443/product-composite/1 -k -H "Authorization: Bearer $ACCESS_TOKEN" -i
It should return the following response:
HTTP/1.1 401 Unauthorized
The error message clearly states that the access token is invalid!
$ ACCESS_TOKEN={a-reader-access-token}
$ curl https://localhost:8443/product-composite/1 -k -H "Authorization: Bearer $ACCESS_TOKEN" -i
Now we will get the 200 OK status code and the expected response body will be returned:
HTTP/1.1 200 OK
Figure 11.12: Valid access token results in a 200 OK response
reader
client, the call will fail:$ READER_ACCESS_TOKEN={a-reader-access-token}
$ curl https://localhost:8443/product-composite/999 -k -H "Authorization: Bearer $READER_ACCESS_TOKEN" -X DELETE -i
It will fail with a response similar to the following:
HTTP/1.1 403 Forbidden
오류 응답에서 요청에 액세스 토큰이 부여된 것보다 더 높은 권한이 필요하기 때문에 API를 호출하는 것이 금지되어 있음이 분명합니다.
docker-compose logs -f product-composite
명령을 사용하여 로그 출력을 살펴보면 다음과 같은 인증 정보를 찾을 수 있습니다.
product-composite_1 Authorization info: Subject: reader, scopes: ["openid","product:read"], expires 2022-04-05T03:43:21Z: issuer: http://auth-server:9999, audience: [reader]
이 정보는 JWT로 인코딩된 액세스 토큰에서 추출되었습니다. product-composite
서비스는 이 정보를 얻기 위해 인증 서버와 통신할 필요가 없습니다!
이 섹션에서는 Swagger UI 구성 요소를 사용하여 보호된 API에 액세스하는 방법을 배웁니다. 위의 '제품 복합' 서비스의 변경 사항만 해당 섹션에 설명된 구성을 통해 Swagger UI에 대한 액세스 토큰을 발급하고 Swagger UI에서 API를 호출할 때 이를 사용할 수 있습니다.
사용해 보려면 다음 단계를 수행하십시오.
웹 브라우저에서 https://localhost:8443/openapi/swagger-ui.html URL로 이동하여 Swagger UI 시작 페이지를 엽니다.
이제 시작 페이지에서 서버 드롭다운 목록 옆에 '승인'이라는 텍스트가 있는 새 버튼이 표시됩니다.
'Accept' 버튼을 클릭하여 승인 코드 부여 흐름을 시작합니다.
Swagger UI는 권한 부여 서버에 액세스 권한을 요청하는 범위 목록을 표시합니다. 모두 선택 텍스트가 있는 링크를 클릭한 다음 'Accept' 버튼을 클릭하여 모든 범위를 선택합니다.
그림 11.15: OAuth 범위를 요청하는 Swagger UI
그런 다음 인증 서버로 리디렉션됩니다. 사용하는 웹 브라우저에서 아직 로그인하지 않은 경우 인증 서버는 인증 코드 부여 흐름 섹션을 사용하여 액세스 토큰 획득에서와 같이 자격 증명을 요청합니다.
사용자 이름 'user'와 비밀번호 'passwd'로 로그인합니다.
다음으로 인증 서버가 귀하의 동의를 요청할 것입니다. 두 범위를 모두 선택하고 동의 제출 버튼을 클릭합니다.
Swagger UI는 완료된 권한 부여 흐름에 대한 정보를 표시하여 권한 부여 프로세스를 완료합니다. 시작 페이지로 돌아가려면 '닫기' 버튼을 클릭하세요.
그림 11.16: OAuth 승인 흐름을 요약한 Swagger UI
다음 섹션에서는 이를 외부 OpenID Connect 호환 공급자로 교체합니다.
인증 서버 대신 OIDC 제공업체로 Auth0
를 사용합니다. Auth0
를 사용하기 위해 다음 주제를 진행할 것입니다.
Auth0
에서 reader, writer 클라이언트 계정 설정Auth0
를 OID 제공자로 사용하기 위한 수정Auth0
에 계정 설정Auth0
에 필요한 대부분의 구성은 Auth0
의 관리 API를 사용하는 스크립트에 의해 처리됩니다. 그러나 Auth0
이 관리 API에 액세스하는 데 사용할 수 있는 클라이언트 ID와 클라이언트 암호를 생성하는 지점까지 몇 가지 단계를 수행해야 합니다.
Auth0
서비스는 다중 테넌트이므로 클라이언트, 리소스 소유자 및 리소스 서버 측면에서 자체 OAuth 객체 도메인을 만들 수 있습니다.
다음 단계를 수행하여 Auth0에서 무료 계정에 가입하고 관리 API에 액세스하는 데 사용할 수 있는 클라이언트를 만듭니다.
https://auth0.com
in your browser.Sign up
button:dev-ml.eu.auth0.com
or dev-wemeetplace.us.auth0.com
Auth0
Account and use the instructions in the email to verify your account".Following sign-up, you will be directed to your dashboard with a "Getting Started" page.
In the menu to the left, click on Applications
to get it expanded, then click on APIs
to find the management API, Auth0 Management API
. This API was created for you during the creation of your tenant. We will use this API to create the required definitions in the tenant.
Click on Auth0 Management API
and select the Test
tab.
A big button with the text CREATE & AUTHORIZE TEST APPLICATION
will appear. Click on it to get a client created that can be used to access the management API.
Once created, a page is displayed with the header Asking Auth0 for tokens from my application
. As a final step, we need to give the created client permission to use the management APIs.
Click on the tab Machine to Machine Applications
, next to the Test tab.
Here we will find the test client, Auth0 Management API (Test Application)
, and we can see that it is authorized to use the management API. If we click on the down arrow next to the Authorized
toggle button, a large number of available privileges are revealed.
Click on the All
choice and then on the UPDATE
button. The screen should look similar to the following screenshot:
Figure 11.17: Auth0
management API client permissions
Press on the CONTINUE
button after understanding that you now have a very powerful client with access to all management APIs within your tenant.
Now, we just need to collect the client ID
and client secret
of the created client. The easiest way to do that is to select Applications
in the menu to the left (under the main menu choice Applications) and then select the application named Auth0 Management API (Test Application)
. A screen similar to the following should be displayed:
Figure 11.18: Auth0
management API client application information
Chapter11/auth0/env.bash
and copy the following values from the screen above:TENANT
MGM_CLIENT_ID
MGM_CLIENT_SECRET
env.bash
file by specifying an email address and password, in the variables USER_EMAIL
and USER_PASSWORD
, of a test user that the script will create for us.Specifying a password for a user like this is not considered best practice from a security perspective.
Auth0
supports enrolling users who will be able to set the password themselves, but it is more involved to set up. For more information, see https://auth0.com/docs/connections/database/password-change. Since this is only used for test purposes, specifying a password like this is OK.
We can now run the script that will create the following definitions for us:
product-composite API
, a resource server in OAuth terminology, with the OAuth scopes product:read
and product:write
product:read
, and the writer application the scopes product:read
and product:write
Run the following commands:
cd $BOOK_HOME/Chapter11/auth0
./setup-tenant.bash
Expect the following output (details removed from the output below):
Auth0 - OAuth2 settings:
export TENANT=dev-wemeetplace.us.auth0.com
export WRITER_CLIENT_ID=0C2IJVeswSuspJA6fbwBh5YyCnzgzmLz
export WRITER_CLIENT_SECRET=VuDoeZ_0HMYqACznyqRoig2yqE2jvHWwEFXToK4HP7qnNx8L4VkHlqLqflrZsOlX
export READER_CLIENT_ID=OorSAjMrLPlWWOQV4AWHEiYD1TpeKtZk
export READER_CLIENT_SECRET=dUbLg0ZZLefQPGce_u0PaNO5EjeWc9uyarscfFAYSd--2yTfrC_Tu3TmrnUgewHn
Figure 11.19: Output from setup-tenant.bash
the first time it is executed
Save a copy of the export commands printed at the end of the output; we will use them multiple times later on in this chapter.
Also, look in your mailbox for the email specified for the test user. You will receive a mail with the subject Verify your email. Use the instructions in the email to verify the test user's email address
.
Note that the script is idempotent, meaning it can be run multiple times without corrupting the configuration. If running the script again, it should respond with:
Figure 11.20: Output from setup-tenant.bash
the next time it is executed
It can be very handy to be able to run the script again, for example, to get access to the reader's and writer's client ID and client secret.
If you need to remove the objects created by
setup-tenant.bash
you can run the scriptreset-tenant.bash
.
With an Auth0
account created and configured, we can move on and apply the necessary configuration changes in the system landscape.
인증서버를 Auth0
로 바꾸기 위한 필요한 설정 변경을 다룹니다. OAuth 리소스 서버 역할인 product-composite
과 gateway
서비스의 설정을 바꾸면 됩니다. 테스트 스크립트는 로컬 인증 서버 대신 Auth0
에서 액세스 토큰을 가져오도록 수정하면 됩니다.
Git으로 제공된 소스는 이 사항이 반영되지 않았으므로 직접 수정해야 합니다.
OAuth 리소스 서버 설정
OpenID Connect 제공자를 사용하려면 OAuth 리소스 서버에서 표준 디스커버리 엔드포인트에 기본 URI를 설정만 하면 됩니다.
product-composite
와 gateway
프로젝트의 application.yml
에서 OIDC 디스커버리 엔드포인트를 로컬 인증서버 대신 Auth0로 변경합니다.
Locate the property spring.security.oauth2.resourceserver.jwt.issuer-uri
.
Replace its value with https://${TENANT}/, where ${TENANT}
should be replaced with your tenant domain name; in my case, it is dev-wemeetplace.us.auth0.com
. Do not forget the trailing /
!
In my case, the configuration of the OIDC discovery endpoint will look like this:
spring.security.oauth2.resourceserver.jwt.issuer-uri: https://dev-wemeetplace.us.auth0.com/
If you are curious, you can see what's in the discovery document by running the following command:
TENANT=dev-wemeetplace.us.auth0.com curl https://${TENANT}/.well-known/openid-configuration -s | jq
Rebuild the
product-composite
andgateway
services as follows:./gradlew build && docker-compose up -d --build product-composite gateway
With the
product-composite
andgateway
services updated, we can move on and also update the test script.
Auth0에서 액세스 토큰을 가져오도록 test-em-all.bash 수정
We also need to update the test script so it acquires access tokens from the Auth0
OIDC provider. This is done by performing the following changes in test-em-all.bash
:
ACCESS_TOKEN=$(curl -k https://writer:secret@$HOST:$PORT/oauth2/token -d grant_type=client_credentials -s | jq .access_token -r)
Replace it with these commands:
export TENANT=dev-wemeetplace.us.auth0.com
export WRITER_CLIENT_ID=0C2IJVeswSuspJA6fbwBh5YyCnzgzmLz
export WRITER_CLIENT_SECRET=VuDoeZ_0HMYqACznyqRoig2yqE2jvHWwEFXToK4HP7qnNx8L4VkHlqLqflrZsOlX
ACCESS_TOKEN=$(curl -X POST https://$TENANT/oauth/token \
-d grant_type=client_credentials \
-d audience=https://localhost:8443/product-composite \
-d scope=product:read+product:write \
-d client_id=$WRITER_CLIENT_ID \
-d client_secret=$WRITER_CLIENT_SECRET -s | jq -r .access_token)
Note from the preceding command that Auth0 requires us to specify the intended audience of the requested access token, as an extra layer of security. The audience is the API we plan to call using the access token. Given that an API implementation verifies the audience field, this would prevent the situation where someone tries to use an access token issued for another purpose to get access to an API.
TENANT
, WRITER_CLIENT_ID
, and WRITER_CLIENT_SECRET
in the preceding commands with the values returned by the setup-tenant.bash
script.As mentioned above, you can run the script again to acquire these values without risking any negative side effects!
READER_ACCESS_TOKEN=$(curl -k https://reader:secret@$HOST:$PORT/oauth2/token -d grant_type=client_credentials -s | jq .access_token -r)
Replace it with this command:
export READER_CLIENT_ID=OorSAjMrLPlWWOQV4AWHEiYD1TpeKtZk
export READER_CLIENT_SECRET=dUbLg0ZZLefQPGce_u0PaNO5EjeWc9uyarscfFAYSd--2yTfrC_Tu3TmrnUgewHn
READER_ACCESS_TOKEN=$(curl -X POST https://$TENANT/oauth/token \
-d grant_type=client_credentials \
-d audience=https://localhost:8443/product-composite \
-d scope=product:read \
-d client_id=$READER_CLIENT_ID \
-d client_secret=$READER_CLIENT_SECRET -s | jq -r .access_token)
Note that we only request the product:read scope and not the product:write scope here.
READER_CLIENT_ID
and READER_CLIENT_SECRET
in the preceding commands with the values returned by the setup-tenant.bash
script.Now the access tokens are issued by Auth0
instead of our local authorization server, and our API implementations can verify the access tokens using information from Auth0's discovery service configured in the application.yml files. The API implementations can, as before, use the scopes in the access tokens to authorize the client to perform the call to the API, or not.
With this, we have all the required changes in place. Let's run some tests to verify that we can acquire access tokens from Auth0.
Now, we are ready to give Auth0 a try!
Run the usual tests, but this time using Auth0 as the OpenID Connect provider, with the following command:
./test-em-all.bash
In the logs, you will be able to find authorization information from the access tokens issued by Auth0. Run the command:
docker-compose logs product-composite | grep "Authorization info"
Expect the following outputs from the command:
Figure 11.21: Authorization information for the writer client from Auth0 in the log output
Figure 11.22: Authorization information for the reader client from Auth0 in the log output
As we can see from the log output, we now also get information regarding the intended audience for this access token. To strengthen security, we could add a test to our service that verifies that its URL, https://localhost:8443/product-composite in this case, is part of the audience list. This would, as mentioned earlier, prevent the situation where someone tries to use an access token issued for another purpose than to get access to our API.
With the automated tests working together with Auth0, we can move on and learn how to acquire access tokens using the different types of grant flow. Let's start with the client credentials grant flow.
If you want to acquire an access token from Auth0 yourself, you can do so by running the following command, using the client credentials grant flow:
export TENANT=...
export WRITER_CLIENT_ID=...
export WRITER_CLIENT_SECRET=...
curl -X POST https://$TENANT/oauth/token \
-d grant_type=client_credentials \
-d audience=https://localhost:8443/product-composite \
-d scope=product:read+product:write \
-d client_id=$WRITER_CLIENT_ID \
-d client_secret=$WRITER_CLIENT_SECRET
Set the values for the environment variables TENANT
, WRITER_CLIENT_ID
, and WRITER_CLIENT_SECRET
in the preceding commands with the values returned by the setup-tenant.bash
script.
Following the instructions in the Calling protected APIs using access tokens section, you should be able to call the APIs using the acquired access token.
In this section, we will learn how to acquire an access token from Auth0 using the authorization code grant flow. As already described above, we first need to acquire an authorization code using a web browser. Next, we can use server-side code to exchange the authorization code for an access token.
Perform the following steps to execute the authorization code grant flow with Auth0:
https://${TENANT}/authorize?audience=https://localhost:8443/product-composite&scope=openid email product:read product:write&response_type=code&client_id=${WRITER_CLIENT_ID}&redirect_uri=https://my.redirect.uri&state=845361.
Replace ${TENANT} and ${WRITER_CLIENT_ID}
in the preceding URL with the tenant domain name and writer client ID returned by the setup-tenant.bash script.
Auth0 should present the following login screen:
Figure 11.23: Authorization code grant flow with Auth0, login screen
Figure 11.24: Authorization code grant flow with Auth0, consent screen
The authorization code is now in the URL in the browser, just like when we tried out the authorization code grant flow with our local authorization server:
Figure 11.25: Authorization code grant flow with Auth0, access token
CODE=...
export TENANT=...
export WRITER_CLIENT_ID=...
export WRITER_CLIENT_SECRET=...
curl -X POST https://$TENANT/oauth/token \
-d grant_type=authorization_code \
-d client_id=$WRITER_CLIENT_ID \
-d client_secret=$WRITER_CLIENT_SECRET \
-d code=$CODE \
-d redirect_uri=https://my.redirect.uri -s | jq .
Set the values for the environment variables TENANT
, WRITER_CLIENT_ID
, and WRITER_CLIENT_SECRET
in the preceding commands to the values returned by the setup-tenant.bash script.
Now that we have learned how to acquire access tokens using both grant flows, we are ready to try calling the external API using an access token acquired from Auth0 in the next section.
We can use access tokens issued by Auth0 to call our APIs, just like when we used access tokens issued by our local authorization server.
For a read-only API, execute the following command:
ACCESS_TOKEN=...
curl https://localhost:8443/product-composite/1 -k -H "Authorization: Bearer $ACCESS_TOKEN" -i
For an updating API, execute the following command:
ACCESS_TOKEN=...
curl https://localhost:8443/product-composite/999 -k -H "Authorization: Bearer $ACCESS_TOKEN" -X DELETE -i
Since we have requested both scopes, product:read and product:write, both the preceding API calls are expected to return 200 OK.
From the log output in Figures 11.21 and 11.22 in the section Running the test script with Auth0 as the OpenID Connect provider, we could not see any information about the user that initiated the API request. If you want your API implementation to know a bit more about the user, it can call Auth0's userinfo_endpoint. The URL of the user-info endpoint can be found in the response of a request to the OIDC discovery endpoint as described in the section Changing the configuration in the OAuth resource servers. To get user info related to an access token, make the following request:
Export TENANT=...
curl -H "Authorization: Bearer $ACCESS_TOKEN" https://$TENANT/userinfo -s | jq
Set the values for the TENANT environment variable in the preceding commands to the values returned by the setup-tenant.bash script.
Note that this command only applies to access tokens issued using the authorization code grant flow. Access tokens issued using the client credentials grant flow don't contain any user information and will result in an error response if tried.
A sample response is as follows:
Figure 11.26: Requesting extra user information from Auth0
This endpoint can also be used to verify that the user hasn't revoked the access token in Auth0.
Wrap up the tests by shutting down the system landscape with the following command:
docker-compose down
This concludes the section where we have learned how to replace the local OAuth 2.0 authorization server with an external alternative. We have also seen how to reconfigure the microservice landscape to validate access tokens using an external OIDC provider.
이 장에서는 Spring Security를 사용하여 API를 보호하는 방법을 배웠습니다.
Spring Security를 사용하여 HTTPS를 활성화하는 것이 얼마나 쉬운지 보았습니다. Spring Security를 사용하면 HTTP 기본 인증을 사용하여 검색 서버인 Netflix Eureka에 대한 액세스를 제한하는 것이 간단하다는 것도 배웠습니다. 마지막으로 Spring Security를 사용하여 OAuth 2.0 및 OpenID Connect의 사용을 단순화하여 타사 클라이언트 애플리케이션이 사용자 이름으로 API에 액세스하도록 허용하지만 사용자가 클라이언트와 자격 증명을 공유하도록 요구하지 않는 방법을 보았습니다. 응용 프로그램. Spring Security를 기반으로 로컬 OAuth 2.0 인증 서버를 설정하는 방법과 외부 OpenID Connect 공급자인 Auth0
을 대신 사용할 수 있도록 구성을 변경하는 방법을 모두 배웠습니다.
그러나 한 가지 문제는 필요한 구성을 관리하는 방법입니다. 각 마이크로서비스 인스턴스에는 자체 구성이 제공되어야 하므로 현재 구성에 대한 좋은 개요를 얻기가 어렵습니다. 여러 마이크로서비스와 관련된 구성 업데이트도 어려울 것입니다. 흩어진 구성에 추가된 사실은 지금까지 본 구성 중 일부에 자격 증명이나 인증서와 같은 민감한 정보가 포함되어 있다는 사실입니다. 여러 협력 마이크로서비스에 대한 구성을 처리하는 더 나은 방법과 구성의 민감한 부분을 처리하는 방법에 대한 솔루션이 필요한 것 같습니다.
다음 장에서는 Spring Cloud Config Server
를 탐색하고 이러한 유형의 문제를 처리하는 데 사용할 수 있는 방법을 살펴보겠습니다..
What are the benefits and shortcomings of using self-signed certificates?
What is the purpose of OAuth 2.0 authorization codes?
What is the purpose of OAuth 2.0 scopes?
What does it mean when a token is a JWT?
How can we trust the information that is stored in a JWT?
Is it suitable to use the OAuth 2.0 authorization code grant flow with a native mobile app?
What does OpenID Connect add to OAuth 2.0?