]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoLoginModule.java
43c54408390bb619490bfe392be40a4e108eee88
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.jackrabbit / src / main / java / org / argeo / security / jackrabbit / ArgeoLoginModule.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.security.jackrabbit;
17
18 import java.security.Principal;
19 import java.security.acl.Group;
20 import java.util.LinkedHashSet;
21 import java.util.Map;
22 import java.util.Set;
23
24 import javax.jcr.Credentials;
25 import javax.jcr.RepositoryException;
26 import javax.jcr.Session;
27 import javax.jcr.SimpleCredentials;
28 import javax.security.auth.callback.CallbackHandler;
29 import javax.security.auth.login.LoginException;
30
31 import org.apache.jackrabbit.core.security.AnonymousPrincipal;
32 import org.apache.jackrabbit.core.security.authentication.AbstractLoginModule;
33 import org.apache.jackrabbit.core.security.authentication.Authentication;
34 import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
35 import org.argeo.security.SystemAuthentication;
36 import org.springframework.security.GrantedAuthority;
37 import org.springframework.security.context.SecurityContextHolder;
38 import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken;
39
40 /** Jackrabbit login mechanism based on Spring Security */
41 public class ArgeoLoginModule extends AbstractLoginModule {
42 private String adminRole = "ROLE_ADMIN";
43
44 @SuppressWarnings("unused")
45 @Override
46 public boolean login() throws LoginException {
47 boolean loginOk = super.login();
48 if (!loginOk) {
49 org.springframework.security.Authentication authen = (org.springframework.security.Authentication) SecurityContextHolder
50 .getContext().getAuthentication();
51 }
52 return loginOk;
53 }
54
55 @SuppressWarnings("unused")
56 @Override
57 public boolean commit() throws LoginException {
58 boolean commitOk = super.commit();
59 if (!commitOk) {
60 org.springframework.security.Authentication authen = (org.springframework.security.Authentication) SecurityContextHolder
61 .getContext().getAuthentication();
62 }
63 return commitOk;
64 }
65
66 /**
67 * Returns the Spring {@link org.springframework.security.Authentication}
68 * (which can be null)
69 */
70 @Override
71 protected Principal getPrincipal(Credentials credentials) {
72 org.springframework.security.Authentication authen = SecurityContextHolder
73 .getContext().getAuthentication();
74 return authen;
75 }
76
77 protected Set<Principal> getPrincipals() {
78 // clear already registered Jackrabbit principals
79 // clearPrincipals(AdminPrincipal.class);
80 // clearPrincipals(AnonymousPrincipal.class);
81 // clearPrincipals(GrantedAuthorityPrincipal.class);
82
83 return syncPrincipals();
84 }
85
86 protected Set<Principal> syncPrincipals() {
87 // use linked HashSet instead of HashSet in order to maintain the order
88 // of principals (as in the Subject).
89 org.springframework.security.Authentication authen = (org.springframework.security.Authentication) principal;
90
91 Set<Principal> principals = new LinkedHashSet<Principal>();
92 principals.add(authen);
93
94 if (authen instanceof SystemAuthentication) {
95 principals.add(new AdminPrincipal(authen.getName()));
96 principals.add(new ArgeoSystemPrincipal(authen.getName()));
97 } else if (authen instanceof AnonymousAuthenticationToken) {
98 principals.add(new AnonymousPrincipal());
99 } else {
100 for (GrantedAuthority ga : authen.getAuthorities()) {
101 principals.add(new GrantedAuthorityPrincipal(ga));
102 // FIXME: make it more generic
103 if (adminRole.equals(ga.getAuthority()))
104 principals.add(new AdminPrincipal(authen.getName()));
105 }
106 }
107
108 // remove previous credentials
109 Set<SimpleCredentials> thisCredentials = subject
110 .getPublicCredentials(SimpleCredentials.class);
111 if (thisCredentials != null)
112 thisCredentials.clear();
113 // override credentials since we did not used the one passed to us
114 // credentials = new SimpleCredentials(authen.getName(), authen
115 // .getCredentials().toString().toCharArray());
116
117 return principals;
118 }
119
120 /**
121 * Super implementation removes all {@link Principal}, the Spring
122 * {@link org.springframework.security.Authentication} as well. Here we
123 * simply clear Jackrabbit related {@link Principal}s.
124 */
125 @Override
126 public boolean logout() throws LoginException {
127 clearPrincipals(AdminPrincipal.class);
128 clearPrincipals(ArgeoSystemPrincipal.class);
129 clearPrincipals(AnonymousPrincipal.class);
130 clearPrincipals(GrantedAuthorityPrincipal.class);
131
132 // we resync with Spring Security since the subject may have been reused
133 // in beetween
134 // TODO: check if this is clean
135 // subject.getPrincipals().addAll(syncPrincipals());
136
137 return true;
138 }
139
140 private <T extends Principal> void clearPrincipals(Class<T> clss) {
141 Set<T> principals = subject.getPrincipals(clss);
142 if (principals != null)
143 principals.clear();
144 }
145
146 @SuppressWarnings("rawtypes")
147 @Override
148 protected void doInit(CallbackHandler callbackHandler, Session session,
149 Map options) throws LoginException {
150 }
151
152 @Override
153 protected boolean impersonate(Principal principal, Credentials credentials)
154 throws RepositoryException, LoginException {
155 throw new UnsupportedOperationException(
156 "Impersonation is not yet supported");
157 }
158
159 @Override
160 protected Authentication getAuthentication(final Principal principal,
161 Credentials creds) throws RepositoryException {
162 if (principal instanceof Group) {
163 return null;
164 }
165 return new Authentication() {
166 public boolean canHandle(Credentials credentials) {
167 return principal instanceof org.springframework.security.Authentication;
168 }
169
170 public boolean authenticate(Credentials credentials)
171 throws RepositoryException {
172 return ((org.springframework.security.Authentication) principal)
173 .isAuthenticated();
174 }
175 };
176 }
177
178 }