├── Oauth.pptx
├── README.md
├── pom.xml
└── src
└── main
├── java
└── com
│ └── auth
│ ├── BootLauncher.java
│ ├── config
│ ├── AuthorizationServerConfig.java
│ └── BasicSecurityConfig.java
│ ├── controller
│ ├── UserController.java
│ └── dto
│ │ └── UserDto.java
│ ├── entity
│ ├── AuthRole.java
│ └── AuthUser.java
│ ├── repository
│ ├── UserRepository.java
│ └── UserRoleRepo.java
│ └── service
│ ├── AuthUserService.java
│ └── UserDetailsServiceImpl.java
└── resources
├── application.yml
└── data.sql
/Oauth.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/github4codedebugger/OAuth-service-Springboot/95cd4839837fd4f2770d8d99c1c5431228ed53b0/Oauth.pptx
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OAuth-service-Springboot
2 |
3 | ## Register endpoint
4 | ~~~
5 | curl --location --request POST 'http://localhost:8080/oauth/users' \
6 | --header 'Content-Type: application/json' \
7 | --data-raw '{
8 | "userName": "hari",
9 | "password": "hari@123",
10 | "email": "hari.singhar@gmail.com",
11 | "mobile": "9856683254"
12 | }'
13 |
14 | ~~~
15 |
16 | ## Generate accesstoken endpoint
17 | ~~~~
18 | Generate Access Token:
19 | curl --location --request POST 'http://localhost:8080/oauth/token?username=hari&password=hari@123&grant_type=password' \
20 | --header 'Authorization: Basic dGVzdDp0ZW1w'
21 | ~~~
22 |
23 |
24 | ## Validate endpoint
25 | ~~~
26 | curl --location --request POST 'http://localhost:8080/oauth/check_token?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTg5NjkyNTgsInVzZXJfbmFtZSI6ImhhcmkiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMjg5Mjc3MjktMjViZi00NWZmLTk5ODAtYjU1ZTM4Y2NiYzYxIiwiY2xpZW50X2lkIjoidGVzdCIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSJdfQ.CNjCm3h7JDNMs_CtxkgvnJOW2bhMN6oct5vQk70g7M0' \
27 | --header 'Authorization: Basic dGVzdDp0ZW1w'
28 | ~~~
29 |
30 | ## Get Access token from Refresh token endpoint
31 | ~~~
32 | curl --location --request POST 'http://localhost:8080/oauth/token?grant_type=refresh_token&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJoYXJpIiwic2NvcGUiOlsicmVhZCIsIndyaXRlIl0sImF0aSI6IjA0YzIxZDQ3LTIyMTctNGYwNi04YjlkLTdiNDBkMzM2YTg5ZCIsImV4cCI6MTU5ODk3MDYwNiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjA5YWI1MmE4LTg5YTktNDdhMy05NjNmLWM4OWFjN2Y2MzJkZiIsImNsaWVudF9pZCI6InRlc3QifQ.tg3YMrTcGXZttCetO6ORlknI5J_Q2OEK97ZYFWYr-bM' \
33 | --header 'Authorization: Basic dGVzdDp0ZW1w'
34 | ~~~
35 |
36 | Client Application implementation : https://youtu.be/qgLE1jx7fmk
37 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.auth
7 | auth-service
8 | 1.0-SNAPSHOT
9 |
10 | org.springframework.boot
11 | spring-boot-starter-parent
12 | 2.2.9.RELEASE
13 |
14 |
15 |
16 | 1.8
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 | org.springframework.boot
26 | spring-boot-starter-data-jpa
27 |
28 |
29 | mysql
30 | mysql-connector-java
31 | runtime
32 |
33 |
34 | org.projectlombok
35 | lombok
36 | provided
37 |
38 |
39 |
40 | org.springframework.security
41 | spring-security-jwt
42 | 1.0.10.RELEASE
43 |
44 |
45 | org.springframework.security.oauth.boot
46 | spring-security-oauth2-autoconfigure
47 | 2.2.9.RELEASE
48 |
49 |
50 |
51 |
52 |
53 |
54 | org.springframework.boot
55 | spring-boot-maven-plugin
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/BootLauncher.java:
--------------------------------------------------------------------------------
1 | package com.auth;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class BootLauncher {
8 | public static void main(String[] args) {
9 | SpringApplication.run(BootLauncher.class, args);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/config/AuthorizationServerConfig.java:
--------------------------------------------------------------------------------
1 | package com.auth.config;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.beans.factory.annotation.Value;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.context.annotation.Primary;
8 | import org.springframework.jdbc.core.JdbcTemplate;
9 | import org.springframework.security.authentication.AuthenticationManager;
10 | import org.springframework.security.core.userdetails.UserDetailsService;
11 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
12 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
13 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
14 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
15 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
16 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
17 | import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
18 | import org.springframework.security.oauth2.provider.token.TokenStore;
19 | import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
20 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
21 |
22 | import java.util.Objects;
23 |
24 | @Configuration
25 | @EnableAuthorizationServer
26 | public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
27 |
28 | @Autowired
29 | private AuthenticationManager authenticationManager;
30 |
31 | @Autowired
32 | private UserDetailsService userDetailsService;
33 |
34 | @Autowired
35 | private JdbcTemplate jdbcTemplate;
36 |
37 | @Value("${security.signing-key}")
38 | private String signingKey;
39 |
40 |
41 | @Override
42 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
43 | JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
44 | converter.setSigningKey(signingKey);
45 |
46 | endpoints.tokenStore(tokenStore(jdbcTemplate))
47 | .reuseRefreshTokens(false)
48 | .accessTokenConverter(converter)
49 | .authenticationManager(authenticationManager)
50 | .userDetailsService(userDetailsService);
51 | }
52 |
53 | @Override
54 | public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
55 | oauthServer.tokenKeyAccess("hasAuthority('ROLE_TRUSTED_CLIENT')")
56 | .checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')");
57 | }
58 |
59 | @Override
60 | public void configure(ClientDetailsServiceConfigurer config) throws Exception {
61 | config.jdbc(jdbcTemplate.getDataSource());
62 | }
63 |
64 |
65 | @Bean
66 | public TokenStore tokenStore(JdbcTemplate jdbcTemplate) {
67 | return new JdbcTokenStore(Objects.requireNonNull(jdbcTemplate.getDataSource()));
68 | }
69 |
70 | @Bean
71 | public BCryptPasswordEncoder passwordEncoder() {
72 | return new BCryptPasswordEncoder();
73 | }
74 |
75 | @Bean
76 | @Primary
77 | public DefaultTokenServices tokenServices() {
78 | DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
79 | defaultTokenServices.setTokenStore(tokenStore(jdbcTemplate));
80 | defaultTokenServices.setSupportRefreshToken(true);
81 | return defaultTokenServices;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/config/BasicSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.auth.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.authentication.AuthenticationManager;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
8 | import org.springframework.security.config.http.SessionCreationPolicy;
9 |
10 | @Configuration
11 | public class BasicSecurityConfig extends WebSecurityConfigurerAdapter {
12 |
13 | @Bean
14 | @Override
15 | protected AuthenticationManager authenticationManager() throws Exception {
16 | return super.authenticationManager();
17 | }
18 |
19 | @Override
20 | protected void configure(HttpSecurity http) throws Exception {
21 | http.csrf()
22 | .disable()
23 | .formLogin().disable()
24 | .logout().disable()
25 | .sessionManagement()
26 | .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
27 | .and()
28 | .httpBasic();
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.auth.controller;
2 |
3 | import com.auth.controller.dto.UserDto;
4 | import com.auth.entity.AuthUser;
5 | import com.auth.service.AuthUserService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.web.bind.annotation.*;
9 |
10 | @RestController
11 | @RequestMapping("/oauth/users")
12 | public class UserController {
13 |
14 | @Autowired
15 | private AuthUserService authUserService;
16 |
17 | @PostMapping
18 | @ResponseStatus(HttpStatus.CREATED)
19 | public AuthUser register(@RequestBody UserDto userDto) {
20 | return authUserService.register(userDto);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/controller/dto/UserDto.java:
--------------------------------------------------------------------------------
1 | package com.auth.controller.dto;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 |
6 | @Getter
7 | @Setter
8 | public class UserDto {
9 |
10 | private String userName;
11 |
12 | private String password;
13 |
14 | private String email;
15 |
16 | private String mobile;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/entity/AuthRole.java:
--------------------------------------------------------------------------------
1 | package com.auth.entity;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 |
6 | import javax.persistence.*;
7 | import java.io.Serializable;
8 |
9 | @Getter
10 | @Setter
11 | @Entity
12 | @Table(name = "auth_role")
13 | public class AuthRole implements Serializable {
14 |
15 | private static final long serialVersionUID = 1L;
16 |
17 | @Id
18 | @GeneratedValue(strategy = GenerationType.IDENTITY)
19 | private Long id;
20 |
21 | @Column(name = "role_name")
22 | private String roleName;
23 |
24 | @Column(name = "description")
25 | private String description;
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/entity/AuthUser.java:
--------------------------------------------------------------------------------
1 | package com.auth.entity;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 |
6 | import javax.persistence.*;
7 | import java.util.List;
8 |
9 | @Getter
10 | @Setter
11 | @Entity
12 | @Table(name = "auth_user")
13 | public class AuthUser {
14 | @Id
15 | @GeneratedValue(strategy = GenerationType.IDENTITY)
16 | @Column(name = "id")
17 | private Long id;
18 |
19 | private String userName;
20 |
21 | private String password;
22 |
23 | private String email;
24 |
25 | private String mobile;
26 |
27 | @ManyToMany(fetch = FetchType.EAGER)
28 | @JoinTable(name = "user_role", joinColumns
29 | = @JoinColumn(name = "user_id",
30 | referencedColumnName = "id"),
31 | inverseJoinColumns = @JoinColumn(name = "role_id",
32 | referencedColumnName = "id"))
33 | private List roles;
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.auth.repository;
2 |
3 | import com.auth.entity.AuthUser;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | import java.util.Optional;
7 |
8 | public interface UserRepository extends JpaRepository {
9 | Optional findByUserName(String username);
10 |
11 | Optional findByUserNameOrEmail(String username, String email);
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/repository/UserRoleRepo.java:
--------------------------------------------------------------------------------
1 | package com.auth.repository;
2 |
3 | import com.auth.entity.AuthRole;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface UserRoleRepo extends JpaRepository {
7 | AuthRole findByRoleNameContaining(String roleName);
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/service/AuthUserService.java:
--------------------------------------------------------------------------------
1 | package com.auth.service;
2 |
3 | import com.auth.controller.dto.UserDto;
4 | import com.auth.entity.AuthUser;
5 | import com.auth.repository.UserRepository;
6 | import com.auth.repository.UserRoleRepo;
7 | import com.fasterxml.jackson.databind.ObjectMapper;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.security.crypto.password.PasswordEncoder;
10 | import org.springframework.stereotype.Service;
11 |
12 | import java.util.Collections;
13 | import java.util.Optional;
14 |
15 | @Service
16 | public class AuthUserService {
17 | @Autowired
18 | private UserRepository userRepository;
19 |
20 | @Autowired
21 | private UserRoleRepo userRoleRepo;
22 |
23 | @Autowired
24 | private PasswordEncoder passwordEncoder;
25 |
26 | public AuthUser register(UserDto userDto) {
27 | AuthUser authUser = new ObjectMapper().convertValue(userDto, AuthUser.class);
28 | authUser.setPassword(passwordEncoder.encode(userDto.getPassword()));
29 | authUser.setRoles(Collections.singletonList(userRoleRepo.findByRoleNameContaining("USER")));
30 | Optional optUser = userRepository.findByUserNameOrEmail(userDto.getUserName(), userDto.getEmail());
31 | if (!optUser.isPresent()) {
32 | return userRepository.save(authUser);
33 | }
34 | throw new RuntimeException("User already exist");
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/auth/service/UserDetailsServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.auth.service;
2 |
3 | import com.auth.entity.AuthUser;
4 | import com.auth.repository.UserRepository;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.security.core.GrantedAuthority;
7 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
8 | import org.springframework.security.core.userdetails.User;
9 | import org.springframework.security.core.userdetails.UserDetails;
10 | import org.springframework.security.core.userdetails.UserDetailsService;
11 | import org.springframework.stereotype.Component;
12 |
13 | import java.util.List;
14 | import java.util.Optional;
15 | import java.util.stream.Collectors;
16 |
17 | @Component
18 | public class UserDetailsServiceImpl implements UserDetailsService {
19 |
20 | @Autowired
21 | private UserRepository userRepository;
22 |
23 | @Override
24 | public UserDetails loadUserByUsername(String userName) {
25 | // it will be called at access token generation time
26 | Optional optUser = userRepository.findByUserName(userName);
27 | if (optUser.isPresent()) {
28 | AuthUser user = optUser.get();
29 | List authorities = user.getRoles()
30 | .stream().map(roles -> new SimpleGrantedAuthority(roles.getRoleName()))
31 | .collect(Collectors.toList());
32 | return new User(user.getUserName(), user.getPassword(), authorities);
33 | }
34 | throw new RuntimeException("user not exist");
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | jpa:
3 | hibernate:
4 | ddl-auto: create
5 | show-sql: true
6 | properties:
7 | hibernate:
8 | dialect: org.hibernate.dialect.MySQL5Dialect
9 | datasource:
10 | url: jdbc:mysql://localhost:3306/db
11 | username: identity
12 | password: identity123
13 | initialization-mode: always
14 | security:
15 | oauth2:
16 | resource:
17 | filter-order: 3
18 | signing-key:
19 |
--------------------------------------------------------------------------------
/src/main/resources/data.sql:
--------------------------------------------------------------------------------
1 | drop table if exists oauth_access_token;
2 | create table oauth_access_token(
3 | token_id VARCHAR(255),
4 | token varbinary(4096),
5 | authentication_id VARCHAR(255),
6 | user_name VARCHAR(255),
7 | client_id VARCHAR(255),
8 | authentication varbinary(4096),
9 | refresh_token VARCHAR(255)
10 | );
11 |
12 | drop table if exists oauth_refresh_token;
13 | create table oauth_refresh_token(
14 | token_id VARCHAR(255),
15 | token varbinary(4096),
16 | authentication varbinary(4096)
17 | );
18 |
19 | drop table if exists oauth_code;
20 | create table oauth_code(
21 | code VARCHAR(255),
22 | authentication varbinary(4096)
23 | );
24 |
25 | drop table if exists oauth_approvals;
26 | create table oauth_approvals(
27 | userId VARCHAR(255),
28 | clientId VARCHAR(255),
29 | scope VARCHAR(255),
30 | status VARCHAR(10),
31 | expiresAt TIMESTAMP,
32 | lastModifiedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
33 | );
34 |
35 | drop table if exists ClientDetails;
36 | create table ClientDetails(
37 | appId VARCHAR(255) PRIMARY KEY,
38 | resourceIds VARCHAR(255),
39 | appSecret VARCHAR(255),
40 | scope VARCHAR(255),
41 | grantTypes VARCHAR(255),
42 | redirectUrl VARCHAR(255),
43 | authorities VARCHAR(255),
44 | access_token_validity INTEGER,
45 | refresh_token_validity INTEGER,
46 | additionalInformation VARCHAR(4096),
47 | autoApproveScopes VARCHAR(255)
48 | );
49 |
50 | create index oauth_access_token_id on oauth_access_token(token_id);
51 | create index oauth_refresh_token_id on oauth_access_token(token_id);
52 |
53 |
54 |
55 | --START CLIENT CREDENTIAL TABLES--
56 |
57 | drop table if exists oauth_client_details;
58 | create table oauth_client_details(
59 | client_id VARCHAR(256) PRIMARY KEY,
60 | resource_ids VARCHAR(256),
61 | client_secret VARCHAR(256),
62 | scope VARCHAR(256),
63 | authorized_grant_types VARCHAR(256),
64 | web_server_redirect_uri VARCHAR(256),
65 | authorities VARCHAR(256),
66 | access_token_validity INTEGER,
67 | refresh_token_validity INTEGER,
68 | additional_information VARCHAR(4096),
69 | autoapprove VARCHAR(256)
70 | );
71 |
72 | drop table if exists oauth_client_token;
73 | create table oauth_client_token(
74 | token_id VARCHAR(255),
75 | token varbinary(4096),
76 | authentication_id VARCHAR(255),
77 | user_name VARCHAR(255),
78 | client_id VARCHAR(255)
79 | );
80 |
81 | drop table if exists user_role;
82 | CREATE TABLE user_role (
83 | user_id bigint(20) NOT NULL,
84 | role_id bigint(20) NOT NULL
85 | );
86 |
87 | -- ############################################################################################# --
88 |
89 | -- BASIC AUTH with token time declarationuser_role
90 | -- ACCESS TOKEN VALIDITY = 300 SECOND
91 | -- REFRESH TOKEN VALIDITY = 1800 SECOND
92 | -- insert client details [clientId = test & clientSecret = temp]
93 | INSERT INTO oauth_client_details
94 | (client_id, client_secret, scope, authorized_grant_types,
95 | authorities, access_token_validity, refresh_token_validity)
96 | VALUES ('test', '$2a$10$qgfrPSuoOvcoTYW1oka1r.XuQ67t9tt6erpZ4pa3/rx4Np0EF.fB6',
97 | 'read,write', 'password,refresh_token,client_credentials,authorization_code',
98 | 'ROLE_TRUSTED_CLIENT', 300, 1800);
99 |
100 |
101 | -- ##########################################################--
102 | -- USER ROLES
103 |
104 | INSERT INTO auth_role(id, role_name, description)
105 | VALUES (1, 'ROLE_ADMIN', 'Admin User - Has permission to perform admin tasks');
106 |
107 | INSERT INTO auth_role(id, role_name, description)
108 | VALUES (2, 'ROLE_USER', 'CONSULTANT - Has no admin rights');
109 |
--------------------------------------------------------------------------------