Spring-boot приложение не аутентифицируется при использовании OAuth2 (обновлено # 2) - PullRequest
0 голосов
/ 14 февраля 2020

Я пытаюсь создать клиент OAuth2 для доступа к стороннему серверу OAuth2. У меня есть эти строки, добавленные в мой application.properties файл:

spring.security.oauth2.client.registration.mercadolivre=mercadolivre
spring.security.oauth2.client.registration.mercadolivre.client-id=...
spring.security.oauth2.client.registration.mercadolivre.client-secret=...
spring.security.oauth2.client.registration.mercadolivre.client-authentication-method=basic
spring.security.oauth2.client.registration.mercadolivre.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.mercadolivre.redirect-uri=http://localhost:8080
spring.security.oauth2.client.provider.mercadolivre.authorization-uri=https://auth.mercadolivre.com.br/authorization
spring.security.oauth2.client.provider.mercadolivre.token-uri=https://auth.mercadolivre.com.br/oauth

У меня есть эта конфигурация безопасности Spring:

@Configuration
@EnableWebSecurity
@EnableOAuth2Sso
public class Security extends WebSecurityConfigurerAdapter {
  @Override
  public void configure(HttpSecurity http) throws Exception {
      http
        .csrf().disable()
        .authorizeRequests()
          .antMatchers("/css/**", "/images/**", "/js/**", "/**").permitAll()
          .anyRequest().authenticated()
        .and()
          .oauth2Login()
        .and()
        .logout()
          .logoutUrl("/logout");
  }
...
}

и это html для моих открытых и защищенных областей:

  <body>
    <ul>
      <!--<li class="navbar-brand">
        <img th:src="@{/img/logo.png}" class="sticky" width="120px" height="120px" alt="logo">
      </li> -->

      <li>
        Loja
      </li>

      <li class="right" sec:authorize="isAnonymous()">
        <a class="button" th:href="@{/oauth2/authorization/mercadolivre}">Entrar</button>
      </li>

      <li sec:authorize="isAuthenticated()">
        Logged in as: <span sec:authentication="name">Bob</span>
      </li>

      <li class="right" sec:authorize="isAuthenticated()">
        <a class="button" th:href="@{/logout}">Sair</button>
      </li>
    </ul>
  </body>

но когда я открываю приложение в браузере и пытаюсь войти в систему, меня перенаправляют на страницу авторизации правильно, но когда я перенаправляю обратно в свое приложение, я не аутентифицируюсь.

Кто-нибудь может увидеть, что здесь не так?

ОБНОВЛЕНИЕ

После того, как я изменил свою конфигурацию безопасности пружины на эту

@Configuration
@EnableWebSecurity
@EnableOAuth2Sso
public class Security extends WebSecurityConfigurerAdapter {
  @Override
  public void configure(HttpSecurity http) throws Exception {
      http
        .csrf().disable()
        .authorizeRequests()
          .antMatchers("/css/**", "/images/**", "/js/**", "/**").permitAll()
          .anyRequest().authenticated()
        .and()
        .formLogin()
          .loginPage("/login")
          .loginProcessingUrl("/doLogin").permitAll()
        .and()
        .oauth2Login()
          .loginPage("/login")
          .loginProcessingUrl("/login/oauth")
        .and()
        .logout()
          .logoutUrl("/logout");
  }
...
}

и application.properties redirect_uri to this:

spring.security.oauth2.client.registration.mercadolivre.redirect-uri=http://localhost:8080/login/oauth

Теперь, когда я пытаюсь войти, я получил эту ошибку:

java.lang.NullPointerException: null
        at org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient.getTokenResponse(DefaultAuthorizationCodeTokenResponseClient.java:84) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient.getTokenResponse(DefaultAuthorizationCodeTokenResponseClient.java:52) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider.authenticate(OAuth2LoginAuthenticationProvider.java:103) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:175) ~[spring-security-core-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter.attemptAuthentication(OAuth2LoginAuthenticationFilter.java:185) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(OAuth2AuthorizationRequestRedirectFilter.java:160) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1598) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]

(URL перенаправления выглядит нормально, в том числе с необходимым кодом: http://localhost:8080/login/oauth?code=...&state=... )

обновление 2

мои текущие настройки приведены ниже. при этом меня перенаправляют на страницу авторизации сервиса, но когда я возвращаюсь в свой проект, я не аутентифицируюсь (код авторизации для получения токенов доступа добавляется к URL с успехом).

Приложение. java

@EnableOAuth2Client
@EnableOAuth2Sso
@SpringBootApplication
@RestController
public class App extends WebSecurityConfigurerAdapter {

    @GetMapping("/user")
    public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
            return Collections.singletonMap("name", principal.getAttribute("name"));
    }

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests(a -> a
                            .antMatchers("/", "/error", "/webjars/**", "/css/**", "/js/**", "/img/**").permitAll()
                            .anyRequest().authenticated()
                    )
                    .exceptionHandling(e -> e
                            .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
                    )
                    .csrf(c -> c
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            )
                    .logout(l -> l
                        .logoutSuccessUrl("/").permitAll()
                    )
                    .oauth2Login();
    }

}

application.properties

security.basic.enabled=false

spring.security.oauth2.client.registration.mercadolivre.client-id=...
spring.security.oauth2.client.registration.mercadolivre.client-secret=...

spring.security.oauth2.client.registration.mercadolivre.client-authentication-method=basic
spring.security.oauth2.client.registration.mercadolivre.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.mercadolivre.scope=read
spring.security.oauth2.client.registration.mercadolivre.redirect-uri=http://localhost:8080

spring.security.oauth2.client.provider.mercadolivre.authorization-uri=https://auth.mercadolibre.com/authorization
spring.security.oauth2.client.provider.mercadolivre.token-uri=https://api.mercadolivre.com.br/oauth/token
spring.security.oauth2.client.provider.mercadolivre.user-info-uri=https://api.mercadolibre.com/users/me
spring.security.oauth2.client.provider.mercadolivre.user-info-authentication-method=form

spring.security.oauth2.client.clientId=...
spring.security.oauth2.client.clientSecret=...
spring.security.oauth2.client.accessTokenUri=https://api.mercadolivre.com.br/oauth/token
spring.security.oauth2.client.userAuthorizationUri=https://auth.mercadolibre.com/authorization
spring.security.oauth2.client.clientAuthenticationScheme=form

spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false

index. html

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title></title>
    <link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}"/>
</head>
<body>
  <nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
    <a class="navbar-brand" href="#">
      <img th:src="@{/img/bootstrap-solid.svg}" width="30" height="30" class="d-inline-block align-top" alt="kleber app store">
      Kleber App Store
    </a>

    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav mr-auto">
      </ul>
      <ul class="navbar-nav">
        <li class="nav-item" sec:authorize="isAnonymous()">
          <a class="nav-link" href="/oauth2/authorization/mercadolivre">
            Fazer login com Mercado Livre
          </a>
        </li>
        <li class="nav-item" sec:authorize="isAuthenticated()">
          <a class="nav-link" href="#">
            Logged in as: <span sec:authentication="name">Bob</span>
          </a>
        </li>
        <li class="nav-item" sec:authorize="isAuthenticated()">
          <a class="btn btn-primary" th:href="@{/logout}">
            Logout
          </a>
        </li>
      </ul>
    </div>
  </nav>

  <script type="text/javascript" th:src="@{/webjars/jquery/jquery.min.js}"></script>
  <script type="text/javascript" th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
  <script type="text/javascript" th:src="@{/webjars/js-cookie/js.cookie.js}"></script>
  <script type="text/javascript" th:src="@{/js/script.js}"></script>
</body>
</html>

Ответы [ 2 ]

1 голос
/ 17 февраля 2020

Обновление

Я бы хотел кое-что прояснить. Поток аутентификации отсутствует, когда вы используете поток авторизации Oauth2, только авторизация обрабатывается на сервере авторизации. Аутентификация все еще выполняется на стороне клиента. Это поток, когда вы используете oauth2Client. С другой стороны, при использовании потока oauth2Login авторизация и аутентификация выполняются на сервере авторизации. В Spring встроена поддержка известных провайдеров, таких как Facebook, Google и так далее. В нашем случае мы предоставляем аутентификацию на сервере авторизации.

Я загрузил рабочий пример здесь

https://github.com/saagar2000/oauth_server

https://github.com/saagar2000/oauth_client

Также обратите внимание, что вы должны обновить файл / etc / hosts /, чтобы включить запись, чтобы предотвратить перезапись клиентского приложения приложения сервера авторизации.

127.0.0.1       server

Оригинальный ответ

Похоже, что ваша конечная точка токена от третьей стороны возвращает пустой ответ. Убедитесь, что правильный запрос отправлен на конечную точку токена или может быть неправильной конечной точкой.

Из документов конечная точка токена должна быть https://api.mercadolibre.com/oauth/token

spring.security.oauth2.client.provider.mercadolivre.token-uri=https://api.mercadolibre.com/oauth/token

Вы можете запустить команду curl для проверки ответа токена

Что-то вроде

curl -X POST https://api.mercadolibre.com/oauth/token?grant_type=authorization_code&client_id=$APP_ID&client_secret=$SECRET_KEY&code=$SERVER_GENERATED_AUTHORIZATION_CODE&redirect_uri=$REDIRECT_URI
0 голосов
/ 14 февраля 2020

Я думаю, что для URI перенаправления клиента OAuth2 должно быть указано что-то вроде:

spring.security.oauth2.client.registration.mercadolivre.redirect-uri=http://localhost:8080/login/oauth2/mercadolivre

, и этот же URI должен быть введен на стороннем сервере авторизации OAuth2 в качестве URL-адреса перенаправления, как это именно здесь сервер авторизации должен отправить код авторизации для безопасности Spring, чтобы в конечном итоге получить токен.

Pero

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...