Moja aplikacja to angularowy frontend oraz springowy backend. Do tej pory security było zaimplementowane za pomocą JWT, chciałem jednak by użytkownicy mieli opcję zalogowania swoim kontem z Facebooka, udało mi się całośc skonfigurować i cały flow wygląda teraz w ten sposób:
-Użytkownik na frontendzie klika "Kontynuj przez Facebooka", co po stronie frontendu robi w sumie tyle
public loginWithFacebook() {
window.location.href = 'http://localhost:8080/oauth2/authorize/facebook?redirect_uri=http://localhost:4200/facebook';
}
Następuje przekierowanie na endpoint mojego backendu, który za pomocą magii spring-security-oauth2-client, przekierowuje mnie na Facebooka by potwierdzić logowanie.
Po potwierdzeniu, odpalony zostaje AuthenticationSuccessHandler, którego implementacja wygląda tak
@Component
@RequiredArgsConstructor
public class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private final TokenProvider tokenProvider;
private final CookieRequestRepository cookieRequestRepository;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
String targetUrl = determineTargetUrl(request, response, authentication);
clearAuthenticationAttributes(request, response);
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
Optional<String> redirectUri = getCookie(request, REDIRECT_URI_PARAM_COOKIE_NAME).map(Cookie::getValue);
String targetUrl = redirectUri.orElse(getDefaultTargetUrl());
String token = tokenProvider.createToken(authentication);
return UriComponentsBuilder.fromUriString(targetUrl + "/" + token)
.build().toUriString();
}
protected void clearAuthenticationAttributes(HttpServletRequest request, HttpServletResponse response) {
super.clearAuthenticationAttributes(request);
cookieRequestRepository.removeAuthorizationRequestCookies(request, response);
}
}
Tutaj po prostu generuje token JWT, taki jakiego używałem do tej pory do zarządzania security oraz przekierowywuje użytkownika do redirect_uri który to podałem w requeście (dopieo teraz się zastanawiam czemu po prostu tego również nie zapiszę w application.properties ale to nie jest problem obecnie).
Następnie wygenerowany token przekazuje w tym redirect_uri do frontendu, tam go odczytuje, zapisuje w localStorage, wszystko do tej pory gra.
Problem pojawia się gdy tego tokenu chcę użyć - mogę go żywcem wyjąć z pamięci przeglądarki, wkleić do postmana i wszystkie endpointy mojego backendu odpowiadają poprawnie.
Jeżeli jednak korzystająć z tego samego tokenu, z poziomu frontendu spróbuje uderzyć do endpointu który wymaga autoryzacji, dostaję
Próbuje zrozumieć co się tutaj dzieje i jak to naprawić... Skoro jestem już zalogowany, strzelam pod zabezpieczony endpoint z poprawnym tokenem, to czemu i tak leci jakiś dziwny redirect do Facebooka?
Poniżej wklejam jeszcze konfigurację security po stronie Springa
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http
.cors()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable()
.formLogin() .disable()
.httpBasic().disable()
.authorizeRequests()
.antMatchers("/auth/**",
"/oauth2/**",
"/policy",
"/user/**",
"/tags",
"/quiz",
"/quiz/list",
"/quiz/search"
).permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.authorizationEndpoint().baseUri("/oauth2/authorize")
.authorizationRequestRepository(cookieRequestRepository)
.and()
.redirectionEndpoint().baseUri("/oauth2/callback/*")
.and()
.userInfoEndpoint().userService(oAuth2UserService)
.and()
.successHandler(successHandler)
.failureHandler(failureHandler);
}
- screenshot-20191228230332.png (71 KB) - ściągnięć: 48