Skip to content

Commit fe537a6

Browse files
committedJun 7, 2019
new version
1 parent d3c9a99 commit fe537a6

25 files changed

+966
-173
lines changed
 

‎README.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ Para el ejemplo se han utilizado algoritmos tanto simétricos como asímetricos.
3030
- ECDSA usando P-512 and SHA-512 (ES512)
3131

3232
Aunque realmente se podrían ampliar para permitir cualquier tipo de algoritmo con poco esfuerzo. El hecho de haber seleccionado estos es debido
33-
a que son los más utilziados.
33+
a que son los más utiliziados.
3434

3535

‎jwt-core/pom.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
<name>${project.artifactId}:${project.version}</name>
1414
<dependencies>
1515
<dependency>
16-
<groupId>io.jsonwebtoken</groupId>
17-
<artifactId>jjwt</artifactId>
16+
<groupId>com.nimbusds</groupId>
17+
<artifactId>nimbus-jose-jwt</artifactId>
1818
</dependency>
1919
<dependency>
2020
<groupId>org.springframework</groupId>

‎jwt-core/src/main/java/org/emaginalabs/security/jwt/JwtAuthenticationEntryPoint.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.emaginalabs.security.jwt;
22

33
import com.fasterxml.jackson.databind.ObjectMapper;
4-
import io.jsonwebtoken.JwtException;
4+
import com.nimbusds.jwt.proc.BadJWTException;
55
import org.springframework.beans.factory.annotation.Autowired;
66
import org.springframework.http.MediaType;
77
import org.springframework.security.core.AuthenticationException;
@@ -34,6 +34,6 @@ public void commence(HttpServletRequest request,
3434
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
3535

3636
mapper.writeValue(response.getWriter(),
37-
new JwtException("Access denied", authException));
37+
new BadJWTException("Access denied", authException));
3838
}
3939
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.emaginalabs.security.jwt.claims;
2+
3+
4+
public class DefaultClaim extends JwtMap {
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package org.emaginalabs.security.jwt.claims;
2+
3+
import org.springframework.util.Assert;
4+
5+
import java.util.Collection;
6+
import java.util.LinkedHashMap;
7+
import java.util.Map;
8+
import java.util.Set;
9+
10+
public class JwtMap implements Map<String, Object> {
11+
12+
private final Map<String, Object> map;
13+
14+
public JwtMap() {
15+
this.map = new LinkedHashMap<>();
16+
}
17+
18+
public JwtMap(Map<String, Object> map) {
19+
this();
20+
Assert.notNull(map, "Map argument cannot be null.");
21+
putAll(map);
22+
}
23+
24+
protected String getString(String name) {
25+
Object v = get(name);
26+
return v != null ? String.valueOf(v) : null;
27+
}
28+
29+
30+
protected void setValue(String name, Object v) {
31+
if (v == null) {
32+
map.remove(name);
33+
} else {
34+
map.put(name, v);
35+
}
36+
}
37+
38+
39+
@Override
40+
public int size() {
41+
return map.size();
42+
}
43+
44+
@Override
45+
public boolean isEmpty() {
46+
return map.isEmpty();
47+
}
48+
49+
@Override
50+
public boolean containsKey(Object o) {
51+
return map.containsKey(o);
52+
}
53+
54+
@Override
55+
public boolean containsValue(Object o) {
56+
return map.containsValue(o);
57+
}
58+
59+
@Override
60+
public Object get(Object o) {
61+
return map.get(o);
62+
}
63+
64+
@Override
65+
public Object put(String s, Object o) {
66+
if (o == null) {
67+
return map.remove(s);
68+
} else {
69+
return map.put(s, o);
70+
}
71+
}
72+
73+
@Override
74+
public Object remove(Object o) {
75+
return map.remove(o);
76+
}
77+
78+
@SuppressWarnings("NullableProblems")
79+
@Override
80+
public void putAll(Map<? extends String, ?> m) {
81+
if (m == null) {
82+
return;
83+
}
84+
for (String s : m.keySet()) {
85+
put(s, m.get(s));
86+
}
87+
}
88+
89+
@Override
90+
public void clear() {
91+
map.clear();
92+
}
93+
94+
@Override
95+
public Set<String> keySet() {
96+
return map.keySet();
97+
}
98+
99+
@Override
100+
public Collection<Object> values() {
101+
return map.values();
102+
}
103+
104+
@Override
105+
public Set<Entry<String, Object>> entrySet() {
106+
return map.entrySet();
107+
}
108+
109+
@Override
110+
public String toString() {
111+
return map.toString();
112+
}
113+
114+
@Override
115+
public int hashCode() {
116+
return map.hashCode();
117+
}
118+
119+
@Override
120+
public boolean equals(Object obj) {
121+
return map.equals(obj);
122+
}
123+
}

‎jwt-core/src/main/java/org/emaginalabs/security/jwt/config/JwtConfiguration.java

+1-4
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,13 @@
33

44
import lombok.extern.slf4j.Slf4j;
55
import org.emaginalabs.security.jwt.JwtAuthenticationEntryPoint;
6-
import org.emaginalabs.security.jwt.JwtWebSecurityConfigurer;
76
import org.emaginalabs.security.jwt.handler.JwtAuthenticationFailureHandler;
87
import org.emaginalabs.security.jwt.provider.JwtAuthenticationProvider;
98
import org.emaginalabs.security.jwt.token.provider.JwtTokenProvider;
10-
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
119
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
1210
import org.springframework.context.annotation.Bean;
1311
import org.springframework.context.annotation.Configuration;
1412
import org.springframework.security.authentication.AuthenticationProvider;
15-
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
1613

1714
/**
1815
* Configuration jwt authentication in GAIA Application
@@ -55,7 +52,7 @@ public JwtAuthenticationFailureHandler jwtAuthenticationFailureHandler() {
5552
}
5653

5754
@ConditionalOnMissingBean
58-
@ConditionalOnBean(AuthenticationManagerBuilder.class)
55+
//@ConditionalOnBean(AuthenticationManagerBuilder.class)
5956
@Bean
6057
public JwtWebSecurityConfigurer jwtWebSecurityConfigurer() {
6158
return new JwtWebSecurityConfigurer(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.emaginalabs.security.jwt.config;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.emaginalabs.security.jwt.JwtAuthenticationEntryPoint;
5+
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
6+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7+
import org.springframework.security.web.DefaultSecurityFilterChain;
8+
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
9+
import org.springframework.util.StringUtils;
10+
11+
import java.util.ArrayList;
12+
import java.util.Arrays;
13+
import java.util.Collections;
14+
import java.util.List;
15+
16+
/**
17+
* User: jose
18+
* Date: 2019-05-30
19+
* Time: 10:50
20+
*/
21+
22+
@Slf4j
23+
public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
24+
25+
private static final String COMMA_SEPARATOR = ",";
26+
27+
private JwtWebSecurityConfigurer configurer;
28+
29+
public JwtConfigurer(JwtWebSecurityConfigurer jwtWebSecurityConfigurer) {
30+
this.configurer = jwtWebSecurityConfigurer;
31+
32+
}
33+
34+
@Override
35+
public void configure(HttpSecurity http) throws Exception {
36+
log.debug("Configuring http security for jwt security...");
37+
//get login path
38+
String loginPath = configurer.getJwtSettings().getLoginPath();
39+
40+
//get paths permits
41+
String permitPathsStr = configurer.getJwtSettings().getPathAllow();
42+
43+
List<String> permitPaths = new ArrayList<String>();
44+
if (StringUtils.hasText(permitPathsStr)) {
45+
Collections.addAll(Arrays.asList(permitPathsStr.split(COMMA_SEPARATOR)));
46+
}
47+
//add login path to exclude path filter
48+
permitPaths.add(permitPaths.size(), loginPath);
49+
//get path to authentication required
50+
String pathSecured = configurer.getJwtSettings().getSecurePath();
51+
if (configurer.getJwtSettings().isApiLoginEnabled()) {
52+
//custom filter to login
53+
http.addFilterBefore(configurer.buildJwtLoginProcessingFilter(loginPath), UsernamePasswordAuthenticationFilter.class);
54+
}
55+
http
56+
// Custom filter for authenticating users using tokens
57+
.addFilterAfter(configurer.buildJwtTokenAuthenticationProcessingFilter(permitPaths, pathSecured),
58+
UsernamePasswordAuthenticationFilter.class)
59+
//exception handler jwt error
60+
.exceptionHandling()
61+
.authenticationEntryPoint(new JwtAuthenticationEntryPoint());
62+
}
63+
64+
}

‎jwt-core/src/main/java/org/emaginalabs/security/jwt/config/JwtSettings.java

+26-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package org.emaginalabs.security.jwt.config;
22

3-
import io.jsonwebtoken.SignatureAlgorithm;
3+
import com.nimbusds.jose.JWEAlgorithm;
4+
import com.nimbusds.jose.JWSAlgorithm;
45
import lombok.Data;
6+
import lombok.extern.slf4j.Slf4j;
57
import org.springframework.beans.factory.annotation.Value;
68

79

810
@Data
11+
@Slf4j
912
public class JwtSettings {
1013

1114
/**
@@ -14,7 +17,7 @@ public class JwtSettings {
1417
@Value("${app.security.jwt.token.expiration.time}")
1518
private Integer tokenExpirationTime = 15;
1619

17-
@Value("${app.security.jwt.path.login:/login}")
20+
@Value("${app.security.jwt.path.login:/api/login}")
1821
private String loginPath;
1922

2023
@Value("${app.security.jwt.path.secure:/**}")
@@ -26,7 +29,7 @@ public class JwtSettings {
2629
* Token issuer.
2730
*/
2831
@Value("${app.security.jwt.token.issuer}")
29-
private String tokenIssuer = "user";
32+
private String tokenIssuer = "gaia-app";
3033

3134
/**
3235
* Key is used to sign token
@@ -47,15 +50,33 @@ public class JwtSettings {
4750
@Value("${app.security.jwt.signature.algorithm}")
4851
private String signatureAlgorithmStr;
4952

53+
@Value("${app.security.jwt.encryptation.algorithm}")
54+
private String encryptationAlgorithmStr;
55+
56+
57+
@Value("${app.security.jwt.encryptation.active:false}")
58+
private boolean encryptation;
5059

5160
@Value("${app.security.jwt.token.response}")
5261
private String tokenResponse;
5362

5463
@Value("${app.security.jwt.token.compresion}")
5564
private boolean compresion;
5665

57-
public SignatureAlgorithm getSignatureAlgorithm() {
58-
return SignatureAlgorithm.forName(signatureAlgorithmStr);
66+
@Value("${app.security.jwt.signature.validate:true}")
67+
private boolean validateSigned;
68+
69+
@Value("${app.security.jwt.login.enabled:false}")
70+
private boolean apiLoginEnabled;
71+
72+
public JWSAlgorithm getSignatureAlgorithm() {
73+
return JWSAlgorithm.parse(signatureAlgorithmStr);
5974
}
6075

76+
public JWEAlgorithm getEncryptationAlgorithm() {
77+
return JWEAlgorithm.parse(encryptationAlgorithmStr);
78+
}
79+
80+
81+
6182
}

‎jwt-core/src/main/java/org/emaginalabs/security/jwt/JwtWebSecurityConfigurer.java ‎jwt-core/src/main/java/org/emaginalabs/security/jwt/config/JwtWebSecurityConfigurer.java

+7-13
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
package org.emaginalabs.security.jwt;
1+
package org.emaginalabs.security.jwt.config;
22

33

4+
import lombok.Getter;
45
import lombok.RequiredArgsConstructor;
56
import lombok.extern.slf4j.Slf4j;
6-
import org.emaginalabs.security.jwt.config.JwtSettings;
7-
import org.emaginalabs.security.jwt.config.SkipPathRequestMatcher;
7+
import org.emaginalabs.security.jwt.JwtAuthenticationEntryPoint;
88
import org.emaginalabs.security.jwt.filter.JwtLoginProcessingFilter;
99
import org.emaginalabs.security.jwt.filter.JwtTokenAuthenticationProcessingFilter;
1010
import org.emaginalabs.security.jwt.token.provider.TokenProvider;
@@ -33,14 +33,7 @@
3333
public class JwtWebSecurityConfigurer implements ApplicationContextAware {
3434

3535
private static final String COMMA_SEPARATOR = ",";
36-
private static final String DEFAULT_PATH_SECURE = "/**";
37-
private static final String DEFAULT_PATH_LOGIN = "/login";
38-
private static final String GAIA_ENV_SECURITY_JWT_PATH_LOGIN = "gaia.env.security.jwt.path.login";
39-
private static final String APP_ENV_SECURITY_JWT_PATH_LOGIN = "app.env.security.jwt.path.login";
40-
private static final String APP_ENV_SECURITY_JQT_PATH_SECURE = "app.env.security.jqt.path.secure";
41-
private static final String GAIA_ENV_SECURITY_JWT_PATH_SECURE = "gaia.env.security.jwt.path.secure";
42-
private static final String GAIA_ENV_SECURITY_JWT_PATHS_ALLOW = "gaia.env.security.jwt.paths.allow";
43-
private static final String APP_ENV_SECURITY_JWT_PATHS_ALLOW = "app.env.security.jwt.paths.allow";
36+
4437

4538
@Autowired
4639
private AuthenticationManagerBuilder authenticationManager;
@@ -49,19 +42,20 @@ public class JwtWebSecurityConfigurer implements ApplicationContextAware {
4942

5043
private final TokenProvider jwtTokenProvider;
5144

45+
@Getter
5246
private final JwtSettings jwtSettings;
5347

5448
private ApplicationContext context;
5549

5650
private final AuthenticationProvider jwtAuthenticationProvider;
5751

5852

59-
private JwtLoginProcessingFilter buildJwtLoginProcessingFilter(String loginEntryPoint) {
53+
protected JwtLoginProcessingFilter buildJwtLoginProcessingFilter(String loginEntryPoint) {
6054
log.debug("Configuring JwtLoginProcessingFilter...");
6155
return new JwtLoginProcessingFilter(loginEntryPoint, authenticationManager.getObject(), jwtTokenProvider, jwtSettings);
6256
}
6357

64-
private JwtTokenAuthenticationProcessingFilter buildJwtTokenAuthenticationProcessingFilter(List<String> pathsToSkip, String pattern) {
58+
protected JwtTokenAuthenticationProcessingFilter buildJwtTokenAuthenticationProcessingFilter(List<String> pathsToSkip, String pattern) {
6559
log.debug("Configuring JwtTokenAuthenticationProcessingFilter...");
6660
SkipPathRequestMatcher matcher = new SkipPathRequestMatcher(pathsToSkip, pattern);
6761
JwtTokenAuthenticationProcessingFilter filter

0 commit comments

Comments
 (0)
Please sign in to comment.