├── .gitignore ├── README.md ├── _config.yml ├── nbactions.xml ├── pom.xml └── src └── main ├── java └── com │ └── github │ └── oauth2 │ └── server │ ├── Application.java │ ├── AuthorizationServerConfig.java │ └── JsonToUrlEncodedAuthenticationFilter.java └── resources └── config └── application.yml /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ 25 | 26 | ### VS Code ### 27 | .vscode 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sample standalone OAuth2 authorization server for Spring Boot (Uses in-memory token store) 2 | 3 | The requesting method for token supports both ```json format``` and ```url-encoded format``` 4 | 5 | 6 | The token validity is currently 60secs. 7 | 8 | 9 | Update any of the ```clienId```/```clientPassword```/```tokenValidity``` to however you want. 10 | ## Other implementations 11 | * Using [JDBC](https://github.com/aldwindelgado/spring-boot-oauth2-server/tree/jdbc) with default token 12 | * Using [JDBC with JWT](https://github.com/aldwindelgado/spring-boot-oauth2-server/tree/jwt) as the token 13 | 14 | ## Running 15 | ```shell 16 | mvn clean package spring-boot:run 17 | ``` 18 | 19 | ## Request for a token 20 | Use any of the curl commands to request an access token. 21 | 22 | #### Using URL-Encoded Format 23 | ``` 24 | curl -X POST -H "Authorization: Basic YWNjb3VudDpwYXNzd29yZA==" -H "Content-Type: application/x-www-form-urlencoded" -v localhost:8080/oauth/token?grant_type=client_credentials 25 | ``` 26 | #### Using JSON Format 27 | ``` 28 | curl -X POST -H "Authorization: Basic YWNjb3VudDpwYXNzd29yZA==" -H "Content-Type: application/json" -d '{ "grant_type": "client_credentials" }' -v localhost:8080/oauth/token 29 | ``` 30 | 31 | ## Resource Server 32 | See [spring-boot-oauth2-client](https://github.com/aldwindelgado/spring-boot-oauth2-client) for running the oauth-client (resource server) 33 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | run 5 | 6 | jar 7 | 8 | 9 | process-classes 10 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 11 | 12 | 13 | -classpath %classpath com.github.oauth2.server.Application 14 | java 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github 5 | spring-boot-oauth2-server 6 | 1.0.0 7 | 8 | spring-boot-oauth2-server 9 | Sample OAuth2 authorization server using Spring Boot 10 | 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 1.5.6.RELEASE 15 | 16 | 17 | 18 | UTF-8 19 | UTF-8 20 | 1.8 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-logging 35 | 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-log4j2 41 | 42 | 46 | 47 | org.springframework.security.oauth 48 | spring-security-oauth2 49 | 50 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-actuator 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-security 61 | 62 | 68 | 69 | org.apache.commons 70 | commons-lang3 71 | 3.1 72 | jar 73 | 74 | 75 | javax.ws.rs 76 | javax.ws.rs-api 77 | 2.0 78 | jar 79 | 80 | 81 | org.json 82 | json 83 | 20160810 84 | jar 85 | 86 | 87 | org.apache.commons 88 | commons-exec 89 | 1.3 90 | jar 91 | 92 | 93 | com.google.guava 94 | guava 95 | 23.0 96 | jar 97 | 98 | 99 | 100 | 101 | 102 | 103 | org.springframework.boot 104 | spring-boot-maven-plugin 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /src/main/java/com/github/oauth2/server/Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package com.github.oauth2.server; 7 | 8 | import org.springframework.boot.SpringApplication; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | import org.springframework.http.HttpStatus; 11 | import org.springframework.http.MediaType; 12 | import org.springframework.http.ResponseEntity; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | 15 | /** 16 | * 17 | * @author Aldwin Delgado 18 | */ 19 | @SpringBootApplication 20 | public class Application { 21 | 22 | public static void main(String[] args) { 23 | SpringApplication.run(Application.class, args); 24 | } 25 | 26 | @RequestMapping( 27 | value = "/", 28 | produces = MediaType.APPLICATION_JSON_VALUE 29 | ) 30 | public ResponseEntity index() { 31 | return new ResponseEntity<>("{\"message\":\"Home!\"}", HttpStatus.OK); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/github/oauth2/server/AuthorizationServerConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package com.github.oauth2.server; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.security.authentication.AuthenticationManager; 11 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 12 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 13 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 14 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 15 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 16 | import org.springframework.security.oauth2.provider.token.TokenStore; 17 | 18 | /** 19 | * 20 | * @author Aldwin Delgado 21 | */ 22 | @Configuration 23 | @EnableAuthorizationServer 24 | public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { 25 | 26 | private TokenStore tokenStore; 27 | 28 | @Autowired 29 | private AuthenticationManager authenticationManager; 30 | 31 | @Override 32 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 33 | endpoints 34 | .authenticationManager(authenticationManager) 35 | .approvalStoreDisabled() 36 | .tokenStore(tokenStore); 37 | } 38 | 39 | @Override 40 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 41 | clients 42 | .inMemory() 43 | .withClient("account") 44 | .secret("password") 45 | .authorizedGrantTypes("client_credentials", "password") 46 | .scopes("read", "write") 47 | .accessTokenValiditySeconds(60) 48 | .resourceIds("sample-oauth"); 49 | } 50 | 51 | @Override 52 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { 53 | security 54 | .checkTokenAccess("isAuthenticated()") 55 | .allowFormAuthenticationForClients(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/github/oauth2/server/JsonToUrlEncodedAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package com.github.oauth2.server; 7 | 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import com.google.common.io.ByteStreams; 10 | import java.io.IOException; 11 | import java.util.Enumeration; 12 | import java.util.Map; 13 | import java.util.Objects; 14 | import java.util.stream.Collectors; 15 | import javax.servlet.FilterChain; 16 | import javax.servlet.ServletException; 17 | import javax.servlet.http.HttpServletRequest; 18 | import javax.servlet.http.HttpServletRequestWrapper; 19 | import javax.servlet.http.HttpServletResponse; 20 | import org.springframework.security.web.savedrequest.Enumerator; 21 | import org.springframework.stereotype.Component; 22 | import org.springframework.web.filter.OncePerRequestFilter; 23 | 24 | /** 25 | * 26 | * @author Aldwin Delgado 27 | */ 28 | @Component 29 | public class JsonToUrlEncodedAuthenticationFilter extends OncePerRequestFilter { 30 | 31 | /** 32 | * @param request 33 | * @param response 34 | * @param filterChain 35 | * @throws javax.servlet.ServletException 36 | * @throws java.io.IOException 37 | * 38 | */ 39 | @Override 40 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 41 | 42 | if (Objects.equals(request.getServletPath(), "/oauth/token") && Objects.equals(request.getContentType(), "application/json")) { 43 | 44 | byte[] json = ByteStreams.toByteArray(request.getInputStream()); 45 | 46 | Map jsonMap = new ObjectMapper().readValue(json, Map.class); 47 | Map parameters 48 | = jsonMap.entrySet().stream() 49 | .collect(Collectors.toMap( 50 | Map.Entry::getKey, 51 | e -> new String[]{e.getValue()}) 52 | ); 53 | 54 | HttpServletRequest requestWrapper = new RequestWrapper(request, parameters); 55 | filterChain.doFilter(requestWrapper, response); 56 | } else { 57 | filterChain.doFilter(request, response); 58 | } 59 | } 60 | 61 | private class RequestWrapper extends HttpServletRequestWrapper { 62 | 63 | private final Map params; 64 | 65 | RequestWrapper(HttpServletRequest request, Map params) { 66 | super(request); 67 | this.params = params; 68 | } 69 | 70 | @Override 71 | public String getParameter(String name) { 72 | if (this.params.containsKey(name)) { 73 | return this.params.get(name)[0]; 74 | } 75 | return ""; 76 | } 77 | 78 | @Override 79 | public Map getParameterMap() { 80 | return this.params; 81 | } 82 | 83 | @Override 84 | public Enumeration getParameterNames() { 85 | return new Enumerator<>(params.keySet()); 86 | } 87 | 88 | @Override 89 | public String[] getParameterValues(String name) { 90 | return params.get(name); 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/resources/config/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: spring-boot-oauth2-server 4 | mvc: 5 | favicon: 6 | enabled: false 7 | throw-exception-if-no-handler-found: true 8 | main: 9 | banner-mode: 'off' 10 | security: 11 | oauth2: 12 | resource: 13 | filter-order: 3 14 | client: 15 | authenticationScheme: header 16 | logging: 17 | level: 18 | # org.springframework.security: DEBUG 19 | 20 | server: 21 | port: 8080 22 | error: 23 | whitelabel: 24 | enabled: false --------------------------------------------------------------------------------