fix: Added support for self signed certificate during OAuth2 flows (#14719)
* Added support for self signed certificate during OAuth2 flows, server side changes * fix: authentication.useSelfSignedCert key added * Merging from release * Fixed issue with dependencies, plus bug with using ssl * Cypress test attempt 1 * Cypress test attempt 2 * Cypress test attempt 3 * Clean up * Review comments * Enabled compression again Co-authored-by: Aman Agarwal <aman@appsmith.com>
This commit is contained in:
parent
b16fadc763
commit
50172ecd64
|
|
@ -17,6 +17,7 @@ describe("Create a rest datasource", function() {
|
||||||
.trigger("click")
|
.trigger("click")
|
||||||
.wait(1000);
|
.wait(1000);
|
||||||
agHelper.ValidateToastMessage("datasource created"); //verifying there is no error toast, Bug 14566
|
agHelper.ValidateToastMessage("datasource created"); //verifying there is no error toast, Bug 14566
|
||||||
|
cy.testSelfSignedCertificateSettingsInREST(false);
|
||||||
cy.saveDatasource();
|
cy.saveDatasource();
|
||||||
cy.contains(".datasource-highlight", "https://mock-api.appsmith.com");
|
cy.contains(".datasource-highlight", "https://mock-api.appsmith.com");
|
||||||
cy.SaveAndRunAPI();
|
cy.SaveAndRunAPI();
|
||||||
|
|
|
||||||
|
|
@ -65,5 +65,9 @@
|
||||||
"mongoUriDropdown": "//p[text()='Use Mongo Connection String URI']/following-sibling::div",
|
"mongoUriDropdown": "//p[text()='Use Mongo Connection String URI']/following-sibling::div",
|
||||||
"mongoUriYes": "//div[text()='Yes']",
|
"mongoUriYes": "//div[text()='Yes']",
|
||||||
"mongoUriInput":"//p[text()='Connection String URI']/following-sibling::div//input",
|
"mongoUriInput":"//p[text()='Connection String URI']/following-sibling::div//input",
|
||||||
|
"advancedSettings": "[data-cy='section-Advanced Settings']",
|
||||||
|
"useSelfSignedCert": ".t--connection\\.ssl\\.authType",
|
||||||
|
"useCertInAuth": "[data-cy='authentication.useSelfSignedCert'] input",
|
||||||
|
"certificateDetails": "[data-cy='section-Certificate Details']",
|
||||||
"saveBtn": ".t--save-datasource"
|
"saveBtn": ".t--save-datasource"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ const loginPage = require("../locators/LoginPage.json");
|
||||||
const signupPage = require("../locators/SignupPage.json");
|
const signupPage = require("../locators/SignupPage.json");
|
||||||
import homePage from "../locators/HomePage";
|
import homePage from "../locators/HomePage";
|
||||||
const pages = require("../locators/Pages.json");
|
const pages = require("../locators/Pages.json");
|
||||||
const datasourceEditor = require("../locators/DatasourcesEditor.json");
|
|
||||||
const datasourceFormData = require("../fixtures/datasources.json");
|
const datasourceFormData = require("../fixtures/datasources.json");
|
||||||
const commonlocators = require("../locators/commonlocators.json");
|
const commonlocators = require("../locators/commonlocators.json");
|
||||||
const queryEditor = require("../locators/QueryEditor.json");
|
const queryEditor = require("../locators/QueryEditor.json");
|
||||||
|
|
@ -144,6 +143,7 @@ Cypress.Commands.add(
|
||||||
);
|
);
|
||||||
expect(firstTxt).to.equal(expectedvalue);
|
expect(firstTxt).to.equal(expectedvalue);
|
||||||
});
|
});
|
||||||
|
cy.testSelfSignedCertificateSettingsInREST(true);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -161,9 +161,25 @@ Cypress.Commands.add(
|
||||||
cy.xpath("//span[text()='Send client credentials in body']").should(
|
cy.xpath("//span[text()='Send client credentials in body']").should(
|
||||||
"be.visible",
|
"be.visible",
|
||||||
);
|
);
|
||||||
|
cy.testSelfSignedCertificateSettingsInREST(true);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Cypress.Commands.add("testSelfSignedCertificateSettingsInREST", (isOAuth2) => {
|
||||||
|
cy.get(datasource.advancedSettings).click();
|
||||||
|
cy.get(datasource.useCertInAuth).should("not.exist");
|
||||||
|
cy.get(datasource.certificateDetails).should("not.exist");
|
||||||
|
cy.TargetDropdownAndSelectOption(datasource.useSelfSignedCert, "Yes");
|
||||||
|
if (isOAuth2) {
|
||||||
|
cy.get(datasource.useCertInAuth).should("exist");
|
||||||
|
} else {
|
||||||
|
cy.get(datasource.useCertInAuth).should("not.exist");
|
||||||
|
}
|
||||||
|
cy.get(datasource.certificateDetails).should("exist");
|
||||||
|
cy.TargetDropdownAndSelectOption(datasource.useSelfSignedCert, "No");
|
||||||
|
cy.get(datasource.advancedSettings).click();
|
||||||
|
});
|
||||||
|
|
||||||
Cypress.Commands.add("addBasicProfileDetails", (username, password) => {
|
Cypress.Commands.add("addBasicProfileDetails", (username, password) => {
|
||||||
cy.get(datasource.authType).click();
|
cy.get(datasource.authType).click();
|
||||||
cy.xpath(datasource.basic).click();
|
cy.xpath(datasource.basic).click();
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ function renderComponent(props: renderComponentProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledCheckbox
|
<StyledCheckbox
|
||||||
|
cypressSelector={props?.input?.name}
|
||||||
isDefaultChecked={props?.input?.checked as boolean}
|
isDefaultChecked={props?.input?.checked as boolean}
|
||||||
{...props}
|
{...props}
|
||||||
info={undefined}
|
info={undefined}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ export interface Oauth2Common {
|
||||||
resource: string;
|
resource: string;
|
||||||
sendScopeWithRefreshToken: string;
|
sendScopeWithRefreshToken: string;
|
||||||
refreshTokenClientCredentialsLocation: string;
|
refreshTokenClientCredentialsLocation: string;
|
||||||
|
useSelfSignedCert?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientCredentials extends Oauth2Common {
|
export interface ClientCredentials extends Oauth2Common {
|
||||||
|
|
|
||||||
|
|
@ -845,10 +845,13 @@ class DatasourceRestAPIEditor extends React.Component<
|
||||||
};
|
};
|
||||||
|
|
||||||
renderOauth2AdvancedSettings = () => {
|
renderOauth2AdvancedSettings = () => {
|
||||||
const { authentication, authType } = this.props.formData;
|
const { authentication, authType, connection } = this.props.formData;
|
||||||
const isGrantTypeAuthorizationCode =
|
const isGrantTypeAuthorizationCode =
|
||||||
_.get(authentication, "grantType") === GrantType.AuthorizationCode;
|
_.get(authentication, "grantType") === GrantType.AuthorizationCode;
|
||||||
const isAuthenticationTypeOAuth2 = authType === AuthType.OAuth2;
|
const isAuthenticationTypeOAuth2 = authType === AuthType.OAuth2;
|
||||||
|
const isConnectSelfSigned =
|
||||||
|
_.get(connection, "ssl.authType") === SSLType.SELF_SIGNED_CERTIFICATE;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isAuthenticationTypeOAuth2 && isGrantTypeAuthorizationCode && (
|
{isAuthenticationTypeOAuth2 && isGrantTypeAuthorizationCode && (
|
||||||
|
|
@ -919,6 +922,16 @@ class DatasourceRestAPIEditor extends React.Component<
|
||||||
"DEFAULT",
|
"DEFAULT",
|
||||||
)}
|
)}
|
||||||
</FormInputContainer>
|
</FormInputContainer>
|
||||||
|
{isAuthenticationTypeOAuth2 && isConnectSelfSigned && (
|
||||||
|
<FormInputContainer data-replay-id={btoa("selfsignedcert")}>
|
||||||
|
{this.renderCheckboxViaFormControl(
|
||||||
|
"authentication.useSelfSignedCert",
|
||||||
|
"Use Self-Signed Certificate for Authorization requests",
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
)}
|
||||||
|
</FormInputContainer>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -1127,6 +1140,30 @@ class DatasourceRestAPIEditor extends React.Component<
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderCheckboxViaFormControl(
|
||||||
|
configProperty: string,
|
||||||
|
label: string,
|
||||||
|
placeholderText: string,
|
||||||
|
isRequired: boolean,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<FormControl
|
||||||
|
config={{
|
||||||
|
id: "",
|
||||||
|
isValid: false,
|
||||||
|
isRequired: isRequired,
|
||||||
|
controlType: "CHECKBOX",
|
||||||
|
configProperty: configProperty,
|
||||||
|
label: label,
|
||||||
|
conditionals: {},
|
||||||
|
placeholderText: placeholderText,
|
||||||
|
formName: DATASOURCE_REST_API_FORM,
|
||||||
|
}}
|
||||||
|
formName={DATASOURCE_REST_API_FORM}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: AppState, props: any) => {
|
const mapStateToProps = (state: AppState, props: any) => {
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,7 @@ const formToDatasourceAuthentication = (
|
||||||
sendScopeWithRefreshToken: authentication.sendScopeWithRefreshToken,
|
sendScopeWithRefreshToken: authentication.sendScopeWithRefreshToken,
|
||||||
refreshTokenClientCredentialsLocation:
|
refreshTokenClientCredentialsLocation:
|
||||||
authentication.refreshTokenClientCredentialsLocation,
|
authentication.refreshTokenClientCredentialsLocation,
|
||||||
|
useSelfSignedCert: authentication.useSelfSignedCert,
|
||||||
};
|
};
|
||||||
if (isClientCredentials(authType, authentication)) {
|
if (isClientCredentials(authType, authentication)) {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,11 @@
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-webflux</artifactId>
|
<artifactId>spring-webflux</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.projectreactor.netty</groupId>
|
||||||
|
<artifactId>reactor-netty-core</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
package com.appsmith.external.helpers;
|
package com.appsmith.external.helpers;
|
||||||
|
|
||||||
|
import com.appsmith.external.models.DatasourceConfiguration;
|
||||||
|
import com.appsmith.external.models.SSLDetails;
|
||||||
import com.appsmith.external.models.UploadedFile;
|
import com.appsmith.external.models.UploadedFile;
|
||||||
|
import reactor.netty.tcp.DefaultSslContextSpec;
|
||||||
|
import reactor.netty.tcp.SslProvider;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
|
@ -14,6 +18,7 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class SSLHelper {
|
public class SSLHelper {
|
||||||
|
|
||||||
|
|
@ -50,4 +55,26 @@ public class SSLHelper {
|
||||||
|
|
||||||
return trustManagerFactory;
|
return trustManagerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Consumer<? super SslProvider.SslContextSpec> sslCheckForHttpClient(DatasourceConfiguration datasourceConfiguration) {
|
||||||
|
|
||||||
|
return (sslContextSpec) -> {
|
||||||
|
final DefaultSslContextSpec sslContextSpec1 = DefaultSslContextSpec.forClient();
|
||||||
|
|
||||||
|
if (datasourceConfiguration.getConnection() != null &&
|
||||||
|
datasourceConfiguration.getConnection().getSsl() != null &&
|
||||||
|
datasourceConfiguration.getConnection().getSsl().getAuthType() == SSLDetails.AuthType.SELF_SIGNED_CERTIFICATE) {
|
||||||
|
|
||||||
|
sslContextSpec1.configure(sslContextBuilder -> {
|
||||||
|
try {
|
||||||
|
final UploadedFile certificateFile = datasourceConfiguration.getConnection().getSsl().getCertificateFile();
|
||||||
|
sslContextBuilder.trustManager(SSLHelper.getSslTrustManagerFactory(certificateFile));
|
||||||
|
} catch (CertificateException | KeyStoreException | IOException | NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
sslContextSpec.sslContext(sslContextSpec1);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,8 @@ public class OAuth2 extends AuthenticationDTO {
|
||||||
|
|
||||||
String resource;
|
String resource;
|
||||||
|
|
||||||
|
boolean useSelfSignedCert = false;
|
||||||
|
|
||||||
public String getScopeString() {
|
public String getScopeString() {
|
||||||
if (scopeString != null && !scopeString.isBlank()) {
|
if (scopeString != null && !scopeString.isBlank()) {
|
||||||
return scopeString;
|
return scopeString;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,22 @@
|
||||||
package com.external.connections;
|
package com.external.connections;
|
||||||
|
|
||||||
|
import com.appsmith.external.helpers.SSLHelper;
|
||||||
|
import com.appsmith.external.models.DatasourceConfiguration;
|
||||||
|
import com.appsmith.external.models.OAuth2;
|
||||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||||
|
import reactor.netty.http.client.HttpClient;
|
||||||
|
|
||||||
// Parent type for all API connections that need to be created during datasource create method.
|
// Parent type for all API connections that need to be created during datasource create method.
|
||||||
public abstract class APIConnection implements ExchangeFilterFunction {
|
public abstract class APIConnection implements ExchangeFilterFunction {
|
||||||
|
|
||||||
|
HttpClient getSecuredHttpClient(DatasourceConfiguration datasourceConfiguration) {
|
||||||
|
final OAuth2 oAuth2 = (OAuth2) datasourceConfiguration.getAuthentication();
|
||||||
|
HttpClient httpClient = HttpClient.create();
|
||||||
|
|
||||||
|
if (oAuth2.isUseSelfSignedCert()) {
|
||||||
|
httpClient = httpClient.secure(SSLHelper.sslCheckForHttpClient(datasourceConfiguration));
|
||||||
|
}
|
||||||
|
|
||||||
|
return httpClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
|
||||||
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
|
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
|
||||||
import com.appsmith.external.models.AuthenticationDTO;
|
import com.appsmith.external.models.AuthenticationDTO;
|
||||||
import com.appsmith.external.models.BasicAuth;
|
import com.appsmith.external.models.BasicAuth;
|
||||||
|
import com.appsmith.external.models.DatasourceConfiguration;
|
||||||
import com.appsmith.external.models.OAuth2;
|
import com.appsmith.external.models.OAuth2;
|
||||||
import com.appsmith.external.models.ApiKeyAuth;
|
import com.appsmith.external.models.ApiKeyAuth;
|
||||||
import com.appsmith.external.models.BearerTokenAuth;
|
import com.appsmith.external.models.BearerTokenAuth;
|
||||||
|
|
@ -12,25 +13,26 @@ import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
public class APIConnectionFactory {
|
public class APIConnectionFactory {
|
||||||
|
|
||||||
public static Mono<APIConnection> createConnection(AuthenticationDTO authenticationType) {
|
public static Mono<APIConnection> createConnection(DatasourceConfiguration datasourceConfiguration) {
|
||||||
if (authenticationType instanceof OAuth2) {
|
final AuthenticationDTO authentication = datasourceConfiguration.getAuthentication();
|
||||||
if (OAuth2.Type.CLIENT_CREDENTIALS.equals(((OAuth2) authenticationType).getGrantType())) {
|
if (authentication instanceof OAuth2) {
|
||||||
return Mono.from(OAuth2ClientCredentials.create((OAuth2) authenticationType));
|
if (OAuth2.Type.CLIENT_CREDENTIALS.equals(((OAuth2) authentication).getGrantType())) {
|
||||||
} else if (OAuth2.Type.AUTHORIZATION_CODE.equals(((OAuth2) authenticationType).getGrantType())) {
|
return Mono.from(OAuth2ClientCredentials.create(datasourceConfiguration));
|
||||||
if (!Boolean.TRUE.equals(authenticationType.getIsAuthorized())) {
|
} else if (OAuth2.Type.AUTHORIZATION_CODE.equals(((OAuth2) authentication).getGrantType())) {
|
||||||
|
if (!Boolean.TRUE.equals(authentication.getIsAuthorized())) {
|
||||||
return Mono.error(new AppsmithPluginException(
|
return Mono.error(new AppsmithPluginException(
|
||||||
AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR, "Please authorize datasource"));
|
AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR, "Please authorize datasource"));
|
||||||
}
|
}
|
||||||
return Mono.from(OAuth2AuthorizationCode.create((OAuth2) authenticationType));
|
return Mono.from(OAuth2AuthorizationCode.create(datasourceConfiguration));
|
||||||
} else {
|
} else {
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
} else if (authenticationType instanceof BasicAuth) {
|
} else if (authentication instanceof BasicAuth) {
|
||||||
return Mono.from(BasicAuthentication.create((BasicAuth) authenticationType));
|
return Mono.from(BasicAuthentication.create((BasicAuth) authentication));
|
||||||
} else if (authenticationType instanceof ApiKeyAuth) {
|
} else if (authentication instanceof ApiKeyAuth) {
|
||||||
return Mono.from(ApiKeyAuthentication.create((ApiKeyAuth) authenticationType));
|
return Mono.from(ApiKeyAuthentication.create((ApiKeyAuth) authentication));
|
||||||
} else if (authenticationType instanceof BearerTokenAuth) {
|
} else if (authentication instanceof BearerTokenAuth) {
|
||||||
return Mono.from(BearerTokenAuthentication.create((BearerTokenAuth) authenticationType));
|
return Mono.from(BearerTokenAuthentication.create((BearerTokenAuth) authentication));
|
||||||
} else {
|
} else {
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import com.appsmith.external.constants.Authentication;
|
||||||
import com.appsmith.external.exceptions.pluginExceptions.StaleConnectionException;
|
import com.appsmith.external.exceptions.pluginExceptions.StaleConnectionException;
|
||||||
import com.appsmith.external.models.AuthenticationDTO;
|
import com.appsmith.external.models.AuthenticationDTO;
|
||||||
import com.appsmith.external.models.AuthenticationResponse;
|
import com.appsmith.external.models.AuthenticationResponse;
|
||||||
|
import com.appsmith.external.models.DatasourceConfiguration;
|
||||||
import com.appsmith.external.models.OAuth2;
|
import com.appsmith.external.models.OAuth2;
|
||||||
import com.appsmith.external.models.UpdatableConnection;
|
import com.appsmith.external.models.UpdatableConnection;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
|
@ -14,6 +15,7 @@ import org.bson.internal.Base64;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.reactive.function.BodyExtractors;
|
import org.springframework.web.reactive.function.BodyExtractors;
|
||||||
|
|
@ -25,6 +27,7 @@ import org.springframework.web.reactive.function.client.ExchangeStrategies;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import reactor.netty.http.client.HttpClient;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
|
|
@ -69,15 +72,16 @@ public class OAuth2AuthorizationCode extends APIConnection implements UpdatableC
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Mono<OAuth2AuthorizationCode> create(OAuth2 oAuth2) {
|
public static Mono<OAuth2AuthorizationCode> create(DatasourceConfiguration datasourceConfiguration) {
|
||||||
if (oAuth2 == null) {
|
if (datasourceConfiguration == null || datasourceConfiguration.getAuthentication() == null) {
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
final OAuth2 oAuth2 = (OAuth2) datasourceConfiguration.getAuthentication();
|
||||||
// Create OAuth2Connection
|
// Create OAuth2Connection
|
||||||
OAuth2AuthorizationCode connection = new OAuth2AuthorizationCode();
|
OAuth2AuthorizationCode connection = new OAuth2AuthorizationCode();
|
||||||
|
|
||||||
if (!isAuthenticationResponseValid(oAuth2)) {
|
if (!isAuthenticationResponseValid(oAuth2)) {
|
||||||
return connection.generateOAuth2Token(oAuth2)
|
return connection.generateOAuth2Token(datasourceConfiguration)
|
||||||
.flatMap(token -> {
|
.flatMap(token -> {
|
||||||
updateConnection(connection, token);
|
updateConnection(connection, token);
|
||||||
return Mono.just(connection);
|
return Mono.just(connection);
|
||||||
|
|
@ -100,8 +104,13 @@ public class OAuth2AuthorizationCode extends APIConnection implements UpdatableC
|
||||||
return now.isAfter(expiresAt.minus(Duration.ofMinutes(1)));
|
return now.isAfter(expiresAt.minus(Duration.ofMinutes(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<OAuth2> generateOAuth2Token(OAuth2 oAuth2) {
|
private Mono<OAuth2> generateOAuth2Token(DatasourceConfiguration datasourceConfiguration) {
|
||||||
|
final OAuth2 oAuth2 = (OAuth2) datasourceConfiguration.getAuthentication();
|
||||||
|
final HttpClient securedHttpClient = this.getSecuredHttpClient(datasourceConfiguration);
|
||||||
|
|
||||||
|
// Webclient
|
||||||
WebClient.Builder webClientBuilder = WebClient.builder()
|
WebClient.Builder webClientBuilder = WebClient.builder()
|
||||||
|
.clientConnector(new ReactorClientHttpConnector(securedHttpClient))
|
||||||
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
.exchangeStrategies(ExchangeStrategies
|
.exchangeStrategies(ExchangeStrategies
|
||||||
.builder()
|
.builder()
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import com.appsmith.external.constants.Authentication;
|
||||||
import com.appsmith.external.exceptions.pluginExceptions.StaleConnectionException;
|
import com.appsmith.external.exceptions.pluginExceptions.StaleConnectionException;
|
||||||
import com.appsmith.external.models.AuthenticationDTO;
|
import com.appsmith.external.models.AuthenticationDTO;
|
||||||
import com.appsmith.external.models.AuthenticationResponse;
|
import com.appsmith.external.models.AuthenticationResponse;
|
||||||
|
import com.appsmith.external.models.DatasourceConfiguration;
|
||||||
import com.appsmith.external.models.OAuth2;
|
import com.appsmith.external.models.OAuth2;
|
||||||
import com.appsmith.external.models.UpdatableConnection;
|
import com.appsmith.external.models.UpdatableConnection;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
|
@ -14,6 +15,7 @@ import org.bson.internal.Base64;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.reactive.function.BodyExtractors;
|
import org.springframework.web.reactive.function.BodyExtractors;
|
||||||
|
|
@ -25,6 +27,7 @@ import org.springframework.web.reactive.function.client.ExchangeStrategies;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import reactor.netty.http.client.HttpClient;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
|
|
@ -45,10 +48,11 @@ public class OAuth2ClientCredentials extends APIConnection implements UpdatableC
|
||||||
private Object tokenResponse;
|
private Object tokenResponse;
|
||||||
private static final int MAX_IN_MEMORY_SIZE = 10 * 1024 * 1024; // 10 MB
|
private static final int MAX_IN_MEMORY_SIZE = 10 * 1024 * 1024; // 10 MB
|
||||||
|
|
||||||
public static Mono<OAuth2ClientCredentials> create(OAuth2 oAuth2) {
|
public static Mono<OAuth2ClientCredentials> create(DatasourceConfiguration datasourceConfiguration) {
|
||||||
if (oAuth2 == null) {
|
if (datasourceConfiguration == null) {
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
final OAuth2 oAuth2 = (OAuth2) datasourceConfiguration.getAuthentication();
|
||||||
// Create OAuth2Connection
|
// Create OAuth2Connection
|
||||||
OAuth2ClientCredentials connection = new OAuth2ClientCredentials();
|
OAuth2ClientCredentials connection = new OAuth2ClientCredentials();
|
||||||
|
|
||||||
|
|
@ -65,7 +69,7 @@ public class OAuth2ClientCredentials extends APIConnection implements UpdatableC
|
||||||
return now.isBefore(expiresAt.minus(Duration.ofMinutes(1)));
|
return now.isBefore(expiresAt.minus(Duration.ofMinutes(1)));
|
||||||
})
|
})
|
||||||
// If invalid, regenerate token
|
// If invalid, regenerate token
|
||||||
.switchIfEmpty(connection.generateOAuth2Token(oAuth2))
|
.switchIfEmpty(connection.generateOAuth2Token(datasourceConfiguration))
|
||||||
// Store valid token
|
// Store valid token
|
||||||
.flatMap(token -> {
|
.flatMap(token -> {
|
||||||
connection.setToken(token.getAuthenticationResponse().getToken());
|
connection.setToken(token.getAuthenticationResponse().getToken());
|
||||||
|
|
@ -77,9 +81,13 @@ public class OAuth2ClientCredentials extends APIConnection implements UpdatableC
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<OAuth2> generateOAuth2Token(OAuth2 oAuth2) {
|
private Mono<OAuth2> generateOAuth2Token(DatasourceConfiguration datasourceConfiguration) {
|
||||||
|
final OAuth2 oAuth2 = (OAuth2) datasourceConfiguration.getAuthentication();
|
||||||
|
final HttpClient securedHttpClient = this.getSecuredHttpClient(datasourceConfiguration);
|
||||||
|
|
||||||
// Webclient
|
// Webclient
|
||||||
WebClient.Builder webClientBuilder = WebClient.builder()
|
final WebClient.Builder webClientBuilder = WebClient.builder()
|
||||||
|
.clientConnector(new ReactorClientHttpConnector(securedHttpClient))
|
||||||
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
.exchangeStrategies(ExchangeStrategies
|
.exchangeStrategies(ExchangeStrategies
|
||||||
.builder()
|
.builder()
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,6 @@ import com.appsmith.external.models.DatasourceTestResult;
|
||||||
import com.appsmith.external.models.PaginationField;
|
import com.appsmith.external.models.PaginationField;
|
||||||
import com.appsmith.external.models.PaginationType;
|
import com.appsmith.external.models.PaginationType;
|
||||||
import com.appsmith.external.models.Property;
|
import com.appsmith.external.models.Property;
|
||||||
import com.appsmith.external.models.SSLDetails;
|
|
||||||
import com.appsmith.external.models.UploadedFile;
|
|
||||||
import com.appsmith.external.plugins.BasePlugin;
|
import com.appsmith.external.plugins.BasePlugin;
|
||||||
import com.appsmith.external.plugins.PluginExecutor;
|
import com.appsmith.external.plugins.PluginExecutor;
|
||||||
import com.appsmith.external.plugins.SmartSubstitutionInterface;
|
import com.appsmith.external.plugins.SmartSubstitutionInterface;
|
||||||
|
|
@ -56,7 +54,6 @@ import reactor.core.Exceptions;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.netty.http.client.HttpClient;
|
import reactor.netty.http.client.HttpClient;
|
||||||
import reactor.netty.resources.ConnectionProvider;
|
import reactor.netty.resources.ConnectionProvider;
|
||||||
import reactor.netty.tcp.DefaultSslContextSpec;
|
|
||||||
import reactor.util.function.Tuple2;
|
import reactor.util.function.Tuple2;
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
|
|
@ -68,9 +65,6 @@ import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -302,25 +296,8 @@ public class RestApiPlugin extends BasePlugin {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
HttpClient httpClient = HttpClient.create(provider)
|
HttpClient httpClient = HttpClient.create(provider)
|
||||||
.secure(sslContextSpec -> {
|
.secure(SSLHelper.sslCheckForHttpClient(datasourceConfiguration))
|
||||||
|
.compress(true);
|
||||||
final DefaultSslContextSpec sslContextSpec1 = DefaultSslContextSpec.forClient();
|
|
||||||
|
|
||||||
if (datasourceConfiguration.getConnection() != null &&
|
|
||||||
datasourceConfiguration.getConnection().getSsl() != null &&
|
|
||||||
datasourceConfiguration.getConnection().getSsl().getAuthType() == SSLDetails.AuthType.SELF_SIGNED_CERTIFICATE) {
|
|
||||||
|
|
||||||
sslContextSpec1.configure(sslContextBuilder -> {
|
|
||||||
try {
|
|
||||||
final UploadedFile certificateFile = datasourceConfiguration.getConnection().getSsl().getCertificateFile();
|
|
||||||
sslContextBuilder.trustManager(SSLHelper.getSslTrustManagerFactory(certificateFile));
|
|
||||||
} catch (CertificateException | KeyStoreException | IOException | NoSuchAlgorithmException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
sslContextSpec.sslContext(sslContextSpec1);
|
|
||||||
}).compress(true);
|
|
||||||
|
|
||||||
if ("true".equals(System.getProperty("java.net.useSystemProxies"))
|
if ("true".equals(System.getProperty("java.net.useSystemProxies"))
|
||||||
&& (!System.getProperty("http.proxyHost", "").isEmpty() || !System.getProperty("https.proxyHost", "").isEmpty())) {
|
&& (!System.getProperty("http.proxyHost", "").isEmpty() || !System.getProperty("https.proxyHost", "").isEmpty())) {
|
||||||
|
|
@ -620,7 +597,7 @@ public class RestApiPlugin extends BasePlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<APIConnection> datasourceCreate(DatasourceConfiguration datasourceConfiguration) {
|
public Mono<APIConnection> datasourceCreate(DatasourceConfiguration datasourceConfiguration) {
|
||||||
return APIConnectionFactory.createConnection(datasourceConfiguration.getAuthentication());
|
return APIConnectionFactory.createConnection(datasourceConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.external.connections;
|
||||||
|
|
||||||
import com.appsmith.external.exceptions.pluginExceptions.StaleConnectionException;
|
import com.appsmith.external.exceptions.pluginExceptions.StaleConnectionException;
|
||||||
import com.appsmith.external.models.AuthenticationResponse;
|
import com.appsmith.external.models.AuthenticationResponse;
|
||||||
|
import com.appsmith.external.models.DatasourceConfiguration;
|
||||||
import com.appsmith.external.models.OAuth2;
|
import com.appsmith.external.models.OAuth2;
|
||||||
import okhttp3.mockwebserver.MockResponse;
|
import okhttp3.mockwebserver.MockResponse;
|
||||||
import okhttp3.mockwebserver.MockWebServer;
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
|
|
@ -56,13 +57,15 @@ public class OAuth2ClientCredentialsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidConnection() {
|
public void testValidConnection() {
|
||||||
|
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
|
||||||
OAuth2 oAuth2 = new OAuth2();
|
OAuth2 oAuth2 = new OAuth2();
|
||||||
|
datasourceConfiguration.setAuthentication(oAuth2);
|
||||||
AuthenticationResponse authenticationResponse = new AuthenticationResponse();
|
AuthenticationResponse authenticationResponse = new AuthenticationResponse();
|
||||||
oAuth2.setIsTokenHeader(true);
|
oAuth2.setIsTokenHeader(true);
|
||||||
authenticationResponse.setToken("SomeToken");
|
authenticationResponse.setToken("SomeToken");
|
||||||
authenticationResponse.setExpiresAt(Instant.now().plusSeconds(1200));
|
authenticationResponse.setExpiresAt(Instant.now().plusSeconds(1200));
|
||||||
oAuth2.setAuthenticationResponse(authenticationResponse);
|
oAuth2.setAuthenticationResponse(authenticationResponse);
|
||||||
OAuth2ClientCredentials connection = OAuth2ClientCredentials.create(oAuth2).block(Duration.ofMillis(100));
|
OAuth2ClientCredentials connection = OAuth2ClientCredentials.create(datasourceConfiguration).block(Duration.ofMillis(100));
|
||||||
assertThat(connection).isNotNull();
|
assertThat(connection).isNotNull();
|
||||||
assertThat(connection.getExpiresAt()).isEqualTo(authenticationResponse.getExpiresAt());
|
assertThat(connection.getExpiresAt()).isEqualTo(authenticationResponse.getExpiresAt());
|
||||||
assertThat(connection.getToken()).isEqualTo("SomeToken");
|
assertThat(connection.getToken()).isEqualTo("SomeToken");
|
||||||
|
|
@ -70,13 +73,15 @@ public class OAuth2ClientCredentialsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStaleFilter() {
|
public void testStaleFilter() {
|
||||||
|
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
|
||||||
OAuth2 oAuth2 = new OAuth2();
|
OAuth2 oAuth2 = new OAuth2();
|
||||||
|
datasourceConfiguration.setAuthentication(oAuth2);
|
||||||
AuthenticationResponse authenticationResponse = new AuthenticationResponse();
|
AuthenticationResponse authenticationResponse = new AuthenticationResponse();
|
||||||
oAuth2.setIsTokenHeader(true);
|
oAuth2.setIsTokenHeader(true);
|
||||||
authenticationResponse.setToken("SomeToken");
|
authenticationResponse.setToken("SomeToken");
|
||||||
authenticationResponse.setExpiresAt(Instant.now().plusSeconds(1200));
|
authenticationResponse.setExpiresAt(Instant.now().plusSeconds(1200));
|
||||||
oAuth2.setAuthenticationResponse(authenticationResponse);
|
oAuth2.setAuthenticationResponse(authenticationResponse);
|
||||||
OAuth2ClientCredentials connection = OAuth2ClientCredentials.create(oAuth2).block(Duration.ofMillis(100));
|
OAuth2ClientCredentials connection = OAuth2ClientCredentials.create(datasourceConfiguration).block(Duration.ofMillis(100));
|
||||||
connection.setExpiresAt(Instant.now());
|
connection.setExpiresAt(Instant.now());
|
||||||
|
|
||||||
Mono<ClientResponse> response = connection.filter(Mockito.mock(ClientRequest.class), Mockito.mock(ExchangeFunction.class));
|
Mono<ClientResponse> response = connection.filter(Mockito.mock(ClientRequest.class), Mockito.mock(ExchangeFunction.class));
|
||||||
|
|
@ -89,7 +94,9 @@ public class OAuth2ClientCredentialsTest {
|
||||||
public void testCreate_withIsAuthorizationHeaderTrue_sendsCredentialsInHeader() throws InterruptedException {
|
public void testCreate_withIsAuthorizationHeaderTrue_sendsCredentialsInHeader() throws InterruptedException {
|
||||||
String baseUrl = String.format("http://localhost:%s", mockEndpoint.getPort());
|
String baseUrl = String.format("http://localhost:%s", mockEndpoint.getPort());
|
||||||
|
|
||||||
|
final DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
|
||||||
OAuth2 oAuth2 = new OAuth2();
|
OAuth2 oAuth2 = new OAuth2();
|
||||||
|
datasourceConfiguration.setAuthentication(oAuth2);
|
||||||
oAuth2.setIsAuthorizationHeader(true);
|
oAuth2.setIsAuthorizationHeader(true);
|
||||||
oAuth2.setGrantType(OAuth2.Type.CLIENT_CREDENTIALS);
|
oAuth2.setGrantType(OAuth2.Type.CLIENT_CREDENTIALS);
|
||||||
oAuth2.setAccessTokenUrl(baseUrl);
|
oAuth2.setAccessTokenUrl(baseUrl);
|
||||||
|
|
@ -101,7 +108,7 @@ public class OAuth2ClientCredentialsTest {
|
||||||
.setBody("{}")
|
.setBody("{}")
|
||||||
.addHeader("Content-Type", "application/json"));
|
.addHeader("Content-Type", "application/json"));
|
||||||
|
|
||||||
final OAuth2ClientCredentials response = OAuth2ClientCredentials.create(oAuth2).block();
|
final OAuth2ClientCredentials response = OAuth2ClientCredentials.create(datasourceConfiguration).block();
|
||||||
final RecordedRequest recordedRequest = mockEndpoint.takeRequest(30, TimeUnit.SECONDS);
|
final RecordedRequest recordedRequest = mockEndpoint.takeRequest(30, TimeUnit.SECONDS);
|
||||||
|
|
||||||
final String authorizationHeader = recordedRequest.getHeader("Authorization");
|
final String authorizationHeader = recordedRequest.getHeader("Authorization");
|
||||||
|
|
@ -113,7 +120,9 @@ public class OAuth2ClientCredentialsTest {
|
||||||
public void testCreate_withIsAuthorizationHeaderFalse_sendsCredentialsInBody() throws InterruptedException, EOFException {
|
public void testCreate_withIsAuthorizationHeaderFalse_sendsCredentialsInBody() throws InterruptedException, EOFException {
|
||||||
String baseUrl = String.format("http://localhost:%s", mockEndpoint.getPort());
|
String baseUrl = String.format("http://localhost:%s", mockEndpoint.getPort());
|
||||||
|
|
||||||
|
final DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
|
||||||
OAuth2 oAuth2 = new OAuth2();
|
OAuth2 oAuth2 = new OAuth2();
|
||||||
|
datasourceConfiguration.setAuthentication(oAuth2);
|
||||||
oAuth2.setGrantType(OAuth2.Type.CLIENT_CREDENTIALS);
|
oAuth2.setGrantType(OAuth2.Type.CLIENT_CREDENTIALS);
|
||||||
oAuth2.setAccessTokenUrl(baseUrl);
|
oAuth2.setAccessTokenUrl(baseUrl);
|
||||||
oAuth2.setClientId("testId");
|
oAuth2.setClientId("testId");
|
||||||
|
|
@ -124,7 +133,7 @@ public class OAuth2ClientCredentialsTest {
|
||||||
.setBody("{}")
|
.setBody("{}")
|
||||||
.addHeader("Content-Type", "application/json"));
|
.addHeader("Content-Type", "application/json"));
|
||||||
|
|
||||||
final OAuth2ClientCredentials response = OAuth2ClientCredentials.create(oAuth2).block();
|
final OAuth2ClientCredentials response = OAuth2ClientCredentials.create(datasourceConfiguration).block();
|
||||||
final RecordedRequest recordedRequest = mockEndpoint.takeRequest(30, TimeUnit.SECONDS);
|
final RecordedRequest recordedRequest = mockEndpoint.takeRequest(30, TimeUnit.SECONDS);
|
||||||
|
|
||||||
final String authorizationHeader = recordedRequest.getHeader("Authorization");
|
final String authorizationHeader = recordedRequest.getHeader("Authorization");
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.appsmith.server.solutions.ce;
|
||||||
import com.appsmith.external.constants.Authentication;
|
import com.appsmith.external.constants.Authentication;
|
||||||
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
|
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
|
||||||
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
|
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
|
||||||
|
import com.appsmith.external.helpers.SSLHelper;
|
||||||
import com.appsmith.external.models.AuthenticationDTO;
|
import com.appsmith.external.models.AuthenticationDTO;
|
||||||
import com.appsmith.external.models.AuthenticationResponse;
|
import com.appsmith.external.models.AuthenticationResponse;
|
||||||
import com.appsmith.external.models.Datasource;
|
import com.appsmith.external.models.Datasource;
|
||||||
|
|
@ -30,6 +31,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
import org.bson.internal.Base64;
|
import org.bson.internal.Base64;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
@ -38,6 +40,7 @@ import org.springframework.web.reactive.function.BodyInserters;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import reactor.netty.http.client.HttpClient;
|
||||||
|
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
@ -164,7 +167,15 @@ public class AuthenticationServiceCEImpl implements AuthenticationServiceCE {
|
||||||
.flatMap(datasourceService::getById)
|
.flatMap(datasourceService::getById)
|
||||||
.flatMap(datasource -> {
|
.flatMap(datasource -> {
|
||||||
OAuth2 oAuth2 = (OAuth2) datasource.getDatasourceConfiguration().getAuthentication();
|
OAuth2 oAuth2 = (OAuth2) datasource.getDatasourceConfiguration().getAuthentication();
|
||||||
WebClient.Builder builder = WebClient.builder().baseUrl(oAuth2.getAccessTokenUrl());
|
final HttpClient httpClient = HttpClient.create();
|
||||||
|
|
||||||
|
if (oAuth2.isUseSelfSignedCert()) {
|
||||||
|
httpClient.secure(SSLHelper.sslCheckForHttpClient(datasource.getDatasourceConfiguration()));
|
||||||
|
}
|
||||||
|
|
||||||
|
WebClient.Builder builder = WebClient.builder()
|
||||||
|
.clientConnector(new ReactorClientHttpConnector(httpClient))
|
||||||
|
.baseUrl(oAuth2.getAccessTokenUrl());
|
||||||
|
|
||||||
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -854,7 +854,6 @@ public class ExamplesWorkspaceClonerTests {
|
||||||
DatasourceConfiguration dc2 = new DatasourceConfiguration();
|
DatasourceConfiguration dc2 = new DatasourceConfiguration();
|
||||||
ds2.setDatasourceConfiguration(dc2);
|
ds2.setDatasourceConfiguration(dc2);
|
||||||
dc2.setAuthentication(new OAuth2(
|
dc2.setAuthentication(new OAuth2(
|
||||||
|
|
||||||
OAuth2.Type.CLIENT_CREDENTIALS,
|
OAuth2.Type.CLIENT_CREDENTIALS,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
|
@ -872,7 +871,8 @@ public class ExamplesWorkspaceClonerTests {
|
||||||
new Property("custom token param 2", "custom token param value 2")
|
new Property("custom token param 2", "custom token param value 2")
|
||||||
),
|
),
|
||||||
null,
|
null,
|
||||||
null
|
null,
|
||||||
|
false
|
||||||
));
|
));
|
||||||
|
|
||||||
final Datasource ds3 = new Datasource();
|
final Datasource ds3 = new Datasource();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user