├── .gitignore
├── .travis.yml
├── README.md
├── auth-server
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── st
│ │ │ └── malike
│ │ │ └── auth
│ │ │ └── server
│ │ │ ├── AuthServerMain.java
│ │ │ ├── config
│ │ │ ├── ClientAuthenticationToken.java
│ │ │ ├── CustomMongoDBConvertor.java
│ │ │ └── UserAuthenticationToken.java
│ │ │ ├── exception
│ │ │ ├── AuthenticationException.java
│ │ │ ├── InvalidClientException.java
│ │ │ └── InvalidUserException.java
│ │ │ ├── model
│ │ │ ├── ClientDetail.java
│ │ │ ├── OAuth2AuthenticationAccessToken.java
│ │ │ ├── OAuth2AuthenticationRefreshToken.java
│ │ │ └── User.java
│ │ │ ├── repository
│ │ │ ├── ClientDetailRepository.java
│ │ │ ├── OAuth2AccessTokenRepository.java
│ │ │ ├── OAuth2RefreshTokenRepository.java
│ │ │ └── UserRepository.java
│ │ │ ├── service
│ │ │ ├── UserService.java
│ │ │ └── security
│ │ │ │ ├── ClientDetailService.java
│ │ │ │ ├── TokenStoreService.java
│ │ │ │ ├── UserAuthConfigService.java
│ │ │ │ └── UserAuthProviderService.java
│ │ │ └── util
│ │ │ └── CORSFilter.java
│ └── resources
│ │ ├── application.properties
│ │ └── spring-security-oauth2.xml
│ └── test
│ └── java
│ └── st
│ └── malike
│ └── auth
│ └── server
│ └── service
│ └── UserServiceTest.java
├── client
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── st
│ │ └── malike
│ │ └── auth
│ │ └── client
│ │ ├── AuthClientMain.java
│ │ ├── http
│ │ └── DemoController.java
│ │ └── security
│ │ ├── ResourceServerConfig.java
│ │ └── SecurityConfig.java
│ └── resources
│ └── application.properties
├── hello_no_token.png
├── hello_token.png
├── oauth_login.png
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | /client/target/
2 | /auth-server/target/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk:
3 | - oraclejdk8
4 | services:
5 | - mongodb
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/malike/sso-auth)
2 |
3 | # sso-auth
4 |
5 | From [Using Spring Security OAuth 2.0 and MongoDB For Single Sign Authentication Server](http://malike.github.io/Spring-Security-OAuth2/) I explained how I chose OAuth 2.0 and MongoDB to build a Single Sign On Auth server that can be used in a microservice architecture.
6 |
7 | *1.* First step. Run sso-auth-client application. And try accessing [http://localhost:8081/hello](http://localhost:8081/hello). Without
8 | passing any headers it returns this
9 |
10 | 
11 |
12 | *2.* Second step. Run sso-auth-server. Lets use the ***password*** **grant_type** to get an access token.
13 | [http://localhost:8080/oauth/token?grant_type=password&username=user@awesome.com&password=cant_hack_this&client_id=sso-auth-client&client_secret=mySecret](http://localhost:8080/oauth/token?grant_type=password&username=user@awesome.com&password=cant_hack_this&client_id=sso-auth-client&client_secret=mySecret)
14 |
15 | 
16 |
17 | *3.* Final step. Lets access [http://localhost:8081/hello](http://localhost:8081/hello) with our access token.
18 | And we are in.
19 |
20 | .
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/auth-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | st.malike
6 | sso-auth-server
7 | 1.0-SNAPSHOT
8 | jar
9 |
10 | sso-auth-server
11 | http://maven.apache.org
12 |
13 |
14 | st.malike
15 | sso-auth
16 | 1.0-SNAPSHOT
17 |
18 |
19 |
20 |
21 | st.malike.auth.server.AuthServerMain
22 | 8
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | org.mockito
32 | mockito-all
33 | test
34 |
35 |
36 |
37 | uk.co.jemos.podam
38 | podam
39 | test
40 |
41 |
42 |
43 | junit
44 | junit
45 | test
46 |
47 |
48 |
49 | org.springframework
50 | spring-test
51 | test
52 |
53 |
54 |
55 |
56 | org.springframework.boot
57 | spring-boot-starter-security
58 |
59 |
60 |
61 |
62 | org.springframework.security.oauth
63 | spring-security-oauth2
64 |
65 |
66 |
67 | org.springframework.boot
68 | spring-boot-starter-tomcat
69 |
70 |
71 |
72 | org.springframework.boot
73 | spring-boot-starter-data-mongodb
74 |
75 |
76 |
77 |
78 | org.springframework.boot
79 | spring-boot-starter-web
80 |
81 |
82 |
83 | com.google.code.gson
84 | gson
85 |
86 |
87 |
88 | commons-lang
89 | commons-lang
90 |
91 |
92 |
93 |
94 |
95 |
96 | org.springframework.boot
97 | spring-boot-maven-plugin
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/AuthServerMain.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 st.malike.auth.server;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import org.springframework.beans.factory.annotation.Autowire;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.boot.SpringApplication;
13 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
14 | import org.springframework.context.ApplicationContext;
15 | import org.springframework.context.annotation.Bean;
16 | import org.springframework.context.annotation.ComponentScan;
17 | import org.springframework.context.annotation.Configuration;
18 | import org.springframework.context.annotation.ImportResource;
19 | import org.springframework.core.convert.converter.Converter;
20 | import org.springframework.data.mongodb.MongoDbFactory;
21 | import org.springframework.data.mongodb.core.MongoTemplate;
22 | import org.springframework.data.mongodb.core.convert.CustomConversions;
23 | import org.springframework.data.mongodb.core.convert.DbRefResolver;
24 | import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
25 | import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
26 | import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
27 | import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
28 | import st.malike.auth.server.config.CustomMongoDBConvertor;
29 |
30 | /**
31 | *
32 | * @author malike_st
33 | */
34 | @Configuration
35 | @EnableAutoConfiguration
36 | @EnableMongoRepositories("st.malike.auth.server.repository")
37 | @ComponentScan
38 | @ImportResource({"classpath*:spring-security-oauth2.xml"})
39 | public class AuthServerMain {
40 |
41 | /**
42 | * @param args the command line arguments
43 | */
44 | public static void main(String[] args) {
45 | // TODO code application logic here
46 | ApplicationContext context = SpringApplication.run(AuthServerMain.class, args);
47 | }
48 |
49 | @Autowired
50 | private CustomMongoDBConvertor customMongoDBConvertor;
51 | @Autowired
52 | private MongoDbFactory mongoDbFactory;
53 |
54 | @Bean
55 | public CustomConversions customConversions() {
56 | List> converterList = new ArrayList<>();
57 | converterList.add(customMongoDBConvertor);
58 | return new CustomConversions(converterList);
59 | }
60 |
61 | @Bean
62 | public MappingMongoConverter mongoConverter() throws Exception {
63 | MongoMappingContext mappingContext = new MongoMappingContext();
64 | DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory);
65 | MappingMongoConverter mongoConverter = new MappingMongoConverter(dbRefResolver, mappingContext);
66 | mongoConverter.setCustomConversions(customConversions());
67 | return mongoConverter;
68 | }
69 |
70 | @Bean(autowire = Autowire.BY_NAME, name = "mongoTemplate")
71 | public MongoTemplate customMongoTemplate() {
72 | try {
73 | return new MongoTemplate(mongoDbFactory, mongoConverter()); // a mongotemplate with custom convertor
74 | } catch (Exception e) {
75 | }
76 | return null;
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/config/ClientAuthenticationToken.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 st.malike.auth.server.config;
7 |
8 | import java.util.Collection;
9 | import org.springframework.security.authentication.AbstractAuthenticationToken;
10 | import org.springframework.security.core.GrantedAuthority;
11 |
12 | /**
13 | *
14 | * @author malike_st
15 | */
16 | public class ClientAuthenticationToken extends AbstractAuthenticationToken {
17 |
18 | private final Object principal;
19 | private final Object credentials;
20 | private final boolean client;
21 |
22 | public ClientAuthenticationToken(Object principal, Object credentials, Collection extends GrantedAuthority> authorities) {
23 | super(authorities);
24 | this.principal = principal;
25 | this.credentials = credentials;
26 | this.client = true;
27 | super.setAuthenticated(true);
28 | }
29 |
30 | @Override
31 | public Object getCredentials() {
32 | return this.credentials;
33 | }
34 |
35 | @Override
36 | public Object getPrincipal() {
37 | return this.principal;
38 | }
39 |
40 | public boolean isClient() {
41 | return client;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/config/CustomMongoDBConvertor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this template, choose Tools | Templates
3 | * and open the template in the editor.
4 | */
5 | package st.malike.auth.server.config;
6 |
7 | import com.mongodb.DBObject;
8 | import java.util.ArrayList;
9 | import java.util.HashSet;
10 | import java.util.List;
11 | import java.util.Map;
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.context.annotation.Bean;
14 | import org.springframework.context.annotation.Configuration;
15 | import org.springframework.core.convert.converter.Converter;
16 | import org.springframework.data.mongodb.core.convert.CustomConversions;
17 | import org.springframework.security.core.Authentication;
18 | import org.springframework.security.oauth2.provider.ClientDetails;
19 | import org.springframework.security.oauth2.provider.OAuth2Authentication;
20 | import org.springframework.security.oauth2.provider.OAuth2Request;
21 | import st.malike.auth.server.model.User;
22 | import st.malike.auth.server.service.security.ClientDetailService;
23 | import st.malike.auth.server.service.security.UserAuthConfigService;
24 |
25 | /**
26 | *
27 | *
28 | * @author malike_st
29 | */
30 | @Configuration
31 | public class CustomMongoDBConvertor implements Converter {
32 |
33 | @Autowired
34 | private UserAuthConfigService authConfigService;
35 | @Autowired
36 | private ClientDetailService clientDetailService;
37 |
38 |
39 |
40 | @Override
41 | public OAuth2Authentication convert(DBObject source) {
42 | DBObject storedRequest = (DBObject) source.get("storedRequest");
43 | OAuth2Request oAuth2Request = new OAuth2Request((Map) storedRequest.get("requestParameters"),
44 | (String) storedRequest.get("clientId"), null, true, new HashSet((List) storedRequest.get("scope")),
45 | null, null, null, null);
46 | DBObject userAuthorization = (DBObject) source.get("userAuthentication");
47 | if (null != userAuthorization) { //its a user
48 | Object prinObj = userAuthorization.get("principal");
49 | User u = null;
50 | if ((null != prinObj) && prinObj instanceof String) {
51 | u = authConfigService.getUser((String) prinObj);
52 | } else if (null != prinObj) {
53 | DBObject principalDBO = (DBObject) prinObj;
54 | String email = (String) principalDBO.get("username");
55 | u = authConfigService.getUser(email);
56 | }
57 | if (null == u) {
58 | return null;
59 | }
60 |
61 | Authentication userAuthentication = new UserAuthenticationToken(u.getEmail(),
62 | (String) userAuthorization.get("credentials"), authConfigService.getRights(u));
63 | OAuth2Authentication authentication = new OAuth2Authentication(oAuth2Request, userAuthentication);
64 | return authentication;
65 | } else { //its a client
66 | String clientId = (String) storedRequest.get("clientId");
67 | ClientDetails client = null;
68 | if ((null != clientId) && clientId instanceof String) {
69 | client = clientDetailService.loadClientByClientId(clientId);
70 | }
71 | if (null == client) {
72 | return null;
73 | }
74 | Authentication userAuthentication = new ClientAuthenticationToken(client.getClientId(),
75 | null, client.getAuthorities());
76 | return new OAuth2Authentication(oAuth2Request, userAuthentication);
77 | }
78 | }
79 |
80 | @Bean
81 | public CustomConversions customConversions() {
82 | List> converterList = new ArrayList<>();
83 | converterList.add(this);
84 | return new CustomConversions(converterList);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/config/UserAuthenticationToken.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this template, choose Tools | Templates
3 | * and open the template in the editor.
4 | */
5 | package st.malike.auth.server.config;
6 |
7 | import java.util.Collection;
8 | import org.springframework.security.authentication.AbstractAuthenticationToken;
9 | import org.springframework.security.core.GrantedAuthority;
10 |
11 | /**
12 | *
13 | *
14 | * @author malike_st
15 | */
16 | public class UserAuthenticationToken extends AbstractAuthenticationToken {
17 |
18 | private final Object principal;
19 | private final Object credentials;
20 | private final boolean client;
21 |
22 | public UserAuthenticationToken(Object principal, Object credentials, Collection extends GrantedAuthority> authorities) {
23 | super(authorities);
24 | this.principal = principal;
25 | this.credentials = credentials;
26 | this.client = false;
27 | super.setAuthenticated(true);
28 | }
29 |
30 | @Override
31 | public Object getCredentials() {
32 | return this.credentials;
33 | }
34 |
35 | @Override
36 | public Object getPrincipal() {
37 | return this.principal;
38 | }
39 |
40 | public boolean isClient() {
41 | return client;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/exception/AuthenticationException.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 st.malike.auth.server.exception;
7 |
8 | /**
9 | *
10 | * @author malike_st
11 | */
12 | public class AuthenticationException extends Exception {
13 |
14 | public AuthenticationException() {
15 | }
16 |
17 | public AuthenticationException(String message) {
18 | super(message);
19 | }
20 |
21 | public AuthenticationException(String message, Throwable cause) {
22 | super(message, cause);
23 | }
24 |
25 | public AuthenticationException(Throwable cause) {
26 | super(cause);
27 | }
28 |
29 | public AuthenticationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
30 | super(message, cause, enableSuppression, writableStackTrace);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/exception/InvalidClientException.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 st.malike.auth.server.exception;
7 |
8 | /**
9 | *
10 | * @author malike_st
11 | */
12 | public class InvalidClientException extends Exception {
13 |
14 | public InvalidClientException() {
15 | }
16 |
17 | public InvalidClientException(String message) {
18 | super(message);
19 | }
20 |
21 | public InvalidClientException(String message, Throwable cause) {
22 | super(message, cause);
23 | }
24 |
25 | public InvalidClientException(Throwable cause) {
26 | super(cause);
27 | }
28 |
29 | public InvalidClientException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
30 | super(message, cause, enableSuppression, writableStackTrace);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/exception/InvalidUserException.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 st.malike.auth.server.exception;
7 |
8 | /**
9 | *
10 | * @author malike_st
11 | */
12 | public class InvalidUserException extends Exception {
13 |
14 | public InvalidUserException() {
15 | }
16 |
17 | public InvalidUserException(String message) {
18 | super(message);
19 | }
20 |
21 | public InvalidUserException(String message, Throwable cause) {
22 | super(message, cause);
23 | }
24 |
25 | public InvalidUserException(Throwable cause) {
26 | super(cause);
27 | }
28 |
29 | public InvalidUserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
30 | super(message, cause, enableSuppression, writableStackTrace);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/model/ClientDetail.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 st.malike.auth.server.model;
7 |
8 | import java.util.Collection;
9 | import java.util.Map;
10 | import java.util.Set;
11 | import org.springframework.data.annotation.Id;
12 | import org.springframework.data.mongodb.core.index.Indexed;
13 | import org.springframework.data.mongodb.core.mapping.Document;
14 |
15 | /**
16 | *
17 | * @author malike_st
18 | */
19 | @Document(collection = "oauth2_client")
20 | public class ClientDetail {
21 |
22 | @Id
23 | private String id;
24 | @Indexed
25 | private String clientId;
26 | private Set resourceIds;
27 | private boolean secretRequired;
28 | @Indexed
29 | private String clientSecret;
30 | private boolean scoped;
31 | private Set scope;
32 | private Set authorizedGrantTypes;
33 | private Set registeredRedirectUri;
34 | private Collection authorities;
35 | private Integer accessTokenValiditySeconds;
36 | private Integer refreshTokenValiditySeconds;
37 | private boolean autoApprove;
38 | private Map additionalInformation;
39 |
40 | public ClientDetail() {
41 | }
42 |
43 | public String getId() {
44 | return id;
45 | }
46 |
47 | public void setId(String id) {
48 | this.id = id;
49 | }
50 |
51 | public String getClientId() {
52 | return clientId;
53 | }
54 |
55 | public void setClientId(String clientId) {
56 | this.clientId = clientId;
57 | }
58 |
59 | public Set getResourceIds() {
60 | return resourceIds;
61 | }
62 |
63 | public void setResourceIds(Set resourceIds) {
64 | this.resourceIds = resourceIds;
65 | }
66 |
67 | public boolean isSecretRequired() {
68 | return secretRequired;
69 | }
70 |
71 | public Set getScope() {
72 | return scope;
73 | }
74 |
75 | public void setScope(Set scope) {
76 | this.scope = scope;
77 | }
78 |
79 | public void setSecretRequired(boolean secretRequired) {
80 | this.secretRequired = secretRequired;
81 | }
82 |
83 | public String getClientSecret() {
84 | return clientSecret;
85 | }
86 |
87 | public void setClientSecret(String clientSecret) {
88 | this.clientSecret = clientSecret;
89 | }
90 |
91 | public boolean isScoped() {
92 | return scoped;
93 | }
94 |
95 | public void setScoped(boolean scoped) {
96 | this.scoped = scoped;
97 | }
98 |
99 | public Set getAuthorizedGrantTypes() {
100 | return authorizedGrantTypes;
101 | }
102 |
103 | public void setAuthorizedGrantTypes(Set authorizedGrantTypes) {
104 | this.authorizedGrantTypes = authorizedGrantTypes;
105 | }
106 |
107 | public Set getRegisteredRedirectUri() {
108 | return registeredRedirectUri;
109 | }
110 |
111 | public void setRegisteredRedirectUri(Set registeredRedirectUri) {
112 | this.registeredRedirectUri = registeredRedirectUri;
113 | }
114 |
115 | public Collection getAuthorities() {
116 | return authorities;
117 | }
118 |
119 | public void setAuthorities(Collection authorities) {
120 | this.authorities = authorities;
121 | }
122 |
123 | public Integer getAccessTokenValiditySeconds() {
124 | return accessTokenValiditySeconds;
125 | }
126 |
127 | public void setAccessTokenValiditySeconds(Integer accessTokenValiditySeconds) {
128 | this.accessTokenValiditySeconds = accessTokenValiditySeconds;
129 | }
130 |
131 | public Integer getRefreshTokenValiditySeconds() {
132 | return refreshTokenValiditySeconds;
133 | }
134 |
135 | public void setRefreshTokenValiditySeconds(Integer refreshTokenValiditySeconds) {
136 | this.refreshTokenValiditySeconds = refreshTokenValiditySeconds;
137 | }
138 |
139 | public boolean isAutoApprove() {
140 | return autoApprove;
141 | }
142 |
143 | public void setAutoApprove(boolean autoApprove) {
144 | this.autoApprove = autoApprove;
145 | }
146 |
147 | public Map getAdditionalInformation() {
148 | return additionalInformation;
149 | }
150 |
151 | public void setAdditionalInformation(Map additionalInformation) {
152 | this.additionalInformation = additionalInformation;
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/model/OAuth2AuthenticationAccessToken.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this template, choose Tools | Templates
3 | * and open the template in the editor.
4 | */
5 | package st.malike.auth.server.model;
6 |
7 | import java.io.Serializable;
8 | import org.springframework.data.mongodb.core.index.Indexed;
9 | import org.springframework.data.mongodb.core.mapping.Document;
10 | import org.springframework.security.oauth2.common.OAuth2AccessToken;
11 | import org.springframework.security.oauth2.provider.OAuth2Authentication;
12 |
13 | /**
14 | *
15 | * @author malike_st
16 | */
17 | @Document(collection = "oauth2_access_token")
18 | public class OAuth2AuthenticationAccessToken implements Serializable {
19 |
20 | @Indexed
21 | private String id;
22 | private String tokenId;
23 | private OAuth2AccessToken oAuth2AccessToken;
24 | private String authenticationId;
25 | private String userName;
26 | private String clientId;
27 | private OAuth2Authentication authentication;
28 | private String refreshToken;
29 |
30 | public OAuth2AuthenticationAccessToken() {
31 | }
32 |
33 | public OAuth2AuthenticationAccessToken(final OAuth2AccessToken oAuth2AccessToken, final OAuth2Authentication authentication, final String authenticationId) {
34 | this.tokenId = oAuth2AccessToken.getValue();
35 | this.oAuth2AccessToken = oAuth2AccessToken;
36 | this.authenticationId = authenticationId;
37 | this.userName = authentication.getName();
38 | this.clientId = authentication.getOAuth2Request().getClientId();
39 | this.authentication = authentication;
40 | this.refreshToken = oAuth2AccessToken.getRefreshToken().getValue();
41 | }
42 |
43 | public String getId() {
44 | return id;
45 | }
46 |
47 | public void setId(String id) {
48 | this.id = id;
49 | }
50 |
51 | public String getTokenId() {
52 | return tokenId;
53 | }
54 |
55 | public OAuth2AccessToken getoAuth2AccessToken() {
56 | return oAuth2AccessToken;
57 | }
58 |
59 | public String getAuthenticationId() {
60 | return authenticationId;
61 | }
62 |
63 | public String getUserName() {
64 | return userName;
65 | }
66 |
67 | public String getClientId() {
68 | return clientId;
69 | }
70 |
71 | public OAuth2Authentication getAuthentication() {
72 | return authentication;
73 | }
74 |
75 | public String getRefreshToken() {
76 | return refreshToken;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/model/OAuth2AuthenticationRefreshToken.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this template, choose Tools | Templates
3 | * and open the template in the editor.
4 | */
5 | package st.malike.auth.server.model;
6 |
7 | import java.io.Serializable;
8 | import org.springframework.data.mongodb.core.index.Indexed;
9 | import org.springframework.data.mongodb.core.mapping.Document;
10 | import org.springframework.security.oauth2.common.OAuth2RefreshToken;
11 | import org.springframework.security.oauth2.provider.OAuth2Authentication;
12 |
13 | /**
14 | *
15 | * @author malike_st
16 | */
17 | @Document(collection = "oauth2_refresh_token")
18 | public class OAuth2AuthenticationRefreshToken implements Serializable {
19 |
20 | @Indexed
21 | private String id;
22 | private final String tokenId;
23 | private final OAuth2RefreshToken oAuth2RefreshToken;
24 | private final OAuth2Authentication authentication;
25 |
26 | public OAuth2AuthenticationRefreshToken(OAuth2RefreshToken oAuth2RefreshToken, OAuth2Authentication authentication) {
27 | this.oAuth2RefreshToken = oAuth2RefreshToken;
28 | this.authentication = authentication;
29 | this.tokenId = oAuth2RefreshToken.getValue();
30 | }
31 |
32 | public String getId() {
33 | return id;
34 | }
35 |
36 | public void setId(String id) {
37 | this.id = id;
38 | }
39 |
40 | public String getTokenId() {
41 | return tokenId;
42 | }
43 |
44 | public OAuth2RefreshToken getoAuth2RefreshToken() {
45 | return oAuth2RefreshToken;
46 | }
47 |
48 | public OAuth2Authentication getAuthentication() {
49 | return authentication;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/model/User.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 st.malike.auth.server.model;
7 |
8 | import java.util.Date;
9 | import java.util.List;
10 | import org.springframework.data.annotation.CreatedDate;
11 | import org.springframework.data.annotation.Id;
12 | import org.springframework.data.mongodb.core.mapping.Document;
13 |
14 | /**
15 | *
16 | * @author malike_st
17 | */
18 | @Document(collection = "oauth2_user")
19 | public class User {
20 |
21 | @Id
22 | private String id;
23 | private String email;
24 | private String password;
25 | private List rights;
26 | @CreatedDate
27 | private Date dateCreated;
28 |
29 | public User() {
30 | }
31 |
32 | public String getId() {
33 | return id;
34 | }
35 |
36 | public void setId(String id) {
37 | this.id = id;
38 | }
39 |
40 | public String getEmail() {
41 | return email;
42 | }
43 |
44 | public void setEmail(String email) {
45 | this.email = email;
46 | }
47 |
48 | public String getPassword() {
49 | return password;
50 | }
51 |
52 | public void setPassword(String password) {
53 | this.password = password;
54 | }
55 |
56 | public Date getDateCreated() {
57 | return dateCreated;
58 | }
59 |
60 | public void setDateCreated(Date dateCreated) {
61 | this.dateCreated = dateCreated;
62 | }
63 |
64 | public List getRights() {
65 | return rights;
66 | }
67 |
68 | public void setRights(List rights) {
69 | this.rights = rights;
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/repository/ClientDetailRepository.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 st.malike.auth.server.repository;
7 |
8 | import java.io.Serializable;
9 | import org.springframework.data.mongodb.repository.MongoRepository;
10 | import st.malike.auth.server.model.ClientDetail;
11 |
12 | /**
13 | *
14 | * @author malike_st
15 | */
16 | public interface ClientDetailRepository extends MongoRepository {
17 |
18 | public ClientDetail findByClientId(String clientId);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/repository/OAuth2AccessTokenRepository.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this template, choose Tools | Templates
3 | * and open the template in the editor.
4 | */
5 |
6 | package st.malike.auth.server.repository;
7 |
8 | import java.io.Serializable;
9 | import org.springframework.data.mongodb.repository.MongoRepository;
10 | import st.malike.auth.server.model.OAuth2AuthenticationAccessToken;
11 |
12 | /**
13 | *
14 | * @author malike_st
15 | */
16 | public interface OAuth2AccessTokenRepository extends MongoRepository {
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/repository/OAuth2RefreshTokenRepository.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this template, choose Tools | Templates
3 | * and open the template in the editor.
4 | */
5 | package st.malike.auth.server.repository;
6 |
7 | import org.springframework.data.mongodb.repository.MongoRepository;
8 | import st.malike.auth.server.model.OAuth2AuthenticationRefreshToken;
9 |
10 | /**
11 | *
12 | * @author malike_st
13 | */
14 |
15 | public interface OAuth2RefreshTokenRepository extends MongoRepository {
16 |
17 |
18 | }
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/repository/UserRepository.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 st.malike.auth.server.repository;
7 |
8 | import java.io.Serializable;
9 | import org.springframework.data.mongodb.repository.MongoRepository;
10 | import st.malike.auth.server.model.User;
11 |
12 | /**
13 | *
14 | * @author malike_st
15 | */
16 | public interface UserRepository extends MongoRepository {
17 |
18 | public User findByEmail(String email);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/service/UserService.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 st.malike.auth.server.service;
7 |
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.stereotype.Service;
10 | import st.malike.auth.server.model.User;
11 | import st.malike.auth.server.repository.UserRepository;
12 |
13 | /**
14 | *
15 | * @author malike_st
16 | */
17 | @Service
18 | public class UserService {
19 |
20 | @Autowired
21 | private UserRepository userRepository;
22 |
23 | public User getUserById(String id) {
24 | return userRepository.findOne(id);
25 | }
26 |
27 | public User save(User user) {
28 | return userRepository.save(user);
29 | }
30 |
31 | public User findByEmail(String email) {
32 | return userRepository.findByEmail(email);
33 | }
34 |
35 | public void deleteAll() {
36 | userRepository.deleteAll();
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/service/security/ClientDetailService.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 st.malike.auth.server.service.security;
7 |
8 | import java.util.LinkedList;
9 | import java.util.List;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.security.crypto.password.PasswordEncoder;
12 | import org.springframework.security.oauth2.provider.ClientAlreadyExistsException;
13 | import org.springframework.security.oauth2.provider.ClientDetails;
14 | import org.springframework.security.oauth2.provider.ClientDetailsService;
15 | import org.springframework.security.oauth2.provider.ClientRegistrationException;
16 | import org.springframework.security.oauth2.provider.ClientRegistrationService;
17 | import org.springframework.security.oauth2.provider.NoSuchClientException;
18 | import org.springframework.security.oauth2.provider.client.BaseClientDetails;
19 | import org.springframework.stereotype.Service;
20 | import st.malike.auth.server.model.ClientDetail;
21 | import st.malike.auth.server.repository.ClientDetailRepository;
22 |
23 | /**
24 | *
25 | * @author malike_st
26 | */
27 | @Service
28 | public class ClientDetailService implements ClientDetailsService, ClientRegistrationService {
29 |
30 | @Autowired
31 | private PasswordEncoder passwordEncoder;
32 | @Autowired
33 | private ClientDetailRepository clientDetailsRepository;
34 |
35 | @Override
36 | public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
37 | ClientDetail clientDetails = clientDetailsRepository.findByClientId(clientId);
38 | if (null == clientDetails) {
39 | throw new ClientRegistrationException("Client not found with id '" + clientId + "'");
40 | }
41 | return getClientFromMongoDBClientDetails(clientDetails);
42 | }
43 |
44 | @Override
45 | public void addClientDetails(ClientDetails cd) throws ClientAlreadyExistsException {
46 | ClientDetail clientDetails = getMongoDBClientDetailsFromClient(cd);
47 | clientDetailsRepository.save(clientDetails);
48 | }
49 |
50 | @Override
51 | public void updateClientDetails(ClientDetails cd) throws NoSuchClientException {
52 | ClientDetail clientDetails = clientDetailsRepository.findByClientId(cd.getClientId());
53 | if (null == clientDetails) {
54 | throw new NoSuchClientException("Client not found with ID '" + cd.getClientId() + "'");
55 | }
56 | clientDetails = getMongoDBClientDetailsFromClient(cd);
57 | clientDetailsRepository.save(clientDetails);
58 | }
59 |
60 | @Override
61 | public void updateClientSecret(String clientId, String secret) throws NoSuchClientException {
62 | ClientDetail clientDetails = clientDetailsRepository.findByClientId(clientId);
63 | if (null == clientDetails) {
64 | throw new NoSuchClientException("Client not found with ID '" + clientId + "'");
65 | }
66 | clientDetails.setClientSecret(passwordEncoder.encode(secret));
67 | clientDetailsRepository.save(clientDetails);
68 | }
69 |
70 | @Override
71 | public void removeClientDetails(String clientId) throws NoSuchClientException {
72 | ClientDetail clientDetails = clientDetailsRepository.findByClientId(clientId);
73 | if (null == clientDetails) {
74 | throw new NoSuchClientException("Client not found with ID '" + clientId + "'");
75 | }
76 | clientDetailsRepository.delete(clientDetails);
77 | }
78 |
79 | @Override
80 | public List listClientDetails() {
81 | List mdbcds = clientDetailsRepository.findAll();
82 | return getClientsFromMongoDBClientDetails(mdbcds);
83 | }
84 |
85 | private List getClientsFromMongoDBClientDetails(List clientDetails) {
86 | List bcds = new LinkedList<>();
87 | if (clientDetails != null && !clientDetails.isEmpty()) {
88 | clientDetails.stream().forEach(mdbcd -> {
89 | bcds.add(getClientFromMongoDBClientDetails(mdbcd));
90 | });
91 | }
92 | return bcds;
93 | }
94 |
95 | private BaseClientDetails getClientFromMongoDBClientDetails(ClientDetail clientDetails) {
96 | BaseClientDetails bc = new BaseClientDetails();
97 | bc.setAccessTokenValiditySeconds(clientDetails.getAccessTokenValiditySeconds());
98 | bc.setAuthorizedGrantTypes(clientDetails.getAuthorizedGrantTypes());
99 | bc.setClientId(clientDetails.getClientId());
100 | bc.setClientSecret(clientDetails.getClientSecret());
101 | bc.setRefreshTokenValiditySeconds(clientDetails.getRefreshTokenValiditySeconds());
102 | bc.setRegisteredRedirectUri(clientDetails.getRegisteredRedirectUri());
103 | bc.setResourceIds(clientDetails.getResourceIds());
104 | bc.setScope(clientDetails.getScope());
105 | return bc;
106 | }
107 |
108 | private ClientDetail getMongoDBClientDetailsFromClient(ClientDetails cd) {
109 | ClientDetail clientDetails = new ClientDetail();
110 | clientDetails.setAccessTokenValiditySeconds(cd.getAccessTokenValiditySeconds());
111 | clientDetails.setAdditionalInformation(cd.getAdditionalInformation());
112 | clientDetails.setAuthorizedGrantTypes(cd.getAuthorizedGrantTypes());
113 | clientDetails.setClientId(cd.getClientId());
114 | clientDetails.setClientSecret(cd.getClientSecret());
115 | clientDetails.setRefreshTokenValiditySeconds(cd.getRefreshTokenValiditySeconds());
116 | clientDetails.setRegisteredRedirectUri(cd.getRegisteredRedirectUri());
117 | clientDetails.setResourceIds(cd.getResourceIds());
118 | clientDetails.setScope(cd.getScope());
119 | clientDetails.setScoped(cd.isScoped());
120 | clientDetails.setSecretRequired(cd.isSecretRequired());
121 | clientDetails.setId(cd.getClientId());
122 | return clientDetails;
123 | }
124 |
125 | public ClientDetail save(ClientDetail authClient) {
126 | return clientDetailsRepository.save(authClient);
127 | }
128 |
129 | public void deleteAll() {
130 | clientDetailsRepository.deleteAll();
131 | }
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/service/security/TokenStoreService.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 st.malike.auth.server.service.security;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Collection;
10 | import java.util.List;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.data.mongodb.core.MongoTemplate;
13 | import org.springframework.data.mongodb.core.query.Criteria;
14 | import org.springframework.data.mongodb.core.query.Query;
15 | import org.springframework.security.oauth2.common.OAuth2AccessToken;
16 | import org.springframework.security.oauth2.common.OAuth2RefreshToken;
17 | import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
18 | import org.springframework.security.oauth2.provider.OAuth2Authentication;
19 | import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;
20 | import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;
21 | import org.springframework.security.oauth2.provider.token.TokenStore;
22 | import st.malike.auth.server.model.OAuth2AuthenticationAccessToken;
23 | import st.malike.auth.server.model.OAuth2AuthenticationRefreshToken;
24 | import st.malike.auth.server.repository.OAuth2AccessTokenRepository;
25 | import st.malike.auth.server.repository.OAuth2RefreshTokenRepository;
26 |
27 | /**
28 | *
29 | * @author malike_st
30 | */
31 | public class TokenStoreService implements TokenStore {
32 |
33 | @Autowired
34 | private OAuth2AccessTokenRepository oAuth2AccessTokenRepository;
35 | @Autowired
36 | private OAuth2RefreshTokenRepository oAuth2RefreshTokenRepository;
37 | @Autowired
38 | private MongoTemplate mongoTemplate;
39 | private final AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();
40 |
41 | @Override
42 | public OAuth2Authentication readAuthentication(OAuth2AccessToken token) {
43 | return readAuthentication(token.getValue());
44 | }
45 |
46 | @Override
47 | public OAuth2Authentication readAuthentication(String tokenId) {
48 | Query query = new Query();
49 | query.addCriteria(Criteria.where("tokenId").is(tokenId));
50 | OAuth2AuthenticationAccessToken token = mongoTemplate.findOne(query, OAuth2AuthenticationAccessToken.class, "oauth2_access_token");
51 | return null == token ? null : token.getAuthentication();
52 | }
53 |
54 | @Override
55 | public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
56 | OAuth2AuthenticationAccessToken oAuth2AuthenticationAccessToken = new OAuth2AuthenticationAccessToken(token,
57 | authentication, authenticationKeyGenerator.extractKey(authentication));
58 | mongoTemplate.save(oAuth2AuthenticationAccessToken);
59 | }
60 |
61 | @Override
62 | public OAuth2AccessToken readAccessToken(String tokenId) {
63 | Query query = new Query();
64 | query.addCriteria(Criteria.where("tokenId").is(tokenId));
65 | OAuth2AuthenticationAccessToken token = mongoTemplate.findOne(query, OAuth2AuthenticationAccessToken.class, "oauth2_access_token");
66 | if (null == token) {
67 | throw new InvalidTokenException("Token not valid");
68 | }
69 | return token.getoAuth2AccessToken();
70 | }
71 |
72 | @Override
73 | public void removeAccessToken(OAuth2AccessToken accessToken) {
74 | Query query = new Query();
75 | query.addCriteria(Criteria.where("tokenId").is(accessToken.getValue()));
76 | OAuth2AuthenticationAccessToken token = mongoTemplate.findOne(query, OAuth2AuthenticationAccessToken.class, "oauth2_access_token");
77 | if (token != null) {
78 | oAuth2AccessTokenRepository.delete(token);
79 | }
80 | }
81 |
82 | @Override
83 | public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {
84 | oAuth2RefreshTokenRepository.save(new OAuth2AuthenticationRefreshToken(refreshToken, authentication));
85 | }
86 |
87 | @Override
88 | public OAuth2RefreshToken readRefreshToken(String accessToken) {
89 | Query query = new Query();
90 | query.addCriteria(Criteria.where("tokenId").is(accessToken));
91 | OAuth2AuthenticationRefreshToken token = mongoTemplate.findOne(query, OAuth2AuthenticationRefreshToken.class, "oauth2_refresh_token");
92 | return token.getoAuth2RefreshToken();
93 | }
94 |
95 | @Override
96 | public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {
97 | Query query = new Query();
98 | query.addCriteria(Criteria.where("tokenId").is(token.getValue()));
99 | OAuth2AuthenticationRefreshToken auth2AuthenticationRefreshToken = mongoTemplate.findOne(query, OAuth2AuthenticationRefreshToken.class, "oauth2_refresh_token");
100 | return auth2AuthenticationRefreshToken.getAuthentication();
101 | }
102 |
103 | @Override
104 | public void removeRefreshToken(OAuth2RefreshToken accessToken) {
105 | Query query = new Query();
106 | query.addCriteria(Criteria.where("tokenId").is(accessToken.getValue()));
107 | OAuth2AuthenticationRefreshToken token = mongoTemplate.findOne(query, OAuth2AuthenticationRefreshToken.class, "oauth2_refresh_token");
108 | if (token != null) {
109 | oAuth2RefreshTokenRepository.delete(token);
110 | }
111 | }
112 |
113 | @Override
114 | public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {
115 | Query query = new Query();
116 | query.addCriteria(Criteria.where("refreshToken").is(refreshToken.getValue()));
117 | OAuth2AuthenticationAccessToken token = mongoTemplate.findOne(query, OAuth2AuthenticationAccessToken.class, "oauth2_access_token");
118 | if (token != null) {
119 | oAuth2AccessTokenRepository.delete(token);
120 | }
121 | }
122 |
123 | @Override
124 | public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
125 | String authenticationId = authenticationKeyGenerator.extractKey(authentication);
126 | if (null == authenticationId) {
127 | return null;
128 | }
129 | Query query = new Query();
130 | query.addCriteria(Criteria.where("authenticationId").is(authenticationId));
131 | OAuth2AuthenticationAccessToken token = mongoTemplate.findOne(query, OAuth2AuthenticationAccessToken.class, "oauth2_access_token");
132 | return token == null ? null : token.getoAuth2AccessToken();
133 | }
134 |
135 | @Override
136 | public Collection findTokensByClientId(String clientId) {
137 | Query query = new Query();
138 | query.addCriteria(Criteria.where("clientId").is(clientId));
139 | List accessTokens = mongoTemplate.find(query, OAuth2AuthenticationAccessToken.class, "oauth2_access_token");
140 | return extractAccessTokens(accessTokens);
141 | }
142 |
143 | @Override
144 | public Collection findTokensByClientIdAndUserName(String clientId, String userName) {
145 | Query query = new Query();
146 | query.addCriteria(Criteria.where("clientId").is(clientId));
147 | query.addCriteria(Criteria.where("userName").is(userName));
148 | List accessTokens = mongoTemplate.find(query, OAuth2AuthenticationAccessToken.class, "oauth2_access_token");
149 | return extractAccessTokens(accessTokens);
150 | }
151 |
152 | private Collection extractAccessTokens(List tokens) {
153 | List accessTokens = new ArrayList<>();
154 | tokens.stream().forEach(token -> {
155 | accessTokens.add(token.getoAuth2AccessToken());
156 | });
157 | return accessTokens;
158 | }
159 |
160 | }
161 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/service/security/UserAuthConfigService.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 st.malike.auth.server.service.security;
7 |
8 | import java.util.LinkedList;
9 | import java.util.List;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.security.core.GrantedAuthority;
12 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
13 | import org.springframework.stereotype.Service;
14 | import st.malike.auth.server.model.User;
15 | import st.malike.auth.server.service.UserService;
16 |
17 | /**
18 | *
19 | * @author malike_st
20 | */
21 | @Service
22 | public class UserAuthConfigService {
23 |
24 | @Autowired
25 | private UserService userService;
26 |
27 | public User getUser(String email) {
28 | return userService.findByEmail(email);
29 | }
30 |
31 | public List getRights(User user) {
32 | List grantedAuthority = new LinkedList<>();
33 | List right = user.getRights();
34 | if (null != right && !right.isEmpty()) {
35 | right.stream().forEach(r -> {
36 | grantedAuthority.add(new SimpleGrantedAuthority(r));
37 | });
38 | }
39 | return grantedAuthority;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/service/security/UserAuthProviderService.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 st.malike.auth.server.service.security;
7 |
8 | import java.util.List;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.security.authentication.AuthenticationProvider;
11 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
12 | import org.springframework.security.core.Authentication;
13 | import org.springframework.security.core.AuthenticationException;
14 | import org.springframework.security.core.GrantedAuthority;
15 | import org.springframework.security.core.context.SecurityContextHolder;
16 | import org.springframework.security.core.userdetails.UserDetails;
17 | import org.springframework.security.crypto.password.PasswordEncoder;
18 | import org.springframework.stereotype.Component;
19 | import st.malike.auth.server.model.User;
20 |
21 | /**
22 | *
23 | * @author malike_st
24 | */
25 | @Component
26 | public class UserAuthProviderService implements AuthenticationProvider {
27 |
28 | @Autowired
29 | private UserAuthConfigService authConfigService;
30 | @Autowired
31 | private PasswordEncoder passwordEncoder;
32 |
33 |
34 | private Authentication signInUser(User user, List roles) {
35 | UserDetails springSecurityUser = new org.springframework.security.core.userdetails.User(user.getEmail(), user.getId(), roles);
36 | Authentication authentication = new UsernamePasswordAuthenticationToken(springSecurityUser, user.getId(), roles);
37 | SecurityContextHolder.getContext().setAuthentication(authentication);
38 | return authentication;
39 | }
40 |
41 | @Override
42 | public Authentication authenticate(Authentication a) throws AuthenticationException {
43 | String email = a.getName();
44 | String password = a.getCredentials().toString();
45 | User user = authConfigService.getUser(email);
46 | if (null != user) {
47 | if (passwordEncoder.matches(password, user.getPassword())) {
48 | List roleAuthority = authConfigService.getRights(user);
49 | return signInUser(user, roleAuthority);
50 | }
51 | throw new AuthenticationException("Password for '" + email + "' not correct.") {
52 | };
53 | }
54 |
55 | throw new AuthenticationException("Could not find user with name '" + email + "'") {
56 | };
57 | }
58 |
59 | @Override
60 | public boolean supports(Class> type) {
61 | return type.equals(UsernamePasswordAuthenticationToken.class);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/auth-server/src/main/java/st/malike/auth/server/util/CORSFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this template, choose Tools | Templates
3 | * and open the template in the editor.
4 | */
5 | package st.malike.auth.server.util;
6 |
7 | import org.springframework.stereotype.Component;
8 |
9 | import javax.servlet.*;
10 | import javax.servlet.http.HttpServletResponse;
11 | import java.io.IOException;
12 |
13 | /**
14 | *
15 | * @author malike_st
16 | */
17 | @Component
18 | public class CORSFilter implements Filter {
19 |
20 | @Override
21 | public void init(FilterConfig filterConfig) {
22 | }
23 |
24 | @Override
25 | public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
26 | HttpServletResponse response = (HttpServletResponse) res;
27 | response.setHeader("Access-Control-Allow-Origin", "*");
28 | response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
29 | response.setHeader("Access-Control-Max-Age", "3600");
30 | response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
31 | chain.doFilter(req, res);
32 | }
33 |
34 | @Override
35 | public void destroy() {
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/auth-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 | server.port=8080
3 |
4 |
5 | security.basic.enabled=false
6 |
7 |
8 | #Client
9 | app.client.id=sso-auth-client
10 | app.client.secret=mySecret
11 |
12 |
13 | #MONGODB
14 | spring.data.mongodb.host=localhost
15 | spring.data.mongodb.port=27017
16 | spring.data.mongodb.database=sso-auth-server
17 |
--------------------------------------------------------------------------------
/auth-server/src/main/resources/spring-security-oauth2.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/auth-server/src/test/java/st/malike/auth/server/service/UserServiceTest.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 st.malike.auth.server.service;
7 |
8 | import java.util.Arrays;
9 | import java.util.HashSet;
10 | import org.apache.commons.lang.RandomStringUtils;
11 | import static org.junit.Assert.assertNotEquals;
12 | import org.junit.Before;
13 | import org.junit.Test;
14 | import org.junit.runner.RunWith;
15 | import org.springframework.beans.factory.annotation.Autowired;
16 | import org.springframework.beans.factory.annotation.Value;
17 | import org.springframework.boot.test.IntegrationTest;
18 | import org.springframework.boot.test.SpringApplicationConfiguration;
19 | import org.springframework.security.crypto.password.PasswordEncoder;
20 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
21 | import org.springframework.test.context.web.WebAppConfiguration;
22 | import st.malike.auth.server.AuthServerMain;
23 | import st.malike.auth.server.model.ClientDetail;
24 | import st.malike.auth.server.model.User;
25 | import st.malike.auth.server.service.security.ClientDetailService;
26 | import uk.co.jemos.podam.api.PodamFactory;
27 | import uk.co.jemos.podam.api.PodamFactoryImpl;
28 |
29 | /**
30 | *
31 | * @author malike_st
32 | */
33 | @RunWith(SpringJUnit4ClassRunner.class)
34 | @SpringApplicationConfiguration(classes = AuthServerMain.class)
35 | @WebAppConfiguration
36 | @IntegrationTest
37 | public class UserServiceTest {
38 |
39 | @Autowired
40 | private UserService userService;
41 | @Autowired
42 | private ClientDetailService clientDetailService;
43 | @Autowired
44 | private PasswordEncoder passwordEncoder;
45 | User awesomeUser;
46 | ClientDetail authClient;
47 | @Value("${app.client.id}")
48 | private String authClientId;
49 | @Value("${app.client.secret}")
50 | private String authClientSecret;
51 |
52 | static PodamFactory podamFactory;
53 |
54 | @Before
55 | public void setUp() {
56 |
57 | podamFactory = new PodamFactoryImpl();
58 | userService.deleteAll();
59 | clientDetailService.deleteAll();
60 |
61 | // awesomeUser = podamFactory.manufacturePojo(User.class);
62 | awesomeUser = new User();
63 |
64 | awesomeUser.setEmail("user@awesome.com");
65 | awesomeUser.setPassword(passwordEncoder.encode("cant_hack_this"));
66 | awesomeUser.setId("thisis-awesome-1");
67 | userService.save(awesomeUser);
68 |
69 | authClient = new ClientDetail();
70 | authClient.setId(RandomStringUtils.randomAlphanumeric(10));
71 | authClient.setClientId(authClientId);
72 | authClient.setResourceIds(new HashSet<>(Arrays.asList("rest_api")));
73 | authClient.setClientSecret(passwordEncoder.encode(authClientSecret));
74 | authClient.setRefreshTokenValiditySeconds(4500);
75 | authClient.setAccessTokenValiditySeconds(4500);
76 | authClient.setAuthorities(new HashSet<>(Arrays.asList("trust", "read", "write")));
77 | authClient.setAuthorizedGrantTypes(new HashSet<>(Arrays.asList("client_credentials", "authorization_code", "implicit", "password", "refresh_token")));
78 | authClient.setScope(new HashSet<>(Arrays.asList("trust", "read", "write")));
79 | authClient.setSecretRequired(true);
80 |
81 | clientDetailService.save(authClient);
82 |
83 | }
84 |
85 | @Test
86 | public void checkingAWESOME() {
87 | assertNotEquals("awesome", "AWESOME");
88 | }
89 |
90 | ///other chats here
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | st.malike
6 | sso-auth-client
7 | 1.0-SNAPSHOT
8 | jar
9 |
10 | sso-auth-client
11 | http://maven.apache.org
12 |
13 |
14 | st.malike
15 | sso-auth
16 | 1.0-SNAPSHOT
17 |
18 |
19 |
20 |
21 | st.malike.auth.client.AuthClientMain
22 | 8
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | org.mockito
31 | mockito-all
32 | test
33 |
34 |
35 |
36 | uk.co.jemos.podam
37 | podam
38 | test
39 | jar
40 |
41 |
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-starter-security
46 |
47 |
48 |
49 |
50 | org.springframework.security.oauth
51 | spring-security-oauth2
52 |
53 |
54 |
55 | org.springframework.boot
56 | spring-boot-starter-tomcat
57 |
58 |
59 |
60 | org.springframework.boot
61 | spring-boot-starter-data-mongodb
62 |
63 |
64 |
65 |
66 | org.springframework.boot
67 | spring-boot-starter-web
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | org.springframework.boot
76 | spring-boot-maven-plugin
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/client/src/main/java/st/malike/auth/client/AuthClientMain.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 st.malike.auth.client;
7 |
8 | import org.springframework.boot.SpringApplication;
9 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
10 | import org.springframework.context.ApplicationContext;
11 | import org.springframework.context.annotation.ComponentScan;
12 | import org.springframework.context.annotation.Configuration;
13 |
14 | /**
15 | *
16 | * @author malike_st
17 | */
18 | @Configuration
19 | @EnableAutoConfiguration
20 | @ComponentScan
21 | public class AuthClientMain {
22 |
23 | /**
24 | * @param args the command line arguments
25 | */
26 | public static void main(String[] args) {
27 | // TODO code application logic here
28 | ApplicationContext context = SpringApplication.run(AuthClientMain.class, args);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/client/src/main/java/st/malike/auth/client/http/DemoController.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 st.malike.auth.client.http;
7 |
8 | import org.springframework.stereotype.Controller;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.ResponseBody;
11 |
12 | /**
13 | *
14 | * @author malike_st
15 | */
16 | @Controller
17 | public class DemoController {
18 |
19 | @RequestMapping("/hello")
20 | @ResponseBody
21 | public String helloWorld() {
22 | return "Hello World.";
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/client/src/main/java/st/malike/auth/client/security/ResourceServerConfig.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 |
7 | package st.malike.auth.client.security;
8 |
9 | import org.springframework.context.annotation.Configuration;
10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
11 | import org.springframework.security.config.http.SessionCreationPolicy;
12 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
13 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
14 |
15 | /**
16 | *
17 | * @author malike_st
18 | */
19 | @Configuration
20 | @EnableResourceServer
21 | public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
22 |
23 |
24 | @Override
25 | public void configure(HttpSecurity http) throws Exception {
26 | http
27 | .authorizeRequests()
28 | .antMatchers("/**").authenticated()
29 | .and()
30 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/client/src/main/java/st/malike/auth/client/security/SecurityConfig.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 |
7 | package st.malike.auth.client.security;
8 |
9 | import org.springframework.beans.factory.annotation.Value;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.context.annotation.Configuration;
12 | import org.springframework.security.authentication.AuthenticationManager;
13 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
14 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
15 | import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager;
16 | import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
17 | import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
18 |
19 | /**
20 | *
21 | * @author malike_st
22 | */
23 | @Configuration
24 | @EnableResourceServer
25 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
26 |
27 | @Value("${app.client.id}")
28 | private String appId;
29 | @Value("${app.client.secret}")
30 | private String appSecret;
31 | @Value("${auth.server.host}")
32 | private String authServerHost;
33 | @Value("${auth.server.port}")
34 | private int authServerPort;
35 |
36 | @Bean
37 | public ResourceServerTokenServices tokenService() {
38 | RemoteTokenServices tokenServices = new RemoteTokenServices();
39 | tokenServices.setClientId(appId);
40 | tokenServices.setClientSecret(appSecret);
41 | tokenServices.setCheckTokenEndpointUrl("http://" + authServerHost + ":" + authServerPort + "/oauth/check_token");
42 | return tokenServices;
43 | }
44 |
45 | @Override
46 | @Bean
47 | public AuthenticationManager authenticationManagerBean() throws Exception {
48 | OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
49 | authenticationManager.setTokenServices(tokenService());
50 | return authenticationManager;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 | server.port=8081
3 |
4 | app.client.id=sso-auth-client
5 | app.client.secret=mySecret
6 |
7 | auth.server.host=localhost
8 | auth.server.port=8080
9 |
10 |
--------------------------------------------------------------------------------
/hello_no_token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malike/sso-auth/21a48d2746006ab148357be6dead51cc0cc06a78/hello_no_token.png
--------------------------------------------------------------------------------
/hello_token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malike/sso-auth/21a48d2746006ab148357be6dead51cc0cc06a78/hello_token.png
--------------------------------------------------------------------------------
/oauth_login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malike/sso-auth/21a48d2746006ab148357be6dead51cc0cc06a78/oauth_login.png
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | st.malike
6 | sso-auth
7 | 1.0-SNAPSHOT
8 | pom
9 |
10 | sso-auth
11 | http://maven.apache.org
12 |
13 | client
14 | auth-server
15 |
16 |
17 |
18 |
19 | maven
20 | mvn
21 | http://central.maven.org/maven2/
22 |
23 |
24 |
25 |
26 |
27 |
28 | maven
29 | http://central.maven.org/maven2/
30 |
31 |
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-parent
36 | 1.2.4.RELEASE
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | org.mockito
46 | mockito-all
47 | 1.9.5
48 |
49 |
50 |
51 | uk.co.jemos.podam
52 | podam
53 | 3.6.0.RELEASE
54 | jar
55 |
56 |
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-starter-security
61 | 1.2.4.RELEASE
62 |
63 |
64 |
65 |
66 | org.springframework.security.oauth
67 | spring-security-oauth2
68 | 2.0.7.RELEASE
69 |
70 |
71 |
72 | org.springframework.boot
73 | spring-boot-starter-tomcat
74 | 1.2.4.RELEASE
75 |
76 |
77 |
78 | org.springframework.boot
79 | spring-boot-starter-data-mongodb
80 | 1.2.4.RELEASE
81 |
82 |
83 |
84 |
85 | org.springframework.boot
86 | spring-boot-starter-web
87 | 1.2.4.RELEASE
88 |
89 |
90 |
91 | com.google.code.gson
92 | gson
93 | 2.4
94 |
95 |
96 |
97 | commons-lang
98 | commons-lang
99 | 2.0
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | org.springframework.boot
109 | spring-boot-maven-plugin
110 | 1.2.4.RELEASE
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------