Last active
August 14, 2016 08:04
-
-
Save aaronanderson/10d47edacd2f20d197117e3e0c04c30d to your computer and use it in GitHub Desktop.
E(FX)clipse Eclipse access secure P2 update site with custom certificate and oauth2/oidc authentication
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Application { | |
@Inject | |
IEclipseContext econtext; | |
// @Override | |
@PostConstruct | |
protected void jfxStart(IApplicationContext context, javafx.application.Application jfxApplication, Stage primaryStage) { | |
performUpdateCheck(); | |
ClientService clientService = ContextInjectionFactory.make(ClientService.class, econtext); | |
econtext.set(ClientService.class, clientService); | |
} | |
public static class StdProgressReporter implements ProgressReporter{ | |
@Override | |
public void taskUnitsChanged(String taskId, int totalUnits) { | |
System.out.format("Task units changed %s %d\n", taskId, totalUnits); | |
} | |
@Override | |
public void taskStart(String taskId, String parentTaskId, String taskName, int totalUnits, boolean cancelable) { | |
System.out.format("Task Start %s %s %s %d %s\n", taskId, parentTaskId, taskName, totalUnits, cancelable); | |
} | |
@Override | |
public void taskEnd(String taskId, boolean canceled) { | |
System.out.format("Task End %s %s \n", taskId, canceled); | |
} | |
@Override | |
public void progress(String taskId, String message, int unitsDone) { | |
System.out.format("Progress %s %s %d\n", taskId, message, unitsDone); | |
} | |
} | |
public void performUpdateCheck() { | |
// https://blog.codecentric.de/en/2015/04/add-p2-update-functionality-to-an-efxclipse-application-eclipse-rcp-cookbook/ | |
CancelableOperation<Optional<UpdatePlan>> check = updateService.checkUpdate(new StdProgressReporter()); | |
check.onComplete((updatePlan) -> { | |
System.out.format("Update Complete\n"); | |
if (updatePlan.isPresent()) { | |
System.out.format("Update available!\n"); | |
CancelableOperation result = updatePlan.get().runUpdate(new StdProgressReporter()); | |
result.onComplete((r) -> { | |
}); | |
} else { | |
System.out.format("Nothing to update\n"); | |
} | |
}); | |
check.onCancel(() -> System.out.format("Operation cancelled\n")); | |
check.onException(t -> { | |
String message = t.getStatus().getMessage(); | |
System.out.format("Update Error %s\n", message); | |
}); | |
System.out.println("MainController - end updates"); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.mercer.cpsg.workspace.app; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.security.KeyStore; | |
import java.security.cert.Certificate; | |
import java.security.cert.CertificateFactory; | |
import java.time.LocalDateTime; | |
import java.util.Base64; | |
import java.util.Optional; | |
import java.util.concurrent.atomic.AtomicReference; | |
import java.util.concurrent.locks.ReadWriteLock; | |
import java.util.concurrent.locks.ReentrantReadWriteLock; | |
import java.util.function.Supplier; | |
import javax.annotation.PostConstruct; | |
import javax.inject.Inject; | |
import javax.inject.Singleton; | |
import javax.json.JsonObject; | |
import javax.net.ssl.SSLContext; | |
import javax.net.ssl.TrustManagerFactory; | |
import javax.ws.rs.client.Client; | |
import javax.ws.rs.client.ClientBuilder; | |
import javax.ws.rs.client.ClientRequestContext; | |
import javax.ws.rs.client.ClientRequestFilter; | |
import javax.ws.rs.client.Entity; | |
import javax.ws.rs.client.WebTarget; | |
import javax.ws.rs.core.Form; | |
import javax.ws.rs.core.MediaType; | |
import javax.ws.rs.core.MultivaluedMap; | |
import javax.ws.rs.core.Response; | |
import org.eclipse.fx.core.event.EventBus; | |
import org.eclipse.fx.core.log.Log; | |
import org.eclipse.fx.core.log.Logger; | |
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; | |
@Singleton | |
public class ClientService { | |
@Inject | |
@Log | |
Logger logger; | |
@Inject | |
private EventBus eventBus; | |
private final AtomicReference<String> refreshRef = new AtomicReference<>(); | |
private final ReadWriteLock tokenLock = new ReentrantReadWriteLock(); | |
private OIDCToken oidcToken; | |
private String refreshToken; | |
private Client client; | |
private String idpURL; | |
private String clientId; | |
private String clientSecret; | |
@PostConstruct | |
public void init() { | |
boolean devMode = Boolean.parseBoolean(System.getProperty("app.devmode", "false")); | |
if (devMode) { | |
idpURL = "https://ORG.okta.com"; | |
clientId = "X"; | |
clientSecret = "X"; | |
} else { | |
idpURL = "https://ORG.okta.com"; | |
clientId = "X"; | |
clientSecret = "X"; | |
} | |
client = buildClient(); | |
} | |
public String getCurrentRefreshToken() throws IOException { | |
if (refreshToken == null) { | |
try { | |
String newRefreshToken = getRefreshToken(); | |
if (refreshRef.compareAndSet(null, newRefreshToken)) { | |
refreshToken = newRefreshToken; | |
} | |
} catch (IOException e) { | |
logger.error(" Security Setup error", e); | |
} | |
} | |
return refreshToken; | |
} | |
public String getRefreshToken() throws IOException { | |
//private | |
} | |
public void setRefreshToken(String token) throws IOException { | |
//private | |
} | |
public String getAccessToken() { | |
if (refreshToken == null) { | |
try { | |
refreshToken = getCurrentRefreshToken(); | |
} catch (IOException e) { | |
logger.error(" auth setup error", e); | |
} | |
} | |
tokenLock.readLock().lock(); | |
try { | |
if ((oidcToken == null || LocalDateTime.now().isAfter(oidcToken.timeoutTime.plusSeconds(30))) && refreshToken != null) { | |
tokenLock.readLock().unlock(); | |
tokenLock.writeLock().lock(); | |
try { | |
if ((oidcToken == null || LocalDateTime.now().isAfter(oidcToken.timeoutTime.plusSeconds(30))) && refreshToken != null) { | |
oidcToken = retrieveAccessToken().orElse(null); | |
} | |
} finally { | |
tokenLock.writeLock().unlock(); | |
tokenLock.readLock().lock(); | |
} | |
} | |
return oidcToken != null ? oidcToken.token : null; | |
} finally { | |
tokenLock.readLock().unlock(); | |
} | |
} | |
public boolean connectionAvailable() { | |
return true; | |
} | |
public WebTarget getTarget(String url) { | |
return client.target(url); | |
} | |
private Client buildClient() { | |
SSLContext sslContext = null; | |
try { | |
sslContext = getSSLContext(); | |
} catch (Throwable t) { | |
logger.error("TLS setup error ", t); | |
return null; | |
} | |
ResteasyClientBuilder builder = new ResteasyClientBuilder(); | |
builder.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY); | |
Client client = builder.connectionPoolSize(200).sslContext(sslContext).build(); | |
OIDCAuthenticator auth = new OIDCAuthenticator(OIDCAuthenticator.Mode.Bearer, this::getAccessToken); | |
return client.register(auth); | |
} | |
public boolean testAuthenticate(String account, String password) { | |
Optional<JsonObject> result = oidcAuthenticate(account, password, "openid"); | |
return result.isPresent() && result.get().containsKey("access_token"); | |
} | |
public Optional<OIDCToken> retrieveAccessToken() { | |
Client oauthClient = ClientBuilder.newBuilder().build(); | |
try { | |
oauthClient.register(new OIDCAuthenticator(OIDCAuthenticator.Mode.Basic, () -> String.format("%s:%s", clientId, clientSecret))); | |
Form form = new Form(); | |
form.param("grant_type", "refresh_token"); | |
form.param("refresh_token", getCurrentRefreshToken()); | |
form.param("scope", "openid profile email groups offline_access"); | |
Response response = oauthClient.target(idpURL).path("/oauth2/v1/token").request().post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); | |
if (response.getStatus() == Response.Status.OK.getStatusCode()) { | |
JsonObject payload = response.readEntity(JsonObject.class); | |
String token = payload.getString("access_token"); | |
long expiry = payload.getJsonNumber("expires_in").longValue(); | |
return Optional.of(new OIDCToken(token, LocalDateTime.now().plusSeconds(expiry))); | |
} else { | |
logger.error(String.format("Invalid OIDC response %d %s", response.getStatus(), response.readEntity(String.class))); | |
} | |
} catch (Throwable t) { | |
logger.error("OIDC ", t); | |
} finally { | |
oauthClient.close(); | |
} | |
return Optional.empty(); | |
} | |
public boolean retrieveTokens(String account, String password) { | |
Optional<JsonObject> result = oidcAuthenticate(account, password, "openid profile email groups offline_access"); | |
if (result.isPresent() && result.get().containsKey("refresh_token")) { | |
refreshToken = result.get().getString("refresh_token"); | |
try { | |
setRefreshToken(refreshToken); | |
} catch (Throwable t) { | |
logger.error("", t); | |
} | |
if (result.get().containsKey("access_token")) { | |
tokenLock.writeLock().lock(); | |
try { | |
String token = result.get().getString("access_token"); | |
long expiry = result.get().getJsonNumber("expires_in").longValue(); | |
oidcToken = new OIDCToken(token, LocalDateTime.now().plusSeconds(expiry)); | |
} finally { | |
tokenLock.writeLock().unlock(); | |
} | |
} | |
return true; | |
} | |
return false; | |
} | |
public Optional<JsonObject> oidcAuthenticate(String account, String password, String scope) { | |
Client oauthClient = ClientBuilder.newBuilder().build(); | |
try { | |
oauthClient.register(new OIDCAuthenticator(OIDCAuthenticator.Mode.Basic, () -> String.format("%s:%s", clientId, clientSecret))); | |
Form form = new Form(); | |
form.param("grant_type", "password"); | |
form.param("username", account); | |
form.param("password", password); | |
form.param("scope", scope); | |
Response response = oauthClient.target(idpURL).path("/oauth2/v1/token").request().post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); | |
if (response.getStatus() == Response.Status.OK.getStatusCode()) { | |
return Optional.of(response.readEntity(JsonObject.class)); | |
} else { | |
logger.error(String.format("Invalid OIDC response %d %s", response.getStatus(), response.readEntity(String.class))); | |
} | |
} catch (Throwable t) { | |
logger.error("OIDC ", t); | |
} finally { | |
oauthClient.close(); | |
} | |
return Optional.empty(); | |
} | |
public static class OIDCAuthenticator implements ClientRequestFilter { | |
private final Mode mode; | |
private final Supplier<String> tokenGenerator; | |
public OIDCAuthenticator(Mode mode, Supplier<String> tokenGenerator) { | |
this.mode = mode; | |
this.tokenGenerator = tokenGenerator; | |
} | |
public void filter(ClientRequestContext requestContext) throws IOException { | |
try { | |
String token = tokenGenerator.get(); | |
if (token == null || token.isEmpty()) { | |
throw new IOException("Empty auth token"); | |
} | |
final String authorization = mode + " " + (mode == Mode.Basic ? Base64.getEncoder().encodeToString(token.getBytes()) : token); | |
MultivaluedMap<String, Object> headers = requestContext.getHeaders(); | |
headers.add("Authorization", authorization); | |
} catch (IllegalArgumentException ex) { | |
throw new IOException(ex); | |
} | |
} | |
public static enum Mode { | |
Basic, Bearer; | |
} | |
} | |
public static class OIDCToken { | |
final String token; | |
final LocalDateTime timeoutTime; | |
public OIDCToken(String token, LocalDateTime timeoutTime) { | |
this.token = token; | |
this.timeoutTime = timeoutTime; | |
} | |
public String getToken() { | |
return token; | |
} | |
} | |
public static SSLContext getSSLContext() throws Exception { | |
InputStream fis = Thread.currentThread().getContextClassLoader().getResourceAsStream("swarm.cer"); | |
CertificateFactory cf = CertificateFactory.getInstance("X.509"); | |
Certificate cert = cf.generateCertificate(fis); | |
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); | |
keyStore.load(null, null); | |
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); | |
keyStore.setCertificateEntry("Integration_Library", cert); | |
tmf.init(keyStore); | |
SSLContext sslContext = SSLContext.getInstance("TLS"); | |
sslContext.init(null, tmf.getTrustManagers(), null); | |
return sslContext; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Manifest-Version: 1.0 | |
Bundle-ManifestVersion: 2 | |
Bundle-Name: Mercer CPSG App | |
Bundle-SymbolicName: com.mercer.cpsg.app; singleton:=true | |
Bundle-Version: 1.0.0.final | |
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | |
Bundle-ActivationPolicy: lazy | |
Require-Bundle: org.eclipse.fx.ui.workbench.fx, | |
org.eclipse.e4.ui.model.workbench, | |
org.eclipse.e4.core.services, | |
org.eclipse.e4.core.di, | |
org.eclipse.e4.ui.di, | |
org.eclipse.e4.core.di.extensions, | |
org.eclipse.fx.ui.theme, | |
org.eclipse.fx.ui.di, | |
org.eclipse.e4.core.contexts, | |
org.eclipse.fx.core.databinding, | |
org.eclipse.fx.ui.databinding, | |
org.eclipse.core.databinding, | |
org.eclipse.core.databinding.observable, | |
org.eclipse.core.databinding.property, | |
org.eclipse.e4.ui.workbench, | |
org.eclipse.e4.ui.services, | |
org.eclipse.fx.ui.services, | |
org.eclipse.fx.ui.controls;bundle-version="2.4.0", | |
org.eclipse.fx.osgi.util;bundle-version="2.4.0", | |
org.eclipse.fx.core, | |
org.eclipse.fx.core.di, | |
org.eclipse.core.runtime, | |
org.eclipse.ecf, | |
org.eclipse.ecf.filetransfer, | |
org.eclipse.ecf.provider.filetransfer, | |
org.eclipse.ecf.provider.filetransfer.httpclient4, | |
org.apache.httpcomponents.httpclient, | |
org.apache.httpcomponents.httpcore | |
Service-Component: OSGI-INF/services/theme-default.xml | |
Import-Package: javax.inject;version="1.0.0" | |
Bundle-ClassPath: ., | |
lib/ | |
Bundle-Vendor: Mercer CPSG |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<?eclipse version="3.0"?> | |
<plugin> | |
<extension | |
id="application" | |
point="org.eclipse.core.runtime.applications"> | |
<application | |
thread="any"> | |
<run | |
class="org.eclipse.fx.ui.di.DIApplication"> | |
<parameter name="mainClass" value="com.mercer.cpsg.app.Application" /> | |
</run> | |
</application> | |
</extension> | |
<extension | |
id="product" | |
point="org.eclipse.core.runtime.products"> | |
<product name="Mercer CPSG App" application="com.mercer.cpsg.app.application" > | |
<property name="appName" value="Mercer CPSGApp" /> | |
</product> | |
</extension> | |
<extension | |
point="org.eclipse.ecf.provider.filetransfer.retrieveFileTransferProtocolFactory"> | |
<retrieveFileTransferProtocolFactory | |
class="com.mercer.cpsg.workspace.app.filetransfer.SecureHttpClientRetrieveFileTransferFactory" | |
protocol="https" | |
priority="40"> | |
</retrieveFileTransferProtocolFactory> | |
</extension> | |
<extension | |
point="org.eclipse.ecf.provider.filetransfer.browseFileTransferProtocolFactory"> | |
<browseFileTransferProtocolFactory | |
class="com.mercer.cpsg.workspace.app.filetransfer.SecureHttpClientBrowseFileTransferFactory" | |
protocol="https" | |
priority="40"> | |
</browseFileTransferProtocolFactory> | |
</extension> | |
</plugin> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.mercer.cpsg.workspace.app.filetransfer; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import org.apache.http.impl.client.DefaultHttpClient; | |
import org.eclipse.core.runtime.Assert; | |
import org.eclipse.ecf.core.identity.IDFactory; | |
import org.eclipse.ecf.core.identity.Namespace; | |
import org.eclipse.ecf.core.security.IConnectContext; | |
import org.eclipse.ecf.core.util.Proxy; | |
import org.eclipse.ecf.filetransfer.IRemoteFileSystemListener; | |
import org.eclipse.ecf.filetransfer.IRemoteFileSystemRequest; | |
import org.eclipse.ecf.filetransfer.RemoteFileSystemException; | |
import org.eclipse.ecf.filetransfer.identity.IFileID; | |
import org.eclipse.ecf.filetransfer.service.IRemoteFileSystemBrowser; | |
import org.eclipse.ecf.filetransfer.service.IRemoteFileSystemBrowserFactory; | |
import org.eclipse.ecf.provider.filetransfer.httpclient4.HttpClientFileSystemBrowser; | |
import org.eclipse.ecf.provider.filetransfer.identity.FileTransferNamespace; | |
import org.eclipse.osgi.util.NLS; | |
public class SecureHttpClientBrowseFileTransferFactory implements IRemoteFileSystemBrowserFactory { | |
public IRemoteFileSystemBrowser newInstance() { | |
return new IRemoteFileSystemBrowser() { | |
private Proxy proxy; | |
private IConnectContext connectContext; | |
public Namespace getBrowseNamespace() { | |
return IDFactory.getDefault().getNamespaceByName(FileTransferNamespace.PROTOCOL); | |
} | |
public IRemoteFileSystemRequest sendBrowseRequest(IFileID directoryOrFileId, IRemoteFileSystemListener listener) throws RemoteFileSystemException { | |
Assert.isNotNull(directoryOrFileId); | |
Assert.isNotNull(listener); | |
URL url; | |
try { | |
url = directoryOrFileId.getURL(); | |
} catch (final MalformedURLException e) { | |
throw new RemoteFileSystemException(NLS.bind("Exception creating URL for {0}", directoryOrFileId)); //$NON-NLS-1$ | |
} | |
DefaultHttpClient client = new DefaultHttpClient(); | |
HttpClientFileSystemBrowser browser = new HttpClientFileSystemBrowser(client, directoryOrFileId, listener, url, connectContext, proxy); | |
SecureHttpClientRetrieveFileTransferFactory.configureHttpClient(client); | |
return browser.sendBrowseRequest(); | |
} | |
public void setConnectContextForAuthentication(IConnectContext connectContext) { | |
this.connectContext = connectContext; | |
} | |
public void setProxy(Proxy proxy) { | |
this.proxy = proxy; | |
} | |
public Object getAdapter(Class adapter) { | |
return null; | |
} | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.mercer.cpsg.workspace.app.filetransfer; | |
import java.io.IOException; | |
import java.security.Principal; | |
import javax.net.ssl.SSLContext; | |
import org.apache.http.Header; | |
import org.apache.http.HttpException; | |
import org.apache.http.HttpHeaders; | |
import org.apache.http.HttpHost; | |
import org.apache.http.HttpRequest; | |
import org.apache.http.HttpRequestInterceptor; | |
import org.apache.http.auth.AuthScheme; | |
import org.apache.http.auth.AuthSchemeFactory; | |
import org.apache.http.auth.AuthScope; | |
import org.apache.http.auth.AuthState; | |
import org.apache.http.auth.AuthenticationException; | |
import org.apache.http.auth.BasicUserPrincipal; | |
import org.apache.http.auth.Credentials; | |
import org.apache.http.auth.MalformedChallengeException; | |
import org.apache.http.client.CredentialsProvider; | |
import org.apache.http.client.protocol.HttpClientContext; | |
import org.apache.http.conn.scheme.PlainSocketFactory; | |
import org.apache.http.conn.scheme.Scheme; | |
import org.apache.http.conn.scheme.SchemeRegistry; | |
import org.apache.http.conn.ssl.SSLSocketFactory; | |
import org.apache.http.impl.client.BasicCredentialsProvider; | |
import org.apache.http.impl.client.DefaultHttpClient; | |
import org.apache.http.impl.conn.SingleClientConnManager; | |
import org.apache.http.message.BasicHeader; | |
import org.apache.http.params.HttpParams; | |
import org.apache.http.protocol.HttpContext; | |
import org.apache.http.protocol.HttpCoreContext; | |
import org.eclipse.e4.core.contexts.EclipseContextFactory; | |
import org.eclipse.e4.core.contexts.IEclipseContext; | |
import org.eclipse.ecf.filetransfer.service.IRetrieveFileTransfer; | |
import org.eclipse.ecf.filetransfer.service.IRetrieveFileTransferFactory; | |
import org.eclipse.ecf.provider.filetransfer.httpclient4.HttpClientRetrieveFileTransfer; | |
import org.eclipse.fx.ui.di.DIApplication; | |
import org.osgi.framework.FrameworkUtil; | |
import com.mercer.cpsg.workspace.app.ClientService; | |
/* | |
ECF uses an old deprecated version of Apache HTTPClient. The authentication functionality available is limited to HttpClient v3.x ntlm and basic authentication with username/password callbacks and no premptive support. | |
Proxy support is also available. Instead of plugging into the old HTTP Client/ECF framework we will just let HttpClientRetrieveFileTransfer setup the client and then override the necessary configurations to | |
a) trust a specific self signed certificate | |
b) insert an oauth 2 access token for SSO | |
*/ | |
public class SecureHttpClientRetrieveFileTransferFactory implements IRetrieveFileTransferFactory { | |
public IRetrieveFileTransfer newInstance() { | |
DefaultHttpClient client = new DefaultHttpClient(new SingleClientConnManager()); | |
HttpClientRetrieveFileTransfer transfer = new HttpClientRetrieveFileTransfer(client); | |
configureHttpClient(client); | |
return transfer; | |
} | |
// Override the schemas. The ECFHttpClientSecureProtocolSocketFactory will not be used but the ISocketEventSource and ISocketListener | |
// references seem to be only used for tracing and monitoring. This is also done here | |
// http://git.eclipse.org/c/ecf/org.eclipse.ecf.git/tree/providers/bundles/org.eclipse.ecf.provider.filetransfer.httpclient4/src/org/eclipse/ecf/provider/filetransfer/httpclient4/SNIAwareHttpClient.java | |
public static void configureHttpClient(DefaultHttpClient client) { | |
SSLContext sslContext = null; | |
try { | |
sslContext = ClientService.getSSLContext(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
SSLSocketFactory factory = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); | |
final SchemeRegistry registry = client.getConnectionManager().getSchemeRegistry(); | |
registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory())); | |
registry.register(new Scheme("https", 443, factory)); | |
registry.register(new Scheme("https", 8443, factory)); | |
/* List authpref = new ArrayList(1); | |
* authpref.add("oauth2"); | |
* client.getParams().setParameter(AuthPNames.PROXY_AUTH_PREF, authpref); | |
* client.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, authpref); | |
* client.getAuthSchemes().register("oauth2", new OAuth2SchemaProvider()); */ | |
BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); | |
credsProvider.setCredentials(new AuthScope(null, -1, null), new OAuthCredentials("OAuth App Name")); | |
client.setCredentialsProvider(credsProvider); | |
client.addRequestInterceptor(new OAuth2Interceptor(), 0); | |
} | |
// http://stackoverflow.com/a/29012443 | |
static class OAuth2Interceptor implements HttpRequestInterceptor { | |
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { | |
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE); | |
// If no auth scheme available yet, try to initialize it | |
// preemptively | |
if (authState.getAuthScheme() == null) { | |
CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(HttpClientContext.CREDS_PROVIDER); | |
HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST); | |
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort()); | |
Credentials creds = credsProvider.getCredentials(authScope); | |
authState.update(new OAuth2Scheme(), creds); | |
} | |
} | |
} | |
public static class OAuthCredentials implements Credentials { | |
private ClientService clientService; | |
private BasicUserPrincipal principal; | |
public OAuthCredentials(String name) { | |
this.principal = new BasicUserPrincipal(name); | |
} | |
@Override | |
public String getPassword() { | |
return null; | |
} | |
@Override | |
public Principal getUserPrincipal() { | |
return principal; | |
} | |
public String getAccessToken() { | |
if (clientService == null) { | |
try { | |
// IEclipseContext injection in application class is in the di bundle context and not the actual application bundle. Make sure to load the same bundle. | |
IEclipseContext serviceContext = EclipseContextFactory.getServiceContext(FrameworkUtil.getBundle(DIApplication.class).getBundleContext()); | |
clientService = serviceContext.get(ClientService.class); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
return clientService.getAccessToken(); | |
} | |
} | |
public static class OAuth2SchemaProvider implements AuthSchemeFactory { | |
@Override | |
public AuthScheme newInstance(HttpParams arg0) { | |
return new OAuth2Scheme(); | |
} | |
} | |
public static class OAuth2Scheme implements AuthScheme { | |
@Override | |
public Header authenticate(Credentials credentials, HttpRequest request) throws AuthenticationException { | |
OAuthCredentials oauthCredentials = (OAuthCredentials) credentials; | |
String token = oauthCredentials.getAccessToken(); | |
if (token == null) { | |
throw new AuthenticationException("OAuth2 access token not available"); | |
} | |
return new BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token); | |
} | |
@Override | |
public String getParameter(String arg0) { | |
return null; | |
} | |
@Override | |
public String getRealm() { | |
// TODO Auto-generated method stub | |
return null; | |
} | |
@Override | |
public String getSchemeName() { | |
return "oauth2"; | |
} | |
@Override | |
public boolean isComplete() { | |
return true; | |
} | |
@Override | |
public boolean isConnectionBased() { | |
return false; | |
} | |
@Override | |
public void processChallenge(Header arg0) throws MalformedChallengeException { | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment