작성자 없음
작성자 정보가 삭제된 글입니다.
23.11.02 15:01 작성
·
622
0
authenticastion Entry Point로 지정 시 cors문제가 계속해서 진행되어 Authorization Code를 받아올 수 없습니다.
코드 첨부
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http
.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults()
);
http
.exceptionHandling((exceptions) -> exceptions
.authenticationEntryPoint(
new LoginUrlAuthenticationEntryPoint("http://localhost:3000")
// new LoginUrlAuthenticationEntryPoint("/login")
))
http.oauth2ResourceServer((resourceServer) -> resourceServer
.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean
public RegisteredClientRepository registeredClientRepository() {
RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("oidc-client")
.clientSecret("{noop}secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.redirectUri("https://oidcdebugger.com/debug")
.redirectUri("https://test-b821b.web.app")
.postLogoutRedirectUri("http://127.0.0.1:8080/")
.scope(OidcScopes.OPENID)
.scope(OidcScopes.PROFILE)
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
return new InMemoryRegisteredClientRepository(oidcClient);
}
@Bean
public AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().issuer("http://localhost:6080").build();
}
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.exposedHeaders("*");
}
};
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
configuration.addAllowedOrigin("http://localhost:3000");
configuration.setExposedHeaders(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors(customCorsConfig ->
customCorsConfig.configurationSource(corsConfigurationSource()))
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorizeHttpRequestsCustomizer ->
authorizeHttpRequestsCustomizer.requestMatchers(AUTH_WHITELIST).permitAll()
.anyRequest().authenticated()
)
.formLogin(
httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.loginPage("http://localhost:3000").loginProcessingUrl("/login")
// Customizer.withDefaults()
)
;
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
UserDetails userDetails = User.builder()
.username("user")
.password(passwordEncoder.encode("password"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(userDetails);
}
@Bean
public JWKSource<SecurityContext> jwkSource() {
KeyPair keyPair = generateRsaKey();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAKey rsaKey = new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
JWKSet jwkSet = new JWKSet(rsaKey);
return new ImmutableJWKSet<>(jwkSet);
}
private static KeyPair generateRsaKey() {
KeyPair keyPair;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
keyPair = keyPairGenerator.generateKeyPair();
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
return keyPair;
}
@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
위 코드로 진행했을 시 발생하는 Cors Error입니다
Access to XMLHttpRequest at 'http://localhost:6080/oauth2/authorize?client_id=oidc-client&redirect_uri=https%3A%2F%2Foidcdebugger.com%2Fdebug&scope=openid&response_type=code&response_mode=form_post&state=3it6dl9kewr&nonce=hyq3pnronj7&continue' (redirected from 'http://localhost:6080/login') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
3. 이로 인해 CorsFilter를 적용하게 되면 해당 Cors는 해결되지만 authorization code 가 Redirect되는 시점에 Cors 에러가 새롭게 나옵니다.
@Component
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
private static final Set<String> allowedOrigins = new HashSet<String>();
static {
allowedOrigins.add(
"http://localhost:3000"
);
}
@Override
public void init(FilterConfig fc) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
String origin = request.getHeader(HttpHeaders.ORIGIN);
log.info("Origin: {}", origin);
if (origin != null) {
Optional<String> first = allowedOrigins.stream().filter(origin::startsWith).findFirst();
first.ifPresent(s -> response.setHeader("Access-Control-Allow-Origin", s));
}
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Key, Authorization");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
@Override
public void destroy() {
}
Access to XMLHttpRequest at 'https://oidcdebugger.com/debug?code=1o_jSQQVu6EB4XDq-xCWP3qrzp2VDdGbH_AN7iBJGU5gQRC7BRFkQYdn2A6P-6G5Aoi8XLJLaVR4MSVktNzDvYLMmj_UXahcWfEwQdA-tk4GCw5Bff4mXn2q6mIYfs_d&state=3it6dl9kewr' (redirected from 'http://localhost:6080/login') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
혹시 외부 로그인 페이지와 연동한 예시가 있거나, Cors 문제를 해결할 방안이 있는지 궁금합니다ㅠㅠ
답변 2
0
2023. 11. 13. 03:39
네
시큐리티에서 CORS 를 위한 필터를 제공하고 있습니다.
다음과 같이 사용하면 됩니다.
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
--
http.cors();
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(List.of("http://localhost:3000"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
config.setAllowedHeaders(List.of("*"));
config.setExposedHeaders(List.of("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
0
안녕하세요 finance 님, 인프런 AI 인턴이에요.
CORS(Cross-Origin Resource Sharing) 오류는 보안 상의 이유로 인해 발생하는 오류로, 서로 다른 출처의 리소스를 주고받는 경우 발생할 수 있습니다.
문제 해결을 위해선 서버 사이드에서 CORS 설정을 해주어야 합니다. 현재 코드에는 @Bean
으로 등록된 CorsConfigurationSource
와 CorsFilter
가 있는 것으로 보이는데, 아래와 같이 수정하여 CORS 설정을 추가해보세요.
@Override
protected void configure(HttpSecurity http) throws Exception {
http
...
.cors(cors -> {
cors.configurationSource(corsConfigurationSource());
})
...
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
또한, React 애플리케이션의 경우, 프록시 설정을 통해 CORS 문제를 우회하는 방법도 있습니다. React의 개발 서버에서 프록시 설정을 추가하여 요청을 중계하는 방식으로 CORS 오류를 해결할 수 있습니다. 예를 들어, package.json
파일에 아래와 같이 프록시 설정을 추가해보세요.
{
...
"proxy": "http://localhost:6080"
}
위 방법으로 CORS 오류가 해결되지 않거나 추가적인 도움이 필요하신 경우, 해당 문제에 대해 더 상세한 정보와 로그를 제공해주시면 더 도움을 드릴 수 있을 것입니다. 감사합니다.