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.beans.factory.config.BeanDefinition;
38 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
39 import org.springframework.boot.context.properties.EnableConfigurationProperties;
40 import org.springframework.context.annotation.Bean;
41 import org.springframework.context.annotation.Configuration;
42 import org.springframework.context.annotation.Role;
43 import org.springframework.security.config.core.GrantedAuthorityDefaults;
44
45 @EnableConfigurationProperties(SecurityProperties.class)
46 @Configuration(proxyBeanMethods = false)
47 public class SecurityContext {
48
49 private static final Logger LOG = LoggerFactory.getLogger(SecurityContext.class);
50
51 @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
52 @Bean
53 public static GrantedAuthorityDefaults grantedAuthorityDefaults() {
54 return new GrantedAuthorityDefaults("");
55 }
56
57 protected static String jwsKey(final JWSAlgorithm jwsAlgorithm, final SecurityProperties props) {
58 String jwsKey = props.getJwsKey();
59 if (jwsKey == null) {
60 throw new IllegalArgumentException("No JWS key provided");
61 }
62
63 if (JWSAlgorithm.Family.HMAC_SHA.contains(jwsAlgorithm)) {
64 int minLength = jwsAlgorithm.equals(JWSAlgorithm.HS256)
65 ? 256 / 8
66 : jwsAlgorithm.equals(JWSAlgorithm.HS384)
67 ? 384 / 8
68 : 512 / 8;
69 if (jwsKey.length() < minLength) {
70 jwsKey = SecureRandomUtils.generateRandomPassword(minLength);
71 props.setJwsKey(jwsKey);
72 LOG.warn("The configured key for {} must be at least {} bits, generating random: {}",
73 jwsAlgorithm, minLength * 8, jwsKey);
74 }
75 }
76
77 return jwsKey;
78 }
79
80 @Bean
81 public CipherAlgorithm adminPasswordAlgorithm(final SecurityProperties props) {
82 return props.getAdminPasswordAlgorithm();
83 }
84
85 @Bean
86 public JWSAlgorithm jwsAlgorithm(final SecurityProperties props) {
87 return JWSAlgorithm.parse(props.getJwsAlgorithm().toUpperCase());
88 }
89
90 @ConditionalOnMissingBean
91 @Bean
92 public DefaultCredentialChecker credentialChecker(
93 final SecurityProperties props,
94 final JWSAlgorithm jwsAlgorithm) {
95
96 return new DefaultCredentialChecker(
97 jwsKey(jwsAlgorithm, props),
98 props.getAdminPassword(),
99 props.getAnonymousKey());
100 }
101
102 @ConditionalOnMissingBean
103 @Bean
104 public AccessTokenJWSVerifier accessTokenJWSVerifier(
105 final JWSAlgorithm jwsAlgorithm,
106 final SecurityProperties props)
107 throws JOSEException, NoSuchAlgorithmException, InvalidKeySpecException {
108
109 return new AccessTokenJWSVerifier(jwsAlgorithm, jwsKey(jwsAlgorithm, props));
110 }
111
112 @ConditionalOnMissingBean
113 @Bean
114 public AccessTokenJWSSigner accessTokenJWSSigner(
115 final JWSAlgorithm jwsAlgorithm,
116 final SecurityProperties props)
117 throws KeyLengthException, NoSuchAlgorithmException, InvalidKeySpecException {
118
119 return new AccessTokenJWSSigner(jwsAlgorithm, jwsKey(jwsAlgorithm, props));
120 }
121
122 @ConditionalOnMissingBean
123 @Bean
124 public SyncopeJWTSSOProvider syncopeJWTSSOProvider(
125 final SecurityProperties props,
126 final AccessTokenJWSVerifier accessTokenJWSVerifier,
127 final UserDAO userDAO,
128 final AccessTokenDAO accessTokenDAO) {
129
130 return new SyncopeJWTSSOProvider(props, accessTokenJWSVerifier, userDAO, accessTokenDAO);
131 }
132
133 @ConditionalOnMissingBean
134 @Bean
135 public PasswordGenerator passwordGenerator() {
136 return new DefaultPasswordGenerator();
137 }
138
139 @ConditionalOnMissingBean
140 @Bean
141 public RuleEnforcer ruleEnforcer(final RealmDAO realmDAO) {
142 return new DefaultRuleEnforcer(realmDAO);
143 }
144
145 @Bean
146 public ApplicationContextProvider applicationContextProvider() {
147 return new ApplicationContextProvider();
148 }
149 }