Spring Boot OAuth 2 SSO, как извлечь токен для передачи толстому клиентскому приложению - PullRequest
0 голосов
/ 10 июня 2019

У меня толстое клиентское приложение (C #, но это не должно иметь значения). Все пользователи уже существуют в системе аутентификации / авторизации (сторонней), которая предоставляет API OAuth 2 (authorize / access_token плюс сервис user_info). У меня есть уровень веб-службы Spring Boot, который будет иметь веб-службы RESTful, которые будут вызываться приложением толстого клиента, которое должно вызываться только аутентифицированными пользователями для защищенных веб-служб. Для аутентификации толстый клиент запустит веб-браузер (ОС установлена ​​по умолчанию) и откроет https для restful.web.server: 8443 / login уровня веб-службы Spring Boot. Это сделает взаимодействие OAuth 2 (authorization_code). После перенаправления обратно с действительным токеном я хочу перенаправить на пользовательский URI, передающий токен, и закрыть браузер (если это возможно), чтобы приложение, зарегистрированное в ОС, могло извлечь токен и передать его через механизм IPC в приложение толстого клиента. Приложение толстого клиента может затем передать токен веб-службам в заголовке (Authorize: TOKEN_TYPE TOKEN_VALUE). Веб-службы должны затем проверить подлинность токена. Веб-службы, вызываемые с недействительным токеном, должны просто возвращать ошибку HTTP и содержимое ошибки JSON (например, код + сообщение), а не пытаться перенаправить на экран входа в систему. Это будет организовано толстым клиентским приложением. Я не имею никакого отношения к какой-либо пользовательской обработке URI, разработке IPC или вызовам веб-службы толстого клиента. Это все, что нужно для Spring / SSO, - получить токен для отправки моему толстому клиенту и вернуть соответствующую ошибку от защищенных веб-сервисов, не возвращая перенаправление на вход в SSO. Кажется, я аутентифицируюсь и мне посылают токен, но затем я получаю исключение.

Я добился определенного прогресса, и похоже, что, запустив браузер вручную и перейдя на уровень моего веб-сервиса https to restful.web.server: 8443 / login, он перенаправляет на сайт SSO https на 3rdparty.sso.server / oauth / авторизация (передача client_id, redirect_uri, response_type = code, state). Я могу войти в систему, и Spring вызывает конечную точку https to 3rdparty.sso.server / oauth / access_token (мне пришлось создать пользовательский RequestEnhancer, чтобы добавить авторизацию: Basic ENCODED_CLIENT_ID_AND_CLIENT_SECRET для удовлетворения требованиям API-интерфейса SSO access_token). Это возвращает 200 ОК, но потом я получаю исключения и не знаю, как извлечь токен. Возвращенный access_token может не использовать стандартные имена свойств, но не уверен, когда нужно идти и проверять, так ли это. Я сделал аутентификацию таким образом, чтобы сохранить идентификатор клиента и секрет клиента вне приложения толстого клиента, и мои веб-сервисы должны все равно выполнить авторизацию. Если есть лучший способ или указатели на то, чтобы кто-то уже делал это, это будет с благодарностью. Я нахожу так много примеров, которые либо не совсем актуальны, либо больше относятся к веб-приложениям.

server:
  port: 8443
  ssl:
    key-store: classpath:keystore.p12
    key-store-password: **********
    keyStoreType: PKCS12
    keyAlias: tomcat
  servlet:
    context-path: /
  session:
    cookie:
      name: UISESSION
security:
  basic:
    enabled: false
  oauth2:
    client:
      clientId: *******
      clientSecret: *****************
      accessTokenUri: https://3rdparty.sso.server/oauth2/access_token
      userAuthorizationUri: https://3rdparty.sso.server/oauth2/authorize
      authorizedGrantTypes: authorization_code,refresh_token
      scope:
      tokenName: accessToken
      redirectUri: https://restful.web.server:8443/login
      authenticationScheme: query
      clientAuthenticationScheme: header
    resource:
      userInfoUri: https://3rdparty.sso.server/oauth2/userinfo
logging:
  level:
    org:
      springframework: DEBUG
spring:
  http:
    logRequestDetails: true
    logResponseDetails: true
@Configuration
@EnableOAuth2Sso
@Order(value=0)
public class ServiceConectWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // From the root '/' down...
                .antMatcher("/**")
                // requests are authorised...
                .authorizeRequests()
                // ...to these url's...
                .antMatchers("/", "/login**", "/debug/**", "/webjars/**", "/error**")
                // ...without security being applied...
                .permitAll()
                // ...any other requests...
                .anyRequest()
                // ...the user must be authenticated.
                .authenticated()
                .and()
                .formLogin().disable()
                .logout()
                .logoutSuccessUrl("/login")
                .permitAll()
                .and()
                .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())

        ;
    }

Я ожидаю, что защищенные веб-службы будут доступны после проверки подлинности через браузер во время тестирования без клиента и не будут ожидать появления исключений. Мне нужно иметь возможность извлечь возвращенный токен и передать его моему толстому клиенту.

Redirects to 'https://3rdparty.sso.server/oauth2/authorize?client_id=***HIDDEN_CLIENT_ID***&redirect_uri=https://localhost:8443/login&response_type=code&state=***HIDDEN_STATE_1***'

Then FilterChainProxy        : /login?code=***HIDDEN_CODE_1***&state=***HIDDEN_STATE_1*** at position 6 of 12 in additional filter chain; 

Request is to process authentication
RestTemplate              : HTTP POST https://3rdparty.sso.server/oauth2/access_token
RestTemplate              : Response 200 OK

IllegalStateException: Access token provider returned a null access token, which is illegal according to the contract.
    at OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:223) ```

Then end up at an error page

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

There was an unexpected error (type=Internal Server Error, status=500).
Access token provider returned a null access token, which is illegal according to the contract.

1 Ответ

0 голосов
/ 24 июня 2019

Служба access_token возвращала нестандартные имена JSON. Я создал MyOwnOAuth2AccessToken с соответствующими нестандартными именами JSON и необходимыми классами де / сериализации. Я создал класс MyOauth2AccesTokenHttpMessageConverter для возврата моего OAuth2AccessToken. MyOauth2AccesTokenHttpMessageConverter был подключен с

    @Configuration
    public class ServiceConnectUserInfoRestTemplateFactory implements UserInfoRestTemplateFactory

в пределах

    @Bean
    @Override
    public OAuth2RestTemplate getUserInfoRestTemplate()

метод со следующим кодом:

    List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
    messageConverters.add(new ItisOAuth2AccessTokenHttpMessageConverter());
    messageConverters.addAll((new RestTemplate()).getMessageConverters());
    accessTokenProvider.setMessageConverters(messageConverters);

Возможно, есть лучший способ сделать это, но у меня это сработало.

...