Spring Secuirty 32 Resource Server Entrypoint
포스트
취소

Spring Secuirty 32 Resource Server Entrypoint

우리는 지난시간에 KeyClock 와 ResourceServer 을 연동을 해보았다 앞에서 OAuth2 로그인시 권한이 없는 유저를 시큐리티가 어떻게 Redirect 했는지 보았는데 Resource - Server 에서도 똑같이 한번 보겠습니다

OAuth2ResourceServerConfigurer

1
2
3
4
5
6
7
8
9
10
@Override
public void init(H http) {

	...
	
	registerDefaultEntryPoint(http);

	...
}

기동을 하게 되면 init 이 호출이 되면서 registerDefaultEntryPoint 를 호출하게 됩니다

1
2
3
4
5
6
private void registerDefaultEntryPoint(H http) {
	...

	exceptionHandling.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, preferredMatcher);	
}

다 생략을 하고 제일 마지막줄에 보면 기본적인 엔트리포인트 전략을 집어넣게 됩니다 this.authenticationEntryPoint 가 BearerTokenAuthenticationEnttyPoint 이것을 호출하게 하고 권한이 없는 요청은 BearerTokenAuthenticationEnttyPoint 이곳에서 처리할 예정입니다

1
2
3
4
5
6
7
8
9
@Override
public void configure(H http) {
	
	...
	
	filter.setAuthenticationEntryPoint(this.authenticationEntryPoint);
	filter = postProcess(filter);
	http.addFilter(filter);
}

configure 은 앞의 init 으로 넘어오는 BearerTokenAuthenticationEnttyPoint filter 에 등록하는 역할을 하게 됩니다 이렇게 되면 모든 요청 건들은 BearerTokenAuthenticationEnttyPoint 에서 권한여부를 체크하게 됩니다

첫번째 상황은 토큰 없이 그냥 주소창에 localhost:8082 를 넣었을때 입니다

BearerTokenAuthenticationEntryPoint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
		AuthenticationException authException) {
	
	HttpStatus status = HttpStatus.UNAUTHORIZED;
	Map<String, String> parameters = new LinkedHashMap<>();

	...
	
	if (authException instanceof OAuth2AuthenticationException) {
		
		...
	}

	String wwwAuthenticate = computeWWWAuthenticateHeaderValue(parameters);
	response.addHeader(HttpHeaders.WWW_AUTHENTICATE, wwwAuthenticate);
	response.setStatus(status.value());
}


이쪽으로 넘어와서 권한이 없는 유저를 되돌리게 되는데 HttpStatus status = HttpStatus.UNAUTHORIZED; 으로 요청을 만들어놓은뒤 마지막에 response.setStatus(status.value()); 처리를 해서 우리는 헤더에 401을 달아버리고 그냥 끝이나게 됩니다 (리다이렉트 없음)

두번째 상황은 post - man 으로 요청을 줄때 올바르지 않은 토큰을 줄떄입니다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
		AuthenticationException authException) {
	HttpStatus status = HttpStatus.UNAUTHORIZED;
	Map<String, String> parameters = new LinkedHashMap<>();
	if (this.realmName != null) {
		parameters.put("realm", this.realmName);
	}
	if (authException instanceof OAuth2AuthenticationException) {
		OAuth2Error error = ((OAuth2AuthenticationException) authException).getError();
		parameters.put("error", error.getErrorCode());
		if (StringUtils.hasText(error.getDescription())) {
			parameters.put("error_description", error.getDescription());
		}
		if (StringUtils.hasText(error.getUri())) {
			parameters.put("error_uri", error.getUri());
		}
		if (error instanceof BearerTokenError) {
			BearerTokenError bearerTokenError = (BearerTokenError) error;
			if (StringUtils.hasText(bearerTokenError.getScope())) {
				parameters.put("scope", bearerTokenError.getScope());
			}
			status = ((BearerTokenError) error).getHttpStatus();
		}
	}
	String wwwAuthenticate = computeWWWAuthenticateHeaderValue(parameters);
	response.addHeader(HttpHeaders.WWW_AUTHENTICATE, wwwAuthenticate);
	response.setStatus(status.value());
	}

아까오는 달리 if (authException instanceof OAuth2AuthenticationException) 이 부분이 rue 로 들어오게 된다 왜냐하면 앞에서는 토큰없이 들어왔기 때문에 authException false 로 뜨는 반면 지금은 토큰은 있고 토큰을 검증하는 와중에 에러가 발생한 것이기 떄문에 이 if 문 안으로 들어오게 됩니다

An error occurred while attempting to decode the Jwt: Invalid JWT serialization: Missing dot delimiter(s) 이런 에러가 메세지메 맺히게 되고 뜻은 jwt 의 점 형식이 맞지 않습니다 뒤에 설명할것이지만 넘어오는 토큰은 jwt 형태로 넘어오게 되고 .을 기준으로 나뉘게 되는데 그런 형식 없이 넘어와서 에러를 발생한 상태입니다

status = ((BearerTokenError) error).getHttpStatus(); 마지막에서 호출되는 status 또는 401 에러로 발생이 되어서 끝나게 됩니다

이로서 알 수 있는 사실은 인증이 없거나 또는 유효하지 않은 토큰을 보내게 되면 BearerTokenAuthenticationEntryPoint 에서 처리를 하는 모습을 볼 수 있습니다 2가지 경우를 보았는데 동일한 401 에러가 발생하는 것을 보았습니다 우리는 앞으로 이곳에서 에러를 한번더 볼 예정입니다 403 에러가 발생될 예정인데 403 에 대해서는 뒤에 scope 할때 다뤄보겠습니다 오늘은 인증이 없는 유저에 대해서 시큐리티가 어떻게 응답을 주는지에 대해서 알아보았습니다