package com.andrewslater.example;

import com.andrewslater.example.security.ExampleUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
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.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.util.StringUtils;

@Configuration
public class OAuthServerConfiguration {

    public static final String RESTSERVICE_RESOURCE_ID = "restservice";

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            resources
                .resourceId(RESTSERVICE_RESOURCE_ID);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .requestMatchers()
                .antMatchers("/api/**")
                .and()
                .authorizeRequests()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/api/**").hasRole("USER");
        }
    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

        private TokenStore tokenStore = new InMemoryTokenStore();

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

        @Autowired private ExampleUserDetailsService userDetailsService;

        @Value("${oauth2.clients.webapp.secret}") private String webappClientSecret;

        @Value("${oauth2.clients.webapp.name}") private String webappClientName;

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

        @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            if (StringUtils.isEmpty(webappClientName)) {
                throw new Exception(
                    "You must specify the oauth client name property: oauth2.clients.webapp.name");
            }

            if (StringUtils.isEmpty(webappClientSecret)) {
                throw new Exception(
                    "You must specify the oauth client secret property: oauth2.clients.webapp.secret");
            }

            clients.inMemory().withClient(webappClientName)
                .authorizedGrantTypes("password", "refresh_token").authorities("USER")
                .scopes("read", "write").resourceIds(RESTSERVICE_RESOURCE_ID)
                .secret(webappClientSecret);
        }

        @Bean @Primary public DefaultTokenServices tokenServices() {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setSupportRefreshToken(false);
            tokenServices.setTokenStore(tokenStore);
            return tokenServices;
        }
    }

}

@@ -96,16 +96,73 @@
 ervice;%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A
 import o
@@ -502,24 +502,74 @@
 on.Primary;%0A
+import org.springframework.core.annotation.Order;%0A
 import org.s
@@ -711,16 +711,144 @@
 curity;%0A
+import org.springframework.security.config.http.SessionCreationPolicy;%0Aimport org.springframework.security.core.Authentication;%0A
 import o
@@ -1873,24 +1873,307 @@
 ork.
-util.StringUtils
+security.web.authentication.session.SessionAuthenticationException;%0Aimport org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;%0Aimport org.springframework.util.StringUtils;%0A%0Aimport javax.servlet.http.HttpServletRequest;%0Aimport javax.servlet.http.HttpServletResponse
 ;%0A%0A@
@@ -2341,24 +2341,38 @@
 ourceServer%0A
+    @Order(1)%0A
     protecte
@@ -2447,32 +2447,134 @@
 figurerAdapter %7B
+%0A        private static final Logger LOG = LoggerFactory.getLogger(ResourceServerConfiguration.class);
 %0A%0A        @Overr
@@ -2886,32 +2886,36 @@
                 
+    
 .antMatchers(%22/a
@@ -2938,16 +2938,20 @@
         
+   
+ 
 .and()%0A 
@@ -2982,24 +2982,28 @@
 eRequests()%0A
+    
             
@@ -3061,32 +3061,36 @@
                 
+ 
+   
 .antMatchers(%22/a
@@ -3112,16 +3112,202 @@
 (%22USER%22)
+%0A                    .and()%0A                .sessionManagement()%0A                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)%0A                    .sessionFixation().none()
 ;%0A      

Fix session fixation problem for API calls