Как связать некоторое состояние сеанса в авторизации OAuth2

Я пытаюсь обработать или "обернуть" приложение-службу RESTful API перед службой HTTP-сервера. Внутренний сервис поддерживает состояние аутентификации через проприетарные сеансы. Аутентификация с внутренним сервером достигается за счет запутанного разговора между аутентифицирующим клиентом и сервером. В целом, взаимодействие с этим сервером является нестандартным и недостаточно хорошим для представления нашим клиентам в виде API. Тем не менее, существует слишком много наследства, чтобы пересмотреть и переработать весь HTTP-интерфейс.

Моя цель состоит в том, чтобы абстрагировать интерфейс от этого внутреннего сервера, предоставив этому серверу RESTful-сервер, который реализует аутентификацию OAuth2 посредством предоставления пароля, чтобы сторонние API могли взаимодействовать с внутренним сервером стандартным и понятным способом. Я создал простое приложение REST SpringBoot, которое может аутентифицироваться с помощью бэкэнда. Часть, с которой я борюсь, - выяснить, как лучше всего сопоставить аутентифицированные токены / запросы с идентификаторами сеансов бэкэнда.

По сути, я пытаюсь связать немного состояния для каждой авторизованной авторизации. В качестве решения я подумал о реализации собственного TokenStore, который будет поддерживать отображение. В качестве альтернативы я подумал о реализации "Custom Token Granter". Однако у меня есть сильная интуиция, что есть лучший и более легкий способ достичь моей цели.

Дополнительная информация:

@EnableAuthorizationServer а также @EnableResourceServer находятся в одном приложении.

Информация о версии:

org.springframework.security.oauth:spring-security-oauth2 2.0.13.RELEASEorg.springframework.security:spring-security-config 4.2.2.RELEASEorg.springframework.boot:spring-boot-starter-security 1.5.3.RELEASE

Это моя конфигурация сервера ресурсов:

@Configuration
@Profile(Common.CONST_EXTAPI_PROFILE)
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and()
        .headers().frameOptions().disable().and()            
            .authorizeRequests()                
            .antMatchers(HttpMethod.GET, "/", "/home","/register","/login", "/auth").permitAll()
            .antMatchers(HttpMethod.OPTIONS,"/oauth/token").permitAll()
            .antMatchers("/extapi/agent", "/extapi/agent/**", "/extapi/account/**", "/extapi/sale/**").authenticated();
    }
}

Это моя конфигурация сервера аутентификации:

@Configuration
@Profile(Common.CONST_EXTAPI_PROFILE)
@EnableAuthorizationServer
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Order(-1)
    public class MyWebSecurity extends WebSecurityConfigurerAdapter {
       @Override
       protected void configure(HttpSecurity http) throws Exception {
           http
              .authorizeRequests()
              .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll();
       }
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        KeyPair keyPair = new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "foobar".toCharArray())
            .getKeyPair("test");
        converter.setKeyPair(keyPair);
        return converter;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception 
    {
        clients.inMemory()
            .withClient("acme")
            .autoApprove(true)
            .secret("acmesecret")
            .authorizedGrantTypes("password", "authorization_code", "refresh_token").scopes("openid");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
            .authenticationManager(authenticationManager)
            .accessTokenConverter(jwtAccessTokenConverter());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer)
        throws Exception {
    oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess(
        "isAuthenticated()");
    }

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }
}

И пользовательский провайдер аутентификации

@Component
@Profile(Common.CONST_EXTAPI_PROFILE)
public class CustomAuthenticationProvider implements AuthenticationProvider 
{
    @Autowired
    private LoginSessionData sessionData;

    @Autowired
    private GuiAuthenticationService authService;

    @Autowired
    private ContextService contextService;

    @Autowired
    private RSAEncryptionService rsaService;

    @Autowired
    private ObjectMapper mapper;

    @Override
    public Authentication authenticate(Authentication auth) throws AuthenticationException {
        final String username = auth.getName();
        final String password = auth.getCredentials().toString();
        Authentication result = null;
        DataWrapper oauthResponse = new DataWrapper();
    try
    {
        BaseResponse resp = authService.authenticate(contextService.getCompanyID(), false, null);        
        oauthResponse.setAuth(rsaService.getPublicKey());
        oauthResponse.setData(mapper.writeValueAsString(resp));
        if(resp.getState().equals("REQUIRE_UTF8_USERNAME")){
            BaseRequest request = new BaseRequest();        
            request.setData(username);
            request.setCid(Integer.toString(contextService.getCompanyID()));
            sessionData.captureData(request);
            resp = authService.process(request);
        }
        if(resp.getState().equals("REQUIRE_RSA_PASSWORD"))
        {
            BaseRequest request = new BaseRequest();        
            request.setData(password);
            request.setCid(Integer.toString(contextService.getCompanyID()));
            resp = authService.process(request);
        }
        if(resp.getState().equals("AUTHENTICATED"))
        {
            UsernamePasswordAuthenticationToken token = 
                new UsernamePasswordAuthenticationToken(username, password, Collections.emptyList());        
            result = token;
        }
    }
    catch (Exception e)
    {
        sessionData.setCurrentState(AuthenticationState.INVALID);
        oauthResponse.setError(e.getLocalizedMessage());
        oauthResponse.setData(Common.CONST_FATAL_ERROR);
        e.printStackTrace();
    }
    if(result == null)
        throw new BadCredentialsException("External system authentication failed");

    return result;
    }

    @Override
    public boolean supports(Class<?> auth) {
        return auth.equals(UsernamePasswordAuthenticationToken.class);
    }
}

0 ответов

Другие вопросы по тегам