Authenticating API Requests There are two ways to authenticate Aspose for Cloud REST APIs.
OAuth 2.0
URL Signing
Though we are still supporting URL Signing, we recommend our users to switch to OAuth 2.0 as it is an industry standard and more convenient to use.
OAuth 2.0
The Aspose Cloud REST API supports the OAuth 2.0 protocol using the client_credentials workflow to authorize calls.
OAuth 2.0 is an authorization framework that enables applications to obtain access to user accounts data through our REST API. OAuth provides authorization flows for web and desktop applications, and mobile devices.
The basic concept and how it works is described in the next image:
Applications
To access the REST API using OAuth2.0 protocol, you need to create an application . To register new applications, login into the Dashboard Developer site using your Aspose Account, and go to the My Apps view. Once you create a new application, we will issue a client_id (App SID**)** and **client_secret** (App Key) that you can use to authenticate your REST API calls using the OAuth2.0 protocol. (You can generate new secrets for your Apps, but make sure you update it when issuing new access tokens using those credentials.)
Get Access/Refresh Token
After you have created a new application you can obtain an access token by sending a POST request to /oauth2/token endpoint. Still, you must authenticate your access token request using Client Credentials authorization grant type flow:
POST request to: https://api.aspose.cloud/oauth2/token
Headers:
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Body:
grant_type: client_credentials
client_id: APP_SID
client_secret: APP_KEY
The endpoint acts as an authorization server and it verifies your credentials, if they are correct it returns a JSON ticket containing several items, through each, you can find the access_token, refresh_token, expire time of both tokens etc. The provided access_token is a Bearer Token that you can further use in the Authorization header of your request.
For each Application you create in the dashboard, you can only have one refresh_token in use for it. Any new request for refresh_token will override and revoke the previous one.
cURL Example
Obtain new Access/Refresh Token using the Refresh Token
The access token is only valid for a small period of time, to continue to work with the REST API you can issue new access token by only using the refresh token provided at the above POST request. To obtain a new access token using the refresh token you can make a POST request to the same /oauth2/token endpoint but using different grant type this time:
POST request to: https://api.aspose.cloud/oauth2/token
Headers:
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Body:
grant_type: refresh_token
refresh_token: the-refresh-token-perviously-generated
The returned ticket will be the same as the above, but a new refresh_token is issued now and the old one is revoked, so make sure you replace it in your application with the new one from the ticket you just received.
cURL Example
Call REST API
Now that you have the Bearer Token (access_token) generated using the application credentials, you can make API calls and authorize by adding the access token in the ‘Authorization’ header, as it’s defined in the OAuth 2.0 protocol.
Headers:
Authorization: Bearer ACCESS_TOKEN
You authorize with one application, but you can access files from all storages in your account, or all Application’s default storage by specifying query parameters (storage or AppSid).
cURL Example
Request
Copy
curl - v "https://api.aspose.cloud/v1.1/cells/myWorkbook.xlsx/documentproperties" \
- X GET \
- H "Content-Type: application/json" \
- H "Accept: application/json" \
- H "Authorization: Bearer VvrtTA8PodA3XbdHsmLvXX0T5k0ge-Nk67NjQx7-3W2YGU_JbPYD7E9bqlNdnYcw7zdoEfrKZKKfYRn_4ADWFngoOQPNp1S5udD1ZCqlIQeJ_WUoUOiSmBfnlgaAkwjMQhKKdL5vzTVu1BLsdiTGrKZw54JdfylTABl4OcQWUtmferlhmZjSzyuFT8ppiuOTxYbiYhVq-KAvNrT1xbYP4JED98nH7CQykbHmznavYedR2PjJ79N2k4riFV9e-F4MmanBOdufqSfs6fFMLlqsmCLQCGbVpHOvQLQcdaaAqmAEWEnp9jiorQIc-phoLnBQgtTQT1vumvP3ecdpxnbBdLP2rru7kv_mGm28uoPv18YKeEiM62Pda04cvjozOyb8G9a6j9R8pqglluuGypaZG_-jdFygR28yIXBpQK18SGRmxE-N"
Response
Copy
{
"DocumentProperties" : {
"DocumentPropertyList" : [
{
"Name" : "Title" ,
"Value" : "worksheet functions.xlsx" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/Title" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "Subject" ,
"Value" : "Excel 2007 Bible" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/Subject" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "Author" ,
"Value" : "John Walkenbach" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/Author" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "Keywords" ,
"Value" : "©2007, JWalk & Associates, Inc." ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/Keywords" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "Comments" ,
"Value" : "Example file distributed with 'Excel 2007 Bile'" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/Comments" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "LastSavedBy" ,
"Value" : "John Walkenbach" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/LastSavedBy" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "CreateTime" ,
"Value" : "8/4/2006 4:30:22 PM" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/CreateTime" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "LastSavedTime" ,
"Value" : "11/13/2006 3:55:46 PM" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/LastSavedTime" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "Category" ,
"Value" : "http://www.j-walk.com/ss" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/Category" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "NameOfApplication" ,
"Value" : "Microsoft Excel" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/NameOfApplication" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "Security" ,
"Value" : "0" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/Security" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "ScaleCrop" ,
"Value" : "False" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/ScaleCrop" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "Company" ,
"Value" : "JWalk & Associates" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/Company" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "LinksUpToDate" ,
"Value" : "False" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/LinksUpToDate" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
{
"Name" : "Version" ,
"Value" : "12.0000" ,
"BuiltIn" : "True" ,
"link" : {
"Href" : "/Version" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
}
],
"link" : {
"Href" : "http://api.aspose.com/v1.1/cells/myWorkbook.xlsx/documentproperties" ,
"Rel" : "self" ,
"Title" : null ,
"Type" : null
}
},
"Code" : 200 ,
"Status" : "OK"
}
Tokens Lifetime
The time of the tokens is finite. By default, the access_token lifetime is 1 day , and the refresh_token lifetime is 1 year . Before you create a new access_token, use it and renew it only before it expires. To detect when an access token expires, you must write specific code that will check for any of these:
expires_in value in the ticket generated by OAuth2 endpoint.
will handle the 401 Unauthorized error responses from the API endpoint and issue a request for a new token.
URL Signing
Each Aspose for Cloud API request must include the following query string parameters:
appSID
The public key provided to a client that allows the Aspose API to know which client is making the API request
signature
A HMAC-SHA1 signature of the request that is generated by the client using their private key
How to authenticate (URL Signing)
Aspose for Cloud uses URL signing for authorization of requests. All requests sent to the Aspose for Cloud Web Service must be signed using user’s private key which they retrieve via the Web UI when they sign up. Using the Private key ensures that only authorized application can create valid REST requests to our Web API.
Please take following steps to generate a valid signature (as an example we are using appSID=c821f123-1a8b-4b97-925a-9d69a6b2fcd8 and key=23e9d89a967a5f18142221fa8f7cbcd0):
Build the URL which requires to be signed including all parameters. https://api.aspose.com/1.1/storage/folder/test_folder
Remove trailing ‘/’ character if any.
Append App SID to the given URL as query parameter
https://api.aspose.com/1.1/storage/folder/test_folder?appSID=c821f123-1a8b-4b97-925a-9d69a6b2fcd8
Use HMAC-SHA1 algorithm to compute the hash of the URL. App Key will be used as a secret cryptographic key.
Use Base64 encoding to convert message authentication code (MAC) from a binary format in an ASCII string format. JgLReiOyORY8BYpCJ32CbCc0UHg=
Remove any trailing ‘=’ characters: JgLReiOyORY8BYpCJ32CbCc0UHg
URL-encode generated string: JgLReiOyORY8BYpCJ32CbCc0UHg. This step encodes the string to be used in a query part of a URL.
Finally, append the encoded value to the URL as a signature parameter.https://api.aspose.com/1.1/storage/folder/test_folder?appSID=c821f123-1a8b-4b97-925a-9d69a6b2fcd8&signature=JgLReiOyORY8BYpCJ32CbCc0UHg
We didn’t use registered application ID and application key here, so the resulting URL does not pass authorization but all calculationwerecompleted using the real algorithm, so you can use the results for internal testing.
See below implementation of the URL signing algorithm in different languages.
URL Signing
C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For complete examples and data files, please go to https://github.com/aspose-total/Aspose.Total-for-Cloud
private static string Sign(string url, string appKey) {
UriBuilder uriBuilder = new UriBuilder(url);
// Remove final slash here as it can be added automatically.
uriBuilder.Path = uriBuilder.Path.TrimEnd('/');
// Compute the hash.
byte[] privateKey = Encoding.UTF8.GetBytes(appKey);
HMACSHA1 algorithm = new HMACSHA1(privateKey);
byte[] sequence = ASCIIEncoding.ASCII.GetBytes(uriBuilder.Uri.AbsoluteUri);
byte[] hash = algorithm.ComputeHash(sequence);
string signature = Convert.ToBase64String(hash);
// Remove invalid symbols.
signature = signature.TrimEnd('=');
signature = HttpUtility.UrlEncode(signature);
// Convert codes to upper case as they can be updated automatically.
signature = Regex.Replace(signature, "%[0-9a-f]{2}", e => e.Value.ToUpper());
// Add the signature to query string.
return string.Format("{0}&signature={1}", uriBuilder.Uri.AbsoluteUri, signature);
}
Java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For complete examples and data files, please go to https://github.com/aspose-total/Aspose.Total-for-Cloud
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
/**
* Computes RFC 2104-compliant HMAC signature.
* @param unsignedURL The URL to be signed.
* @return The Base64-encoded RFC 2104-compliant HMAC signature.
* @throws java.security.SignatureException when signature generation fails
*/
public static String sign(String unsignedURL) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
StringBuilder mUnsignedURL = new StringBuilder(unsignedURL);
//Remove any trailing '/' character
if(mUnsignedURL.charAt(mUnsignedURL.length()-1) == '/') {
mUnsignedURL.deleteCharAt(mUnsignedURL.length()-1);
}
if(mUnsignedURL.indexOf("?") == -1) {
mUnsignedURL.append("?");
} else {
mUnsignedURL.append("&");
}
//Add appSID parameter to the query string
mUnsignedURL.append("appSID=" + AsposeApp.APP_SID);
//Calculate a hash of the current URL
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
SecretKeySpec key = new SecretKeySpec((AsposeApp.APP_KEY).getBytes("UTF-8"), mac.getAlgorithm());
mac.init(key);
byte[] bytes = mac.doFinal(mUnsignedURL.toString().getBytes("UTF-8"));
String urlHash = new String(Base64.encodeBase64(bytes));
//Remove any trailing '=' characters
if(urlHash.endsWith("=")) {
urlHash = urlHash.substring(0, urlHash.length()-1);
}
//URL-encode generated string
urlHash = URLEncoder.encode(urlHash, "utf-8");
//Add the encoded value to the current URL as a signature parameter
mUnsignedURL.append("&signature=" + urlHash);
return mUnsignedURL.toString();
}
PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For complete examples and data files, please go to https://github.com/aspose-total/Aspose.Total-for-Cloud
public function sign($url, $queryParams) {
// parse the url
$UrlToSign = rtrim($url, "/");
$url = parse_url($UrlToSign);
$urlQuery = http_build_query($queryParams);
$urlPartToSign = $url['scheme'] . '://' . $url['host'] . $url['path'] . "?" . $url['query'];
// Create a signature using the private key and the URL-encoded
// string using HMAC SHA1. This signature will be binary.
$signature = hash_hmac('sha1', $urlPartToSign, $this->apiKey, true);
$encodedSignature = self::encodeBase64UrlSafe($signature);
$encodedSignature = str_replace(array('=', '-', '_'), array('', '%2b', '%2f'), $encodedSignature);
preg_match_all("/%[0-9a-f]{2}/", $encodedSignature, $m);
foreach ($m[0] as $code) {
$encodedSignature = str_replace($code, strtoupper($code), $encodedSignature);
}
$url = $urlPartToSign . '&signature=' . $encodedSignature;
return $url;
}
Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# For complete examples and data files, please go to https://github.com/aspose-total/Aspose.Total-for-Cloud
# Signs a URI with your appSID and Key.
# * :url describes the URL to sign
def sign(url, query_params)
fail "Please set Aspose App key and SID first. You can get App key and App SID from https://cloud.aspose.com" if AsposeApp.app_key.nil? || AsposeApp.app_sid.nil?
url = url[0..-2] if url[-1].eql? '/'
unless query_params.empty?
url = "#{url}?"
query_params.each { |key, value|
url = "#{url}#{key}=#{value}&"
}
url = url[0..-2]
end
url = URI.escape(url)
parsed_url = URI.parse(url)
url_to_sign = "#{parsed_url.scheme}://#{parsed_url.host}#{parsed_url.path}"
url_to_sign += "?#{parsed_url.query}" if parsed_url.query
if parsed_url.query
url_to_sign += "&appSID=#{AsposeApp.app_sid}"
else
url_to_sign += "?appSID=#{AsposeApp.app_sid}"
end
# create a signature using the private key and the URL
raw_signature = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), AsposeApp.app_key, url_to_sign)
#Convert raw to encoded string
signature = Base64.strict_encode64(raw_signature).tr('+/', '-_')
#remove invalid character
signature = signature.gsub(/[=_-]/, '=' => '', '_' => '%2f', '-' => '%2b')
#Define expression
pat = Regexp.new('%[0-9a-f]{2}')
#Replace the portion matched to the above pattern to upper case
6.times do
signature = signature.sub(pat, pat.match(signature).to_s.upcase)
end
# prepend the server and append the signature.
url_to_sign + "&signature=#{signature}"
end
Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For complete examples and data files, please go to https://github.com/aspose-total/Aspose.Total-for-Cloud
def sign(self, url_to_sign, appSid, apiKey):
url_to_sign = url_to_sign.replace(" ", "%20");
url = urlparse(url_to_sign);
if url.query == "":
url_part_to_sign = url.scheme + "://" + url.netloc + url.path
else:
url_part_to_sign = url.scheme + "://" + url.netloc + url.path + "?" + url.query
logging.debug("url_part_to_sign" + url_part_to_sign + "apiKey" + apiKey)
signature = hmac.new(apiKey, url_part_to_sign, hashlib.sha1).digest().encode('base64')[:-1]
signature = re.sub('[=_-]', '', signature)
signature = quote(signature, safe='')
if url.query == "":
return url.scheme + "://" + url.netloc + url.path + "?signature=" + signature
else:
return url.scheme + "://" + url.netloc + url.path + "?" + url.query + "&signature=" + signature
Node.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# For complete examples and data files, please go to https://github.com/aspose-total/Aspose.Total-for-Cloud
ApiClient.prototype.Sign = function(unsignedURL, privateKey){
if(this.config.debug){console.log("privateKey :: " + privateKey); console.log("unsignedURL :: " + unsignedURL);}
var signature = crypto.createHmac('sha1', privateKey)
.update(unsignedURL)
.digest('base64')
.replace('=', '');
return signature;
};
Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For complete examples and data files, please go to https://github.com/aspose-total/Aspose.Total-for-Cloud
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
/**
* Computes RFC 2104-compliant HMAC signature.
* @param unsignedURL The URL to be signed.
* @return The Base64-encoded RFC 2104-compliant HMAC signature.
* @throws java.security.SignatureException when signature generation fails
*/
public static String sign(String unsignedURL) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
StringBuilder mUnsignedURL = new StringBuilder(unsignedURL);
//Remove any trailing '/' character
if(mUnsignedURL.charAt(mUnsignedURL.length()-1) == '/') {
mUnsignedURL.deleteCharAt(mUnsignedURL.length()-1);
}
if(mUnsignedURL.indexOf("?") == -1) {
mUnsignedURL.append("?");
} else {
mUnsignedURL.append("&");
}
//Add appSID parameter to the query string
mUnsignedURL.append("appSID=" + AsposeApp.APP_SID);
//Calculate a hash of the current URL
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
SecretKeySpec key = new SecretKeySpec((AsposeApp.APP_KEY).getBytes("UTF-8"), mac.getAlgorithm());
mac.init(key);
byte[] bytes = mac.doFinal(mUnsignedURL.toString().getBytes("UTF-8"));
String urlHash = new String(Base64.encodeBase64(bytes));
//Remove any trailing '=' characters
if(urlHash.endsWith("=")) {
urlHash = urlHash.substring(0, urlHash.length()-1);
}
//URL-encode generated string
urlHash = URLEncoder.encode(urlHash, "utf-8");
//Add the encoded value to the current URL as a signature parameter
mUnsignedURL.append("&signature=" + urlHash);
return mUnsignedURL.toString();
}
Objective C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For complete examples and data files, please go to https://github.com/aspose-total/Aspose.Total-for-Cloud
+ (NSString *) sign:(NSString *) unsignedURL {
NSParameterAssert([ASPOSEApp appSID]);
NSParameterAssert([ASPOSEApp appKey]);
NSParameterAssert(unsignedURL);
NSMutableString *mUnsignedURL = [NSMutableString stringWithString:unsignedURL];
//Remove any trailing '/' character
if([mUnsignedURL hasSuffix:@"/"]) {
[mUnsignedURL deleteCharactersInRange:NSMakeRange([mUnsignedURL length] -1, 1)];
}
if ([mUnsignedURL rangeOfString:@"?"].location == NSNotFound) {
[mUnsignedURL appendString:@"?"];
} else {
[mUnsignedURL appendString:@"&"];
}
//Add appSID parameter to the query string
[mUnsignedURL appendFormat:@"appSID=%@", [ASPOSEApp appSID]];
//Calculate a hash of the current url
const char *cKey = [[ASPOSEApp appKey] cStringUsingEncoding:NSUTF8StringEncoding];
const char *cData = [mUnsignedURL cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMACData = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSString *hash = [HMACData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
//Remove any trailing '=' characters
if([hash hasSuffix:@"="]) {
hash = [hash substringToIndex:[hash length]-1];
}
//URL-encode generated string
hash = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)hash, NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8));
//Add the encoded value to the current url as a signature parameter
[mUnsignedURL appendFormat:@"&signature=%@", hash];
return mUnsignedURL;
}
Perl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For complete examples and data files, please go to https://github.com/aspose-total/Aspose.Total-for-Cloud
sub sign {
my ($self, $url_to_sign, $appSid, $appKey) = @_;
#return if (!defined($url_to_sign) || scalar(@$auth_settings) == 0);
my $hmac = Digest::HMAC_SHA1->new($appKey);
$hmac->add($url_to_sign);
my $signature = $hmac->digest;
$signature = encode_base64($signature, '');
$signature =~ s/=//;
$log->debugf ("signature :: ".$signature);
return $signature;
}