blob: 46bcc4b1da9de31f40577fa98aad5149df67429c [file] [log] [blame]
/*
* Copyright (c) 2020 Kentyou.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kentyou - initial API and implementation
*/
package org.eclipse.sensinact.gateway.security.oauth2;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
import java.util.regex.Pattern;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.sensinact.gateway.protocol.http.client.ConnectionConfigurationImpl;
import org.eclipse.sensinact.gateway.protocol.http.client.SimpleRequest;
import org.eclipse.sensinact.gateway.protocol.http.client.SimpleResponse;
import org.eclipse.sensinact.gateway.util.crypto.Base64;
import org.json.JSONArray;
import org.json.JSONObject;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
public class OpenIDServer extends IdentityServerWrapper implements oAuthServer {
private Hashtable<String, UserInfo> credentials;
UserInfo anonymous;
URI authEP;
URI tokenEP;
URI userinfoEP;
String publicKey;
String client_id;
String client_secret;
String issuer;
StringBuilder returnToUrl;
String localAuth;
Properties properties;
public OpenIDServer(BundleContext context, String configfile) {
anonymous = new OpenID();
String discoveryURL = null;
String certsURL = null;
try {
properties = new Properties();
properties.load(new FileInputStream(configfile));
discoveryURL = properties.getProperty("discoveryURL").toString();
certsURL = properties.getProperty("certsURL");
client_id = properties.getProperty("client_id").toString();
client_secret = properties.getProperty("client_secret").toString();
Bundle bundles[] = context.getBundles();
for (Bundle bundle : bundles) {
checkBundle(bundle);
}
context.addBundleListener(new BundleListener() {
public void bundleChanged(BundleEvent e) {
checkBundle(e.getBundle());
}
});
} catch (Exception e) {
e.printStackTrace();
}
credentials = new Hashtable<String, UserInfo>();
localAuth = System.getProperty(AUTH_BASEURL_PROP, AUTH_BASEURL_DEFAULT);
try {
ConnectionConfigurationImpl conf = new ConnectionConfigurationImpl();
conf.setHttpMethod("GET");
conf.setAccept("application/json");
conf.setUri(discoveryURL.toString());
SimpleResponse response = new SimpleRequest(conf).send();
int status = response.getStatusCode();
if (status == 200) {
JSONObject jsonObject = new JSONObject(new String(response.getContent(), "UTF-8"));
authEP = new URI(jsonObject.getString("authorization_endpoint"));
tokenEP = new URI(jsonObject.getString("token_endpoint"));
userinfoEP = new URI(jsonObject.getString("userinfo_endpoint"));
issuer = jsonObject.getString("issuer");
}
conf = new ConnectionConfigurationImpl();
conf.setHttpMethod("GET");
conf.setAccept("application/json");
conf.setUri(certsURL.toString());
response = new SimpleRequest(conf).send();
status = response.getStatusCode();
if (status == 200) {
JSONArray array = new JSONObject(new String(response.getContent(), "UTF-8")).getJSONArray("keys");
JSONObject keys = array.getJSONObject(0);
publicKey = new StringBuilder(
).append(keys.getString("n")
).append("."
).append(keys.getString("e")
).toString();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void checkBundle(Bundle bundle) {
String bundlename = bundle.getSymbolicName();
String bundleconfig;
bundleconfig = properties.getProperty(bundlename);
if (bundleconfig != null) {
String configs[] = bundleconfig.split(":");
register(configs[0], configs[1], Pattern.compile(configs[2]));
}
int i = 0;
bundleconfig = properties.getProperty(bundlename + "[" + i + "]");
while (bundleconfig != null) {
String configs[] = bundleconfig.split(":");
register(configs[0], configs[1], Pattern.compile(configs[2]));
i++;
bundleconfig = properties.getProperty(bundlename + "[" + i + "]");
}
try {
Properties properties2 = new Properties();
FileInputStream input = new FileInputStream("cfgs/" + bundlename + ".config");
properties2.load(input);
bundleconfig = properties2.getProperty("securityfilter");
if (bundleconfig != null) {
String configs[] = bundleconfig.split(":");
register(configs[0], configs[1], Pattern.compile(configs[2]));
}
i = 0;
bundleconfig = properties2.getProperty("securityfilter[" + i + "]");
while (bundleconfig != null) {
String configs[] = bundleconfig.split(":");
register(configs[0], configs[1], Pattern.compile(configs[2]));
i++;
bundleconfig = properties2.getProperty("securityfilter[" + i + "]");
}
} catch (IOException e) {
}
}
String getClientId() {
return client_id;
}
String getClientSecret() {
return client_secret;
}
String getPublicKey() {
return publicKey;
}
/**********************************************/
/** oAuthServer API **/
/**********************************************/
@Override
public JSONObject verify(String code, ServletRequest req) {
JSONObject jsonObject = null;
ConnectionConfigurationImpl conf = new ConnectionConfigurationImpl();
conf.setHttpMethod("POST");
conf.setContentType("application/x-www-form-urlencoded");
try {
conf.setUri(tokenEP.toURL().toExternalForm());
String credentials = new String(client_id + ":" + client_secret);
String basic = Base64.encodeBytes(credentials.getBytes(StandardCharsets.UTF_8));
conf.addHeader("Authorization", "Basic " + basic);
StringBuilder urlParameters = new StringBuilder();
if (returnToUrl == null) {
returnToUrl = new StringBuilder().append(req.getScheme()
).append("://").append(req.getServerName()).append(":"
).append(req.getServerPort()).append(localAuth);
}
urlParameters.append("redirect_uri=");
urlParameters.append(returnToUrl.toString());
urlParameters.append("&client_id=");
urlParameters.append(client_id);
urlParameters.append("&code=");
urlParameters.append(code);
urlParameters.append("&scope=openid%20roles");
urlParameters.append("&grant_type=authorization_code");
urlParameters.append("&response_type=id_token%20token");
conf.setContent(urlParameters.toString());
String access_token = null;
SimpleResponse response;
try {
response = new SimpleRequest(conf).send();
int status = response.getStatusCode();
if (status == 200) {
jsonObject = new JSONObject(new String(response.getContent(),"UTF-8"));
access_token = jsonObject.getString("access_token");
}
} catch (Exception e) {
e.printStackTrace();
}
if (access_token != null) {
return jsonObject;
}
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
return null;
}
@Override
public boolean handleSecurity(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
if (localAuth.equals(req.getPathInfo()))
return true;
try {
returnToUrl = new StringBuilder().append(req.getScheme()
).append("://").append(req.getServerName()).append(":"
).append(req.getServerPort()).append(localAuth);
StringBuilder builder= new StringBuilder().append(authEP.getScheme()
).append("://").append(authEP.getHost()).append(":"
).append(authEP.getPort()).append(authEP.getPath()
).append("?").append("redirect_uri"
).append("=").append(returnToUrl.toString()
).append("&").append("client_id").append("="
).append(client_id).append("&").append("scope"
).append("=").append("openid%20profile%20roles"
).append("&").append("response_type").append("="
).append("code");
res.sendRedirect(builder.toString());
HttpSession session = req.getSession();
session.setAttribute("redirect_uri", req.getRequestURI());
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public UserInfo check(String access_token) throws IOException {
OpenID found = (OpenID) credentials.get(access_token);
if (found != null)
return found;
try {
found = new OpenID(this, access_token);
if (found.isValid())
return found;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String basicToken(ServletRequest request, String authorization) {
try {
ConnectionConfigurationImpl conf = new ConnectionConfigurationImpl();
conf.setHttpMethod("POST");
conf.setContentType("application/x-www-form-urlencoded");
conf.setUri(tokenEP.toURL().toExternalForm());
String credentials = new String(client_id + ":" + client_secret);
String basic = Base64.encodeBytes(credentials.getBytes(StandardCharsets.UTF_8));
conf.addHeader("Authorization", "Basic " + basic);
StringBuilder urlParameters = new StringBuilder();
HttpServletRequest req = (HttpServletRequest) request;
if (returnToUrl == null) {
returnToUrl = new StringBuilder().append(req.getScheme()
).append("://").append(req.getServerName()).append(":"
).append(req.getServerPort()).append(localAuth);
}
String credentialsStr = new String(Base64.decode(authorization.substring(6)));
String credentialsArr[] = credentialsStr.split(":");
String username = credentialsArr[0];
String password = credentialsArr[1];
urlParameters.append("redirect_uri=");
urlParameters.append(returnToUrl.toString());
urlParameters.append("&client_id=");
urlParameters.append(client_id);
urlParameters.append("&username=");
urlParameters.append(username);
urlParameters.append("&password=");
urlParameters.append(password);
urlParameters.append("&scope=openid%20roles");
urlParameters.append("&grant_type=password");
urlParameters.append("&response_type=id_token%20token");
conf.setContent(urlParameters.toString());
SimpleResponse response = new SimpleRequest(conf).send();
int status = response.getStatusCode();
if (status == 200) {
JSONObject obj = new JSONObject(new String(response.getContent(),"UTF-8"));
return obj.getString("access_token");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public UserInfo anonymous() {
return anonymous;
}
public void addCredentials(String token, UserInfo newUser) {
((OpenID) newUser).add("access_token", token);
credentials.put(token, newUser);
}
/**********************************************/
/** IdentityServer API **/
/**********************************************/
@Override
public UserInfo getUserInfo(String token, String authorization) {
OpenID user = null;
try {
ConnectionConfigurationImpl conf = new ConnectionConfigurationImpl();
conf.setHttpMethod("GET");
conf.setUri(userinfoEP.toURL().toExternalForm()+ "?client_id=" + client_id);
conf.addHeader("Authorization", "Bearer " + authorization);
SimpleResponse response = new SimpleRequest(conf).send();
String resp = new String(response.getContent(),"UTF-8");
int status = response.getStatusCode();
if (status == 200) {
JSONObject jsonObject = new JSONObject(resp);
user = new OpenID(jsonObject);
Iterator<?> it = jsonObject.keys();
while (it.hasNext()) {
String key = String.valueOf(it.next());
user.put(key, jsonObject.get(key));
}
} else {
System.out.println(userinfoEP + " response : " + status);
System.out.println(response.getHeaders());
System.out.println("error " + resp);
}
} catch (Exception e) {
e.printStackTrace();
}
return user;
}
public boolean check(UserInfo user, ServletRequest request) {
return super.check(user, request);
}
}