Skip to content

Commit

Permalink
Add helper classes for OAuth authorization
Browse files Browse the repository at this point in the history
This commits adds classes which handle the creation of the authorization
URL, the token exchange and the automatic token refresh. The class
DracoonAuth is used to configure which authorization steps are made by
user and by the SDK. (This enables the user to write web, desktop and
console applications.)

See: #SDKJAVA-38
  • Loading branch information
mkellnhofer committed Feb 21, 2018
1 parent 0faa9b7 commit 5b82586
Show file tree
Hide file tree
Showing 19 changed files with 930 additions and 136 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.dracoon.sdk.example;

import com.dracoon.sdk.DracoonAuth;
import com.dracoon.sdk.DracoonClient;
import com.dracoon.sdk.Log;
import com.dracoon.sdk.error.DracoonException;
Expand Down Expand Up @@ -28,18 +29,19 @@
import java.util.Date;
import java.util.List;

public class Main {
public class ApiExamples {

private static final String SERVER_URL = "https://dracoon.team";
private static final String ACCESS_TOKEN = "access-token";
private static final String ENCRYPTION_PASSWORD = "encryption-password";

public static void main(String[] args) throws Exception {
String serverUrl = "https://dracoon.team";
String accessToken = "";
String encryptionPassword = "secret";
DracoonAuth auth = new DracoonAuth(ACCESS_TOKEN);

DracoonClient client = new DracoonClient.Builder(serverUrl)
DracoonClient client = new DracoonClient.Builder(SERVER_URL)
.log(new Logger(Log.DEBUG))
.accessToken(accessToken)
.encryptionPassword(encryptionPassword)
.httpRetryEnabled(true)
.auth(auth)
.encryptionPassword(ENCRYPTION_PASSWORD)
.build();

//getServerData(client);
Expand Down
173 changes: 173 additions & 0 deletions src/main/java/com/dracoon/sdk/DracoonAuth.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package com.dracoon.sdk;

/**
* The Dracoon SDK uses OAuth 2.0 for client authorization. See <a href="https://tools.ietf.org/
* html/rfc6749">RFC 6749</a> for a detailed description of OAuth 2.0. Because OAuth can be
* difficult to implement for beginners, the Dracoon SDK can handle the OAuth authorization steps to
* obtain and refresh tokens.<br>
* <br>
* This class is used to configure which steps of the OAuth authorization are made by the Dracoon
* SDK.<br>
* <br>
* Following three modes are supported:<br>
* <br>
* - Authorization Code Mode: ({@link DracoonAuth#DracoonAuth(String clientId, String clientSecret,
* String authorizationCode)})<br>
* This is the most common mode. Your application must request authorization and obtain an
* authorization code and the retrieval of the access and refresh tokens with the authorization
* code as well as the automatic token refresh is handled by the Dracoon SDK.<br>
* <br>
* The authorization is done within the user's browser or a web view. After the user has logged in
* and authorized your application you receive the authorization code via a callback to a
* pre-defined redirect URI. Depending on the type of your application you must open a local TCP
* port, register the redirect URI at your OS or provide an HTTP endpoint which receives the
* callback.<br>
* <br>
* (You can use {@link OAuthHelper} to create the Authorization URL which must be opened in the
* user's browser or web view and to extract the state and code from the redirect URI.)<br>
* <br>
* - Access Token Mode: ({@link DracoonAuth#DracoonAuth(String accessToken)})<br>
* This is a simple mode. You can use it at the development or for terminal applications and
* scripts where a specific user account is used.<br>
* <br>
* - Access and Refresh Token Mode: ({@link DracoonAuth#DracoonAuth(String clientId,
* String clientSecret, String accessToken, String refreshToken)})<br>
* This mode can be used to obtain access and refresh token yourself.
*/
@SuppressWarnings("unused")
public class DracoonAuth {

/**
* Enumeration of authorization modes.
*/
public enum Mode {
AUTHORIZATION_CODE,
ACCESS_TOKEN,
ACCESS_REFRESH_TOKEN;
}

private Mode mMode;

private String mClientId;
private String mClientSecret;
private String mAuthorizationCode;
private String mAccessToken;
private String mRefreshToken;

/**
* Constructs a new configuration for the Authorization Code Mode.
*
* @param clientId The OAuth client ID.
* @param clientSecret The OAuth client secret.
* @param authorizationCode The OAuth authorization code.
*/
public DracoonAuth(String clientId, String clientSecret, String authorizationCode) {
mMode = Mode.AUTHORIZATION_CODE;
validateParameter("Client ID", clientId, false);
mClientId = clientId;
validateParameter("Client secret", clientSecret, false);
mClientSecret = clientSecret;
validateParameter("Authorization code", clientSecret, false);
mAuthorizationCode = authorizationCode;
}

/**
* Constructs a new configuration for the Access Token Mode.
*
* @param accessToken The OAuth access token.
*/
public DracoonAuth(String accessToken) {
mMode = Mode.ACCESS_TOKEN;
validateParameter("Access token", accessToken, false);
mAccessToken = accessToken;
}

/**
* Constructs a new configuration for the Access and Refresh Token Mode.
*
* @param clientId The OAuth client ID.
* @param clientSecret The OAuth client secret.
* @param accessToken The OAuth access token.
* @param refreshToken The OAuth refresh token.
*/
public DracoonAuth(String clientId, String clientSecret, String accessToken,
String refreshToken) {
mMode = Mode.ACCESS_REFRESH_TOKEN;
validateParameter("Client ID", clientId, false);
mClientId = clientId;
validateParameter("Client secret", clientSecret, false);
mClientSecret = clientSecret;
validateParameter("Access token", accessToken, false);
mAccessToken = accessToken;
validateParameter("Refresh token", refreshToken, true);
mRefreshToken = refreshToken;
}

/**
* Returns the used authorization mode.<br>
* <br>
* See: {@link DracoonAuth.Mode}
*
* @return the used authorization mode
*/
public Mode getMode() {
return mMode;
}

/**
* Returns the OAuth client ID.
*
* @return the OAuth client ID
*/
public String getClientId() {
return mClientId;
}

/**
* Returns the OAuth client secret.
*
* @return the OAuth client secret
*/
public String getClientSecret() {
return mClientSecret;
}

/**
* Returns the OAuth authorization code.
*
* @return the OAuth authorization code
*/
public String getAuthorizationCode() {
return mAuthorizationCode;
}

/**
* Returns the OAuth access token.
*
* @return the OAuth access token
*/
public String getAccessToken() {
return mAccessToken;
}

/**
* Returns the OAuth access token.
*
* @return the OAuth access token.
*/
public String getRefreshToken() {
return mRefreshToken;
}

// --- Helper methods ---

private static void validateParameter(String name, String value, boolean nullable) {
if (value == null && !nullable) {
throw new IllegalArgumentException(name + " cannot be null.");
}
if (value != null && value.isEmpty()) {
throw new IllegalArgumentException(name + " cannot be empty.");
}
}

}
76 changes: 19 additions & 57 deletions src/main/java/com/dracoon/sdk/DracoonClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -500,14 +500,9 @@ DownloadShare createDownloadShare(CreateDownloadShareRequest request)

protected String mServerUrl;

protected String mAccessToken;
protected DracoonAuth mAuth;
protected String mEncryptionPassword;

protected boolean mIsHttpRetryEnabled;
protected int mHttpConnectTimeout;
protected int mHttpReadTimeout;
protected int mHttpWriteTimeout;

/**
* Constructs a new Dracoon client.
*
Expand All @@ -527,21 +522,12 @@ public String getServerUrl() {
}

/**
* Returns the client's access token.
* Returns the authorization data.
*
* @return access token
* @return authorization data
*/
public String getAccessToken() {
return mAccessToken;
}

/**
* Sets the client's access token.
*
* @param accessToken The new access token.
*/
public void setAccessToken(String accessToken) {
mAccessToken = accessToken;
public DracoonAuth getAuth() {
return mAuth;
}

/**
Expand Down Expand Up @@ -609,13 +595,15 @@ public void setEncryptionPassword(String encryptionPassword) {
* <br>
* Following properties can be set:<br>
* - Server URL (mandatory): {@link Builder#Builder(String)}<br>
* - Access token: {@link Builder#accessToken(String)}<br>
* - Logger: {@link Builder#log(Log)}<br>
* - Authorization data: {@link Builder#auth(DracoonAuth)}<br>
* - Encryption password: {@link Builder#encryptionPassword(String)}<br>
* - Logger: {@link Builder#log(Log)}
* - HTTP configuration: {@link Builder#httpConfig(DracoonHttpConfig)}
*/
public static class Builder {

private DracoonClientImpl mClient;
private DracoonHttpConfig mHttpConfig;

/**
* Constructs a new builder for a specific Dracoon server.
Expand All @@ -624,11 +612,7 @@ public static class Builder {
*/
public Builder(String serverUrl) {
mClient = new DracoonClientImpl(serverUrl);

mClient.mIsHttpRetryEnabled = false;
mClient.mHttpConnectTimeout = 15;
mClient.mHttpReadTimeout = 15;
mClient.mHttpWriteTimeout = 15;
mHttpConfig = new DracoonHttpConfig();
}

/**
Expand All @@ -644,14 +628,14 @@ public Builder log(Log log) {
}

/**
* Sets the access token which is used at requests.
* Sets the authorization data for accessing protected resources.
*
* @param accessToken The access token.
* @param auth The authorization data.
*
* @return a reference to this object
*/
public Builder accessToken(String accessToken) {
mClient.mAccessToken = accessToken;
public Builder auth(DracoonAuth auth) {
mClient.mAuth = auth;
return this;
}

Expand All @@ -668,37 +652,14 @@ public Builder encryptionPassword(String encryptionPassword) {
}

/**
* Enables/disables HTTP retry. If enabled, requests which failed due to a network error
* will be retried 2 times.<br>
* <br>
* The HTTP retry is disabled by default.
*
* @param isHttpRetryEnabled <code>true</code> to enable HTTP retry; otherwise
* <code>false</code>
*
* @return a reference to this object
*/
public Builder httpRetryEnabled(boolean isHttpRetryEnabled) {
mClient.mIsHttpRetryEnabled = isHttpRetryEnabled;
return this;
}

/**
* Sets HTTP timeouts. A value of 0 means no timeout.<br>
* <br>
* The HTTP timeouts are set to 15 seconds by default.
* Sets the HTTP configuration.
*
* @param httpConnectTimeout The connect timeout for new connections in seconds.
* @param httpReadTimeout The read timeout for new connections in seconds.
* @param httpWriteTimeout The write timeout for new connections in seconds.
* @param httpConfig The HTTP configuration.
*
* @return a reference to this object
*/
public Builder httpTimeout(int httpConnectTimeout, int httpReadTimeout,
int httpWriteTimeout) {
mClient.mHttpConnectTimeout = httpConnectTimeout;
mClient.mHttpReadTimeout = httpReadTimeout;
mClient.mHttpWriteTimeout = httpWriteTimeout;
public Builder httpConfig(DracoonHttpConfig httpConfig) {
mHttpConfig = httpConfig;
return this;
}

Expand All @@ -708,6 +669,7 @@ public Builder httpTimeout(int httpConnectTimeout, int httpReadTimeout,
* @return a new {@link DracoonClient} instance
*/
public DracoonClient build() {
mClient.setHttpConfig(mHttpConfig);
mClient.init();
return mClient;
}
Expand Down
Loading

0 comments on commit 5b82586

Please sign in to comment.