1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.persistence.jpa.inner;
20
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24
25 import java.time.LocalDateTime;
26 import java.time.OffsetDateTime;
27 import java.util.List;
28 import java.util.Optional;
29 import java.util.stream.Collectors;
30 import java.util.stream.IntStream;
31 import org.apache.syncope.common.lib.wa.GoogleMfaAuthAccount;
32 import org.apache.syncope.common.lib.wa.GoogleMfaAuthToken;
33 import org.apache.syncope.common.lib.wa.ImpersonationAccount;
34 import org.apache.syncope.common.lib.wa.U2FDevice;
35 import org.apache.syncope.common.lib.wa.WebAuthnDeviceCredential;
36 import org.apache.syncope.core.persistence.api.dao.AuthProfileDAO;
37 import org.apache.syncope.core.persistence.api.entity.am.AuthProfile;
38 import org.apache.syncope.core.persistence.jpa.AbstractTest;
39 import org.apache.syncope.core.persistence.jpa.entity.am.JPAAuthProfile;
40 import org.apache.syncope.core.spring.security.SecureRandomUtils;
41 import org.junit.jupiter.api.BeforeEach;
42 import org.junit.jupiter.api.Test;
43 import org.springframework.beans.factory.annotation.Autowired;
44 import org.springframework.transaction.annotation.Transactional;
45
46 @Transactional("Master")
47 public class AuthProfileTest extends AbstractTest {
48
49 @Autowired
50 private AuthProfileDAO authProfileDAO;
51
52 @BeforeEach
53 public void beforeEach() {
54 entityManager().createQuery("DELETE FROM " + JPAAuthProfile.class.getSimpleName()).executeUpdate();
55 }
56
57 @Test
58 public void googleMfaToken() {
59 String id = SecureRandomUtils.generateRandomUUID().toString();
60
61 createAuthProfileWithToken(id, 123456);
62
63 Optional<AuthProfile> result = authProfileDAO.findByOwner(id);
64 assertTrue(result.isPresent());
65
66 assertFalse(authProfileDAO.findAll(-1, -1).isEmpty());
67
68 AuthProfile authProfile = result.get();
69 result = Optional.ofNullable(authProfileDAO.find(authProfile.getKey()));
70 assertTrue(result.isPresent());
71
72 authProfile.setOwner("SyncopeCreate-New");
73 authProfile.setGoogleMfaAuthTokens(List.of());
74 authProfileDAO.save(authProfile);
75
76 assertFalse(authProfileDAO.findByOwner(id).isPresent());
77 }
78
79 @Test
80 public void u2fRegisteredDevice() {
81 String id = SecureRandomUtils.generateRandomUUID().toString();
82 createAuthProfileWithU2FDevice(id, "{ 'record': 1 }");
83
84 Optional<AuthProfile> result = authProfileDAO.findByOwner(id);
85 assertTrue(result.isPresent());
86
87 assertFalse(authProfileDAO.findAll(-1, -1).isEmpty());
88
89 AuthProfile authProfile = result.get();
90 result = Optional.ofNullable(authProfileDAO.find(authProfile.getKey()));
91 assertTrue(result.isPresent());
92
93 authProfile.setOwner("SyncopeCreate-NewU2F");
94 authProfile.setU2FRegisteredDevices(List.of());
95 authProfileDAO.save(authProfile);
96
97 assertFalse(authProfileDAO.findByOwner(id).isPresent());
98 }
99
100 @Test
101 public void webAuthnRegisteredDevice() {
102 String id = SecureRandomUtils.generateRandomUUID().toString();
103 String record = "[ {"
104 + " \"userIdentity\" : {"
105 + " \"name\" : \"casuser\","
106 + " \"displayName\" : \"casuser\""
107 + " },"
108 + " \"credential\" : {"
109 + " \"credentialId\" : \"fFGyV3K5x1\""
110 + " },"
111 + " \"username\" : \"casuser\""
112 + " } ]";
113
114 WebAuthnDeviceCredential credential = new WebAuthnDeviceCredential.Builder().
115 json(record).
116 identifier("fFGyV3K5x1").
117 build();
118
119 createAuthProfileWithWebAuthnDevice(id, List.of(credential));
120
121 Optional<AuthProfile> result = authProfileDAO.findByOwner(id);
122 assertTrue(result.isPresent());
123
124 assertFalse(authProfileDAO.findAll(-1, -1).isEmpty());
125
126 AuthProfile authProfile = result.get();
127 result = Optional.ofNullable(authProfileDAO.find(authProfile.getKey()));
128 assertTrue(result.isPresent());
129
130 authProfile.setOwner("SyncopeCreate-NewU2F");
131 authProfile.setWebAuthnDeviceCredentials(List.of());
132 authProfileDAO.save(authProfile);
133
134 assertFalse(authProfileDAO.findByOwner(id).isPresent());
135 }
136
137 @Test
138 public void googleMfaAccount() {
139 String id = SecureRandomUtils.generateRandomUUID().toString();
140
141 createAuthProfileWithAccount(id);
142
143 Optional<AuthProfile> result = authProfileDAO.findByOwner(id);
144 assertTrue(result.isPresent());
145
146 assertFalse(authProfileDAO.findAll(-1, -1).isEmpty());
147
148 AuthProfile authProfile = result.get();
149 result = Optional.ofNullable(authProfileDAO.find(authProfile.getKey()));
150 assertTrue(result.isPresent());
151
152 String secret = SecureRandomUtils.generateRandomUUID().toString();
153 List<GoogleMfaAuthAccount> googleMfaAuthAccounts = authProfile.getGoogleMfaAuthAccounts();
154 assertFalse(googleMfaAuthAccounts.isEmpty());
155 GoogleMfaAuthAccount googleMfaAuthAccount = googleMfaAuthAccounts.get(0);
156 googleMfaAuthAccount.setSecretKey(secret);
157
158 authProfile.setGoogleMfaAuthAccounts(googleMfaAuthAccounts);
159 authProfile = authProfileDAO.save(authProfile);
160 assertEquals(secret, authProfile.getGoogleMfaAuthAccounts().get(0).getSecretKey());
161 }
162
163 @Test
164 public void impersonationAccounts() {
165 String id = SecureRandomUtils.generateRandomUUID().toString();
166
167 createAuthProfileWithAccount(id);
168
169 Optional<AuthProfile> result = authProfileDAO.findByOwner(id);
170 assertTrue(result.isPresent());
171
172 AuthProfile authProfile = result.get();
173 result = Optional.ofNullable(authProfileDAO.find(authProfile.getKey()));
174 assertTrue(result.isPresent());
175
176 List<ImpersonationAccount> accounts = IntStream.range(1, 10).
177 mapToObj(i -> new ImpersonationAccount.Builder().impersonated("impersonatee" + i).build()).
178 collect(Collectors.toList());
179
180 authProfile.setImpersonationAccounts(accounts);
181 authProfile = authProfileDAO.save(authProfile);
182 assertEquals(accounts.size(), authProfile.getImpersonationAccounts().size());
183 }
184
185 private AuthProfile createAuthProfileWithToken(final String owner, final Integer otp) {
186 AuthProfile profile = entityFactory.newEntity(AuthProfile.class);
187 profile.setOwner(owner);
188 GoogleMfaAuthToken token = new GoogleMfaAuthToken.Builder().issueDate(LocalDateTime.now()).token(otp).build();
189 profile.setGoogleMfaAuthTokens(List.of(token));
190 return authProfileDAO.save(profile);
191 }
192
193 private AuthProfile createAuthProfileWithU2FDevice(final String owner, final String record) {
194 AuthProfile profile = entityFactory.newEntity(AuthProfile.class);
195 profile.setOwner(owner);
196 U2FDevice device = new U2FDevice.Builder().issueDate(OffsetDateTime.now()).record(record).build();
197 profile.setU2FRegisteredDevices(List.of(device));
198 return authProfileDAO.save(profile);
199 }
200
201 private AuthProfile createAuthProfileWithWebAuthnDevice(
202 final String owner,
203 final List<WebAuthnDeviceCredential> credentials) {
204
205 AuthProfile profile = entityFactory.newEntity(AuthProfile.class);
206 profile.setOwner(owner);
207 profile.setWebAuthnDeviceCredentials(credentials);
208 return authProfileDAO.save(profile);
209 }
210
211 private AuthProfile createAuthProfileWithAccount(final String owner) {
212 AuthProfile profile = entityFactory.newEntity(AuthProfile.class);
213 profile.setOwner(owner);
214 GoogleMfaAuthAccount account = new GoogleMfaAuthAccount.Builder()
215 .registrationDate(OffsetDateTime.now())
216 .scratchCodes(List.of(1, 2, 3, 4, 5))
217 .secretKey(SecureRandomUtils.generateRandomUUID().toString())
218 .validationCode(123456)
219 .name(SecureRandomUtils.generateRandomUUID().toString())
220 .build();
221 profile.setGoogleMfaAuthAccounts(List.of(account));
222 return authProfileDAO.save(profile);
223 }
224 }