001package com.box.sdk; 002 003import static com.box.sdk.http.ContentType.APPLICATION_FORM_URLENCODED; 004 005import com.eclipsesource.json.Json; 006import com.eclipsesource.json.JsonObject; 007import java.net.URL; 008 009/** 010 * Creates and manages Client Credentials Grant API connection. 011 */ 012public final class BoxCCGAPIConnection extends BoxAPIConnection { 013 014 static final String ENTERPRISE_SUBJECT_TYPE = "enterprise"; 015 static final String USER_SUBJECT_TYPE = "user"; 016 private String subjectType; 017 private String subjectId; 018 019 // Hiding constructor 020 private BoxCCGAPIConnection(String accessToken) { 021 super(accessToken); 022 } 023 024 // Hiding constructor 025 private BoxCCGAPIConnection(String clientID, String clientSecret, String accessToken, String refreshToken) { 026 super(clientID, clientSecret, accessToken, refreshToken); 027 } 028 029 // Hiding constructor 030 private BoxCCGAPIConnection(String clientID, String clientSecret, String authCode) { 031 super(clientID, clientSecret, authCode); 032 } 033 034 // Hiding constructor 035 private BoxCCGAPIConnection(String clientID, String clientSecret) { 036 super(clientID, clientSecret); 037 } 038 039 // Hiding constructor 040 private BoxCCGAPIConnection(BoxConfig boxConfig) { 041 super(boxConfig); 042 } 043 044 /** 045 * Creates connection that authenticates as a Service Account 046 * 047 * @param clientId the client ID to use when getting the access token. 048 * @param clientSecret the client secret to use when getting the access token. 049 * @param enterpriseId the enterprise ID to use when getting the access token. 050 * @return Client Credentials Grant API connection. 051 */ 052 public static BoxCCGAPIConnection applicationServiceAccountConnection( 053 String clientId, String clientSecret, String enterpriseId 054 ) { 055 BoxCCGAPIConnection api = new BoxCCGAPIConnection(clientId, clientSecret); 056 api.subjectType = ENTERPRISE_SUBJECT_TYPE; 057 api.subjectId = enterpriseId; 058 return api; 059 } 060 061 /** 062 * Creates connection that authenticates as a User 063 * 064 * @param clientId the client ID to use when getting the access token. 065 * @param clientSecret the client secret to use when getting the access token. 066 * @param userId the user ID to use when getting the access token. 067 * @return Client Credentials Grant API connection. 068 */ 069 public static BoxCCGAPIConnection userConnection(String clientId, String clientSecret, String userId) { 070 BoxCCGAPIConnection api = new BoxCCGAPIConnection(clientId, clientSecret); 071 api.subjectType = USER_SUBJECT_TYPE; 072 api.subjectId = userId; 073 return api; 074 } 075 076 /** 077 * Restores a BoxAPIConnection from a saved state. 078 * 079 * @param clientID the client ID to use with the connection. 080 * @param clientSecret the client secret to use with the connection. 081 * @param state the saved state that was created with {@link #save}. 082 * @return a restored API connection. 083 * @see #save 084 */ 085 public static BoxCCGAPIConnection restore(String clientID, String clientSecret, String state) { 086 BoxCCGAPIConnection api = new BoxCCGAPIConnection(clientID, clientSecret); 087 api.restore(state); 088 return api; 089 } 090 091 @Override 092 protected BoxAPIRequest createTokenRequest(URL url) { 093 String urlParameters = String.format( 094 "grant_type=client_credentials&client_id=%s&client_secret=%s&box_subject_type=%s&box_subject_id=%s", 095 this.getClientID(), this.getClientSecret(), this.subjectType, this.subjectId); 096 BoxAPIRequest request = new BoxAPIRequest(this, url, "POST"); 097 request.shouldAuthenticate(false); 098 request.setBody(urlParameters); 099 request.addHeader("Content-Type", APPLICATION_FORM_URLENCODED); 100 return request; 101 } 102 103 @Override 104 protected void extractTokens(JsonObject jsonObject) { 105 this.setAccessToken(jsonObject.get("access_token").asString()); 106 this.setLastRefresh(System.currentTimeMillis()); 107 this.setExpires(jsonObject.get("expires_in").asLong() * 1000); 108 } 109 110 @Override 111 public boolean canRefresh() { 112 return true; 113 } 114 115 public boolean isUserConnection() { 116 return subjectType.equals(USER_SUBJECT_TYPE); 117 } 118 119 @Override 120 public String save() { 121 JsonObject state = new JsonObject() 122 .add("accessToken", this.getAccessToken()) 123 .add("lastRefresh", this.getLastRefresh()) 124 .add("expires", this.getExpires()) 125 .add("userAgent", this.getUserAgent()) 126 .add("tokenURL", this.getTokenURL()) 127 .add("baseURL", this.getBaseURL()) 128 .add("baseUploadURL", this.getBaseUploadURL()) 129 .add("autoRefresh", this.getAutoRefresh()) 130 .add("maxRetryAttempts", this.getMaxRetryAttempts()) 131 .add("subjectType", this.subjectType) 132 .add("subjectId", this.subjectId); 133 return state.toString(); 134 } 135 136 @Override 137 public void restore(String state) { 138 JsonObject json = Json.parse(state).asObject(); 139 String accessToken = json.get("accessToken").asString(); 140 long lastRefresh = json.get("lastRefresh").asLong(); 141 long expires = json.get("expires").asLong(); 142 String userAgent = json.get("userAgent").asString(); 143 String tokenURL = json.get("tokenURL").asString(); 144 String baseURL = json.get("baseURL").asString(); 145 String baseUploadURL = json.get("baseUploadURL").asString(); 146 boolean autoRefresh = json.get("autoRefresh").asBoolean(); 147 String subjectType = json.get("subjectType").asString(); 148 String subjectId = json.get("subjectId").asString(); 149 150 int maxRetryAttempts = -1; 151 if (json.names().contains("maxRetryAttempts")) { 152 maxRetryAttempts = json.get("maxRetryAttempts").asInt(); 153 } 154 155 this.setAccessToken(accessToken); 156 setLastRefresh(lastRefresh); 157 setExpires(expires); 158 setUserAgent(userAgent); 159 setTokenURL(tokenURL); 160 setBaseURL(baseURL); 161 setBaseUploadURL(baseUploadURL); 162 setAutoRefresh(autoRefresh); 163 setMaxRetryAttempts(maxRetryAttempts); 164 this.subjectType = subjectType; 165 this.subjectId = subjectId; 166 167 } 168}