]> git.argeo.org Git - lgpl/argeo-commons.git/blob - RemoteAuthUtils.java
cf30d8a715ea72cca0d8916ce9d9925081e478e8
[lgpl/argeo-commons.git] / RemoteAuthUtils.java
1 package org.argeo.cms.auth;
2
3 import java.security.AccessControlContext;
4 import java.security.AccessController;
5 import java.security.PrivilegedAction;
6 import java.util.Base64;
7 import java.util.function.Supplier;
8
9 import javax.security.auth.Subject;
10 import javax.security.auth.kerberos.KerberosTicket;
11
12 import org.argeo.api.cms.CmsSession;
13 import org.argeo.cms.internal.runtime.CmsContextImpl;
14 import org.ietf.jgss.GSSContext;
15 import org.ietf.jgss.GSSException;
16 import org.ietf.jgss.GSSManager;
17 import org.ietf.jgss.GSSName;
18 import org.ietf.jgss.Oid;
19
20 /** Remote authentication utilities. */
21 public class RemoteAuthUtils {
22 static final String REMOTE_USER = "org.osgi.service.http.authentication.remote.user";
23 private final static Oid KERBEROS_OID;
24 // private final static Oid KERB_V5_OID, KRB5_PRINCIPAL_NAME_OID;
25 static {
26 try {
27 KERBEROS_OID = new Oid("1.3.6.1.5.5.2");
28 // KERB_V5_OID = new Oid("1.2.840.113554.1.2.2");
29 // KRB5_PRINCIPAL_NAME_OID = new Oid("1.2.840.113554.1.2.2.1");
30 } catch (GSSException e) {
31 throw new IllegalStateException("Cannot create Kerberos OID", e);
32 }
33 }
34
35 /**
36 * Execute this supplier, using the CMS class loader as context classloader.
37 * Useful to log in to JCR.
38 */
39 public final static <T> T doAs(Supplier<T> supplier, RemoteAuthRequest req) {
40 ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
41 Thread.currentThread().setContextClassLoader(RemoteAuthUtils.class.getClassLoader());
42 try {
43 return Subject.doAs(
44 Subject.getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName())),
45 new PrivilegedAction<T>() {
46
47 @Override
48 public T run() {
49 return supplier.get();
50 }
51
52 });
53 } finally {
54 Thread.currentThread().setContextClassLoader(currentContextCl);
55 }
56 }
57
58 public final static void configureRequestSecurity(RemoteAuthRequest req) {
59 if (req.getAttribute(AccessControlContext.class.getName()) != null)
60 throw new IllegalStateException("Request already authenticated.");
61 AccessControlContext acc = AccessController.getContext();
62 req.setAttribute(REMOTE_USER, CurrentUser.getUsername());
63 req.setAttribute(AccessControlContext.class.getName(), acc);
64 }
65
66 public final static void clearRequestSecurity(RemoteAuthRequest req) {
67 if (req.getAttribute(AccessControlContext.class.getName()) == null)
68 throw new IllegalStateException("Cannot clear non-authenticated request.");
69 req.setAttribute(REMOTE_USER, null);
70 req.setAttribute(AccessControlContext.class.getName(), null);
71 }
72
73 public static CmsSession getCmsSession(RemoteAuthRequest req) {
74 Subject subject = Subject
75 .getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName()));
76 CmsSession cmsSession = CmsContextImpl.getCmsContext().getCmsSession(subject);
77 return cmsSession;
78 }
79
80 public static String getGssToken(Subject subject, String service, String server) {
81 if (subject.getPrivateCredentials(KerberosTicket.class).isEmpty())
82 throw new IllegalArgumentException("Subject " + subject + " is not GSS authenticated.");
83 return Subject.doAs(subject, (PrivilegedAction<String>) () -> {
84 // !! different format than Kerberos
85 String serverPrinc = service + "@" + server;
86 GSSContext context = null;
87 String tokenStr = null;
88
89 try {
90 // Get service's principal name
91 GSSManager manager = GSSManager.getInstance();
92 // GSSName serverName = manager.createName(serverPrinc,
93 // GSSName.NT_HOSTBASED_SERVICE, KERBEROS_OID);
94 GSSName serverName = manager.createName(serverPrinc, GSSName.NT_HOSTBASED_SERVICE);
95
96 // Get the context for authentication
97 context = manager.createContext(serverName, KERBEROS_OID, null, GSSContext.DEFAULT_LIFETIME);
98 // context.requestMutualAuth(true); // Request mutual authentication
99 // context.requestConf(true); // Request confidentiality
100 context.requestCredDeleg(true);
101
102 byte[] token = new byte[0];
103
104 // token is ignored on the first call
105 token = context.initSecContext(token, 0, token.length);
106
107 // Send a token to the server if one was generated by
108 // initSecContext
109 if (token != null) {
110 tokenStr = Base64.getEncoder().encodeToString(token);
111 // complete=true;
112 }
113 return tokenStr;
114
115 } catch (GSSException e) {
116 throw new IllegalStateException("Cannot authenticate to " + serverPrinc, e);
117 }
118 });
119 }
120 }