package demo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
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.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableResourceServer
@RestController
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@RequestMapping("/")
public String home() {
return "Hello World";
}
@RequestMapping(value = "/", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public String create(@RequestBody MultiValueMap<String, String> map) {
return "OK";
}
@Configuration
@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// @formatter:off
clients.inMemory().withClient("my-trusted-client")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT").scopes("read", "write", "trust")
.resourceIds("oauth2-resource").accessTokenValiditySeconds(600).and()
.withClient("my-client-with-registered-redirect").authorizedGrantTypes("authorization_code")
.authorities("ROLE_CLIENT").scopes("read", "trust").resourceIds("oauth2-resource")
.redirectUris("http://anywhere?key=value").and().withClient("my-client-with-secret")
.authorizedGrantTypes("client_credentials", "password").authorities("ROLE_CLIENT").scopes("read")
.resourceIds("oauth2-resource").secret("secret");
// @formatter:on
}
}
@Autowired
public void authenticationManager(AuthenticationManagerBuilder builder, UserRepository repository) throws Exception {
if (repository.count()==0) {
repository.save(new User("user", "password", Arrays.asList(new Role("USER"), new Role("ACTUATOR"))));
}
builder.userDetailsService(userDetailsService(repository));
}
private UserDetailsService userDetailsService(final UserRepository repository) {
return new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return new CustomUserDetails(repository.findByUsername(username));
}
};
}
}
class CustomUserDetails implements UserDetails {
private static final long serialVersionUID = 1L;
private Collection<? extends GrantedAuthority> authorities;
private String password;
private String username;
public CustomUserDetails(User user) {
this.username = user.getUsername();
this.password = user.getPassword();
this.authorities = translate(user.getRoles());
}
private Collection<? extends GrantedAuthority> translate(List<Role> roles) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (Role role : roles) {
String name = role.getName().toUpperCase();
if (!name.startsWith("ROLE_")) {
name = "ROLE_" + name;
}
authorities.add(new SimpleGrantedAuthority(name));
}
return authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
@Entity
class User {
@Id
@GeneratedValue
private Long id;
private String username;
private String password;
@OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
private List<Role> roles;
User() {
}
public User(String username, String password, List<Role> roles) {
this.username = username;
this.password = password;
this.roles = roles;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
@Entity
class Role {
@Id
@GeneratedValue
private Long id;
Role() {
}
public Role(String name) {
this.name = name;
}
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}