// Path: src/main/java/com/rizki/mufrizal/spring/oauth2/custom/service/OAuth2AccessTokenRedis.java
// public interface OAuth2AccessTokenRedis {
// 
//     public Set<byte[]> getKeyRedis(String key);
// }
// 
// Path: src/main/java/com/rizki/mufrizal/spring/oauth2/custom/service/OAuth2CountAccessService.java
// public interface OAuth2CountAccessService {
// 
//     public OAuth2CountAccess findByClientId(String clientId);
// 
//     public void saveOAuth2CountAccess(OAuth2CountAccess oAuth2CountAccess);
// 
//     public void updateOAuth2CountAccess(OAuth2CountAccess oAuth2CountAccess);
// 
// }


import com.rizki.mufrizal.spring.oauth2.custom.service.OAuth2AccessTokenRedis;
import com.rizki.mufrizal.spring.oauth2.custom.service.OAuth2CountAccessService;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
        private OAuth2CountAccessService oAuth2CountAccessService;

        @Autowired
        private OAuth2AccessTokenRedis oAuth2AccessTokenRedis;

        @Override
        public void configure(ResourceServerSecurityConfigurer resourceServerSecurityConfigurer) throws Exception {
            TokenExtractorConfiguration tokenExtractorConfiguration = new TokenExtractorConfiguration(oAuth2CountAccessService, oAuth2AccessTokenRedis);
            resourceServerSecurityConfigurer
                    .resourceId(RESOURCE_ID)
                    .tokenExtractor(tokenExtractorConfiguration);
        }

        @Override
        public void configure(HttpSecurity httpSecurity) throws Exception {
            httpSecurity
                    .authorizeRequests()
                    .antMatchers("/api/*").fullyAuthenticated()
                    .and()
                    .addFilterBefore(new CorsConfiguration(), ChannelProcessingFilter.class);
        }

    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

        @Autowired
        @Qualifier("authenticationManagerBean")
// Path: src/main/java/com/rizki/mufrizal/spring/oauth2/custom/service/OAuth2AccessTokenRedis.java
// public interface OAuth2AccessTokenRedis {
// 
//     public Set<byte[]> getKeyRedis(String key);
// }
// 
// Path: src/main/java/com/rizki/mufrizal/spring/oauth2/custom/service/OAuth2CountAccessService.java
// public interface OAuth2CountAccessService {
// 
//     public OAuth2CountAccess findByClientId(String clientId);
// 
//     public void saveOAuth2CountAccess(OAuth2CountAccess oAuth2CountAccess);
// 
//     public void updateOAuth2CountAccess(OAuth2CountAccess oAuth2CountAccess);
// 
// }


// Path: src/main/java/com/rizki/mufrizal/spring/oauth2/custom/configuration/OAuth2Configuration.java
import com.rizki.mufrizal.spring.oauth2.custom.service.OAuth2AccessTokenRedis;
import com.rizki.mufrizal.spring.oauth2.custom.service.OAuth2CountAccessService;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;

        private OAuth2CountAccessService oAuth2CountAccessService;

        @Autowired
        private OAuth2AccessTokenRedis oAuth2AccessTokenRedis;

        @Override
        public void configure(ResourceServerSecurityConfigurer resourceServerSecurityConfigurer) throws Exception {
            TokenExtractorConfiguration tokenExtractorConfiguration = new TokenExtractorConfiguration(oAuth2CountAccessService, oAuth2AccessTokenRedis);
            resourceServerSecurityConfigurer
                    .resourceId(RESOURCE_ID)
                    .tokenExtractor(tokenExtractorConfiguration);
        }

        @Override
        public void configure(HttpSecurity httpSecurity) throws Exception {
            httpSecurity
                    .authorizeRequests()
                    .antMatchers("/api/*").fullyAuthenticated()
                    .and()
                    .addFilterBefore(new CorsConfiguration(), ChannelProcessingFilter.class);
        }

    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;