001package com.box.sdk; 002 003import com.eclipsesource.json.Json; 004import com.eclipsesource.json.JsonObject; 005import java.io.UnsupportedEncodingException; 006import java.net.MalformedURLException; 007import java.net.URL; 008import java.net.URLEncoder; 009 010/** 011 * Represents an authenticated transactional connection to the Box API. 012 * 013 * <p>This class handles everything for transactional API that isn't already handled by 014 * BoxAPIConnection. 015 */ 016public class BoxTransactionalAPIConnection extends BoxAPIConnection { 017 018 private static final String SUBJECT_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:access_token"; 019 private static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:token-exchange"; 020 021 /** 022 * Constructs a new BoxTransactionalAPIConnection that authenticates with an access token. 023 * 024 * @param accessToken a transactional auth access token. 025 */ 026 public BoxTransactionalAPIConnection(String accessToken) { 027 super(accessToken); 028 super.setAutoRefresh(false); 029 } 030 031 /** 032 * Request a scoped transactional token. 033 * 034 * @param accessToken application access token. 035 * @param scope scope of transactional token. 036 * @return a BoxAPIConnection which can be used to perform transactional requests. 037 */ 038 public static BoxAPIConnection getTransactionConnection(String accessToken, String scope) { 039 return BoxTransactionalAPIConnection.getTransactionConnection(accessToken, scope, null); 040 } 041 042 /** 043 * Request a scoped transactional token for a particular resource. 044 * 045 * @param accessToken application access token. 046 * @param scope scope of transactional token. 047 * @param resource resource transactional token has access to. 048 * @return a BoxAPIConnection which can be used to perform transactional requests. 049 */ 050 public static BoxAPIConnection getTransactionConnection( 051 String accessToken, String scope, String resource) { 052 BoxAPIConnection apiConnection = new BoxAPIConnection(accessToken); 053 054 URL url; 055 try { 056 url = new URL(apiConnection.getTokenURL()); 057 } catch (MalformedURLException e) { 058 assert false : "An invalid token URL indicates a bug in the SDK."; 059 throw new RuntimeException("An invalid token URL indicates a bug in the SDK.", e); 060 } 061 062 String urlParameters; 063 try { 064 urlParameters = 065 String.format( 066 "grant_type=%s&subject_token=%s&subject_token_type=%s&scope=%s", 067 GRANT_TYPE, 068 URLEncoder.encode(accessToken, "UTF-8"), 069 SUBJECT_TOKEN_TYPE, 070 URLEncoder.encode(scope, "UTF-8")); 071 072 if (resource != null) { 073 urlParameters += "&resource=" + URLEncoder.encode(resource, "UTF-8"); 074 } 075 } catch (UnsupportedEncodingException e) { 076 throw new BoxAPIException( 077 "An error occurred while attempting to encode url parameters for a transactional token request"); 078 } 079 080 // authentication uses form url encoded params but response is JSON 081 BoxAPIRequest request = new BoxAPIRequest(apiConnection, url, "POST"); 082 request.shouldAuthenticate(false); 083 request.setBody(urlParameters); 084 085 try (BoxJSONResponse response = (BoxJSONResponse) request.send()) { 086 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 087 088 final String fileToken = responseJSON.get("access_token").asString(); 089 BoxTransactionalAPIConnection transactionConnection = 090 new BoxTransactionalAPIConnection(fileToken); 091 transactionConnection.setExpires(responseJSON.get("expires_in").asLong() * 1000); 092 093 return transactionConnection; 094 } 095 } 096 097 /** 098 * Disabling the non-Box Developer Edition authenticate method. 099 * 100 * @param authCode an auth code obtained from the first half of the OAuth process. 101 * @throws UnsupportedOperationException Box Transactional API does not support authentication 102 * with an auth code 103 */ 104 @Override 105 public void authenticate(String authCode) { 106 throw new UnsupportedOperationException( 107 "BoxTransactionalAPIConnection does not support the authenticate method."); 108 } 109 110 /** 111 * BoxTransactionalAPIConnection can never refresh. 112 * 113 * @return false always. 114 */ 115 @Override 116 public boolean canRefresh() { 117 return false; 118 } 119 120 /** 121 * Auto refresh is not available for transactional auth. 122 * 123 * @param autoRefresh true to enable auto token refresh; otherwise false. 124 * @throws UnsupportedOperationException Box Transactional API tokens can not be refreshed 125 */ 126 @Override 127 public void setAutoRefresh(boolean autoRefresh) { 128 throw new UnsupportedOperationException( 129 "BoxTransactionalAPIConnection does not support token refreshing, " 130 + "access tokens can be generated in the developer console."); 131 } 132 133 /** 134 * Transactional auth does not support token refreshes. 135 * 136 * @throws UnsupportedOperationException Box Transactional API tokens can not be refreshed 137 */ 138 @Override 139 public void refresh() { 140 throw new UnsupportedOperationException( 141 "BoxTransactionalAPIConnection does not support token refreshing, " 142 + "access tokens can be generated in the developer console."); 143 } 144}