Merge branch 'release/5.45.0'
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / application / RunAsAuthenticator.java
1 /**
2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.cdm.api.application;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13
14 import org.apache.logging.log4j.LogManager;
15 import org.apache.logging.log4j.Logger;
16 import org.springframework.security.access.intercept.RunAsUserToken;
17 import org.springframework.security.authentication.AnonymousAuthenticationToken;
18 import org.springframework.security.authentication.AuthenticationProvider;
19 import org.springframework.security.core.Authentication;
20 import org.springframework.security.core.GrantedAuthority;
21 import org.springframework.security.core.context.SecurityContext;
22 import org.springframework.security.core.context.SecurityContextHolder;
23
24 /**
25 *
26 * Helper class to work around the apparently broken @RunAs("ROLE_ADMIN")
27 * in spring see: https://jira.springsource.org/browse/SEC-1671
28 *
29 * @author a.kohlbecker
30 * @since Jul 24, 2017
31 */
32 public class RunAsAuthenticator {
33
34 private static final Logger logger = LogManager.getLogger();
35
36 /**
37 * must match the key in eu/etaxonomy/cdm/services_security.xml
38 */
39 private static final String RUN_AS_KEY = "TtlCx3pgKC4l";
40
41 // not to be autowired, since the FirstdataInserter must be usable without security
42 private AuthenticationProvider runAsAuthenticationProvider = null;
43
44 private Authentication authentication;
45
46 /**
47 * needed to work around the broken @RunAs("ROLE_ADMIN") which seems to be
48 * broken in spring see: https://jira.springsource.org/browse/SEC-1671
49 * @param ga
50 */
51 public void runAsAuthentication(GrantedAuthority ga) {
52 if(runAsAuthenticationProvider == null){
53 logger.debug("no RunAsAuthenticationProvider set, skipping run-as authentication");
54 return;
55 }
56
57 SecurityContext securityContext = SecurityContextHolder.getContext();
58 authentication = securityContext.getAuthentication();
59
60 Collection<GrantedAuthority> rules = new ArrayList<>();
61 rules.add(ga);
62 RunAsUserToken adminToken = new RunAsUserToken(
63 RUN_AS_KEY,
64 "system-admin",
65 null,
66 rules,
67 (authentication != null ? authentication.getClass() : AnonymousAuthenticationToken.class));
68
69 Authentication runAsAuthentication = runAsAuthenticationProvider.authenticate(adminToken);
70 SecurityContextHolder.getContext().setAuthentication(runAsAuthentication);
71
72 logger.debug("switched to run-as authentication: " + runAsAuthentication);
73 }
74
75 /**
76 * needed to work around the broken @RunAs("ROLE_ADMIN") which
77 * seems to be broken in spring see: https://jira.springsource.org/browse/SEC-1671
78 */
79 public void restoreAuthentication() {
80 if(runAsAuthenticationProvider == null){
81 logger.debug("no RunAsAuthenticationProvider set, thus nothing to restore");
82 }
83 SecurityContext securityContext = SecurityContextHolder.getContext();
84 securityContext.setAuthentication(authentication);
85 logger.debug("last authentication restored: " + (authentication != null ? authentication : "NULL"));
86 }
87
88 public AuthenticationProvider getRunAsAuthenticationProvider() {
89 return runAsAuthenticationProvider;
90 }
91 public void setRunAsAuthenticationProvider(AuthenticationProvider runAsAuthenticationProvider) {
92 this.runAsAuthenticationProvider = runAsAuthenticationProvider;
93 }
94 }