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 java.util.Collection;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Optional;
25 import java.util.Set;
26 import java.util.concurrent.Callable;
27 import java.util.stream.Collectors;
28 import org.apache.commons.lang3.StringUtils;
29 import org.apache.syncope.common.lib.SyncopeConstants;
30 import org.apache.syncope.common.lib.types.EntitlementsHolder;
31 import org.apache.syncope.core.persistence.api.dao.UserDAO;
32 import org.apache.syncope.core.spring.ApplicationContextProvider;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
36 import org.springframework.security.core.Authentication;
37 import org.springframework.security.core.GrantedAuthority;
38 import org.springframework.security.core.context.SecurityContextHolder;
39 import org.springframework.security.core.userdetails.User;
40
41 public final class AuthContextUtils {
42
43 private static final Logger LOG = LoggerFactory.getLogger(AuthContextUtils.class);
44
45 private static final String PLACEHOLDER_PWD = "PLACEHOLDER_PWD";
46
47 private static final String UNAUTHENTICATED = "unauthenticated";
48
49 public static String getUsername() {
50 Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
51 return authentication == null ? UNAUTHENTICATED : authentication.getName();
52 }
53
54 public static void updateUsername(final String newUsername) {
55 Authentication auth = SecurityContextHolder.getContext().getAuthentication();
56
57 UsernamePasswordAuthenticationToken newAuth = new UsernamePasswordAuthenticationToken(
58 new User(newUsername, PLACEHOLDER_PWD, auth.getAuthorities()),
59 auth.getCredentials(), auth.getAuthorities());
60 newAuth.setDetails(auth.getDetails());
61 SecurityContextHolder.getContext().setAuthentication(newAuth);
62 }
63
64 public static Optional<String> getDelegatedBy() {
65 Authentication auth = SecurityContextHolder.getContext().getAuthentication();
66
67 return auth != null && auth.getDetails() instanceof SyncopeAuthenticationDetails
68 ? Optional.ofNullable(SyncopeAuthenticationDetails.class.cast(auth.getDetails()).getDelegatedBy())
69 : Optional.empty();
70 }
71
72 public static String getWho() {
73 return getUsername() + getDelegatedBy().map(d -> {
74 String delegatedBy = callAsAdmin(getDomain(),
75 () -> ApplicationContextProvider.getApplicationContext().getBean(UserDAO.class).findUsername(d)).
76 orElse(d);
77 return " [delegated by " + delegatedBy + "]";
78 }).orElse(StringUtils.EMPTY);
79 }
80
81 public static Set<SyncopeGrantedAuthority> getAuthorities() {
82 return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()).
83 map(authentication -> authentication.getAuthorities().stream().
84 filter(SyncopeGrantedAuthority.class::isInstance).
85 map(SyncopeGrantedAuthority.class::cast).
86 collect(Collectors.toSet())).
87 orElse(Set.of());
88 }
89
90 public static Map<String, Set<String>> getAuthorizations() {
91 return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()).
92 map(authentication -> authentication.getAuthorities().stream().
93 filter(SyncopeGrantedAuthority.class::isInstance).
94 map(SyncopeGrantedAuthority.class::cast).
95 collect(Collectors.toMap(SyncopeGrantedAuthority::getAuthority, SyncopeGrantedAuthority::getRealms))).
96 orElse(Map.of());
97 }
98
99 public static String getDomain() {
100 Authentication auth = SecurityContextHolder.getContext().getAuthentication();
101
102 String domainKey = auth != null && auth.getDetails() instanceof SyncopeAuthenticationDetails
103 ? SyncopeAuthenticationDetails.class.cast(auth.getDetails()).getDomain()
104 : null;
105 if (StringUtils.isBlank(domainKey)) {
106 domainKey = SyncopeConstants.MASTER_DOMAIN;
107 }
108
109 return domainKey;
110 }
111
112 private static <T> T call(final Authentication authentication, final Callable<T> callable) {
113 Authentication original = SecurityContextHolder.getContext().getAuthentication();
114 SecurityContextHolder.getContext().setAuthentication(authentication);
115 try {
116 return callable.call();
117 } catch (Exception e) {
118 LOG.debug("Error during execution under authentication {}", authentication, e);
119 if (e instanceof RuntimeException) {
120 throw (RuntimeException) e;
121 } else {
122 throw new RuntimeException(e);
123 }
124 } finally {
125 SecurityContextHolder.getContext().setAuthentication(original);
126 }
127 }
128
129 public static <T> T callAs(
130 final String domain,
131 final String username,
132 final Collection<String> entitlements,
133 final Callable<T> callable) {
134
135 List<GrantedAuthority> authorities = entitlements.stream().
136 map(entitlement -> new SyncopeGrantedAuthority(entitlement, SyncopeConstants.ROOT_REALM)).
137 collect(Collectors.toList());
138 UsernamePasswordAuthenticationToken asAuth = new UsernamePasswordAuthenticationToken(
139 new User(username, PLACEHOLDER_PWD, authorities), PLACEHOLDER_PWD, authorities);
140 asAuth.setDetails(new SyncopeAuthenticationDetails(domain, getDelegatedBy().orElse(null)));
141
142 return call(asAuth, callable);
143 }
144
145 public static <T> T callAsAdmin(final String domain, final Callable<T> callable) {
146 SecurityProperties properties = ApplicationContextProvider.getBeanFactory().getBean(SecurityProperties.class);
147 return callAs(
148 domain,
149 properties.getAdminUser(),
150 EntitlementsHolder.getInstance().getValues(),
151 callable);
152 }
153
154
155
156
157 private AuthContextUtils() {
158 }
159 }