1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.wa.starter.mfa;
20
21 import java.io.Serializable;
22 import java.time.ZoneId;
23 import java.time.ZonedDateTime;
24 import java.util.Date;
25 import java.util.HashSet;
26 import java.util.Optional;
27 import java.util.Set;
28 import java.util.stream.Collectors;
29 import org.apache.syncope.common.lib.wa.MfaTrustedDevice;
30 import org.apache.syncope.common.rest.api.beans.MfaTrustedDeviceQuery;
31 import org.apache.syncope.common.rest.api.service.wa.MfaTrustStorageService;
32 import org.apache.syncope.wa.bootstrap.WARestClient;
33 import org.apache.syncope.wa.starter.services.WAServiceRegistry;
34 import org.apereo.cas.configuration.model.support.mfa.trusteddevice.TrustedDevicesMultifactorProperties;
35 import org.apereo.cas.trusted.authentication.api.MultifactorAuthenticationTrustRecord;
36 import org.apereo.cas.trusted.authentication.api.MultifactorAuthenticationTrustRecordKeyGenerator;
37 import org.apereo.cas.trusted.authentication.storage.BaseMultifactorAuthenticationTrustStorage;
38 import org.apereo.cas.util.crypto.CipherExecutor;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 public class WAMultifactorAuthenticationTrustStorage extends BaseMultifactorAuthenticationTrustStorage {
43
44 private static final Logger LOG = LoggerFactory.getLogger(WAServiceRegistry.class);
45
46 protected static final int PAGE_SIZE = 500;
47
48 protected final WARestClient waRestClient;
49
50 public WAMultifactorAuthenticationTrustStorage(
51 final TrustedDevicesMultifactorProperties trustedDevicesMultifactorProperties,
52 final CipherExecutor<Serializable, String> cipherExecutor,
53 final MultifactorAuthenticationTrustRecordKeyGenerator keyGenerationStrategy,
54 final WARestClient waRestClient) {
55
56 super(trustedDevicesMultifactorProperties, cipherExecutor, keyGenerationStrategy);
57 this.waRestClient = waRestClient;
58 }
59
60 @Override
61 protected MultifactorAuthenticationTrustRecord saveInternal(final MultifactorAuthenticationTrustRecord record) {
62 MfaTrustedDevice device = new MfaTrustedDevice();
63 device.setRecordKey(record.getRecordKey());
64 device.setId(record.getId());
65 device.setName(record.getName());
66 device.setDeviceFingerprint(record.getDeviceFingerprint());
67 Optional.ofNullable(record.getExpirationDate()).
68 ifPresent(date -> device.setExpirationDate(date.toInstant().atZone(ZoneId.systemDefault())));
69 device.setRecordDate(record.getRecordDate());
70
71 LOG.trace("Saving multifactor authentication trust record [{}]", device);
72
73 waRestClient.getService(MfaTrustStorageService.class).create(record.getPrincipal(), device);
74
75 return record;
76 }
77
78 @Override
79 public void remove(final ZonedDateTime expirationDate) {
80 waRestClient.getService(MfaTrustStorageService.class).delete(
81 new MfaTrustedDeviceQuery.Builder().expirationDate(expirationDate.toOffsetDateTime()).build());
82 }
83
84 @Override
85 public void remove(final String recordKey) {
86 waRestClient.getService(MfaTrustStorageService.class).delete(
87 new MfaTrustedDeviceQuery.Builder().recordKey(recordKey).build());
88 }
89
90 protected MultifactorAuthenticationTrustRecord translate(final MfaTrustedDevice device) {
91 MultifactorAuthenticationTrustRecord record = new MultifactorAuthenticationTrustRecord();
92 record.setRecordKey(device.getRecordKey());
93 record.setId(device.getId());
94 record.setName(device.getName());
95 record.setDeviceFingerprint(device.getDeviceFingerprint());
96 Optional.ofNullable(device.getExpirationDate()).
97 ifPresent(date -> record.setExpirationDate(Date.from(date.toInstant())));
98 record.setRecordDate(device.getRecordDate());
99 return record;
100 }
101
102 @Override
103 public Set<? extends MultifactorAuthenticationTrustRecord> getAll() {
104 if (!waRestClient.isReady()) {
105 LOG.debug("Syncope client is not yet ready to fetch MFA trusted device records");
106 return Set.of();
107 }
108
109 int count = waRestClient.getService(MfaTrustStorageService.class).
110 search(new MfaTrustedDeviceQuery.Builder().page(1).size(0).build()).getTotalCount();
111
112 Set<MultifactorAuthenticationTrustRecord> result = new HashSet<>();
113
114 for (int page = 1; page <= (count / PAGE_SIZE) + 1; page++) {
115 waRestClient.getService(MfaTrustStorageService.class).
116 search(new MfaTrustedDeviceQuery.Builder().page(page).size(PAGE_SIZE).
117 orderBy("expirationDate").build()).
118 getResult().stream().
119 map(this::translate).
120 forEach(result::add);
121 }
122
123 return result;
124 }
125
126 @Override
127 public Set<? extends MultifactorAuthenticationTrustRecord> get(final ZonedDateTime onOrAfterDate) {
128 if (!waRestClient.isReady()) {
129 LOG.debug("Syncope client is not yet ready to fetch MFA trusted device records");
130 return Set.of();
131 }
132
133 return waRestClient.getService(MfaTrustStorageService.class).
134 search(new MfaTrustedDeviceQuery.Builder().recordDate(onOrAfterDate.toOffsetDateTime()).build()).
135 getResult().stream().
136 map(this::translate).
137 collect(Collectors.toSet());
138 }
139
140 @Override
141 public Set<? extends MultifactorAuthenticationTrustRecord> get(final String principal) {
142 if (!waRestClient.isReady()) {
143 LOG.debug("Syncope client is not yet ready to fetch MFA trusted device records");
144 return Set.of();
145 }
146
147 return waRestClient.getService(MfaTrustStorageService.class).
148 search(new MfaTrustedDeviceQuery.Builder().principal(principal).build()).getResult().stream().
149 map(this::translate).
150 collect(Collectors.toSet());
151 }
152
153 @Override
154 public MultifactorAuthenticationTrustRecord get(final long id) {
155 if (!waRestClient.isReady()) {
156 LOG.debug("Syncope client is not yet ready to fetch MFA trusted device records");
157 return null;
158 }
159
160 return waRestClient.getService(MfaTrustStorageService.class).
161 search(new MfaTrustedDeviceQuery.Builder().id(id).build()).getResult().stream().findFirst().
162 map(this::translate).
163 orElse(null);
164 }
165 }