]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoLoginModule.java
Clean up Jackrabbit Security
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.jackrabbit / src / main / java / org / argeo / security / jackrabbit / ArgeoLoginModule.java
1 package org.argeo.security.jackrabbit;
2
3 import java.security.Principal;
4 import java.security.acl.Group;
5 import java.util.LinkedHashSet;
6 import java.util.Map;
7 import java.util.Set;
8
9 import javax.jcr.Credentials;
10 import javax.jcr.RepositoryException;
11 import javax.jcr.Session;
12 import javax.jcr.SimpleCredentials;
13 import javax.security.auth.callback.CallbackHandler;
14 import javax.security.auth.login.LoginException;
15
16 import org.apache.jackrabbit.core.security.AnonymousPrincipal;
17 import org.apache.jackrabbit.core.security.authentication.AbstractLoginModule;
18 import org.apache.jackrabbit.core.security.authentication.Authentication;
19 import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
20 import org.argeo.security.SystemAuthentication;
21 import org.springframework.security.GrantedAuthority;
22 import org.springframework.security.context.SecurityContextHolder;
23 import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken;
24
25 /** Jackrabbit login mechanism based on Spring Security */
26 public class ArgeoLoginModule extends AbstractLoginModule {
27 private String adminRole = "ROLE_ADMIN";
28
29 /**
30 * Returns the Spring {@link org.springframework.security.Authentication}
31 * (which can be null)
32 */
33 @Override
34 protected Principal getPrincipal(Credentials credentials) {
35 org.springframework.security.Authentication authen = SecurityContextHolder
36 .getContext().getAuthentication();
37 return authen;
38 }
39
40 protected Set<Principal> getPrincipals() {
41 // clear already registered Jackrabbit principals
42 //clearPrincipals(AdminPrincipal.class);
43 //clearPrincipals(AnonymousPrincipal.class);
44 //clearPrincipals(GrantedAuthorityPrincipal.class);
45
46 return syncPrincipals();
47 }
48
49 protected Set<Principal> syncPrincipals() {
50 // use linked HashSet instead of HashSet in order to maintain the order
51 // of principals (as in the Subject).
52 org.springframework.security.Authentication authen = (org.springframework.security.Authentication) principal;
53
54 Set<Principal> principals = new LinkedHashSet<Principal>();
55 principals.add(authen);
56
57 if (authen instanceof SystemAuthentication) {
58 principals.add(new AdminPrincipal(authen.getName()));
59 principals.add(new ArgeoSystemPrincipal(authen.getName()));
60 } else if (authen instanceof AnonymousAuthenticationToken) {
61 principals.add(new AnonymousPrincipal());
62 } else {
63 for (GrantedAuthority ga : authen.getAuthorities()) {
64 principals.add(new GrantedAuthorityPrincipal(ga));
65 // FIXME: make it more generic
66 if (adminRole.equals(ga.getAuthority()))
67 principals.add(new AdminPrincipal(authen.getName()));
68 }
69 }
70
71 // remove previous credentials
72 Set<SimpleCredentials> thisCredentials = subject
73 .getPublicCredentials(SimpleCredentials.class);
74 if (thisCredentials != null)
75 thisCredentials.clear();
76 // override credentials since we did not used the one passed to us
77 // credentials = new SimpleCredentials(authen.getName(), authen
78 // .getCredentials().toString().toCharArray());
79
80 return principals;
81 }
82
83 /**
84 * Super implementation removes all {@link Principal}, the Spring
85 * {@link org.springframework.security.Authentication} as well. Here we
86 * simply clear Jackrabbit related {@link Principal}s.
87 */
88 @Override
89 public boolean logout() throws LoginException {
90 clearPrincipals(AdminPrincipal.class);
91 clearPrincipals(ArgeoSystemPrincipal.class);
92 clearPrincipals(AnonymousPrincipal.class);
93 clearPrincipals(GrantedAuthorityPrincipal.class);
94
95 // we resync with Spring Security since the subject may have been reused
96 // in beetween
97 // TODO: check if this is clean
98 // subject.getPrincipals().addAll(syncPrincipals());
99
100 return true;
101 }
102
103 private <T extends Principal> void clearPrincipals(Class<T> clss) {
104 Set<T> principals = subject.getPrincipals(clss);
105 if (principals != null)
106 principals.clear();
107 }
108
109 @SuppressWarnings("rawtypes")
110 @Override
111 protected void doInit(CallbackHandler callbackHandler, Session session,
112 Map options) throws LoginException {
113 }
114
115 @Override
116 protected boolean impersonate(Principal principal, Credentials credentials)
117 throws RepositoryException, LoginException {
118 throw new UnsupportedOperationException(
119 "Impersonation is not yet supported");
120 }
121
122 @Override
123 protected Authentication getAuthentication(final Principal principal,
124 Credentials creds) throws RepositoryException {
125 if (principal instanceof Group) {
126 return null;
127 }
128 return new Authentication() {
129 public boolean canHandle(Credentials credentials) {
130 return principal instanceof org.springframework.security.Authentication;
131 }
132
133 public boolean authenticate(Credentials credentials)
134 throws RepositoryException {
135 return ((org.springframework.security.Authentication) principal)
136 .isAuthenticated();
137 }
138 };
139 }
140
141 }