-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: naver 추가 * feat: Account memberId nullable * feat: LocalSecurityConfig 분리 * feat: access token, id token 로그인 * prune: 기존 id token 로그인 제거 * feat: 회원가입 수정 account memberid nullable 반영, jwt 제거 * docs: 토큰 로그인 * prune: usernameservice remove
- Loading branch information
1 parent
07940ce
commit f16be69
Showing
21 changed files
with
367 additions
and
351 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
...in/java/org/cmc/curtaincall/web/security/config/OAuth2TokenLoginAuthenticationFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package org.cmc.curtaincall.web.security.config; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import org.cmc.curtaincall.web.security.request.TokenLoginRequest; | ||
import org.springframework.security.authentication.AuthenticationManager; | ||
import org.springframework.security.authentication.AuthenticationManagerResolver; | ||
import org.springframework.security.authentication.AuthenticationServiceException; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.AuthenticationException; | ||
import org.springframework.security.core.authority.AuthorityUtils; | ||
import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | ||
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; | ||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; | ||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; | ||
import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | ||
import org.springframework.security.oauth2.core.OAuth2Error; | ||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||
import org.springframework.security.oauth2.core.user.OAuth2User; | ||
import org.springframework.security.oauth2.jwt.JwtClaimNames; | ||
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationToken; | ||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; | ||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; | ||
|
||
import java.io.IOException; | ||
import java.util.Map; | ||
|
||
public class OAuth2TokenLoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter { | ||
|
||
public static final String FILTER_PROCESSES_URI = "/login/oauth2/token/*"; | ||
|
||
private final AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver; | ||
|
||
private final ClientRegistrationRepository clientRegistrationRepository; | ||
|
||
private final Map<String, String> issuerToProvider; | ||
|
||
private final ObjectMapper objectMapper; | ||
|
||
private final OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService = new DefaultOAuth2UserService(); | ||
|
||
public OAuth2TokenLoginAuthenticationFilter( | ||
final AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver, | ||
final ClientRegistrationRepository clientRegistrationRepository, | ||
final Map<String, String> issuerToProvider, | ||
final ObjectMapper objectMapper | ||
) { | ||
super(FILTER_PROCESSES_URI); | ||
setAuthenticationManager(authentication -> { | ||
throw new AuthenticationServiceException("Cannot authenticate " + authentication); | ||
}); | ||
this.authenticationManagerResolver = authenticationManagerResolver; | ||
this.clientRegistrationRepository = clientRegistrationRepository; | ||
this.issuerToProvider = issuerToProvider; | ||
this.objectMapper = objectMapper; | ||
} | ||
|
||
@Override | ||
public Authentication attemptAuthentication( | ||
final HttpServletRequest request, final HttpServletResponse response | ||
) throws AuthenticationException, IOException, ServletException { | ||
final String provider = request.getServletPath().split("/")[4]; | ||
final TokenLoginRequest loginRequest = objectMapper.readValue(request.getReader(), TokenLoginRequest.class); | ||
if ("naver".equals(provider)) { | ||
final ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId(provider); | ||
final OAuth2User oAuth2User = oauth2UserService.loadUser(new OAuth2UserRequest(clientRegistration, new OAuth2AccessToken( | ||
OAuth2AccessToken.TokenType.BEARER, loginRequest.token(), null, null | ||
))); | ||
return UsernamePasswordAuthenticationToken.authenticated( | ||
provider + "-" + oAuth2User.getName(), null, AuthorityUtils.NO_AUTHORITIES | ||
); | ||
} else { | ||
final BearerTokenAuthenticationToken authenticationToken = new BearerTokenAuthenticationToken( | ||
loginRequest.token()); | ||
final AuthenticationManager authenticationManager = authenticationManagerResolver.resolve(request); | ||
final JwtAuthenticationToken authentication = (JwtAuthenticationToken) authenticationManager | ||
.authenticate(authenticationToken); | ||
final String issuer = (String) authentication.getTokenAttributes().get(JwtClaimNames.ISS); | ||
if (!provider.equals(issuerToProvider.get(issuer))) { | ||
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST)); | ||
} | ||
|
||
return UsernamePasswordAuthenticationToken.authenticated( | ||
provider + "-" + authentication.getName(), null, AuthorityUtils.NO_AUTHORITIES | ||
); | ||
} | ||
|
||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
...org/cmc/curtaincall/web/security/config/OAuth2TokenLoginAuthenticationSuccessHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package org.cmc.curtaincall.web.security.config; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.cmc.curtaincall.domain.account.Account; | ||
import org.cmc.curtaincall.domain.account.repository.AccountRepository; | ||
import org.cmc.curtaincall.domain.member.MemberId; | ||
import org.cmc.curtaincall.web.security.response.LoginResponse; | ||
import org.cmc.curtaincall.web.security.service.CurtainCallJwtEncoderService; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.oauth2.jwt.Jwt; | ||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | ||
|
||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.time.LocalDateTime; | ||
import java.time.ZoneId; | ||
import java.util.Optional; | ||
|
||
@RequiredArgsConstructor | ||
public class OAuth2TokenLoginAuthenticationSuccessHandler implements AuthenticationSuccessHandler { | ||
|
||
private final ObjectMapper objectMapper; | ||
|
||
private final CurtainCallJwtEncoderService jwtEncoderService; | ||
|
||
private final AccountRepository accountRepository; | ||
|
||
@Override | ||
public void onAuthenticationSuccess( | ||
final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication | ||
) throws IOException, ServletException { | ||
response.setStatus(HttpServletResponse.SC_OK); | ||
response.setContentType(MediaType.APPLICATION_JSON_VALUE); | ||
response.setCharacterEncoding(StandardCharsets.UTF_8.name()); | ||
|
||
final String username = authentication.getName(); | ||
final Account account = accountRepository.findByUsername(username) | ||
.orElseGet(() -> accountRepository.save(new Account(username))); | ||
final Jwt jwt = jwtEncoderService.encode(username); | ||
final LoginResponse loginResponse = new LoginResponse( | ||
Optional.ofNullable(account.getMemberId()).map(MemberId::getId).orElse(null), | ||
jwt.getTokenValue(), | ||
LocalDateTime.ofInstant(jwt.getExpiresAt(), ZoneId.systemDefault()) | ||
); | ||
objectMapper.writeValue(response.getWriter(), loginResponse); | ||
} | ||
} |
Oops, something went wrong.