Introduction
In this tutorial, we will build a simple application to
demonstrate the autonomous authentication process. We will
go through the following steps: requesting a nonce, building
a self-signed token, requesting a client token, and finally,
requesting a delegation token. When using the SmartVault
libraries, you will be abstracted from some of these steps.
Here’s What You’ll Need
To perform autonomous authentication, you’ll first need to generate a RSA key pair. Visit Generate a Key Pair to view the steps.
If you have not yet created a developer account or client id, click here to do so:
Create a Client ID. (For OAuth Support, select Autonomous since this is how we will be authenticating, and copy and paste the contents of the public key you just created into the Public Key field.)
Installing the Library
We could form individual REST API calls and communicate with SmartVault that way, but why reinvent the wheel, right? Our Java API wrapper library allows you to perform actions with SmartVault without writing individual REST API requests.
This wrapper library can be downloaded down below.
There is one important dependency you will need in order to use our library: protobuf-java 2.4.1.
For this tutorial, we will also make use of two other libraries: commons-io and bcprov-jdk16.
All of these extra libraries can be obtained using Maven. How you set them up will depend on the environment you are using. If you are using an IDE, check its documentation if you are unsure about how to do this.
Setting Up
Let’s create a new class called SmartVault to handle communication with the SmartVault API. We will need to include the SmartVault library.
import com.smartvault.proto.*; import com.smartvault.rest.*; public class SmartVault { . . . }
Opening the Connection
Let’s add two instance variables to our class to handle communication with SmartVault:
private ClientProtocol _protocol; private DelegatedProtocol _delegation;
The protocol object created here will handle tasks on behalf of the client. In our case, this will be mainly for authentication. The delegation object will allow us to perform actions on behalf of the user. We can use this to do a variety of tasks including browsing and managing files, as well as performing uploads and downloads.
Let’s create a constructor to set up an initial connection with SmartVault. This will initialize the _protocol object and authenticate using the private key.
public SmartVault() throws Exception { String clientId = "JavaTutorial"; // Change this to your client ID String privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEowIBAAKCAQEAuyF+b+lfhw6kXpf6/F6P3YnU7WirZJnwIFwlC4weje+VI3JS\n" + "qXUFOmMMVAHTNcofsOnYp5E4UYufkXtR10HqnVGslpsSYS9XxKEK5dkWNXYSaqrf\n" + "Q+iuX0kwnysnyomGxTnOqM6Vva/d07IjWCWR1byLrmF1Lyp/JOc+hXPbLJqbwhlf\n" + "lWxMhbKoYeYjL3ZdrOlclRX4nttxAwjQZKVxkeEAA1PymldHumBY3OTeASWQMeAg\n" + "EDrOiXDEA6kMkDoKz58aK11Xi2FwmFKQEU5rOD0xIYkYcLlFW1hPKnSiDOC1sJ0D\n" + "pqQZ71yQ/Qte6CV87oyi5O6+T0D4LarHEYEimQIDAQABAoIBAAjb1I76ts1/eXOK\n" + "8VRKK7haooxcpKR+DxqREiXiS73/ZgmIC3a/NfCmKLq/XV7SAz8OSvXfz5E4sWSj\n" + "OGQe2Dr7V1bH345fPeHul8P6y2zbepK3JRujY8HaBqW6VsdlTE6A5pIiOX+B2FgB\n" + "ul+dY7KBGwG11mTVt7ApDFIoAmuxjynW08vl6pIxMhwZ+I1lfABkw35HFWIRpcVz\n" + "zBklTs2tn2jXa6KgEoq1I5YfO2J8g7MvKvAuSsNtMGBs+T/yPtJNUL/eu9IkXqG2\n" + "nrMNg+aJFzoZRzhl+2KTUOoGxdp9d5j9kSbYomFjeUyS39QQSCLFHY4kyrfgNly0\n" + "AXwZZMkCgYEAwsViuBPn8LlWozrG14qFTfyeZwBqVBYeOd/pcmqJuaEVvj5hmX5n\n" + "JP94DY+0P1xXZdT67M2sV0ctZlnT+ovWXXolvHzLNAcPnEGxS8hwhtv/lLr9uu83\n" + "CaGP5LTV0VUioKZKLtDMu7rqlV++XiR+W/qzDo2hw4/OqI4IUI64gf0CgYEA9fU/\n" + "Kac/6mo6aXcnfjH0iQkjfFKnIebYC69uniLrVARlrMB2s97xZp25RzIOydJnFwnF\n" + "9WMMTfFHjJAuyjyKZTZv/xBvGILxQ+6PFF72fC6ccHI4P0qJot0VEoMtssjhBQk8\n" + "v0PZqODUSG5gkSC4O+Ode3uemOndT+taKkJZp80CgYEAoPEN0+HPBKGBr7u/1xeF\n" + "c53NHnu/YOAt9dDKTFswlw0+tEdDytwiSvY2s64NWVXqeiD1f3usbypHn42Wli+6\n" + "4N8wE4JjPwieo5W89UwZf7aGiNXDGBbXOcQg7PFoxWM+C9Wc8vZiVrXrZacJ3Sz2\n" + "pPaRwvLRupE4SRukTzy/xdkCgYBfWBOFFRV8zHMaQRtpGvpdSNKdtfid9ruXRAlQ\n" + "ed7Zsd6sKeuZ7HmNuuSAydHbwJk/4AUCC8RQTpDa12Wb9f38IC8oI/m8+b2HBOoo\n" + "DmvkVblFCbHuLvnNzYAGrh0/6gj4h80po6azhXwlG8yJVbK1XJXGsXQYeMfW3DgW\n" + "m6PfnQKBgG2x8MQehdLQ0A9kGCmTlVu2oU0PTg21cHjCnVghXi6G79bsradlTFpD\n" + "kCUyj/DttTWSY8MoXL/4tk1uIGygRXFyNG+FCuIKq2UQwT4hLmVyYIPxEPLA3vJt\n" + "Q7SZvekEgOEP8Epz2Y/EtWEC7P6a3nzap5p06KMlLH2sn+IV9DPi\n" + "-----END RSA PRIVATE KEY-----\n"; Security.addProvider(new BouncyCastleProvider()); StringReader reader = new StringReader(privateKey); KeyPair keyPair = (KeyPair) new PEMReader(reader).readObject(); ServerCfg cfg = new ServerCfg("https://rest.smartvault.com", clientId, keyPair.getPrivate()); Authentication auth = new Authentication(cfg); _protocol = auth.createClientProtocol(); }
NOTE: You will need to change the Client ID to the one you registered earlier using the SmartVault Portal.
You should also never include the private key in your code like this in a production application, as it is a huge security risk. We are only doing this to simplify things for this basic example.
For production applications, you should take every step possible to ensure the security of your private key. For example, Java has its own key store designed for storing cryptographic keys. Windows also has key containers that you can use if you are running Windows. You should avoid storing the private key in plain-text, since this would allow anybody to have access to it.
Delegating
Since we’re using autonomous authentication, all we need to be able to do tasks as a user is their email address. However, the user must first give us permission to do this by authorizing our application.
Authorizing
The SmartVault API has a call to get a URL from the server for the user to visit in order to authorize our application. We will need the user’s email address in order to do this.
Let’s start by creating a method called requestAuthorization, which will take in the user’s email address and output the URL as a string. There’s just one simple library call that we’ll need to do in order to get the URL. Here’s the implementation for requestAuthorization:
public String requestAuthorization(String email) throws Exception { BasicUserInfoProto.BasicUserInfoResponse response = _protocol.statUser(email); return response.getMessage().getAuthorizationUri(); }
Delegating as a User
Once the user has authorized our application, we can use their email address to perform actions on their behalf. Let’s create a method called authenticate to take care of this. This is where the _delegation object gets initialized.
public void authenticate(String email) throws Exception { _delegation = _protocol.createDelegatedProtocol(email); }
Trying It Out
Setting It Up
We’re now ready to test our authenticate method. Let’s begin with a simple main method.
public static void main(String[] args) { . . . }
Opening the Connection
All we need to do is create an instance of our SmartVault class to open a connection.
public static void main(String[] args) { try { SmartVault smartVault = new SmartVault(); . . . } catch (Exception e) { e.printStackTrace(); } }
Authenticating
Let’s call a new method to handle authenticating with SmartVault. This method, called authenticate, will need to take in the SmartVault object.
public static void main(String[] args) { try { SmartVault smartVault = new SmartVault(); authenticate(smartVault); } catch (Exception e) { e.printStackTrace(); } }
Now let’s start implementing the authenticate method. We’ll need the user’s email address in order to authenticate. Let’s have them enter their email address from the console. In order to do this, we’ll need a Scanner object to allow the user to input data.
private static Scanner keyboard = new Scanner(System.in);
Now we can ask the user for their email address and have them enter it from the console.
private static void authenticate(SmartVault smartVault) throws Exception { // Autonomous authentication System.out.print("Enter your email address:"); String email = keyboard.nextLine();. . . }
Next, we’ll need to delegate as that user, but we can’t assume that they have already authorized our application! For this tutorial, let’s ask the user if they have authorized our application. If they haven’t, we’ll open the URL to do this in their default web browser.
private static void authenticate(SmartVault smartVault) throws Exception { // Autonomous authentication System.out.print("Enter your email address:"); String email = keyboard.nextLine(); System.out.print("Have you authorized this application? [y/n]:"); String response = keyboard.nextLine(); if (!response.toLowerCase().startsWith("y")) { String url = smartVault.requestAuthorization(email); Desktop.getDesktop().browse(URI.create(url)); System.out.println("\nPress 'Enter' once you have allowed this application."); keyboard.nextLine(); } . . . }
Now that we know the user has authorized our application, we can authenticate.
private static void authenticate(SmartVault smartVault) throws Exception { // Autonomous authentication System.out.print("Enter your email address:"); String email = keyboard.nextLine(); System.out.print("Have you authorized this application? [y/n]:"); String response = keyboard.nextLine(); if (!response.toLowerCase().startsWith("y")) { String url = smartVault.requestAuthorization(email); Desktop.getDesktop().browse(URI.create(url)); System.out.println("\nPress 'Enter' once you have allowed this application."); keyboard.nextLine(); } smartVault.authenticate(email); }
Finishing It Up
Since console applications generally quit after they finish, let’s prevent that by adding a quick prompt to have the user press the Enter key to exit. This allows us to see the end of the program’s output easily if it is not launched from a command line window. (It is not necessary to do this if you do not want it.)
public static void main(String[] args) { try { SmartVault smartVault = new SmartVault(); authenticate(smartVault); } catch (Exception e) { e.printStackTrace(); } System.out.println("\nPress 'Enter' key to exit"); keyboard.nextLine(); }
Putting it together.
SmartVault.java
import com.smartvault.proto.*; import com.smartvault.rest.*; import org.apache.commons.io.IOUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMReader;import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.StringReader; import java.nio.file.Paths; import java.security.KeyPair; import java.security.Security; public class SmartVault { private ClientProtocol _protocol; private DelegatedProtocol _delegation; public SmartVault() throws Exception { String clientId = "JavaTutorial"; // Change this to your client ID String privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpAIBAAKCAQEAxmh2LZYY5SzT+BMmSNoGsjyI7O6fzmozR+mviyOiAIk0bBXa\n" + "U/kLGnaTYe4WE8DyQHweBQq1C5ovUA3L5rqKshoxmhrOtJ04YvMXmEaPBxxfxpLH\n" + "ogqg+7kkjDMs+Mb+EpYwguHKGXhFF80AWMZmfVVquTCuhG6bXUHFmdcVSg4imiE2\n" + "Ah75matYfD/X9aQecLC32gdgUAx7+6JflmQp+xAhr4s+LUORwCLT6v6znzpA89Qy\n" + "/8cc8FS3RrOZtxpjPcY9xK60uY94huPXjuW9Yj9nBgYnqE1hNPZGZCKcwxSInEtC\n" + "GjsAx+bvRiNYdNwtOZz6z6oAN/QX4mEQkE2wlQIDAQABAoIBAHkpD4n1EAzbXDIw\n" + "139DjTVI3ED706EEn345yVZJk0OKhfW/Po1rFwm5AXWbI+Y6PHV+lgJ0MGz+Yggb\n" + "9LlYjxwF/OZjmnkXTXi3hGAcLnmkLSShO8HLhdVSkWwAUGU3d644AzXZ1kXJeT/4\n" + "k06jEbFV+Q9QGDKNLNk9MgMpIjoO5Na5doiGd6UpIVGkZhNL1MVRa1x2ktCz211a\n" + "b9MvsufNB1d7Ady8lY8z794r035ixclCToimMtd4Q5GPjQIVXhSHGjxtMElRv43k\n" + "Xp9EIzdLgOkM7L2tOxMIrBU/5aaErCIfqRER/yIBHc3zlPqh2dp5pK92qx6aml9U\n" + "S3uUL90CgYEA+ztEVRNu4dMiJUBQjJxfx8OWZhfsEsVR6G4+aictXrXFQIppiXZE\n" + "aZrUiGSZm1lnK7/XdbgPowFvBafObe3MtVDEx5xYE9ZYSI5wm4xyqkybLlr2wmQK\n" + "mFdn8l26SpWxnhfBp2nuFk8FyJhuq1kLuTG6zq7xfHZTmH1pSR+jO9sCgYEAyiyG\n" + "lHRGe7TMqzlJ0KTUwVBK75b31pAG/yLWIzyeoU/Y7cTNakj/SGloX6kx0Kk2v2/L\n" + "lsKFab0wMf1XQgX+C+sxvQ+bM8oiVcvQmlfaRLuFYBzdJRd4xhz69Ir4vRaOAY9K\n" + "pbSV9tmEs58oRtm+k/Ks6bRT0KRqTjEebCD8KE8CgYEA7Tpdn+glv9/aUkqUxPG0\n" + "D7HEhsr4BBGG8m+HSD2OPexuQi9w0Hh4yS+GmPRFh8e4ADu6fFI9kbJ8315BMtRl\n" + "hKCr78DV+oVf/8Ng2cCZVe3YasFCWPSWfJusb9PJYTxQ5/OOzULdqvsbfvtRJUOE\n" + "Km+m8huHs/sXnNpvXLkfLhkCgYBg4wuvszVf7Vo0KCUuvv9SkRcIULH++lDQDjLO\n" + "+isPJUPRVoIWkFr+qb0iMuQzmhQpk/reCeSDsu2Y107szhBcR98zOnpnTFQ+B4m1\n" + "nap1S+R0FgEI2IHBd3vwm3TusRNmvfPJC4zemolUx042/fytzBt/eDK+hzyGslVg\n" + "/kG5UwKBgQCG4U6kaT3BjF8Rr+S65JfPKEdZfO6pngva8ySMwB5xdzuX37nMqVZr\n" + "TGc654yj1FCa80UMwUo2ptUE0oCKh3VdZElinG9+wNpO/3nIS/b404A5EdF8QJ6w\n" + "1lHO1FsptGDOpb69WIjqoUzTiMfMEeOCNKlvFI2ZamzDdR6l39J8Cw==\n" + "-----END RSA PRIVATE KEY-----\n"; Security.addProvider(new BouncyCastleProvider()); StringReader reader = new StringReader(privateKey); KeyPair keyPair = (KeyPair) new PEMReader(reader).readObject(); ServerCfg cfg = new ServerCfg("https://rest.smartvault.com", clientId, keyPair.getPrivate()); Authentication auth = new Authentication(cfg); _protocol = auth.createClientProtocol(); } public String requestAuthorization(String email) throws Exception { BasicUserInfoProto.BasicUserInfoResponse response = _protocol.statUser(email); return response.getMessage().getAuthorizationUri(); } public void authenticate(String email) throws Exception { _delegation = _protocol.createDelegatedProtocol(email); } }
Program.java
import com.smartvault.proto.NodeProto;import java.awt.*; import java.net.URI; import java.nio.file.Paths; import java.util.Scanner; public class Program { private static Scanner keyboard = new Scanner(System.in); public static void main(String[] args) { try { SmartVault smartVault = new SmartVault(); authenticate(smartVault); } catch (Exception e) { e.printStackTrace(); } System.out.println("\nPress 'Enter' key to exit"); keyboard.nextLine(); } private static void authenticate(SmartVault smartVault) throws Exception { // Autonomous authentication System.out.print("Enter your email address: "); String email = keyboard.nextLine(); System.out.print("Have you authorized this application? [y/n]: "); String response = keyboard.nextLine(); if (!response.toLowerCase().startsWith("y")) { String url = smartVault.requestAuthorization(email); Desktop.getDesktop().browse(URI.create(url)); System.out.println ("\nPress 'Enter' once you have allowed this application."); keyboard.nextLine(); } smartVault.authenticate(email); } }
Here’s What You’ll Need
To perform autonomous authentication, you’ll first need to generate a RSA key pair. Visit Generate a Key Pair to view the steps.
If you have not yet created a developer account or client ID, click here to do so:
Create a Client ID. (For OAuth Support, select Autonomous since this is how we will be authenticating and copy and paste the contents of the public key you just created into the Public Key field.)
Setting Up
Let’s begin by creating some global variables that we will be using throughout this tutorial.
static $client_id = "PHPTutorial"; static $endpoint = "https://rest.smartvault.com"; static $email= "phpexample@smartvault.com"; $private_key = "qqwkHMTo+/gFeUtafHP3bRBAztIz6wmiLXaSV/ WhmZZoUGJqDXOnZwIdWDIs39BeJU5wqUu7yJzFn/JoZs4qH3YhSP8auPtbnu eNnYU8sLA0pkEd14PRZIAQeoE5USEtNGV3t3L6uaTC0NYemWnqcGHXsJ8qLX 9DYw50LCT/JlO19t4NRcnJNxwkbBDZ0lQZt3gE/xY1Ut3LmE9UHOV6usU8Ou /NriOOhWHCS+yaN+JeefXkq9jZWYPhr53ZTtNd3j39CSL+fbXJ2dDrsx2NJe RJ2lm8OBw+F14L3a30I/GA5gobZ/ny+K4qtCpvhE+GuhM6sEJ+XgguHleP8T CnZQ==AQABy8lNtyFth443JHdl 5nr/Vt2U6H1GoSEqExpTTM/eghJ/UZBo0 Uu59NzCmrSCDIHbars9S8fu3ud4 YRfJdYHjWurfY7oC+VfdQLSjgjmncGzA +U+Zrfq8K8zDdheWFRwMG5Nxa1dJ wFkry00UZMKOpeV7Y/4/pNVjpgnW1hs fE8M=1mbWvPzBMWQIJUtiw DtDc3rzQe7KwyLEzxj7ujCGG3rlo5HuVw5 h+XKmE6ZtPz3h+gBkYIr4Xw1FE lFxGUJtc8hwLbVTPvsluM6rzYkicOqwdl fOrv+T0ROYHkCHoiLt6B+6ulIUV 1kP71J3v4UFh/WQtOK3aup862MmDg+67 bc=jxIOUMLUPfY3eo+k5 /J0b8zzLWI+gwNgoba6wtOxmMpZvq7PGBm9 PU78BVczcop8vGsmNpzwdGg32 Jq1op0FPKBnI4HFcr8gI7xuiw/lIQYJWT9 sWnwNPgbtN2yJvtpJGdcjKsRGk BdKqtm7tp3tPkVloqcukZAK/Ngtj3XNFL c=coipengDtKDdgR7O eCawl8Y8oSIxiyDNxlxwTTySx6dVeZYBntv+FsXaV nD3t2sVhvoipThYCl8K YQjExFuqIMoYszJEcEa2Fg3B1aDGl0+oSPALZ4z8 qBoxjyelzUWflfstQ0+J skfPrWd+tP8Yv1K9pQPgO+tcJFro/2YD0+0=RZo AXQtlg XiisdfFARu6t9Xj1W+zTpy7XwHZUqpDL/piD1biMLa913s8mKK4WR h+e+912 QllaIgC6tA61xRS7MzRQDgvW6K6rRVZidSxP8ruhk6lkcL4DQGlj qdli3Wby Bu1tOJ6mOf83bX4R/8xQY74nIp89YJC5SLVzgoAvgg=G8H ovaU TdKdfJzL81xt6ijUH1UXqm7dIC7d/uukqtx1MfzECU92+GXVb6xQoqDNDRzN Sr2CvJxltgBifUi5a5h2tnCmhNvnqahWkD+ezedOukbuAFvpL+9m4KbRf619 HSCuYejArsYr9BD9OtV9nJDqa0bw70oUizeFz6MS7mofkH4CKoB5gBFMcXPE ZHt98gSbmmDKYWE1oOBJXIuOdFTGAs/IKMXhsCLB8cHKXaILa+1Fx40VSzeO tMQAaXMc5xvRacPu/iazl+qu+/inIL3Njzr/i4DIas8+lkLC8tqBprvQvxih NqU9uBcHDisUNgc2vJKpSpfYwoxzpWFXkoQ==";
NOTE: You will need to change the client_id and email to the ones you used to register on the SmartVault Portal. In addition, change private_key to the private key you generated earlier.
Also note that it is not recommended to provide the private key this way, as it is a huge security risk. This implementation is purely for example purposes and production code should take great care to protect this private key. For example, Java has its own key store designed for storing cryptographic keys. Windows also has key containers that you can use if you are running Windows. You should avoid storing the private key in plain-text, since this would allow anybody to have access to it.
Authenticating
Requesting a Nonce
A SmartVault nonce will be used to begin the authentication process with the SmartVault service.
To request a nonce from SmartVault, we will setup an HttpWebRequest that interacts with this URI: http://rest.smartvault.com/auto/auth/nonce/1.
function request_nonce( &$callback ) { global $endpoint; $uri = $endpoint . "/auto/auth/nonce/1"; . . . }
Let’s build the message we will be sending and convert it to JSON format. All you will need for this request is your client ID.
function request_nonce( &$callback ) { global $endpoint; $uri = $endpoint . "/auto/auth/nonce/1"; global $client_id; $http_body = new http\Message\Body(); $http_body->append( json_encode( array( "client_id" => $client_id ) ) ); . . . }
We can now set up a connection with SmartVault. We’ll need to indicate the type of request (POST), the URI (http://rest.smartvault.com/auto/auth/nonce/1), the format of the request and the response (JSON), and the body of the message we are sending. After sending the request, SmartVault will respond by sending us a nonce.
function request_nonce( &$callback ) { global $endpoint; global $client_id; $uri = $endpoint . "/auto/auth/nonce/1"; $http_body = new http\Message\Body(); $http_body->append( json_encode( array( "client_id" => $client_id ) ) ); $headers = array( "accept" => "application/json" ); $http_client = new http\Client(); $http_request = new http\Client\Request( "POST", $uri, $headers, $http_body ); $http_request->setContentType( "application/json" ); $http_client->enqueue( $http_request, $callback ); return $http_client->send(); }
Creating a Self-Signed Token
Now that we have a nonce, we can construct a self-signed token, which will uniquely identify your application so that the SmartVault service can recognize it. The self-signed token will be created using the nonce you just received, your client ID, your private key, and a prefix (“SLF00”). It can later be exchanged for a client token that can log on as your client program.
function generate_self_token( &$nonce ) { global $client_id; global $private_key; $prefix = "SLF00"; . . . }
To construct the self-signed token, we will have to combine the prefix, the length of the client ID, the client ID, the length of the nonce, and the nonce and save this data in a blob.
function generate_self_token( &$nonce ) { global $client_id; global $private_key; $prefix = "SLF00"; $data = array(); $temp = unpack( "C*", $prefix ); $data = array_merge( $data, $temp ); $data[] = strlen( $client_id ); $temp = unpack( "C*", $client_id ); $data = array_merge( $data, $temp ); $data[] = strlen( $nonce ); $temp = unpack( "C*", $nonce ); $data = array_merge( $data, $temp ); print json_encode( $data ) . "\n"; $blob = join ( "", array_map( function ( &$i ) { return chr( $i ); }, $data ) ); . . . }
Next, let’s first use openssl_sign() to generate a digital signature and then do a base 64 encoding of the blob and signature combined. And voila! We just created our own self-encoded token.
function generate_self_token( &$nonce ) { global $client_id; global $private_key; $prefix = "SLF00"; $data = array(); $temp = unpack( "C*", $prefix ); $data = array_merge( $data, $temp ); $data[] = strlen( $client_id ); $temp = unpack( "C*", $client_id ); $data = array_merge( $data, $temp ); $data[] = strlen( $nonce ); $temp = unpack( "C*", $nonce ); $data = array_merge( $data, $temp ); print json_encode( $data ) . "\n"; $blob = join ( "", array_map( function ( &$i ) { return chr( $i ); }, $data ) ); $signature = ""; openssl_sign( $blob, $signature, $private_key, OPENSSL_ALGO_SHA256 ); print "blob: " . bin2hex( $blob ) . "\n"; print "signature: " . bin2hex( $signature ) . "\n"; $token = base64_encode( $blob . $signature ); print "token: " . $token . "\n"; return $token; }
Requesting a Client Token
Using your self-signed token, your application can now request a client token from the SmartVault service, which you can use to perform administrative tasks or to exchange for a delegation token.
function request_client_token( &$self_token, &$callback ) { global $endpoint; $uri = $endpoint . "/auto/auth/ctoken/1"; . . . }
Let’s create a request to for a client token. The body of the message we send will only consist of our self-signed token. Let’s convert it to JSON format.
function request_client_token( &$self_token, &$callback ) { global $endpoint; $uri = $endpoint . "/auto/auth/ctoken/1"; $http_body = new http\Message\Body(); $http_body->append( json_encode( array( "token" => $self_token ) ) ); . . . }
Now we can begin the request process. Indicate the method type (POST), the URI (http://rest.smartvault.com/auto/auth/ctoken/1), the request and response formats (JSON), and the message body.
function request_client_token( &$self_token, &$callback ) { global $endpoint; $uri = $endpoint . "/auto/auth/ctoken/1"; $http_body = new http\Message\Body(); $http_body->append( json_encode( array( "token" => $self_token ) ) ); $headers = array( "accept" => "application/json" ); $http_client = new http\Client(); $http_request = new http\Client\Request("POST", $uri, $headers, $http_body); $http_request->setContentType( "application/json" ); . . . }
We will need to create a function that will read the body of the response, check to see if the request is a success, extract the token, and stat the user to make sure that the user holds a valid account. Finally, send the request.
function request_client_token( &$self_token, &$callback ) { global $endpoint; $uri = $endpoint . "/auto/auth/ctoken/1"; $http_body = new http\Message\Body(); $http_body->append( json_encode( array( "token" => $self_token ) ) ); $headers = array( "accept" => "application/json" ); $http_client = new http\Client(); $http_request = new http\Client\Request( "POST", $uri, $headers, $http_body ); $http_request->setContentType( "application/json" ); $action = function ( &$response ) use ( $callback ) { print $response->toString() . "\n"; $response_code = $response->getTransferInfo()->response_code; $body = $response->getBody(); $envelope = json_decode( $body ); if ( 200 == $response_code && true == $envelope->error->success ) { print "Do something with the client token\n"; $client_token = $envelope-"message-"token; stat_user( $client_token, $callback ); } }; $http_client-"enqueue( $http_request, $action ); return $http_client-"send(); }
Stat User
Let’s create the stat_user method we used after requesting a client token. Stating a user determines if a user account is activated and if they have authorized your application to act on their behalf. The response from the call provides a URL for the user to authorize your application if they have not.
In order to stat a user, we will need the client token, the endpoint, the client ID, and the email. The path of the requested resource will be http://rest.smartvault.com/auto/usr/phpexample@smartvault.com.
function stat_user( &$client_token, &$callback ) { global $endpoint; global $client_id; global $email; $uri = $endpoint . "/auto/usr/" . $email; . . . }
Set the method (GET), the URI we will be interacting with (http://rest.smartvault.com/auto/usr/phpexample@smartvault.com), the request and response formats (JSON), and the message body.
function stat_user( &$client_token, &$callback ) { global $endpoint; global $client_id; global $email; $uri = $endpoint . "/auto/usr/" . $email; $headers = array( "accept" =" "application/json" ); $auth_basic = 1; $http_client = new http\Client(); $http_client-"setOptions( array( "httpauthtype" =" $auth_basic, "httpauth" =" $client_id . ":" . $client_token ) ); $http_request = new http\Client\Request( "GET", $uri, $headers ); $http_request-"setContentType( "application/json" ); . . . }
Now let’s create a function that will check if the user’s status. First check if the user has activated their account. If they have not, let the user know to activate their account. Next, check if the user has authorized your client Id. If they have not, extract the authorization URI that that SmartVault provided you in the response message and redirect them to this site so that they can sign in to SmartVault and authorize your application. If the user passes both of these, you are ready to call the method to request a delegation token.
function stat_user( &$client_token, &$callback ) { global $endpoint; global $client_id; global $email; $uri = $endpoint . "/auto/usr/" . $email; $headers = array( "accept" =" "application/json" ); $auth_basic = 1; $http_client = new http\Client(); $http_client-"setOptions( array( "httpauthtype" =" $auth_basic, "httpauth" =" $client_id . ":" . $client_token ) ); $http_request = new http\Client\Request( "GET", $uri, $headers ); $http_request-"setContentType( "application/json" ); $action = function ( &$response ) use ( $client_token, $callback ) { print $response-"toString() . "\n"; $response_code = $response-"getTransferInfo()-"response_code; $body = $response-"getBody(); $envelope = json_decode( $body ); if ( 200 == $response_code && true == $envelope-"error-"success ) { print "User statted correctly\n"; if ( !$envelope-"message-"activated ) { print "User needs to activate their account"; } elseif ( !$envelope-"message-"authorized ) { print "User needs to authorize their account for your client:\n "; print $envelope-"message-"authorization_uri . "\n"; /* You can add a redirect_uri=some_url as a URL parameter to that link to send the user back to your page after they authorize. */ } else { request_delegation_token( $client_token, $callback ); } } }; $http_client-"enqueue( $http_request, $action ); return $http_client-"send(); }
Requesting a Delegation Token
We can now use the client token to request a delegation token. Delegation tokens are used to perform operations on behalf of a SmartVault user.
For this step, we will need the endpoint, the client ID, and the email. The path we will be interacting with will be the following: http://rest.smartvault.com/auto/auth/dtoken/1.
function request_delegation_token( &$client_token, &$callback ) { global $endpoint; global $client_id; global $email; $uri = $endpoint . "/auto/auth/dtoken/1"; . . . }
The body of the message we will be sending will consist of the user’s email. Let’s convert it to JSON format.
function request_delegation _token( &$client_token, &$callback ) { global $endpoint; global $client_id; global $email; $uri = $endpoint . "/auto/auth/dtoken/1"; $http_body = new http\Message\Body(); $http_body-"append( json_encode( array( "user_email" =" $email ) ) ); . . . }
Indicate the method (POST), the URI (http://rest.smartvault.com/auto/auth/nonce/1), the request and response formats (JSON), and the message body.
function request_delegation_token( &$client_token, &$callback ) { global $endpoint; global $client_id; global $email; $uri = $endpoint . "/auto/auth/dtoken/1"; $http_body = new http\Message\Body(); $http_body-"append( json_encode( array( "user_email" =" $email ) ) ); $headers = array( "accept" =" "application/json" ); $auth_basic = 1; // pulled from docs $http_client = new http\Client(); $http_client-"setOptions( array( "httpauthtype" =" $auth_basic, "httpauth" =" $client_id . ":" . $client_token ) ); print "Client token: " . $client_token . "\n"; $http_request = new http\Client\Request( "POST", $uri, $headers, $http_body ); $http_request-"setContentType( "application/json" ); . . . }
Let’s create a function to check if the delegation token request was a success. (A response code of 200 indicates that a request succeeded and that the requested resource has been returned in the message body.). Finally, let’s return the delegation token.
function request_delegation_token( &$client_token, &$callback ) { global $endpoint; global $client_id; global $email; $uri = $endpoint . "/auto/auth/dtoken/1"; $http_body = new http\Message\Body(); $http_body-"append( json_encode( array( "user_email" =" $email ) ) ); $headers = array( "accept" =" "application/json" ); $auth_basic = 1; // pulled from docs $http_client = new http\Client(); $http_client-"setOptions( array( "httpauthtype" =" $auth_basic, "httpauth" =" $client_id . ":" . $client_token ) ); print "Client token: " . $client_token . "\n"; $http_request = new http\Client\Request( "POST", $uri, $headers, $http_body ); $http_request-"setContentType( "application/json" ); $action = function ( &$response ) use ( $callback ) { print $response-"toString() . "\n"; $response_code = $response-"getTransferInfo()-"response_code; $body = $response-"getBody(); $envelope = json_decode( $body ); if ( 200 == $response_code && true == $envelope-"error-"success ) { $callback( $envelope-"message-"token ); } }; $http_client-"enqueue( $http_request, $action ); return $http_client-"send(); }
Authenticating
It’s time to begin the SmartVault authentication process.
Let’s start by looking at the response from the nonce request. If the request was successful, get the nonce. Then call the function to generate a self-signed token, and lastly, request a client token.
function authenticate( &$callback ) { $nonce_callback = function ( &$response ) use ( $callback ) { print $response-"toString() . "\n"; $response_code = $response-"getTransferInfo()-"response_code; $body = $response-"getBody(); $envelope = json_decode( $body ); if ( 200 == $response_code && true == $envelope-"error-"success ) { $nonce = $envelope-"message-"code; $self_token = generate_self_token( $nonce ); request_client_token( $self_token, $callback ); } }; $http_client = request_nonce( $nonce_callback ); }
Once you are in possession of a delegation token for a SmartVault user, you can begin to execute commands against the SmartVault service on their behalf. In this case, we are performing a simple browse from the root of their login to a depth of two.
$fetch_data = function ( &$delegation_token ) { print "fetching data\n"; global $sv_host; global $sv_user_email; $uri = $sv_host . "/nodes/pth/?children=2"; $headers = array( "accept" =" "application/json" ); $auth_basic = 1; // pulled from docs $http_client = new http\Client(); $http_client-"setOptions( array( "httpauthtype" =" $auth_basic, "httpauth" =" $sv_user_email . ":" . $delegation_token ) ); $http_request = new http\Client\Request( "GET", $uri, $headers ); $http_request-"setContentType( "application/json" ); $action = function ( &$response ) { print $response-"toString() . "\n"; }; $http_client-"enqueue( $http_request, $action ); return $http_client-"send(); };
Putting it together.
qqwkHMTo+/gFeUtafHP3bRBAztIz6wmiLXaSV/ WhmZZoUGJqDXOnZwIdWDIs39BeJU5wqUu7yJzFn/JoZs4qH3YhSP8auPtbnu eNnYU8sLA0pkEd14PRZIAQeoE5USEtNGV3t3L6uaTC0NYemWnqcGHXsJ8qLX 9DYw50LCT/JlO19t4NRcnJNxwkbBDZ0lQZt3gE/xY1Ut3LmE9UHOV6usU8Ou /NriOOhWHCS+yaN+JeefXkq9jZWYPhr53ZTtNd3j39CSL+fbXJ2dDrsx2NJe RJ2lm8OBw+F14L3a30I/GA5gobZ/ny+K4qtCpvhE+GuhM6sEJ+XgguHleP8T CnZQ== AQAB y8lNtyFth443JHdl 5nr/Vt2U6H1GoSEqExpTTM/eghJ/UZBo0Uu59NzCmrSCDIHbars9S8fu3ud4 YRfJdYHjWurfY7oC+VfdQLSjgjmncGzA+U+Zrfq8K8zDdheWFRwMG5Nxa1dJ wFkry00UZMKOpeV7Y/4/pNVjpgnW1hsfE8M=
1mbWvPzBMWQIJUtiw DtDc3rzQe7KwyLEzxj7ujCGG3rlo5HuVw5h+XKmE6ZtPz3h+gBkYIr4Xw1FE lFxGUJtc8hwLbVTPvsluM6rzYkicOqwdlfOrv+T0ROYHkCHoiLt6B+6ulIUV 1kP71J3v4UFh/WQtOK3aup862MmDg+67bc=jxIOUMLUPfY3eo+k5 /J0b8zzLWI+gwNgoba6wtOxmMpZvq7PGBm9PU78BVczcop8vGsmNpzwdGg32 Jq1op0FPKBnI4HFcr8gI7xuiw/lIQYJWT9sWnwNPgbtN2yJvtpJGdcjKsRGk BdKqtm7tp3tPkVloqcukZAK/Ngtj3XNFLc= coipengDtKDdgR7O eCawl8Y8oSIxiyDNxlxwTTySx6dVeZYBntv+FsXaVnD3t2sVhvoipThYCl8K YQjExFuqIMoYszJEcEa2Fg3B1aDGl0+oSPALZ4z8qBoxjyelzUWflfstQ0+J skfPrWd+tP8Yv1K9pQPgO+tcJFro/2YD0+0= RZoAXQtlg XiisdfFARu6t9Xj1W+zTpy7XwHZUqpDL/piD1biMLa913s8mKK4WRh+e+912 QllaIgC6tA61xRS7MzRQDgvW6K6rRVZidSxP8ruhk6lkcL4DQGljqdli3Wby Bu1tOJ6mOf83bX4R/8xQY74nIp89YJC5SLVzgoAvgg= G8H ovaUTdKdfJzL81xt6ijUH1UXqm7dIC7d/uukqtx1MfzECU92+GXVb6xQoqDN DRzNSr2CvJxltgBifUi5a5h2tnCmhNvnqahWkD+ezedOukbuAFvpL+9m4KbR f619HSCuYejArsYr9BD9OtV9nJDqa0bw70oUizeFz6MS7mofkH4CKoB5gBFM cXPEZHt98gSbmmDKYWE1oOBJXIuOdFTGAs/IKMXhsCLB8cHKXaILa+1Fx40V SzeOtMQAaXMc5xvRacPu/iazl+qu+/inIL3Njzr/i4DIas8+lkLC8tqBprvQ vxihNqU9uBcHDisUNgc2vJKpSpfYwoxzpWFXkoQ== "; function request_nonce( &$callback ) { global $endpoint; global $client_id; $uri = $endpoint . "/auto/auth/nonce/1"; $http_body = new http\Message\Body(); $http_body->append( json_encode( array( "client_id" => $client_id ) ) ); $headers = array( "accept" => "application/json" ); $http_client = new http\Client(); $http_request = new http\Client\Request( "POST", $uri, $headers, $http_body ); $http_request->setContentType( "application/json" ); $http_client->enqueue( $http_request, $callback ); return $http_client->send(); } function generate_self_token( &$nonce ) { global $client_id; global $private_key; $prefix = "SLF00"; $data = array(); $temp = unpack( "C*", $prefix ); $data = array_merge( $data, $temp ); $data[] = strlen( $client_id ); $temp = unpack( "C*", $client_id ); $data = array_merge( $data, $temp ); $data[] = strlen( $nonce ); $temp = unpack( "C*", $nonce ); $data = array_merge( $data, $temp ); print json_encode( $data ) . "\n"; $blob = join ( "", array_map( function ( &$i ) { return chr( $i ); }, $data ) ); $signature = ""; openssl_sign( $blob, $signature, $private_key, OPENSSL_ALGO_SHA256 ); print "blob: " . bin2hex( $blob ) . "\n"; print "signature: " . bin2hex( $signature ) . "\n"; $token = base64_encode( $blob . $signature ); print "token: " . $token . "\n"; return $token; } function request_delegation_token( &$client_token, &$callback ) { global $endpoint; global $client_id; global $email; $uri = $endpoint . "/auto/auth/dtoken/1"; $http_body = new http\Message\Body(); $http_body->append( json_encode( array( "user_email" => $email ) ) ); $headers = array( "accept" => "application/json" ); $auth_basic = 1; // pulled from docs $http_client = new http\Client(); $http_client->setOptions( array( "httpauthtype" => $auth_basic, "httpauth" => $client_id . ":" . $client_token ) ); print "Client token: " . $client_token . "\n"; $http_request = new http\Client\Request( "POST", $uri, $headers, $http_body ); $http_request->setContentType( "application/json" ); $action = function ( &$response ) use ( $callback ) { print $response->toString() . "\n"; $response_code = $response->getTransferInfo()->response_code; $body = $response->getBody(); $envelope = json_decode( $body ); if ( 200 == $response_code && true == $envelope->error->success ) { $callback( $envelope->message->token ); } }; $http_client->enqueue( $http_request, $action ); return $http_client->send(); } function stat_user( &$client_token, &$callback ) { global $endpoint; global $client_id; global $email; $uri = $endpoint . "/auto/usr/" . $email; $headers = array( "accept" => "application/json" ); $auth_basic = 1; $http_client = new http\Client(); $http_client->setOptions( array( "httpauthtype" => $auth_basic, "httpauth" => $client_id . ":" . $client_token ) ); $http_request = new http\Client\Request( "GET", $uri, $headers ); $http_request->setContentType( "application/json" ); $action = function ( &$response ) use ( $client_token, $callback ) { print $response->toString() . "\n"; $response_code = $response->getTransferInfo()->response_code; $body = $response->getBody(); $envelope = json_decode( $body ); if ( 200 == $response_code && true == $envelope->error->success ) { print "User statted correctly\n"; if ( !$envelope->message->activated ) { print "User needs to activate their account"; } elseif ( !$envelope->message->authorized ) { print "User needs to authorize their account for your client:\n "; print $envelope->message->authorization_uri . "\n"; /* You can add a redirect_uri=some_url as a URL parameter to that link to send the user back to your page after they authorize. */ } else { request_delegation_token( $client_token, $callback ); } } }; $http_client->enqueue( $http_request, $action ); return $http_client->send(); } function request_client_token( &$self_token, &$callback ) { global $endpoint; $uri = $endpoint . "/auto/auth/ctoken/1"; $http_body = new http\Message\Body(); $http_body->append( json_encode( array( "token" => $self_token ) ) ); $headers = array( "accept" => "application/json" ); $http_client = new http\Client(); $http_request = new http\Client\Request( "POST", $uri, $headers, $http_body ); $http_request->setContentType( "application/json" ); $action = function ( &$response ) use ( $callback ) { print $response->toString() . "\n"; $response_code = $response->getTransferInfo()->response_code; $body = $response->getBody(); $envelope = json_decode( $body ); if ( 200 == $response_code && true == $envelope->error->success ) { print "Do something with the client token\n"; $client_token = $envelope->message->token; stat_user( $client_token, $callback ); } }; $http_client->enqueue( $http_request, $action ); return $http_client->send(); } function authenticate( &$callback ) { $nonce_callback = function ( &$response ) use ( $callback ) { print $response->toString() . "\n"; $response_code = $response->getTransferInfo()->response_code; $body = $response->getBody(); $envelope = json_decode( $body ); if ( 200 == $response_code && true == $envelope->error->success ) { $nonce = $envelope->message->code; $self_token = generate_self_token( $nonce ); request_client_token( $self_token, $callback ); } }; $http_client = request_nonce( $nonce_callback ); } $fetch_data = function ( &$delegation_token ) { print "fetching data\n"; global $endpoint; global $email; $filename = “php_example.txt”; $local_file = “C:\Users\SV\Documents\php_example.txt”; $remote_location = $endpoint . "/nodes/pth/?children=0/My First Vault/My First folder"; $headers = array( "accept" => "application/json" ); $auth_basic = 1; $http_client = new http\Client(); $http_client->setOptions( array( "httpauthtype" => $auth_basic, "httpauth" => $email . ":" . $delegation_token ) ); $http_request = new http\Client\Request( "GET", $uri, $headers ); $http_request->setContentType( "application/json" ); $action = function ( &$response ) { print $response->toString() . "\n"; }; move_uploaded_file(local_file, remote_location); set_time_limit(0); //disable the time limit for the script output_file($remote_location, filename, ‘text/plain’); if ($fd = fopen ($remote_location, “r”)) { $size = filesize($remote_location); header(‘Content-Type: ‘.$mime_type); header(‘Content-Disposition: attachment; filename=’“.$filename.”); header(“Content-Length: “.$size); header(“Cache-control: private”); while(!feof($fd)){ $buffer = fread($fd, 2048); echo $buffer; } } fdlose($fd); $http_client->enqueue( $http_request, $action ); return $http_client->send(); } authenticate( $fetch_data ) ?>
Here’s What You’ll Need
If you have not yet created a developer account or client ID, visit Creating a Developer Account to view the steps on how to create them. (For OAuth Support, select Autonomous since this is how we will be authenticating.)
Installing the Library
We could form individual REST API calls and communicate with SmartVault that way, but why do this when this work has already been done for you? Our C# API wrapper library allows you to perform actions with SmartVault without writing individual REST API requests. This is available as a NuGet package called SmartVault.Rest and can be obtained from the standard nuget.org repository:
Now that we have the library installed, we can start writing some code.
Setting Up
Let’s create a new class called SmartVault to handle communication with the SmartVault API. First we’ll need to include the SmartVault library:
using SmartVault.Core; using SmartVault.Proto; using SmartVault.Rest; class SmartVault { ... }
Opening the Connection
Let’s add two instance variables to our class to handle communication with SmartVault:
private ClientProtocol _protocol; private DelegatedProtocol _delegation;
The protocol object created here will handle tasks on behalf of the client. In our case, this will be mainly for authentication. The delegation object will allow us to perform actions on behalf of the user. We can use this to browse and manage files, as well as perform uploads and downloads.
Let’s create a constructor to set up an initial connection with SmartVault. This will initialize the _protocol object and authenticate using the private key.
public SmartVault() { string clientId = "CSharpTutorial"; // Change this to your client ID string privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpAIBAAKCAQEAxmh2LZYY5SzT+BMmSNoGsjyI7O6fzmozR+mviyOiAIk0bBXa\n" + "U/kLGnaTYe4WE8DyQHweBQq1C5ovUA3L5rqKshoxmhrOtJ04YvMXmEaPBxxfxpLH\n" + "ogqg+7kkjDMs+Mb+EpYwguHKGXhFF80AWMZmfVVquTCuhG6bXUHFmdcVSg4imiE2\n" + "Ah75matYfD/X9aQecLC32gdgUAx7+6JflmQp+xAhr4s+LUORwCLT6v6znzpA89Qy\n" + "/8cc8FS3RrOZtxpjPcY9xK60uY94huPXjuW9Yj9nBgYnqE1hNPZGZCKcwxSInEtC\n" + "GjsAx+bvRiNYdNwtOZz6z6oAN/QX4mEQkE2wlQIDAQABAoIBAHkpD4n1EAzbXDIw\n" + "139DjTVI3ED706EEn345yVZJk0OKhfW/Po1rFwm5AXWbI+Y6PHV+lgJ0MGz+Yggb\n" + "9LlYjxwF/OZjmnkXTXi3hGAcLnmkLSShO8HLhdVSkWwAUGU3d644AzXZ1kXJeT/4\n" + "k06jEbFV+Q9QGDKNLNk9MgMpIjoO5Na5doiGd6UpIVGkZhNL1MVRa1x2ktCz211a\n" + "b9MvsufNB1d7Ady8lY8z794r035ixclCToimMtd4Q5GPjQIVXhSHGjxtMElRv43k\n" + "Xp9EIzdLgOkM7L2tOxMIrBU/5aaErCIfqRER/yIBHc3zlPqh2dp5pK92qx6aml9U\n" + "S3uUL90CgYEA+ztEVRNu4dMiJUBQjJxfx8OWZhfsEsVR6G4+aictXrXFQIppiXZE\n" + "aZrUiGSZm1lnK7/XdbgPowFvBafObe3MtVDEx5xYE9ZYSI5wm4xyqkybLlr2wmQK\n" + "mFdn8l26SpWxnhfBp2nuFk8FyJhuq1kLuTG6zq7xfHZTmH1pSR+jO9sCgYEAyiyG\n" + "lHRGe7TMqzlJ0KTUwVBK75b31pAG/yLWIzyeoU/Y7cTNakj/SGloX6kx0Kk2v2/L\n" + "lsKFab0wMf1XQgX+C+sxvQ+bM8oiVcvQmlfaRLuFYBzdJRd4xhz69Ir4vRaOAY9K\n" + "pbSV9tmEs58oRtm+k/Ks6bRT0KRqTjEebCD8KE8CgYEA7Tpdn+glv9/aUkqUxPG0\n" + "D7HEhsr4BBGG8m+HSD2OPexuQi9w0Hh4yS+GmPRFh8e4ADu6fFI9kbJ8315BMtRl\n" + "hKCr78DV+oVf/8Ng2cCZVe3YasFCWPSWfJusb9PJYTxQ5/OOzULdqvsbfvtRJUOE\n" + "Km+m8huHs/sXnNpvXLkfLhkCgYBg4wuvszVf7Vo0KCUuvv9SkRcIULH++lDQDjLO\n" + "+isPJUPRVoIWkFr+qb0iMuQzmhQpk/reCeSDsu2Y107szhBcR98zOnpnTFQ+B4m1\n" + "nap1S+R0FgEI2IHBd3vwm3TusRNmvfPJC4zemolUx042/fytzBt/eDK+hzyGslVg\n" + "/kG5UwKBgQCG4U6kaT3BjF8Rr+S65JfPKEdZfO6pngva8ySMwB5xdzuX37nMqVZr\n" + "TGc654yj1FCa80UMwUo2ptUE0oCKh3VdZElinG9+wNpO/3nIS/b404A5EdF8QJ6w\n" + "1lHO1FsptGDOpb69WIjqoUzTiMfMEeOCNKlvFI2ZamzDdR6l39J8Cw==\n" + "-----END RSA PRIVATE KEY-----\n"; StringReader reader = new StringReader(privateKey); RSAKeyPair keyPair = (RSAKeyPair)new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject(); ServerCfg cfg = new ServerCfg(clientId, keyPair.Private); Authentication auth = new Authentication(cfg); _protocol = auth.CreateClientProtocol(); }
NOTE: You will need to change the Client ID and the private key to the actual ones you registered earlier using the SmartVault Portal.
You should also never include the private key in your code like this in a production application as it is a huge security risk. We are only doing this to simplify things for this basic example.
For production applications, you should take every step possible to ensure the security of your private key. For example, Java has its own key store designed for storing cryptographic keys. Windows also has key containers that you can use if you are running Windows. You should avoid storing the private key in plain-text, since this would allow anybody to have access to it.
Delegating
Since we’re using autonomous authentication, all we need to be able to do tasks as a user is their email address. However, the user must first give us permission to do this by authorizing our application.
Authorization
The SmartVault API has a call to get a URL from the server for the user to visit in order to authorize our application. We will need the user’s email address in order to do this.
Let’s start by creating a method called requestAuthorization which will take in the user’s email address and output the URL as a string. There’s just one simple library call that we’ll need to do in order to get the URL. Here’s the implementation for requestAuthorization:
public string RequestAuthorization(string email) { BasicUserInfoResponse response = _protocol.StatUser(email); return response.Message.AuthorizationUri; }
Delegating as a User
Once the user has authorized our application, we can use their email address to perform actions as them. Let’s create a method called Authenticate to take care of this. This is where the _delegation object gets initialized.
public void Authenticate(string email) { _delegation = _protocol.CreateDelegatedProtocol(email); }
Trying it out.
Setting it up
We’re now ready to test our authenticate method. Let’s begin with a simple Main method.
class Program { static void Main(string[] args) { . . . } }
Opening the connection
All we need to do is create an instance of our SmartVault class to open a connection.
static void Main(string[] args) { try { SmartVault smartVault = new SmartVault(); . . . } catch (Exception e) { Console.WriteLine(e.Message); } }
Authenticating
Let’s call a new method to handle authenticating with SmartVault. This method, called Authenticate, will need to take in the SmartVault object.
public static void Main(String[] args) { try { SmartVault smartVault = new SmartVault(); Authenticate(smartVault); } catch (Exception e) { Console.WriteLine(e.Message); } }
Now let’s start implementing the Authenticate method. We’ll need the user’s email address in order to authenticate. Let’s have them enter their email address from the console.
private static void Authenticate(SmartVault smartVault) { // Autonomous authentication Console.Write("Enter your email address: "); string email = Console.ReadLine(); . . . }
Next, we’ll need to delegate as that user, but we can’t assume that they have already authorized our application! For this tutorial, let’s ask the user if they have authorized our application, and if they haven’t, we’ll open the URL to do this in their default web browser.
private static void Authenticate(SmartVault smartVault) { // Autonomous authentication Console.Write("Enter your email address: "); string email = Console.ReadLine(); Console.Write("Have you authorized this application? [y/n]: "); string response = Console.ReadLine(); if (!response.ToLower().StartsWith("y")) { string url = smartVault.RequestAuthorization(email); Process.Start(url); Console.WriteLine("\nPress 'Enter' once you have allowed this applicatoin."); Console.ReadLine(); } . . . }
Now that we know the user has authorized our application, we can authenticate.
private static void Authenticate(SmartVault smartVault) { // Autonomous authentication Console.Write("Enter your email address: "); string email = Console.ReadLine(); Console.Write("Have you authorized this application? [y/n]: "); string response = Console.ReadLine(); if (!response.ToLower().StartsWith("y")) { string url = smartVault.RequestAuthorization(email); Process.Start(url); Console.WriteLine("\nPress 'Enter' once you have allowed this applicatoin."); Console.ReadLine(); } smartVault.Authenticate(email); }
Finishing It up
Since console applications generally quit after they finish, let’s prevent that by adding a quick prompt to have the user press the Enter key to exit. This allows us to see the end of the program’s output easily if it is not launched from a command line window. It is not necessary to do this if you do not want it.
public static void Main(String[] args) { try { SmartVault smartVault = new SmartVault(); Authenticate(smartVault); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("\nPress any key to exit"); Console.ReadKey(); }
Putting It Together
SmartVault.cs
using System; using SmartVault.Core; using SmartVault.Proto; using SmartVault.Rest; using System.IO; namespace HelloWorldSVRest { class SmartVault { private ClientProtocol _protocol; private DelegatedProtocol _delegation; public SmartVault() { string clientId = "CSharpTutorial"; // Change this to your client ID string privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpAIBAAKCAQEAxmh2LZYY5SzT+BMmSNoGsjyI7O6fzmozR+mviyOiAIk0bBXa\n" + "U/kLGnaTYe4WE8DyQHweBQq1C5ovUA3L5rqKshoxmhrOtJ04YvMXmEaPBxxfxpLH\n" + "ogqg+7kkjDMs+Mb+EpYwguHKGXhFF80AWMZmfVVquTCuhG6bXUHFmdcVSg4imiE2\n" + "Ah75matYfD/X9aQecLC32gdgUAx7+6JflmQp+xAhr4s+LUORwCLT6v6znzpA89Qy\n" + "/8cc8FS3RrOZtxpjPcY9xK60uY94huPXjuW9Yj9nBgYnqE1hNPZGZCKcwxSInEtC\n" + "GjsAx+bvRiNYdNwtOZz6z6oAN/QX4mEQkE2wlQIDAQABAoIBAHkpD4n1EAzbXDIw\n" + "139DjTVI3ED706EEn345yVZJk0OKhfW/Po1rFwm5AXWbI+Y6PHV+lgJ0MGz+Yggb\n" + "9LlYjxwF/OZjmnkXTXi3hGAcLnmkLSShO8HLhdVSkWwAUGU3d644AzXZ1kXJeT/4\n" + "k06jEbFV+Q9QGDKNLNk9MgMpIjoO5Na5doiGd6UpIVGkZhNL1MVRa1x2ktCz211a\n" + "b9MvsufNB1d7Ady8lY8z794r035ixclCToimMtd4Q5GPjQIVXhSHGjxtMElRv43k\n" + "Xp9EIzdLgOkM7L2tOxMIrBU/5aaErCIfqRER/yIBHc3zlPqh2dp5pK92qx6aml9U\n" + "S3uUL90CgYEA+ztEVRNu4dMiJUBQjJxfx8OWZhfsEsVR6G4+aictXrXFQIppiXZE\n" + "aZrUiGSZm1lnK7/XdbgPowFvBafObe3MtVDEx5xYE9ZYSI5wm4xyqkybLlr2wmQK\n" + "mFdn8l26SpWxnhfBp2nuFk8FyJhuq1kLuTG6zq7xfHZTmH1pSR+jO9sCgYEAyiyG\n" + "lHRGe7TMqzlJ0KTUwVBK75b31pAG/yLWIzyeoU/Y7cTNakj/SGloX6kx0Kk2v2/L\n" + "lsKFab0wMf1XQgX+C+sxvQ+bM8oiVcvQmlfaRLuFYBzdJRd4xhz69Ir4vRaOAY9K\n" + "pbSV9tmEs58oRtm+k/Ks6bRT0KRqTjEebCD8KE8CgYEA7Tpdn+glv9/aUkqUxPG0\n" + "D7HEhsr4BBGG8m+HSD2OPexuQi9w0Hh4yS+GmPRFh8e4ADu6fFI9kbJ8315BMtRl\n" + "hKCr78DV+oVf/8Ng2cCZVe3YasFCWPSWfJusb9PJYTxQ5/OOzULdqvsbfvtRJUOE\n" + "Km+m8huHs/sXnNpvXLkfLhkCgYBg4wuvszVf7Vo0KCUuvv9SkRcIULH++lDQDjLO\n" + "+isPJUPRVoIWkFr+qb0iMuQzmhQpk/reCeSDsu2Y107szhBcR98zOnpnTFQ+B4m1\n" + "nap1S+R0FgEI2IHBd3vwm3TusRNmvfPJC4zemolUx042/fytzBt/eDK+hzyGslVg\n" + "/kG5UwKBgQCG4U6kaT3BjF8Rr+S65JfPKEdZfO6pngva8ySMwB5xdzuX37nMqVZr\n" + "TGc654yj1FCa80UMwUo2ptUE0oCKh3VdZElinG9+wNpO/3nIS/b404A5EdF8QJ6w\n" + "1lHO1FsptGDOpb69WIjqoUzTiMfMEeOCNKlvFI2ZamzDdR6l39J8Cw==\n" + "-----END RSA PRIVATE KEY-----\n"; StringReader reader = new StringReader(privateKey); RSAKeyPair keyPair = RSAPrivateKey2.KeyPairFromPem(privateKey); ServerCfg cfg = new ServerCfg(clientId, keyPair.Private); Authentication auth = new Authentication(cfg); _protocol = auth.CreateClientProtocol(); } public string RequestAuthorization(string email) { BasicUserInfoResponse response = _protocol.StatUser(email); return response.Message.AuthorizationUri; } public void Authenticate(string email) { _delegation = _protocol.CreateDelegatedProtocol(email); } } }
Program.cs
using System; using System.Diagnostics; using System.IO; namespace HelloWorldSVRest { class Program { static void Main(string[] args) { try { SmartVault smartVault = new SmartVault(); Authenticate(smartVault); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("\nPress any key to exit"); Console.ReadKey(); } private static void Authenticate(SmartVault smartVault) { // Autonomous authentication Console.Write("Enter your email address: "); string email = Console.ReadLine(); Console.Write("Have you authorized this application? [y/n]: "); string response = Console.ReadLine(); if (!response.ToLower().StartsWith("y")) { string url = smartVault.RequestAuthorization(email); Process.Start(url); Console.WriteLine("\nPress 'Enter' once you have allowed this applicatoin."); Console.ReadLine(); } smartVault.Authenticate(email); } } }
Leave A Comment?