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.core.logic;
20  
21  import java.lang.reflect.Method;
22  import java.time.OffsetDateTime;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.stream.Collectors;
26  import org.apache.commons.lang3.tuple.Pair;
27  import org.apache.syncope.common.lib.SyncopeClientException;
28  import org.apache.syncope.common.lib.to.AccessTokenTO;
29  import org.apache.syncope.common.lib.types.CipherAlgorithm;
30  import org.apache.syncope.common.lib.types.ClientExceptionType;
31  import org.apache.syncope.common.lib.types.IdRepoEntitlement;
32  import org.apache.syncope.core.persistence.api.dao.AccessTokenDAO;
33  import org.apache.syncope.core.persistence.api.dao.NotFoundException;
34  import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
35  import org.apache.syncope.core.persistence.api.entity.AccessToken;
36  import org.apache.syncope.core.provisioning.api.data.AccessTokenDataBinder;
37  import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
38  import org.apache.syncope.core.spring.security.AuthContextUtils;
39  import org.apache.syncope.core.spring.security.Encryptor;
40  import org.apache.syncope.core.spring.security.SecurityProperties;
41  import org.springframework.security.access.prepost.PreAuthorize;
42  
43  public class AccessTokenLogic extends AbstractTransactionalLogic<AccessTokenTO> {
44  
45      protected static final Encryptor ENCRYPTOR = Encryptor.getInstance();
46  
47      protected static byte[] getAuthorities() {
48          byte[] authorities = null;
49          try {
50              authorities = ENCRYPTOR.encode(POJOHelper.serialize(
51                      AuthContextUtils.getAuthorities()), CipherAlgorithm.AES).
52                      getBytes();
53          } catch (Exception e) {
54              LOG.error("Could not fetch authorities", e);
55          }
56  
57          return authorities;
58      }
59  
60      protected final SecurityProperties securityProperties;
61  
62      protected final AccessTokenDataBinder binder;
63  
64      protected final AccessTokenDAO accessTokenDAO;
65  
66      public AccessTokenLogic(
67              final SecurityProperties securityProperties,
68              final AccessTokenDataBinder binder,
69              final AccessTokenDAO accessTokenDAO) {
70  
71          this.securityProperties = securityProperties;
72          this.binder = binder;
73          this.accessTokenDAO = accessTokenDAO;
74      }
75  
76      @PreAuthorize("isAuthenticated()")
77      public Pair<String, OffsetDateTime> login() {
78          if (securityProperties.getAnonymousUser().equals(AuthContextUtils.getUsername())) {
79              SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRequest);
80              sce.getElements().add(securityProperties.getAnonymousUser() + " cannot be granted an access token");
81              throw sce;
82          }
83  
84          return binder.create(
85                  AuthContextUtils.getUsername(),
86                  Collections.<String, Object>emptyMap(),
87                  getAuthorities(),
88                  false);
89      }
90  
91      @PreAuthorize("isAuthenticated()")
92      public Pair<String, OffsetDateTime> refresh() {
93          AccessToken accessToken = accessTokenDAO.findByOwner(AuthContextUtils.getUsername());
94          if (accessToken == null) {
95              throw new NotFoundException("AccessToken for " + AuthContextUtils.getUsername());
96          }
97  
98          return binder.update(accessToken, getAuthorities());
99      }
100 
101     @PreAuthorize("isAuthenticated()")
102     public void logout() {
103         AccessToken accessToken = accessTokenDAO.findByOwner(AuthContextUtils.getUsername());
104         if (accessToken == null) {
105             throw new NotFoundException("AccessToken for " + AuthContextUtils.getUsername());
106         }
107 
108         delete(accessToken.getKey());
109     }
110 
111     @PreAuthorize("hasRole('" + IdRepoEntitlement.ACCESS_TOKEN_LIST + "')")
112     public Pair<Integer, List<AccessTokenTO>> list(
113             final int page,
114             final int size,
115             final List<OrderByClause> orderByClauses) {
116 
117         Integer count = accessTokenDAO.count();
118 
119         List<AccessTokenTO> result = accessTokenDAO.findAll(page, size, orderByClauses).stream().
120                 map(binder::getAccessTokenTO).collect(Collectors.toList());
121 
122         return Pair.of(count, result);
123     }
124 
125     @PreAuthorize("hasRole('" + IdRepoEntitlement.ACCESS_TOKEN_DELETE + "')")
126     public void delete(final String key) {
127         accessTokenDAO.delete(key);
128     }
129 
130     @Override
131     protected AccessTokenTO resolveReference(final Method method, final Object... args)
132             throws UnresolvedReferenceException {
133 
134         throw new UnresolvedReferenceException();
135     }
136 }