Skip to content

Commit 8e00f6e

Browse files
authored
Use secure passwords for OAuth2 logins (#157)
1 parent 00d2e91 commit 8e00f6e

File tree

6 files changed

+353
-24
lines changed

6 files changed

+353
-24
lines changed

src/main/java/org/gitlab4j/api/AbstractApi.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import javax.ws.rs.core.Form;
88
import javax.ws.rs.core.MultivaluedMap;
99
import javax.ws.rs.core.Response;
10+
import javax.ws.rs.core.StreamingOutput;
1011

1112
import org.gitlab4j.api.GitLabApi.ApiVersion;
1213

@@ -141,6 +142,25 @@ protected Response post(Response.Status expectedStatus, Object payload, Object..
141142
}
142143
}
143144

145+
/**
146+
* Perform an HTTP POST call with the specified payload object and path objects, returning
147+
* a ClientResponse instance with the data returned from the endpoint.
148+
*
149+
* @param expectedStatus the HTTP status that should be returned from the server
150+
* @param stream the StreamingOutput taht will be used for the POST data
151+
* @param mediaType the content-type for the streamed data
152+
* @param pathArgs variable list of arguments used to build the URI
153+
* @return a ClientResponse instance with the data returned from the endpoint
154+
* @throws GitLabApiException if any exception occurs during execution
155+
*/
156+
protected Response post(Response.Status expectedStatus, StreamingOutput stream, String mediaType, Object... pathArgs) throws GitLabApiException {
157+
try {
158+
return validate(getApiClient().post(stream, mediaType, pathArgs), expectedStatus);
159+
} catch (Exception e) {
160+
throw handle(e);
161+
}
162+
}
163+
144164
/**
145165
* Perform an HTTP POST call with the specified form data and path objects, returning
146166
* a ClientResponse instance with the data returned from the endpoint.

src/main/java/org/gitlab4j/api/GitLabApi.java

Lines changed: 159 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
import java.util.Optional;
66
import java.util.WeakHashMap;
77

8+
import javax.ws.rs.core.MediaType;
89
import javax.ws.rs.core.Response;
910

1011
import org.gitlab4j.api.Constants.TokenType;
1112
import org.gitlab4j.api.models.OauthTokenResponse;
1213
import org.gitlab4j.api.models.Session;
1314
import org.gitlab4j.api.models.User;
1415
import org.gitlab4j.api.models.Version;
16+
import org.gitlab4j.api.utils.Oauth2LoginStreamingOutput;
17+
import org.gitlab4j.api.utils.SecretString;
1518

1619
/**
1720
* This class is provides a simplified interface to a GitLab API server, and divides the API up into
@@ -95,11 +98,44 @@ public final GitLabApi duplicate() {
9598
* @param password password for a given {@code username}
9699
* @return new {@code GitLabApi} instance configured for a user-specific token
97100
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
101+
* @deprecated As of release 4.8.7, replaced by {@link #oauth2Login(String, String, CharSequence)}, will be removed in 4.9.0
98102
*/
103+
@Deprecated
99104
public static GitLabApi oauth2Login(String url, String username, String password) throws GitLabApiException {
100105
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, null, null, false));
101106
}
102107

108+
/**
109+
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
110+
* and creates a new {@code GitLabApi} instance using returned access token.</p>
111+
*
112+
* @param url GitLab URL
113+
* @param username user name for which private token should be obtained
114+
* @param password a CharSequence containing the password for a given {@code username}
115+
* @return new {@code GitLabApi} instance configured for a user-specific token
116+
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
117+
*/
118+
public static GitLabApi oauth2Login(String url, String username, CharSequence password) throws GitLabApiException {
119+
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, null, null, false));
120+
}
121+
122+
/**
123+
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
124+
* and creates a new {@code GitLabApi} instance using returned access token.</p>
125+
*
126+
* @param url GitLab URL
127+
* @param username user name for which private token should be obtained
128+
* @param password a char array holding the password for a given {@code username}
129+
* @return new {@code GitLabApi} instance configured for a user-specific token
130+
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
131+
*/
132+
public static GitLabApi oauth2Login(String url, String username, char[] password) throws GitLabApiException {
133+
134+
try (SecretString secretPassword = new SecretString(password)) {
135+
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, secretPassword, null, null, false));
136+
}
137+
}
138+
103139
/**
104140
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
105141
* and creates a new {@code GitLabApi} instance using returned access token.</p>
@@ -110,11 +146,46 @@ public static GitLabApi oauth2Login(String url, String username, String password
110146
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
111147
* @return new {@code GitLabApi} instance configured for a user-specific token
112148
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
149+
* @deprecated As of release 4.8.7, replaced by {@link #oauth2Login(String, String, CharSequence, boolean)}, will be removed in 4.9.0
113150
*/
151+
@Deprecated
114152
public static GitLabApi oauth2Login(String url, String username, String password, boolean ignoreCertificateErrors) throws GitLabApiException {
115153
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, null, null, ignoreCertificateErrors));
116154
}
117155

156+
/**
157+
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
158+
* and creates a new {@code GitLabApi} instance using returned access token.</p>
159+
*
160+
* @param url GitLab URL
161+
* @param username user name for which private token should be obtained
162+
* @param password a CharSequence containing the password for a given {@code username}
163+
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
164+
* @return new {@code GitLabApi} instance configured for a user-specific token
165+
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
166+
*/
167+
public static GitLabApi oauth2Login(String url, String username, CharSequence password, boolean ignoreCertificateErrors) throws GitLabApiException {
168+
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, null, null, ignoreCertificateErrors));
169+
}
170+
171+
/**
172+
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
173+
* and creates a new {@code GitLabApi} instance using returned access token.</p>
174+
*
175+
* @param url GitLab URL
176+
* @param username user name for which private token should be obtained
177+
* @param password a char array holding the password for a given {@code username}
178+
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
179+
* @return new {@code GitLabApi} instance configured for a user-specific token
180+
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
181+
*/
182+
public static GitLabApi oauth2Login(String url, String username, char[] password, boolean ignoreCertificateErrors) throws GitLabApiException {
183+
184+
try (SecretString secretPassword = new SecretString(password)) {
185+
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, secretPassword, null, null, ignoreCertificateErrors));
186+
}
187+
}
188+
118189
/**
119190
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
120191
* and creates a new {@code GitLabApi} instance using returned access token.</p>
@@ -127,13 +198,77 @@ public static GitLabApi oauth2Login(String url, String username, String password
127198
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
128199
* @return new {@code GitLabApi} instance configured for a user-specific token
129200
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
201+
* @deprecated As of release 4.8.7, will be removed in 4.9.0
130202
*/
131-
public static GitLabApi oauth2Login(String url, String username, String password,
132-
String secretToken, Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors)
133-
throws GitLabApiException {
203+
@Deprecated
204+
public static GitLabApi oauth2Login(String url, String username, String password, String secretToken,
205+
Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors) throws GitLabApiException {
206+
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, secretToken, clientConfigProperties, ignoreCertificateErrors));
207+
}
208+
209+
/**
210+
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
211+
* and creates a new {@code GitLabApi} instance using returned access token.</p>
212+
*
213+
* @param url GitLab URL
214+
* @param username user name for which private token should be obtained
215+
* @param password a CharSequence containing the password for a given {@code username}
216+
* @param secretToken use this token to validate received payloads
217+
* @param clientConfigProperties Map instance with additional properties for the Jersey client connection
218+
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
219+
* @return new {@code GitLabApi} instance configured for a user-specific token
220+
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
221+
*/
222+
public static GitLabApi oauth2Login(String url, String username, CharSequence password, String secretToken,
223+
Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors) throws GitLabApiException {
134224
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, secretToken, clientConfigProperties, ignoreCertificateErrors));
135225
}
136226

227+
/**
228+
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
229+
* and creates a new {@code GitLabApi} instance using returned access token.</p>
230+
*
231+
* @param url GitLab URL
232+
* @param username user name for which private token should be obtained
233+
* @param password a char array holding the password for a given {@code username}
234+
* @param secretToken use this token to validate received payloads
235+
* @param clientConfigProperties Map instance with additional properties for the Jersey client connection
236+
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
237+
* @return new {@code GitLabApi} instance configured for a user-specific token
238+
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
239+
*/
240+
public static GitLabApi oauth2Login(String url, String username, char[] password, String secretToken,
241+
Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors) throws GitLabApiException {
242+
243+
try (SecretString secretPassword = new SecretString(password)) {
244+
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, secretPassword,
245+
secretToken, clientConfigProperties, ignoreCertificateErrors));
246+
}
247+
}
248+
249+
/**
250+
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
251+
* and creates a new {@code GitLabApi} instance using returned access token.</p>
252+
*
253+
* @param url GitLab URL
254+
* @param apiVersion the ApiVersion specifying which version of the API to use
255+
* @param username user name for which private token should be obtained
256+
* @param password a char array holding the password for a given {@code username}
257+
* @param secretToken use this token to validate received payloads
258+
* @param clientConfigProperties Map instance with additional properties for the Jersey client connection
259+
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
260+
* @return new {@code GitLabApi} instance configured for a user-specific token
261+
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
262+
*/
263+
public static GitLabApi oauth2Login(ApiVersion apiVersion, String url, String username, char[] password, String secretToken,
264+
Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors) throws GitLabApiException {
265+
266+
try (SecretString secretPassword = new SecretString(password)) {
267+
return (GitLabApi.oauth2Login(apiVersion, url, username, secretPassword,
268+
secretToken, clientConfigProperties, ignoreCertificateErrors));
269+
}
270+
}
271+
137272
/**
138273
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
139274
* and creates a new {@code GitLabApi} instance using returned access token.</p>
@@ -148,7 +283,7 @@ public static GitLabApi oauth2Login(String url, String username, String password
148283
* @return new {@code GitLabApi} instance configured for a user-specific token
149284
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
150285
*/
151-
public static GitLabApi oauth2Login(ApiVersion apiVersion, String url, String username, String password,
286+
public static GitLabApi oauth2Login(ApiVersion apiVersion, String url, String username, CharSequence password,
152287
String secretToken, Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors)
153288
throws GitLabApiException {
154289

@@ -167,19 +302,17 @@ class Oauth2Api extends AbstractApi {
167302
}
168303
}
169304

170-
GitLabApiForm formData = new GitLabApiForm()
171-
.withParam("grant_type", "password", true)
172-
.withParam("username", username, true)
173-
.withParam("password", password, true);
305+
try (Oauth2LoginStreamingOutput stream = new Oauth2LoginStreamingOutput(username, password)) {
174306

175-
Response response = new Oauth2Api(gitLabApi).post(Response.Status.OK, formData, "oauth", "token");
176-
OauthTokenResponse oauthToken = response.readEntity(OauthTokenResponse.class);
177-
gitLabApi = new GitLabApi(apiVersion, url, TokenType.ACCESS, oauthToken.getAccessToken(), secretToken, clientConfigProperties);
178-
if (ignoreCertificateErrors) {
179-
gitLabApi.setIgnoreCertificateErrors(true);
180-
}
307+
Response response = new Oauth2Api(gitLabApi).post(Response.Status.OK, stream, MediaType.APPLICATION_JSON, "oauth", "token");
308+
OauthTokenResponse oauthToken = response.readEntity(OauthTokenResponse.class);
309+
gitLabApi = new GitLabApi(apiVersion, url, TokenType.ACCESS, oauthToken.getAccessToken(), secretToken, clientConfigProperties);
310+
if (ignoreCertificateErrors) {
311+
gitLabApi.setIgnoreCertificateErrors(true);
312+
}
181313

182-
return (gitLabApi);
314+
return (gitLabApi);
315+
}
183316
}
184317

185318
/**
@@ -195,7 +328,9 @@ class Oauth2Api extends AbstractApi {
195328
* @param password password for a given {@code username}
196329
* @return new {@code GitLabApi} instance configured for a user-specific token
197330
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
331+
* @deprecated As of release 4.8.7, will be removed in 4.9.0
198332
*/
333+
@Deprecated
199334
public static GitLabApi login(ApiVersion apiVersion, String url, String username, String password) throws GitLabApiException {
200335
return (GitLabApi.login(apiVersion, url, username, password, false));
201336
}
@@ -212,7 +347,9 @@ public static GitLabApi login(ApiVersion apiVersion, String url, String username
212347
* @param password password for a given {@code username}
213348
* @return new {@code GitLabApi} instance configured for a user-specific token
214349
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
350+
* @deprecated As of release 4.8.7, will be removed in 4.9.0
215351
*/
352+
@Deprecated
216353
public static GitLabApi login(String url, String username, String password) throws GitLabApiException {
217354
return (GitLabApi.login(ApiVersion.V4, url, username, password, false));
218355
}
@@ -231,7 +368,9 @@ public static GitLabApi login(String url, String username, String password) thro
231368
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
232369
* @return new {@code GitLabApi} instance configured for a user-specific token
233370
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
371+
* @deprecated As of release 4.8.7, will be removed in 4.9.0
234372
*/
373+
@Deprecated
235374
public static GitLabApi login(ApiVersion apiVersion, String url, String username, String password, boolean ignoreCertificateErrors) throws GitLabApiException {
236375

237376
GitLabApi gitLabApi = new GitLabApi(apiVersion, url, (String)null);
@@ -273,7 +412,9 @@ public static GitLabApi login(ApiVersion apiVersion, String url, String username
273412
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
274413
* @return new {@code GitLabApi} instance configured for a user-specific token
275414
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
415+
* @deprecated As of release 4.8.7, will be removed in 4.9.0
276416
*/
417+
@Deprecated
277418
public static GitLabApi login(String url, String username, String password, boolean ignoreCertificateErrors) throws GitLabApiException {
278419
return (GitLabApi.login(ApiVersion.V4, url, username, password, ignoreCertificateErrors));
279420
}
@@ -287,7 +428,7 @@ public static GitLabApi login(String url, String username, String password, bool
287428
* @param password password for a given {@code username}
288429
* @return new {@code GitLabApi} instance configured for a user-specific token
289430
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
290-
* @deprecated As of release 4.2.0, replaced by {@link #login(String, String, String)}, will be removed in 5.0.0
431+
* @deprecated As of release 4.2.0, replaced by {@link #login(String, String, String)}, will be removed in 4.9.0
291432
*/
292433
@Deprecated
293434
public static GitLabApi create(String url, String username, String password) throws GitLabApiException {
@@ -301,8 +442,9 @@ public static GitLabApi create(String url, String username, String password) thr
301442
* <strong>NOTE</strong>: For GitLab servers 10.2 and above this method will always return null.
302443
*
303444
* @return the Session instance
304-
* @deprecated This method will be removed in Release 5.0.0
445+
* @deprecated This method will be removed in Release 4.9.0
305446
*/
447+
@Deprecated
306448
public Session getSession() {
307449
return session;
308450
}

0 commit comments

Comments
 (0)