1
1
package cloud .stackit .sdk .core ;
2
2
3
+ import cloud .stackit .sdk .core .auth .SetupAuth ;
3
4
import cloud .stackit .sdk .core .config .CoreConfiguration ;
4
5
import cloud .stackit .sdk .core .config .EnvironmentVariables ;
5
6
import cloud .stackit .sdk .core .exception .ApiException ;
23
24
import java .util .UUID ;
24
25
import java .util .concurrent .TimeUnit ;
25
26
import okhttp3 .*;
27
+ import org .jetbrains .annotations .NotNull ;
26
28
27
- /** KeyFlowAuthenticator handles the Key Flow Authentication based on the Service Account Key. */
28
- public class KeyFlowAuthenticator {
29
- private final String REFRESH_TOKEN = "refresh_token" ;
30
- private final String ASSERTION = "assertion" ;
31
- private final String DEFAULT_TOKEN_ENDPOINT = "https://service-account.api.stackit.cloud/token" ;
32
- private final long DEFAULT_TOKEN_LEEWAY = 60 ;
33
- private final int CONNECT_TIMEOUT = 10 ;
34
- private final int WRITE_TIMEOUT = 10 ;
35
- private final int READ_TIMEOUT = 10 ;
29
+ /* KeyFlowAuthenticator handles the Key Flow Authentication based on the Service Account Key. */
30
+ public class KeyFlowAuthenticator implements Authenticator {
31
+ private static final String REFRESH_TOKEN = "refresh_token" ;
32
+ private static final String ASSERTION = "assertion" ;
33
+ private static final String DEFAULT_TOKEN_ENDPOINT =
34
+ "https://service-account.api.stackit.cloud/token" ;
35
+ private static final long DEFAULT_TOKEN_LEEWAY = 60 ;
36
+ private static final int CONNECT_TIMEOUT = 10 ;
37
+ private static final int WRITE_TIMEOUT = 10 ;
38
+ private static final int READ_TIMEOUT = 10 ;
36
39
37
40
private final OkHttpClient httpClient ;
38
41
private final ServiceAccountKey saKey ;
@@ -41,6 +44,100 @@ public class KeyFlowAuthenticator {
41
44
private final String tokenUrl ;
42
45
private long tokenLeewayInSeconds = DEFAULT_TOKEN_LEEWAY ;
43
46
47
+ /**
48
+ * Creates the initial service account and refreshes expired access token.
49
+ *
50
+ * @deprecated use constructor with OkHttpClient instead to prevent resource leaks. Will be
51
+ * removed in April 2026.
52
+ * @param cfg Configuration to set a custom token endpoint and the token expiration leeway.
53
+ * @param saKey Service Account Key, which should be used for the authentication
54
+ */
55
+ @ Deprecated
56
+ public KeyFlowAuthenticator (CoreConfiguration cfg , ServiceAccountKey saKey ) {
57
+ this (new OkHttpClient (), cfg , saKey , new EnvironmentVariables ());
58
+ }
59
+
60
+ /**
61
+ * Creates the initial service account and refreshes expired access token.
62
+ *
63
+ * @deprecated use constructor with OkHttpClient instead to prevent resource leaks. Will be
64
+ * removed in April 2026.
65
+ * @param cfg Configuration to set a custom token endpoint and the token expiration leeway.
66
+ * @param saKey Service Account Key, which should be used for the authentication
67
+ */
68
+ @ Deprecated
69
+ public KeyFlowAuthenticator (
70
+ CoreConfiguration cfg ,
71
+ ServiceAccountKey saKey ,
72
+ EnvironmentVariables environmentVariables ) {
73
+ this (new OkHttpClient (), cfg , saKey , environmentVariables );
74
+ }
75
+
76
+ /**
77
+ * Creates the initial service account and refreshes expired access token.
78
+ *
79
+ * @param httpClient OkHttpClient object
80
+ * @param cfg Configuration to set a custom token endpoint and the token expiration leeway.
81
+ */
82
+ public KeyFlowAuthenticator (OkHttpClient httpClient , CoreConfiguration cfg ) throws IOException {
83
+ this (httpClient , cfg , SetupAuth .setupKeyFlow (cfg ), new EnvironmentVariables ());
84
+ }
85
+
86
+ /**
87
+ * Creates the initial service account and refreshes expired access token.
88
+ *
89
+ * @param httpClient OkHttpClient object
90
+ * @param cfg Configuration to set a custom token endpoint and the token expiration leeway.
91
+ * @param saKey Service Account Key, which should be used for the authentication
92
+ */
93
+ public KeyFlowAuthenticator (
94
+ OkHttpClient httpClient , CoreConfiguration cfg , ServiceAccountKey saKey ) {
95
+ this (httpClient , cfg , saKey , new EnvironmentVariables ());
96
+ }
97
+
98
+ protected KeyFlowAuthenticator (
99
+ OkHttpClient httpClient ,
100
+ CoreConfiguration cfg ,
101
+ ServiceAccountKey saKey ,
102
+ EnvironmentVariables environmentVariables ) {
103
+ this .saKey = saKey ;
104
+ this .gson = new Gson ();
105
+ this .httpClient =
106
+ httpClient
107
+ .newBuilder ()
108
+ .connectTimeout (CONNECT_TIMEOUT , TimeUnit .SECONDS )
109
+ .writeTimeout (WRITE_TIMEOUT , TimeUnit .SECONDS )
110
+ .readTimeout (READ_TIMEOUT , TimeUnit .SECONDS )
111
+ .build ();
112
+
113
+ if (Utils .isStringSet (cfg .getTokenCustomUrl ())) {
114
+ this .tokenUrl = cfg .getTokenCustomUrl ();
115
+ } else if (Utils .isStringSet (environmentVariables .getStackitTokenBaseurl ())) {
116
+ this .tokenUrl = environmentVariables .getStackitTokenBaseurl ();
117
+ } else {
118
+ this .tokenUrl = DEFAULT_TOKEN_ENDPOINT ;
119
+ }
120
+ if (cfg .getTokenExpirationLeeway () != null && cfg .getTokenExpirationLeeway () > 0 ) {
121
+ this .tokenLeewayInSeconds = cfg .getTokenExpirationLeeway ();
122
+ }
123
+ }
124
+
125
+ @ Override
126
+ public Request authenticate (Route route , @ NotNull Response response ) throws IOException {
127
+ String accessToken ;
128
+ try {
129
+ accessToken = getAccessToken ();
130
+ } catch (ApiException | InvalidKeySpecException e ) {
131
+ throw new RuntimeException (e );
132
+ }
133
+
134
+ // Return a new request with the refreshed token
135
+ return response .request ()
136
+ .newBuilder ()
137
+ .header ("Authorization" , "Bearer " + accessToken )
138
+ .build ();
139
+ }
140
+
44
141
protected static class KeyFlowTokenResponse {
45
142
@ SerializedName ("access_token" )
46
143
private String accessToken ;
@@ -79,45 +176,6 @@ protected String getAccessToken() {
79
176
}
80
177
}
81
178
82
- public KeyFlowAuthenticator (CoreConfiguration cfg , ServiceAccountKey saKey ) {
83
- this (cfg , saKey , null );
84
- }
85
-
86
- /**
87
- * Creates the initial service account and refreshes expired access token.
88
- *
89
- * @param cfg Configuration to set a custom token endpoint and the token expiration leeway.
90
- * @param saKey Service Account Key, which should be used for the authentication
91
- */
92
- public KeyFlowAuthenticator (
93
- CoreConfiguration cfg ,
94
- ServiceAccountKey saKey ,
95
- EnvironmentVariables environmentVariables ) {
96
- this .saKey = saKey ;
97
- this .gson = new Gson ();
98
- this .httpClient =
99
- new OkHttpClient .Builder ()
100
- .connectTimeout (CONNECT_TIMEOUT , TimeUnit .SECONDS )
101
- .writeTimeout (WRITE_TIMEOUT , TimeUnit .SECONDS )
102
- .readTimeout (READ_TIMEOUT , TimeUnit .SECONDS )
103
- .build ();
104
-
105
- if (environmentVariables == null ) {
106
- environmentVariables = new EnvironmentVariables ();
107
- }
108
-
109
- if (Utils .isStringSet (cfg .getTokenCustomUrl ())) {
110
- this .tokenUrl = cfg .getTokenCustomUrl ();
111
- } else if (Utils .isStringSet (environmentVariables .getStackitTokenBaseurl ())) {
112
- this .tokenUrl = environmentVariables .getStackitTokenBaseurl ();
113
- } else {
114
- this .tokenUrl = DEFAULT_TOKEN_ENDPOINT ;
115
- }
116
- if (cfg .getTokenExpirationLeeway () != null && cfg .getTokenExpirationLeeway () > 0 ) {
117
- this .tokenLeewayInSeconds = cfg .getTokenExpirationLeeway ();
118
- }
119
- }
120
-
121
179
/**
122
180
* Returns access token. If the token is expired it creates a new token.
123
181
*
0 commit comments