Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FusionAuth need support ssl #22

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ String apiKey = "5a826da2-1e3a-49df-85ba-cd88575e4e9d";
FusionAuthClient client = new FusionAuthClient(apiKey, "http://localhost:9011");
```

### Build the SSL Client

```java
String apiKey = "5a826da2-1e3a-49df-85ba-cd88575e4e9d";
FusionAuthClient client = new FusionAuthClient(apiKey, "http://localhost:9011", Boolean.TRUE, "BASE64 Encode ssl certificate value");
```

### Login a user

```java
Expand Down
83 changes: 73 additions & 10 deletions src/main/java/io/fusionauth/client/FusionAuthClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
import io.fusionauth.domain.oauth2.OAuthError;
import io.fusionauth.domain.oauth2.JWKSResponse;
import io.fusionauth.domain.provider.IdentityProviderType;
import io.fusionauth.ssl.SSLRestClient;

/**
* Client that connects to a FusionAuth server and provides access to the full set of FusionAuth APIs.
Expand Down Expand Up @@ -224,24 +225,73 @@ public class FusionAuthClient {

public int readTimeout;

/**
* fusion auth client support https
*/
public final Boolean sslEnable;

/**
* ssl certificate context
*/
public final String sslCertificate;

public FusionAuthClient(String apiKey, String baseURL) {
this(apiKey, baseURL, null);
}

public FusionAuthClient(String apiKey, String baseURL, String tenantId) {
this(apiKey, baseURL, 2000, 2000, tenantId);
this(apiKey, baseURL, 2000, 2000, tenantId, Boolean.FALSE, null);
}

public FusionAuthClient(String apiKey, String baseURL, int connectTimeout, int readTimeout) {
this(apiKey, baseURL, connectTimeout, readTimeout, null);
this(apiKey, baseURL, connectTimeout, readTimeout, null, Boolean.FALSE, null);
}

/**
* ssl construct
* @param apiKey
* @param baseURL
* @param sslEnable
* @param sslCertificate
*/
public FusionAuthClient(String apiKey, String baseURL, Boolean sslEnable, String sslCertificate) {
this(apiKey, baseURL, null, sslEnable, sslCertificate);
}

public FusionAuthClient(String apiKey, String baseURL, int connectTimeout, int readTimeout, String tenantId) {
/**
* sslCertificate
* @param apiKey
* @param baseURL
* @param tenantId
* @param sslEnable
* @param sslCertificate
*/
public FusionAuthClient(String apiKey, String baseURL, String tenantId, Boolean sslEnable, String sslCertificate) {
this(apiKey, baseURL, 2000, 2000, tenantId, sslEnable, sslCertificate);
}

/**
* sslCertificate
* @param apiKey
* @param baseURL
* @param connectTimeout
* @param readTimeout
* @param sslEnable
* @param sslCertificate
*/
public FusionAuthClient(String apiKey, String baseURL, int connectTimeout, int readTimeout, Boolean sslEnable, String sslCertificate) {
this(apiKey, baseURL, connectTimeout, readTimeout, null, sslEnable, sslCertificate);
}

public FusionAuthClient(String apiKey, String baseURL, int connectTimeout, int readTimeout, String tenantId,
Boolean sslEnable, String sslCertificate) {
this.apiKey = apiKey;
this.baseURL = baseURL;
this.connectTimeout = connectTimeout;
this.readTimeout = readTimeout;
this.tenantId = tenantId;
this.sslEnable = sslEnable;
this.sslCertificate = sslCertificate;
}

/**
Expand All @@ -258,7 +308,7 @@ public FusionAuthClient setTenantId(UUID tenantId) {
return this;
}

return new FusionAuthClient(apiKey, baseURL, connectTimeout, readTimeout, tenantId.toString());
return new FusionAuthClient(apiKey, baseURL, connectTimeout, readTimeout, tenantId.toString(), sslEnable, sslCertificate);
}

/**
Expand Down Expand Up @@ -4992,12 +5042,25 @@ protected <T, U> RESTClient<T, U> start(Class<T> type, Class<U> errorType) {
}

protected <T, U> RESTClient<T, U> startAnonymous(Class<T> type, Class<U> errorType) {
RESTClient<T, U> client = new RESTClient<>(type, errorType)
.successResponseHandler(type != Void.TYPE ? new JSONResponseHandler<>(type, objectMapper) : null)
.errorResponseHandler(errorType != Void.TYPE ? new JSONResponseHandler<>(errorType, objectMapper) : null)
.url(baseURL)
.connectTimeout(connectTimeout)
.readTimeout(readTimeout);
RESTClient<T, U> client;

if(Boolean.TRUE.equals(sslEnable)){
client = new SSLRestClient<>(type, errorType)
.successResponseHandler(type != Void.TYPE ? new JSONResponseHandler<>(type, objectMapper) : null)
.errorResponseHandler(errorType != Void.TYPE ? new JSONResponseHandler<>(errorType, objectMapper) : null)
.url(baseURL)
.connectTimeout(connectTimeout)
.readTimeout(readTimeout)
.certificate(sslCertificate)
.disableSNIVerification();
}else {
client = new RESTClient<>(type, errorType)
.successResponseHandler(type != Void.TYPE ? new JSONResponseHandler<>(type, objectMapper) : null)
.errorResponseHandler(errorType != Void.TYPE ? new JSONResponseHandler<>(errorType, objectMapper) : null)
.url(baseURL)
.connectTimeout(connectTimeout)
.readTimeout(readTimeout);
}

if (tenantId != null) {
client.header(TENANT_ID_HEADER, tenantId);
Expand Down
68 changes: 68 additions & 0 deletions src/main/java/io/fusionauth/ssl/SSLCertificateContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package io.fusionauth.ssl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Base64;

/**
* @author zcyang
* @description get Singleton SSLSocketFactory
*/
public class SSLCertificateContext {

private volatile static SSLCertificateContext instance = null;

private static final Logger logger = LoggerFactory.getLogger(SSLCertificateContext.class);

private final SSLSocketFactory sslSocketFactory;

public static SSLCertificateContext getInstance(String cert) {
if (instance == null) {
synchronized (SSLCertificateContext.class) {
if (instance == null) {
instance = new SSLCertificateContext(getSSLContext(cert));
}
}
}
return instance;
}

private SSLCertificateContext(SSLSocketFactory sslSocketFactory) {
this.sslSocketFactory = sslSocketFactory;
}

public SSLSocketFactory getSslSocketFactory() {
return sslSocketFactory;
}

public static SSLSocketFactory getSSLContext(String certificate) {
SSLContext context = null;
SSLSocketFactory factory = null;
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
InputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(certificate));
Certificate ca = certificateFactory.generateCertificate(inputStream);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, null);
keystore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm);
trustManagerFactory.init(keystore);
context = SSLContext.getInstance("TLS");
context.init(null, trustManagerFactory.getTrustManagers(), null);
factory = context.getSocketFactory();
} catch (Exception ex) {
logger.error(ex.getMessage());
}
return factory;
}
}
Loading