1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.spring.security;
20
21 import com.nimbusds.jose.JOSEException;
22 import com.nimbusds.jose.JWSAlgorithm;
23 import com.nimbusds.jose.KeyLengthException;
24 import java.security.NoSuchAlgorithmException;
25 import java.security.spec.InvalidKeySpecException;
26 import org.apache.syncope.common.lib.types.CipherAlgorithm;
27 import org.apache.syncope.core.persistence.api.dao.AccessTokenDAO;
28 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
29 import org.apache.syncope.core.persistence.api.dao.UserDAO;
30 import org.apache.syncope.core.provisioning.api.rules.RuleEnforcer;
31 import org.apache.syncope.core.spring.ApplicationContextProvider;
32 import org.apache.syncope.core.spring.policy.DefaultRuleEnforcer;
33 import org.apache.syncope.core.spring.security.jws.AccessTokenJWSSigner;
34 import org.apache.syncope.core.spring.security.jws.AccessTokenJWSVerifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
38 import org.springframework.boot.context.properties.EnableConfigurationProperties;
39 import org.springframework.context.annotation.Bean;
40 import org.springframework.context.annotation.Configuration;
41 import org.springframework.security.config.core.GrantedAuthorityDefaults;
42
43 @EnableConfigurationProperties(SecurityProperties.class)
44 @Configuration(proxyBeanMethods = false)
45 public class SecurityContext {
46
47 private static final Logger LOG = LoggerFactory.getLogger(SecurityContext.class);
48
49 @Bean
50 public CipherAlgorithm adminPasswordAlgorithm(final SecurityProperties props) {
51 return props.getAdminPasswordAlgorithm();
52 }
53
54 @Bean
55 public JWSAlgorithm jwsAlgorithm(final SecurityProperties props) {
56 return JWSAlgorithm.parse(props.getJwsAlgorithm().toUpperCase());
57 }
58
59 private static String jwsKey(final JWSAlgorithm jwsAlgorithm, final SecurityProperties props) {
60 String jwsKey = props.getJwsKey();
61 if (jwsKey == null) {
62 throw new IllegalArgumentException("No JWS key provided");
63 }
64
65 if (JWSAlgorithm.Family.HMAC_SHA.contains(jwsAlgorithm)) {
66 int minLength = jwsAlgorithm.equals(JWSAlgorithm.HS256)
67 ? 256 / 8
68 : jwsAlgorithm.equals(JWSAlgorithm.HS384)
69 ? 384 / 8
70 : 512 / 8;
71 if (jwsKey.length() < minLength) {
72 jwsKey = SecureRandomUtils.generateRandomPassword(minLength);
73 props.setJwsKey(jwsKey);
74 LOG.warn("The configured key for {} must be at least {} bits, generating random: {}",
75 jwsAlgorithm, minLength * 8, jwsKey);
76 }
77 }
78
79 return jwsKey;
80 }
81
82 @ConditionalOnMissingBean
83 @Bean
84 public DefaultCredentialChecker credentialChecker(
85 final SecurityProperties props,
86 final JWSAlgorithm jwsAlgorithm) {
87
88 return new DefaultCredentialChecker(
89 jwsKey(jwsAlgorithm, props),
90 props.getAdminPassword(),
91 props.getAnonymousKey());
92 }
93
94 @ConditionalOnMissingBean
95 @Bean
96 public AccessTokenJWSVerifier accessTokenJWSVerifier(
97 final JWSAlgorithm jwsAlgorithm,
98 final SecurityProperties props)
99 throws JOSEException, NoSuchAlgorithmException, InvalidKeySpecException {
100
101 return new AccessTokenJWSVerifier(jwsAlgorithm, jwsKey(jwsAlgorithm, props));
102 }
103
104 @ConditionalOnMissingBean
105 @Bean
106 public AccessTokenJWSSigner accessTokenJWSSigner(
107 final JWSAlgorithm jwsAlgorithm,
108 final SecurityProperties props)
109 throws KeyLengthException, NoSuchAlgorithmException, InvalidKeySpecException {
110
111 return new AccessTokenJWSSigner(jwsAlgorithm, jwsKey(jwsAlgorithm, props));
112 }
113
114 @ConditionalOnMissingBean
115 @Bean
116 public SyncopeJWTSSOProvider syncopeJWTSSOProvider(
117 final SecurityProperties props,
118 final AccessTokenJWSVerifier accessTokenJWSVerifier,
119 final UserDAO userDAO,
120 final AccessTokenDAO accessTokenDAO) {
121
122 return new SyncopeJWTSSOProvider(props, accessTokenJWSVerifier, userDAO, accessTokenDAO);
123 }
124
125 @ConditionalOnMissingBean
126 @Bean
127 public PasswordGenerator passwordGenerator() {
128 return new DefaultPasswordGenerator();
129 }
130
131 @ConditionalOnMissingBean
132 @Bean
133 public RuleEnforcer ruleEnforcer(final RealmDAO realmDAO) {
134 return new DefaultRuleEnforcer(realmDAO);
135 }
136
137 @Bean
138 public GrantedAuthorityDefaults grantedAuthorityDefaults() {
139 return new GrantedAuthorityDefaults("");
140 }
141
142 @Bean
143 public ApplicationContextProvider applicationContextProvider() {
144 return new ApplicationContextProvider();
145 }
146 }