Skip to content

Use secure passwords for OAuth2 logins #157

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

Merged
merged 6 commits into from
Mar 13, 2018
Merged
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
20 changes: 20 additions & 0 deletions src/main/java/org/gitlab4j/api/AbstractApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;

import org.gitlab4j.api.GitLabApi.ApiVersion;

Expand Down Expand Up @@ -141,6 +142,25 @@ protected Response post(Response.Status expectedStatus, Object payload, Object..
}
}

/**
* Perform an HTTP POST call with the specified payload object and path objects, returning
* a ClientResponse instance with the data returned from the endpoint.
*
* @param expectedStatus the HTTP status that should be returned from the server
* @param stream the StreamingOutput taht will be used for the POST data
* @param mediaType the content-type for the streamed data
* @param pathArgs variable list of arguments used to build the URI
* @return a ClientResponse instance with the data returned from the endpoint
* @throws GitLabApiException if any exception occurs during execution
*/
protected Response post(Response.Status expectedStatus, StreamingOutput stream, String mediaType, Object... pathArgs) throws GitLabApiException {
try {
return validate(getApiClient().post(stream, mediaType, pathArgs), expectedStatus);
} catch (Exception e) {
throw handle(e);
}
}

/**
* Perform an HTTP POST call with the specified form data and path objects, returning
* a ClientResponse instance with the data returned from the endpoint.
Expand Down
176 changes: 159 additions & 17 deletions src/main/java/org/gitlab4j/api/GitLabApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
import java.util.Optional;
import java.util.WeakHashMap;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.gitlab4j.api.Constants.TokenType;
import org.gitlab4j.api.models.OauthTokenResponse;
import org.gitlab4j.api.models.Session;
import org.gitlab4j.api.models.User;
import org.gitlab4j.api.models.Version;
import org.gitlab4j.api.utils.Oauth2LoginStreamingOutput;
import org.gitlab4j.api.utils.SecretString;

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

/**
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
* and creates a new {@code GitLabApi} instance using returned access token.</p>
*
* @param url GitLab URL
* @param username user name for which private token should be obtained
* @param password a CharSequence containing the password for a given {@code username}
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
*/
public static GitLabApi oauth2Login(String url, String username, CharSequence password) throws GitLabApiException {
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, null, null, false));
}

/**
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
* and creates a new {@code GitLabApi} instance using returned access token.</p>
*
* @param url GitLab URL
* @param username user name for which private token should be obtained
* @param password a char array holding the password for a given {@code username}
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
*/
public static GitLabApi oauth2Login(String url, String username, char[] password) throws GitLabApiException {

try (SecretString secretPassword = new SecretString(password)) {
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, secretPassword, null, null, false));
}
}

/**
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
* and creates a new {@code GitLabApi} instance using returned access token.</p>
Expand All @@ -110,11 +146,46 @@ public static GitLabApi oauth2Login(String url, String username, String password
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
* @deprecated As of release 4.8.7, replaced by {@link #oauth2Login(String, String, CharSequence, boolean)}, will be removed in 4.9.0
*/
@Deprecated
public static GitLabApi oauth2Login(String url, String username, String password, boolean ignoreCertificateErrors) throws GitLabApiException {
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, null, null, ignoreCertificateErrors));
}

/**
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
* and creates a new {@code GitLabApi} instance using returned access token.</p>
*
* @param url GitLab URL
* @param username user name for which private token should be obtained
* @param password a CharSequence containing the password for a given {@code username}
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
*/
public static GitLabApi oauth2Login(String url, String username, CharSequence password, boolean ignoreCertificateErrors) throws GitLabApiException {
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, null, null, ignoreCertificateErrors));
}

/**
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
* and creates a new {@code GitLabApi} instance using returned access token.</p>
*
* @param url GitLab URL
* @param username user name for which private token should be obtained
* @param password a char array holding the password for a given {@code username}
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
*/
public static GitLabApi oauth2Login(String url, String username, char[] password, boolean ignoreCertificateErrors) throws GitLabApiException {

try (SecretString secretPassword = new SecretString(password)) {
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, secretPassword, null, null, ignoreCertificateErrors));
}
}

/**
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
* and creates a new {@code GitLabApi} instance using returned access token.</p>
Expand All @@ -127,13 +198,77 @@ public static GitLabApi oauth2Login(String url, String username, String password
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
* @deprecated As of release 4.8.7, will be removed in 4.9.0
*/
public static GitLabApi oauth2Login(String url, String username, String password,
String secretToken, Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors)
throws GitLabApiException {
@Deprecated
public static GitLabApi oauth2Login(String url, String username, String password, String secretToken,
Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors) throws GitLabApiException {
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, secretToken, clientConfigProperties, ignoreCertificateErrors));
}

/**
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
* and creates a new {@code GitLabApi} instance using returned access token.</p>
*
* @param url GitLab URL
* @param username user name for which private token should be obtained
* @param password a CharSequence containing the password for a given {@code username}
* @param secretToken use this token to validate received payloads
* @param clientConfigProperties Map instance with additional properties for the Jersey client connection
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
*/
public static GitLabApi oauth2Login(String url, String username, CharSequence password, String secretToken,
Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors) throws GitLabApiException {
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, password, secretToken, clientConfigProperties, ignoreCertificateErrors));
}

/**
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
* and creates a new {@code GitLabApi} instance using returned access token.</p>
*
* @param url GitLab URL
* @param username user name for which private token should be obtained
* @param password a char array holding the password for a given {@code username}
* @param secretToken use this token to validate received payloads
* @param clientConfigProperties Map instance with additional properties for the Jersey client connection
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
*/
public static GitLabApi oauth2Login(String url, String username, char[] password, String secretToken,
Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors) throws GitLabApiException {

try (SecretString secretPassword = new SecretString(password)) {
return (GitLabApi.oauth2Login(ApiVersion.V4, url, username, secretPassword,
secretToken, clientConfigProperties, ignoreCertificateErrors));
}
}

/**
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
* and creates a new {@code GitLabApi} instance using returned access token.</p>
*
* @param url GitLab URL
* @param apiVersion the ApiVersion specifying which version of the API to use
* @param username user name for which private token should be obtained
* @param password a char array holding the password for a given {@code username}
* @param secretToken use this token to validate received payloads
* @param clientConfigProperties Map instance with additional properties for the Jersey client connection
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
*/
public static GitLabApi oauth2Login(ApiVersion apiVersion, String url, String username, char[] password, String secretToken,
Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors) throws GitLabApiException {

try (SecretString secretPassword = new SecretString(password)) {
return (GitLabApi.oauth2Login(apiVersion, url, username, secretPassword,
secretToken, clientConfigProperties, ignoreCertificateErrors));
}
}

/**
* <p>Logs into GitLab using OAuth2 with the provided {@code username} and {@code password},
* and creates a new {@code GitLabApi} instance using returned access token.</p>
Expand All @@ -148,7 +283,7 @@ public static GitLabApi oauth2Login(String url, String username, String password
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
*/
public static GitLabApi oauth2Login(ApiVersion apiVersion, String url, String username, String password,
public static GitLabApi oauth2Login(ApiVersion apiVersion, String url, String username, CharSequence password,
String secretToken, Map<String, Object> clientConfigProperties, boolean ignoreCertificateErrors)
throws GitLabApiException {

Expand All @@ -167,19 +302,17 @@ class Oauth2Api extends AbstractApi {
}
}

GitLabApiForm formData = new GitLabApiForm()
.withParam("grant_type", "password", true)
.withParam("username", username, true)
.withParam("password", password, true);
try (Oauth2LoginStreamingOutput stream = new Oauth2LoginStreamingOutput(username, password)) {

Response response = new Oauth2Api(gitLabApi).post(Response.Status.OK, formData, "oauth", "token");
OauthTokenResponse oauthToken = response.readEntity(OauthTokenResponse.class);
gitLabApi = new GitLabApi(apiVersion, url, TokenType.ACCESS, oauthToken.getAccessToken(), secretToken, clientConfigProperties);
if (ignoreCertificateErrors) {
gitLabApi.setIgnoreCertificateErrors(true);
}
Response response = new Oauth2Api(gitLabApi).post(Response.Status.OK, stream, MediaType.APPLICATION_JSON, "oauth", "token");
OauthTokenResponse oauthToken = response.readEntity(OauthTokenResponse.class);
gitLabApi = new GitLabApi(apiVersion, url, TokenType.ACCESS, oauthToken.getAccessToken(), secretToken, clientConfigProperties);
if (ignoreCertificateErrors) {
gitLabApi.setIgnoreCertificateErrors(true);
}

return (gitLabApi);
return (gitLabApi);
}
}

/**
Expand All @@ -195,7 +328,9 @@ class Oauth2Api extends AbstractApi {
* @param password password for a given {@code username}
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
* @deprecated As of release 4.8.7, will be removed in 4.9.0
*/
@Deprecated
public static GitLabApi login(ApiVersion apiVersion, String url, String username, String password) throws GitLabApiException {
return (GitLabApi.login(apiVersion, url, username, password, false));
}
Expand All @@ -212,7 +347,9 @@ public static GitLabApi login(ApiVersion apiVersion, String url, String username
* @param password password for a given {@code username}
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
* @deprecated As of release 4.8.7, will be removed in 4.9.0
*/
@Deprecated
public static GitLabApi login(String url, String username, String password) throws GitLabApiException {
return (GitLabApi.login(ApiVersion.V4, url, username, password, false));
}
Expand All @@ -231,7 +368,9 @@ public static GitLabApi login(String url, String username, String password) thro
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
* @deprecated As of release 4.8.7, will be removed in 4.9.0
*/
@Deprecated
public static GitLabApi login(ApiVersion apiVersion, String url, String username, String password, boolean ignoreCertificateErrors) throws GitLabApiException {

GitLabApi gitLabApi = new GitLabApi(apiVersion, url, (String)null);
Expand Down Expand Up @@ -273,7 +412,9 @@ public static GitLabApi login(ApiVersion apiVersion, String url, String username
* @param ignoreCertificateErrors if true will set up the Jersey system ignore SSL certificate errors
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
* @deprecated As of release 4.8.7, will be removed in 4.9.0
*/
@Deprecated
public static GitLabApi login(String url, String username, String password, boolean ignoreCertificateErrors) throws GitLabApiException {
return (GitLabApi.login(ApiVersion.V4, url, username, password, ignoreCertificateErrors));
}
Expand All @@ -287,7 +428,7 @@ public static GitLabApi login(String url, String username, String password, bool
* @param password password for a given {@code username}
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
* @deprecated As of release 4.2.0, replaced by {@link #login(String, String, String)}, will be removed in 5.0.0
* @deprecated As of release 4.2.0, replaced by {@link #login(String, String, String)}, will be removed in 4.9.0
*/
@Deprecated
public static GitLabApi create(String url, String username, String password) throws GitLabApiException {
Expand All @@ -301,8 +442,9 @@ public static GitLabApi create(String url, String username, String password) thr
* <strong>NOTE</strong>: For GitLab servers 10.2 and above this method will always return null.
*
* @return the Session instance
* @deprecated This method will be removed in Release 5.0.0
* @deprecated This method will be removed in Release 4.9.0
*/
@Deprecated
public Session getSession() {
return session;
}
Expand Down
Loading