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