Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package gg.agit.konect.global.auth.filter;

import java.io.IOException;
import java.net.URI;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

@Component
public class OAuth2RedirectUriSaveFilter extends OncePerRequestFilter {

public static final String REDIRECT_URI_SESSION_KEY = "redirect_uri";

@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain
) throws ServletException, IOException {

if (request.getRequestURI().startsWith("/oauth2/authorization/")) {
String redirectUri = request.getParameter("redirect_uri");

if (isValidOriginOnlyRedirect(redirectUri)) {
HttpSession session = request.getSession(true);
session.setAttribute(REDIRECT_URI_SESSION_KEY, redirectUri);
}
}

filterChain.doFilter(request, response);
}

private boolean isValidOriginOnlyRedirect(String redirectUri) {
if (redirectUri == null || redirectUri.isBlank()) {
return false;
}

try {
URI uri = URI.create(redirectUri);

if (uri.getScheme() == null || uri.getHost() == null) {
return false;
}

if ((uri.getPath() != null && !uri.getPath().isEmpty())
|| uri.getQuery() != null
|| uri.getFragment() != null) {
return false;
}

return true;
} catch (Exception e) {
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package gg.agit.konect.global.auth.handler;

import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
Expand All @@ -11,11 +13,12 @@
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import gg.agit.konect.global.code.ApiResponseCode;
import gg.agit.konect.global.exception.CustomException;
import gg.agit.konect.domain.user.enums.Provider;
import gg.agit.konect.domain.user.model.User;
import gg.agit.konect.domain.user.repository.UserRepository;
import gg.agit.konect.global.code.ApiResponseCode;
import gg.agit.konect.global.config.SecurityProperties;
import gg.agit.konect.global.exception.CustomException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
Expand All @@ -31,6 +34,7 @@ public class OAuth2LoginSuccessHandler implements AuthenticationSuccessHandler {
private static final int TEMP_SESSION_EXPIRATION_SECONDS = 600;

private final UserRepository userRepository;
private final SecurityProperties securityProperties;

@Override
public void onAuthenticationSuccess(
Expand Down Expand Up @@ -76,7 +80,10 @@ private void sendLoginSuccessResponse(
HttpSession session = request.getSession(true);
session.setAttribute("userId", user.getId());

response.sendRedirect(frontendBaseUrl + "/home");
String redirectUri = (String) session.getAttribute("redirect_uri");
session.removeAttribute("redirect_uri");

response.sendRedirect(resolveSafeRedirect(redirectUri));
}

private String extractEmail(OAuth2User oauthUser, Provider provider) {
Expand All @@ -92,4 +99,32 @@ private String extractEmail(OAuth2User oauthUser, Provider provider) {

return (String)current;
}

private String resolveSafeRedirect(String redirectUri) {
if (redirectUri == null || redirectUri.isBlank()) {
return frontendBaseUrl + "/home";
}

Set<String> allowedOrigins = securityProperties.getAllowedRedirectOrigins();

try {
URI uri = URI.create(redirectUri);

if (uri.getScheme() == null || uri.getHost() == null) {
return frontendBaseUrl + "/home";
}

String origin = uri.getScheme() + "://" + uri.getHost() + portPart(uri);

if (allowedOrigins.contains(origin)) {
return redirectUri;
}
} catch (Exception ignored) {}

return frontendBaseUrl + "/home";
}

private String portPart(URI uri) {
return (uri.getPort() == -1) ? "" : ":" + uri.getPort();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
import org.springframework.security.web.SecurityFilterChain;

import gg.agit.konect.global.auth.filter.OAuth2RedirectUriSaveFilter;
import gg.agit.konect.global.auth.handler.OAuth2LoginSuccessHandler;
import gg.agit.konect.global.auth.oauth.SocialOAuthService;
import lombok.RequiredArgsConstructor;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

@Value("${app.frontend.base-url}")
Expand All @@ -30,6 +34,9 @@ public class SecurityConfig {
@Autowired
private OAuth2LoginSuccessHandler oAuth2LoginSuccessHandler;

@Autowired
private OAuth2RedirectUriSaveFilter redirectUriSaveFilter;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
Expand Down Expand Up @@ -59,6 +66,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
})
);

http.addFilterBefore(redirectUriSaveFilter, OAuth2AuthorizationRequestRedirectFilter.class);

return http.build();
}
}
18 changes: 18 additions & 0 deletions src/main/java/gg/agit/konect/global/config/SecurityProperties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package gg.agit.konect.global.config;

import java.util.Set;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "app")
public class SecurityProperties {

private Set<String> allowedRedirectOrigins;
}
2 changes: 1 addition & 1 deletion src/main/resources/config
Loading