├── .gitignore ├── LICENSE ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── dazito │ │ └── oauthexample │ │ ├── OauthExampleApplication.java │ │ ├── config │ │ └── AppConfig.java │ │ ├── entities │ │ └── Account.java │ │ ├── oauth │ │ └── AuthServerOAuth2Config.java │ │ ├── repository │ │ └── AccountRepository.java │ │ ├── resource │ │ └── PrincipalResource.java │ │ └── service │ │ └── AccountUserDetailsService.java └── resources │ ├── application.properties │ ├── data.sql │ └── schema.sql └── test └── java └── com └── dazito └── oauthexample └── OauthExampleApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 22 | hs_err_pid* 23 | mvnw 24 | mvnw.cmd 25 | *.iml 26 | .idea/ 27 | .mvn/ 28 | target/ 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Pedro M. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.dazito 7 | oauth-example 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | oauth-example 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.5.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | Dalston.SR1 26 | 27 | 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-starter-oauth2 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-data-jpa 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-web 40 | 41 | 42 | mysql 43 | mysql-connector-java 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-test 49 | test 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.springframework.cloud 57 | spring-cloud-dependencies 58 | ${spring-cloud.version} 59 | pom 60 | import 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | org.springframework.boot 69 | spring-boot-maven-plugin 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/main/java/com/dazito/oauthexample/OauthExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.dazito.oauthexample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 6 | 7 | @EnableResourceServer 8 | @SpringBootApplication 9 | public class OauthExampleApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(OauthExampleApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/dazito/oauthexample/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.dazito.oauthexample.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.jdbc.datasource.DriverManagerDataSource; 7 | import org.springframework.security.oauth2.provider.token.TokenStore; 8 | import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; 9 | 10 | import javax.sql.DataSource; 11 | 12 | /** 13 | * Created by daz on 01/07/2017. 14 | */ 15 | @Configuration 16 | public class AppConfig { 17 | 18 | @Value("${spring.datasource.url}") 19 | private String datasourceUrl; 20 | 21 | @Value("${spring.database.driverClassName}") 22 | private String dbDriverClassName; 23 | 24 | @Value("${spring.datasource.username}") 25 | private String dbUsername; 26 | 27 | @Value("${spring.datasource.password}") 28 | private String dbPassword; 29 | 30 | @Bean 31 | public DataSource dataSource() { 32 | final DriverManagerDataSource dataSource = new DriverManagerDataSource(); 33 | 34 | dataSource.setDriverClassName(dbDriverClassName); 35 | dataSource.setUrl(datasourceUrl); 36 | dataSource.setUsername(dbUsername); 37 | dataSource.setPassword(dbPassword); 38 | 39 | return dataSource; 40 | } 41 | 42 | @Bean 43 | public TokenStore tokenStore() { 44 | return new JdbcTokenStore(dataSource()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/dazito/oauthexample/entities/Account.java: -------------------------------------------------------------------------------- 1 | package com.dazito.oauthexample.entities; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.Id; 7 | 8 | /** 9 | * Created by daz on 29/06/2017. 10 | */ 11 | @Entity 12 | public class Account { 13 | 14 | @Id 15 | @GeneratedValue 16 | private Long id; 17 | @Column(name = "username", length = 128) 18 | private String username; 19 | @Column(name = "password", length = 128) 20 | private String password; 21 | 22 | public Account() { 23 | } 24 | 25 | public Account(String username, String password) { 26 | 27 | this.username = username; 28 | this.password = password; 29 | } 30 | 31 | public Long getId() { 32 | return id; 33 | } 34 | 35 | public void setId(Long id) { 36 | this.id = id; 37 | } 38 | 39 | public String getUsername() { 40 | return username; 41 | } 42 | 43 | public void setUsername(String username) { 44 | this.username = username; 45 | } 46 | 47 | public String getPassword() { 48 | return password; 49 | } 50 | 51 | public void setPassword(String password) { 52 | this.password = password; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/dazito/oauthexample/oauth/AuthServerOAuth2Config.java: -------------------------------------------------------------------------------- 1 | package com.dazito.oauthexample.oauth; 2 | 3 | import com.dazito.oauthexample.config.AppConfig; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.authentication.AuthenticationManager; 7 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 8 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 9 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 10 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 11 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 12 | 13 | /** 14 | * Created by daz on 27/06/2017. 15 | */ 16 | @EnableAuthorizationServer 17 | @Configuration 18 | public class AuthServerOAuth2Config extends AuthorizationServerConfigurerAdapter { 19 | 20 | private final AuthenticationManager authenticationManager; 21 | private final AppConfig appConfig; 22 | 23 | @Autowired 24 | public AuthServerOAuth2Config(AuthenticationManager authenticationManager, AppConfig appConfig) { 25 | this.authenticationManager = authenticationManager; 26 | this.appConfig = appConfig; 27 | } 28 | 29 | @Override 30 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 31 | clients.jdbc(appConfig.dataSource()); 32 | } 33 | 34 | @Override 35 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { 36 | /* 37 | * Allow our tokens to be delivered from our token access point as well as for tokens 38 | * to be validated from this point 39 | */ 40 | security.checkTokenAccess("permitAll()"); 41 | } 42 | 43 | @Override 44 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 45 | endpoints 46 | .authenticationManager(authenticationManager) 47 | .tokenStore(appConfig.tokenStore()); // Persist the tokens in the database 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/dazito/oauthexample/repository/AccountRepository.java: -------------------------------------------------------------------------------- 1 | package com.dazito.oauthexample.repository; 2 | 3 | import com.dazito.oauthexample.entities.Account; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.Optional; 7 | 8 | /** 9 | * Created by daz on 29/06/2017. 10 | */ 11 | public interface AccountRepository extends JpaRepository { 12 | 13 | Optional findByUsername(String username); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/dazito/oauthexample/resource/PrincipalResource.java: -------------------------------------------------------------------------------- 1 | package com.dazito.oauthexample.resource; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RequestMethod; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import java.security.Principal; 8 | 9 | /** 10 | * Created by daz on 29/06/2017. 11 | */ 12 | @RestController 13 | @RequestMapping(path = "/account") 14 | public class PrincipalResource { 15 | 16 | @RequestMapping(method = RequestMethod.POST) 17 | public Principal oauth(Principal principal) { 18 | /* 19 | * Translate the incoming request, which has an access token 20 | * Spring security takes the incoming request and injects the Java Security Principal 21 | * The converter inside Spring Security will handle the to json method which the Spring Security 22 | * Oauth client will know how to read 23 | * 24 | * The @EnableResourceServer on the application entry point is what makes all this magic happen. 25 | * If there is an incoming request token it will check the token validity and handle it accordingly 26 | */ 27 | return principal; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/dazito/oauthexample/service/AccountUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.dazito.oauthexample.service; 2 | 3 | import com.dazito.oauthexample.repository.AccountRepository; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.security.core.authority.AuthorityUtils; 6 | import org.springframework.security.core.userdetails.User; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 | import org.springframework.stereotype.Service; 11 | 12 | /** 13 | * Created by daz on 29/06/2017. 14 | */ 15 | @Service 16 | public class AccountUserDetailsService implements UserDetailsService { 17 | 18 | private AccountRepository accountRepository; 19 | 20 | @Autowired 21 | public AccountUserDetailsService(AccountRepository accountRepository) { 22 | this.accountRepository = accountRepository; 23 | } 24 | 25 | @Override 26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 27 | return accountRepository 28 | .findByUsername(username) 29 | .map(account -> new User(account.getUsername(), account.getPassword(), AuthorityUtils.createAuthorityList("ROLE_USER"))) 30 | .orElseThrow(() -> new UsernameNotFoundException("Could not find " + username)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8181 2 | 3 | # =============================== 4 | # = DATA SOURCE 5 | # =============================== 6 | 7 | # Set here configurations for the database connection 8 | 9 | # Connection url for the database w/createDatabaseIfNotExist=true 10 | spring.datasource.url = jdbc:mysql://localhost:3306/oauth_example?createDatabaseIfNotExist=true 11 | spring.database.driverClassName = com.mysql.jdbc.Driver 12 | spring.jpa.database = MySQL 13 | spring.datasource.platform = mysql 14 | 15 | # Database - data initialization 16 | spring.jpa.generate-ddl = true 17 | 18 | # Username and password 19 | spring.datasource.username = root 20 | spring.datasource.password = admin 21 | 22 | # =============================== 23 | # = JPA / HIBERNATE 24 | # =============================== 25 | 26 | # Use spring.jpa.properties.* for Hibernate native properties (the prefix is 27 | # stripped before adding them to the entity manager). 28 | 29 | # Show or not log for each sql query 30 | spring.jpa.show-sql = true 31 | 32 | # Transactions 33 | spring.jpa.open-in-view = false 34 | 35 | # Hibernate ddl auto (create, create-drop, update): with "update" the database 36 | # schema will be automatically updated accordingly to java entities found in 37 | # the project 38 | spring.jpa.hibernate.ddl-auto = update 39 | 40 | # Naming strategy 41 | spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy 42 | 43 | # spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true 44 | # Allows Hibernate to generate SQL optimized for a particular DBMS 45 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect -------------------------------------------------------------------------------- /src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | /** Oauth - populate the oauth_client_details table */ 2 | INSERT INTO `oauth_client_details` (`client_id`, `client_secret`, `scope`, `authorized_grant_types`, `access_token_validity`, `additional_information`) 3 | VALUES 4 | ('web', 'secret', 'read', 'authorization_code,password,refresh_token,implicit', '900', '{}') 5 | ON DUPLICATE key UPDATE 6 | client_secret = VALUES(`client_secret`), 7 | scope = VALUES(`scope`), 8 | authorized_grant_types = VALUES(`authorized_grant_types`), 9 | access_token_validity = VALUES(`access_token_validity`), 10 | additional_information = VALUES(`additional_information`); 11 | 12 | INSERT INTO `oauth_example`.`account` (`id`, `password`, `username`) VALUES (' 1 ', 'dazito.com', 'dazito') 13 | ON DUPLICATE key UPDATE 14 | password = VALUES(`password`), 15 | username = VALUES(`username`); 16 | -------------------------------------------------------------------------------- /src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | create table if not exists oauth_client_details ( 2 | client_id VARCHAR(255) PRIMARY KEY, 3 | resource_ids VARCHAR(255), 4 | client_secret VARCHAR(255), 5 | scope VARCHAR(255), 6 | authorized_grant_types VARCHAR(255), 7 | web_server_redirect_uri VARCHAR(255), 8 | authorities VARCHAR(255), 9 | access_token_validity INTEGER, 10 | refresh_token_validity INTEGER, 11 | additional_information VARCHAR(4096), 12 | autoapprove VARCHAR(255) 13 | ); 14 | 15 | create table if not exists oauth_client_token ( 16 | token_id VARCHAR(255), 17 | token LONG VARBINARY, 18 | authentication_id VARCHAR(255) PRIMARY KEY, 19 | user_name VARCHAR(255), 20 | client_id VARCHAR(255) 21 | ); 22 | 23 | create table if not exists oauth_access_token ( 24 | token_id VARCHAR(255), 25 | token LONG VARBINARY, 26 | authentication_id VARCHAR(255) PRIMARY KEY, 27 | user_name VARCHAR(255), 28 | client_id VARCHAR(255), 29 | authentication LONG VARBINARY, 30 | refresh_token VARCHAR(255) 31 | ); 32 | 33 | create table if not exists oauth_refresh_token ( 34 | token_id VARCHAR(255), 35 | token LONG VARBINARY, 36 | authentication LONG VARBINARY 37 | ); 38 | 39 | create table if not exists oauth_code ( 40 | code VARCHAR(255), authentication LONG VARBINARY 41 | ); 42 | 43 | create table if not exists oauth_approvals ( 44 | userId VARCHAR(255), 45 | clientId VARCHAR(255), 46 | scope VARCHAR(255), 47 | status VARCHAR(10), 48 | expiresAt TIMESTAMP, 49 | lastModifiedAt TIMESTAMP 50 | ); 51 | 52 | create table if not exists ClientDetails ( 53 | appId VARCHAR(255) PRIMARY KEY, 54 | resourceIds VARCHAR(255), 55 | appSecret VARCHAR(255), 56 | scope VARCHAR(255), 57 | grantTypes VARCHAR(255), 58 | redirectUrl VARCHAR(255), 59 | authorities VARCHAR(255), 60 | access_token_validity INTEGER, 61 | refresh_token_validity INTEGER, 62 | additionalInformation VARCHAR(4096), 63 | autoApproveScopes VARCHAR(255) 64 | ); -------------------------------------------------------------------------------- /src/test/java/com/dazito/oauthexample/OauthExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.dazito.oauthexample; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class OauthExampleApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------