44import static ai .pluggy .utils .Asserts .assertValidUrl ;
55
66import ai .pluggy .client .auth .ApiKeyAuthInterceptor ;
7- import ai .pluggy .client .auth .TokenProvider ;
87import ai .pluggy .client .response .AuthResponse ;
98import ai .pluggy .client .response .ErrorResponse ;
109import ai .pluggy .exception .PluggyException ;
1716import java .util .concurrent .TimeUnit ;
1817import okhttp3 .MediaType ;
1918import okhttp3 .OkHttpClient ;
19+ import okhttp3 .OkHttpClient .Builder ;
2020import okhttp3 .Request ;
2121import okhttp3 .RequestBody ;
2222import okhttp3 .ResponseBody ;
23- import org .apache .logging .log4j .LogManager ;
24- import org .apache .logging .log4j .Logger ;
2523import retrofit2 .Retrofit ;
2624import retrofit2 .converter .gson .GsonConverterFactory ;
2725
2826public final class PluggyClient {
2927
30- private static final Logger logger = LogManager .getLogger (PluggyClient .class );
31-
28+ public static String AUTH_URL_PATH = "/auth" ;
3229 private String baseUrl ;
33- private String authUrlPath = "/auth" ;
3430
3531 private String clientId ;
3632 private String clientSecret ;
@@ -109,14 +105,22 @@ public static class PluggyClientBuilder {
109105 private static Integer DEFAULT_HTTP_CONNECT_TIMEOUT_SECONDS = 10 ;
110106 private static Integer DEFAULT_HTTP_READ_TIMEOUT_SECONDS = 180 ;
111107
112- private String authPath = "/auth" ;
113108 private String clientId ;
114109 private String clientSecret ;
115110 private String baseUrl ;
111+ private Builder okHttpClientBuilder ;
112+ private boolean disableDefaultAuthInterceptor = false ;
113+
114+ private PluggyClientBuilder () {
115+ // init OkHttpClient.Builder instance, to expose it for configurability
116+ this .okHttpClientBuilder = new Builder ()
117+ .readTimeout (DEFAULT_HTTP_READ_TIMEOUT_SECONDS , TimeUnit .SECONDS )
118+ .connectTimeout (DEFAULT_HTTP_CONNECT_TIMEOUT_SECONDS , TimeUnit .SECONDS );
119+ }
116120
117121 public PluggyClientBuilder clientIdAndSecret (String clientId , String clientSecret ) {
118- assertNotNull (clientId , "client id " );
119- assertNotNull (clientSecret , "secret " );
122+ assertNotNull (clientId , "clientId " );
123+ assertNotNull (clientSecret , "clientSecret " );
120124 this .clientId = clientId ;
121125 this .clientSecret = clientSecret ;
122126 return this ;
@@ -128,16 +132,37 @@ public PluggyClientBuilder baseUrl(String baseUrl) {
128132 return this ;
129133 }
130134
135+ /**
136+ * Opt-out from provided default ApiKeyAuthInterceptor, which takes care of apiKey authorization,
137+ * by requesting a new apiKey token when it's not set, or by reactively refreshing an existing
138+ * one and retrying a request in case of 401 or 403 unauthorized error responses.
139+ *
140+ * In case of opt-out, the client will have to provide it's own auth interceptor implementation,
141+ * which has to take care of including the "x-api-key" auth header to each http request.
142+ */
143+ public PluggyClientBuilder noAuthInterceptor () {
144+ this .disableDefaultAuthInterceptor = true ;
145+ return this ;
146+ }
147+
148+ /**
149+ * Provides access to the OkHttpClient.Builder instance,
150+ * for more complex builds and configurations (interceptors, SSL, etc.)
151+ */
152+ public OkHttpClient .Builder okHttpClientBuilder () {
153+ return okHttpClientBuilder ;
154+ }
155+
131156 private OkHttpClient buildOkHttpClient (String baseUrl ) {
132- String authUrlPath = baseUrl + authPath ;
157+ if (!disableDefaultAuthInterceptor ) {
158+ // use ApiKeyAuthInterceptor, unless decided to opt-out and use your own
159+ // auth header interceptor implementation.
160+ String authUrlPath = baseUrl + PluggyClient .AUTH_URL_PATH ;
161+ this .okHttpClientBuilder
162+ .addInterceptor (new ApiKeyAuthInterceptor (authUrlPath , clientId , clientSecret ));
163+ }
133164
134- OkHttpClient httpClient = new OkHttpClient .Builder ()
135- .readTimeout (DEFAULT_HTTP_READ_TIMEOUT_SECONDS , TimeUnit .SECONDS )
136- .connectTimeout (DEFAULT_HTTP_CONNECT_TIMEOUT_SECONDS , TimeUnit .SECONDS )
137- .addInterceptor (
138- new ApiKeyAuthInterceptor (authUrlPath , clientId , clientSecret , new TokenProvider ()))
139- .build ();
140- return httpClient ;
165+ return okHttpClientBuilder .build ();
141166 }
142167
143168 private Gson buildGson () {
@@ -148,7 +173,7 @@ private Gson buildGson() {
148173
149174 public PluggyClient build () {
150175 if (clientId == null || clientSecret == null ) {
151- throw new IllegalArgumentException ("Must set a clientId and secret ." );
176+ throw new IllegalArgumentException ("Must set a clientId and clientSecret ." );
152177 }
153178
154179 if (baseUrl == null ) {
@@ -159,6 +184,7 @@ public PluggyClient build() {
159184 }
160185
161186 OkHttpClient httpClient = buildOkHttpClient (baseUrl );
187+
162188 Retrofit retrofit = new Retrofit .Builder ()
163189 .baseUrl (baseUrl )
164190 .validateEagerly (true )
@@ -199,7 +225,7 @@ public String authenticate() throws IOException {
199225 RequestBody body = RequestBody .create (jsonBody , mediaType );
200226
201227 Request request = new Request .Builder ()
202- .url (this .baseUrl + this . authUrlPath )
228+ .url (this .baseUrl + AUTH_URL_PATH )
203229 .post (body )
204230 .addHeader ("content-type" , "application/json" )
205231 .addHeader ("cache-control" , "no-cache" )
@@ -218,6 +244,7 @@ public String authenticate() throws IOException {
218244 assertNotNull (responseBody , "response.body()" );
219245 authResponse = gson .fromJson (responseBody .string (), AuthResponse .class );
220246 }
247+
221248 return authResponse .getApiKey ();
222249 }
223250
0 commit comments