]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoLoginModule.java
b1da974da67763695ca0484bf158edf7946721c0
[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 Mathieu Baudier
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 @Override
45 public boolean login() throws LoginException {
46 boolean loginOk = super.login();
47 if (!loginOk) {
48 org.springframework.security.Authentication authen = (org.springframework.security.Authentication) SecurityContextHolder
49 .getContext().getAuthentication();
50 }
51 return loginOk;
52 }
53
54 @Override
55 public boolean commit() throws LoginException {
56 boolean commitOk = super.commit();
57 if (!commitOk) {
58 org.springframework.security.Authentication authen = (org.springframework.security.Authentication) SecurityContextHolder
59 .getContext().getAuthentication();
60 }
61 return commitOk;
62 }
63
64 /**
65 * Returns the Spring {@link org.springframework.security.Authentication}
66 * (which can be null)
67 */
68 @Override
69 protected Principal getPrincipal(Credentials credentials) {
70 org.springframework.security.Authentication authen = SecurityContextHolder
71 .getContext().getAuthentication();
72 return authen;
73 }
74
75 protected Set<Principal> getPrincipals() {
76 // clear already registered Jackrabbit principals
77 // clearPrincipals(AdminPrincipal.class);
78 // clearPrincipals(AnonymousPrincipal.class);
79 // clearPrincipals(GrantedAuthorityPrincipal.class);
80
81 return syncPrincipals();
82 }
83
84 protected Set<Principal> syncPrincipals() {
85 // use linked HashSet instead of HashSet in order to maintain the order
86 // of principals (as in the Subject).
87 org.springframework.security.Authentication authen = (org.springframework.security.Authentication) principal;
88
89 Set<Principal> principals = new LinkedHashSet<Principal>();
90 principals.add(authen);
91
92 if (authen instanceof SystemAuthentication) {
93 principals.add(new AdminPrincipal(authen.getName()));
94 principals.add(new ArgeoSystemPrincipal(authen.getName()));
95 } else if (authen instanceof AnonymousAuthenticationToken) {
96 principals.add(new AnonymousPrincipal());
97 } else {
98 for (GrantedAuthority ga : authen.getAuthorities()) {
99 principals.add(new GrantedAuthorityPrincipal(ga));
100 // FIXME: make it more generic
101 if (adminRole.equals(ga.getAuthority()))
102 principals.add(new AdminPrincipal(authen.getName()));
103 }
104 }
105
106 // remove previous credentials
107 Set<SimpleCredentials> thisCredentials = subject
108 .getPublicCredentials(SimpleCredentials.class);
109 if (thisCredentials != null)
110 thisCredentials.clear();
111 // override credentials since we did not used the one passed to us
112 // credentials = new SimpleCredentials(authen.getName(), authen
113 // .getCredentials().toString().toCharArray());
114
115 return principals;
116 }
117
118 /**
119 * Super implementation removes all {@link Principal}, the Spring
120 * {@link org.springframework.security.Authentication} as well. Here we
121 * simply clear Jackrabbit related {@link Principal}s.
122 */
123 @Override
124 public boolean logout() throws LoginException {
125 clearPrincipals(AdminPrincipal.class);
126 clearPrincipals(ArgeoSystemPrincipal.class);
127 clearPrincipals(AnonymousPrincipal.class);
128 clearPrincipals(GrantedAuthorityPrincipal.class);
129
130 // we resync with Spring Security since the subject may have been reused
131 // in beetween
132 // TODO: check if this is clean
133 // subject.getPrincipals().addAll(syncPrincipals());
134
135 return true;
136 }
137
138 private <T extends Principal> void clearPrincipals(Class<T> clss) {
139 Set<T> principals = subject.getPrincipals(clss);
140 if (principals != null)
141 principals.clear();
142 }
143
144 @SuppressWarnings("rawtypes")
145 @Override
146 protected void doInit(CallbackHandler callbackHandler, Session session,
147 Map options) throws LoginException {
148 }
149
150 @Override
151 protected boolean impersonate(Principal principal, Credentials credentials)
152 throws RepositoryException, LoginException {
153 throw new UnsupportedOperationException(
154 "Impersonation is not yet supported");
155 }
156
157 @Override
158 protected Authentication getAuthentication(final Principal principal,
159 Credentials creds) throws RepositoryException {
160 if (principal instanceof Group) {
161 return null;
162 }
163 return new Authentication() {
164 public boolean canHandle(Credentials credentials) {
165 return principal instanceof org.springframework.security.Authentication;
166 }
167
168 public boolean authenticate(Credentials credentials)
169 throws RepositoryException {
170 return ((org.springframework.security.Authentication) principal)
171 .isAuthenticated();
172 }
173 };
174 }
175
176 }