View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.wa.starter.gauth;
20  
21  import com.warrenstrange.googleauth.IGoogleAuthenticator;
22  import java.time.OffsetDateTime;
23  import java.util.Collection;
24  import java.util.List;
25  import java.util.stream.Collectors;
26  import org.apache.syncope.common.lib.SyncopeClientException;
27  import org.apache.syncope.common.lib.types.ClientExceptionType;
28  import org.apache.syncope.common.lib.wa.GoogleMfaAuthAccount;
29  import org.apache.syncope.common.rest.api.service.wa.GoogleMfaAuthAccountService;
30  import org.apache.syncope.wa.bootstrap.WARestClient;
31  import org.apereo.cas.authentication.OneTimeTokenAccount;
32  import org.apereo.cas.gauth.credential.BaseGoogleAuthenticatorTokenCredentialRepository;
33  import org.apereo.cas.gauth.credential.GoogleAuthenticatorAccount;
34  import org.apereo.cas.util.crypto.CipherExecutor;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  public class WAGoogleMfaAuthCredentialRepository extends BaseGoogleAuthenticatorTokenCredentialRepository {
39  
40      protected static final Logger LOG = LoggerFactory.getLogger(WAGoogleMfaAuthTokenRepository.class);
41  
42      protected final WARestClient waRestClient;
43  
44      public WAGoogleMfaAuthCredentialRepository(
45              final WARestClient waRestClient, final IGoogleAuthenticator googleAuthenticator) {
46  
47          super(CipherExecutor.noOpOfStringToString(), CipherExecutor.noOpOfNumberToNumber(), googleAuthenticator);
48          this.waRestClient = waRestClient;
49      }
50  
51      protected GoogleMfaAuthAccount mapGoogleMfaAuthAccount(final OneTimeTokenAccount otta) {
52          return new GoogleMfaAuthAccount.Builder().
53                  registrationDate(OffsetDateTime.now()).
54                  scratchCodes(otta.getScratchCodes().stream().map(Number::intValue).collect(Collectors.toList())).
55                  validationCode(otta.getValidationCode()).
56                  secretKey(otta.getSecretKey()).
57                  id(otta.getId()).
58                  build();
59      }
60  
61      protected GoogleAuthenticatorAccount mapGoogleMfaAuthAccount(final GoogleMfaAuthAccount gmfaa) {
62          return GoogleAuthenticatorAccount.builder().
63                  secretKey(gmfaa.getSecretKey()).
64                  validationCode(gmfaa.getValidationCode()).
65                  scratchCodes(gmfaa.getScratchCodes().stream().map(Number::intValue).collect(Collectors.toList())).
66                  name(gmfaa.getName()).
67                  id(gmfaa.getId()).
68                  build();
69      }
70  
71      protected GoogleMfaAuthAccountService service() {
72          return waRestClient.getService(GoogleMfaAuthAccountService.class);
73      }
74  
75      @Override
76      public OneTimeTokenAccount get(final long id) {
77          try {
78              GoogleMfaAuthAccount account = service().read(id);
79              if (account != null) {
80                  return mapGoogleMfaAuthAccount(account);
81              }
82          } catch (SyncopeClientException e) {
83              if (e.getType() == ClientExceptionType.NotFound) {
84                  LOG.info("Could not locate account for id {}", id);
85              } else {
86                  LOG.error(e.getMessage(), e);
87              }
88          }
89          return null;
90      }
91  
92      @Override
93      public OneTimeTokenAccount get(final String username, final long id) {
94          try {
95              return service().read(username).
96                      getResult().stream().
97                      filter(account -> account.getId() == id).
98                      map(this::mapGoogleMfaAuthAccount).
99                      findFirst().
100                     orElse(null);
101         } catch (SyncopeClientException e) {
102             if (e.getType() == ClientExceptionType.NotFound) {
103                 LOG.info("Could not locate account for owner {} and id {}", username, id);
104             } else {
105                 LOG.error(e.getMessage(), e);
106             }
107         }
108         return null;
109     }
110 
111     @Override
112     public Collection<? extends OneTimeTokenAccount> get(final String username) {
113         try {
114             return service().read(username).
115                     getResult().stream().
116                     map(this::mapGoogleMfaAuthAccount).
117                     collect(Collectors.toList());
118         } catch (SyncopeClientException e) {
119             if (e.getType() == ClientExceptionType.NotFound) {
120                 LOG.info("Could not locate account for owner {}", username);
121             } else {
122                 LOG.error(e.getMessage(), e);
123             }
124         }
125         return List.of();
126     }
127 
128     @Override
129     public Collection<? extends OneTimeTokenAccount> load() {
130         return service().list().
131                 getResult().stream().
132                 map(this::mapGoogleMfaAuthAccount).
133                 collect(Collectors.toList());
134     }
135 
136     @Override
137     public OneTimeTokenAccount save(final OneTimeTokenAccount otta) {
138         GoogleMfaAuthAccount account = new GoogleMfaAuthAccount.Builder().
139                 registrationDate(OffsetDateTime.now()).
140                 scratchCodes(otta.getScratchCodes().stream().map(Number::intValue).collect(Collectors.toList())).
141                 validationCode(otta.getValidationCode()).
142                 secretKey(otta.getSecretKey()).
143                 name(otta.getName()).
144                 id(otta.getId()).
145                 build();
146         service().create(otta.getUsername(), account);
147         return mapGoogleMfaAuthAccount(account);
148     }
149 
150     @Override
151     public OneTimeTokenAccount update(final OneTimeTokenAccount tokenAccount) {
152         GoogleMfaAuthAccount acct = mapGoogleMfaAuthAccount(tokenAccount);
153         service().update(tokenAccount.getUsername(), acct);
154         return tokenAccount;
155     }
156 
157     @Override
158     public void deleteAll() {
159         service().deleteAll();
160     }
161 
162     @Override
163     public void delete(final String username) {
164         try {
165             service().delete(username);
166         } catch (SyncopeClientException e) {
167             if (e.getType() == ClientExceptionType.NotFound) {
168                 LOG.info("Could not locate account for owner {}", username);
169             } else {
170                 LOG.error(e.getMessage(), e);
171             }
172         }
173     }
174 
175     @Override
176     public void delete(final long id) {
177         service().delete(id);
178     }
179 
180     @Override
181     public long count() {
182         return service().list().getTotalCount();
183     }
184 
185     @Override
186     public long count(final String username) {
187         try {
188             return service().read(username).getTotalCount();
189         } catch (SyncopeClientException e) {
190             if (e.getType() == ClientExceptionType.NotFound) {
191                 LOG.info("Could not locate account for owner {}", username);
192             } else {
193                 LOG.error(e.getMessage(), e);
194             }
195             return 0L;
196         }
197     }
198 }