Introduction
In this tutorial, we will build a simple application using the
wrapper library to upload a file. The application will need
to point the user to a URL to authorize the application, and
from there we can easily access the user’s documents. We
will use the generic integration model, which effectively makes
SmartVault a basic file storage system similar to a hard drive.
Here’s What You’ll Need
To perform autonomous authentication, we will first need to generate a RSA key pair. Visit Generating a Key Pair to view the steps on how to create them.
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.
Setting Up
You will also need to install the Java API wrapper library, begin communicating with SmartVault, and create a method to handle autonomous authentication. The following tutorial will guide you through this process:
Autonomous Authentication
Browsing the Folder Structure
A very common task in SmartVault is browsing the folder structure. For generic integrations, this is done using the /nodes/pth structure. The root of this structure contains the user’s accounts. Accounts contain vaults, and vaults contain folders. Folders are where files are typically stored.
Let’s create a method called browsePath to implement browsing this structure in a simplified way. This method will take in a path to browse and output the response. The variable children controls how deep in the structure we want to traverse on each call. Setting this to 1 will make the response contain the immediate contents of the path retrieved.
public NodeProto.NodeResponse browsePath(String path) throws Exception { int children = 1; // Immediate contents only return _delegation.navigate(path, children); }
Uploading Files
Let’s create a method called uploadFile to handle uploading files from the local computer to SmartVault. This method can take in a string containing the path to the file on the local machine, and the path to folder in SmartVault where we want to store it.
public void uploadFile(String localFile, String remoteFolder) throws Exception { ... }
The first step with uploading a file is creating a Stream pointing to the file on the local computer. This stream will be read by the library and used to transmit the file’s data to SmartVault.
public void uploadFile(String localFile, String remoteFolder) throws Exception { FileInputStream stream = new FileInputStream(localFile); ... }
Now we need to build an UploadFileRequest in order to upload the file. This contains the file’s metadata, including the file name in SmartVault. For this example, we will use the same filename as used for the original file on the local computer.
public void uploadFile(String localFile, String remoteFolder) throws Exception { FileInputStream stream = new FileInputStream(localFile); UploadFileProto.UploadFileRequest.Builder builder = UploadFileProto.UploadFileRequest.newBuilder(); builder.setName(Paths.get(localFile).getFileName().toString()); ... }
Next, we need to actually upload the file, using a library call that takes in the request, the folder path to store it in, and the stream pointing to the file data.
public void uploadFile(String localFile, String remoteFolder) throws Exception { FileInputStream stream = new FileInputStream(localFile); UploadFileProto.UploadFileRequest.Builder builder = UploadFileProto.UploadFileRequest.newBuilder(); builder.setName(Paths.get(localFile).getFileName().toString()); _delegation.postFile(remoteFolder, builder.build(), stream); ... }
Finally, we’re going to want to close that stream.
public void uploadFile(String localFile, String remoteFolder) throws Exception { FileInputStream stream = new FileInputStream(localFile); UploadFileProto.UploadFileRequest.Builder builder = UploadFileProto.UploadFileRequest.newBuilder(); builder.setName(Paths.get(localFile).getFileName().toString()); _delegation.postFile(remoteFolder, builder.build(), stream); stream.close(); }
Trying It Out
Setting Up
Now that we’ve got a nice wrapper class to handle some basic operations, let’s try it out! We’re going to make a simple console program that uploads a file to SmartVault.
Let’s start with a simple main method.
public static void main(String[] args) { ... }
Authenticating
Include the authenticate method you created using the Autonomous Authentication tutorial.
public static void main(String[] args) { try { SmartVault smartVault = new SmartVault(); authenticate(smartVault); } catch (Exception e) { e.printStackTrace(); } }
Uploading a File
Before we can upload a file, we need two pieces of information: the path to the file on the local system, and the path in SmartVault where the file needs to be stored. Let’s call a new method called getLocalFile to get the local file path from the user.
public static void main(String[] args) { try { SmartVault smartVault = new SmartVault(); authenticate(smartVault); String localFile = getLocalFile(); ... } catch (Exception e) { e.printStackTrace(); } }
Now let’s implement the getLocalFile method. This will ask the user to input a file from the console.
private static String getLocalFile() { System.out.print("\nEnter the path to a file to upload. " + "(Hint: drag a file to the console window): "); String localFile = keyboard.nextLine(); return localFile.replace("\"", ""); // Remove quotes, if supplied }
Let’s go back to our main method and call a new method called getRemoteFolder to determine where to store the file in SmartVault.
public static void main(String[] args) { try { SmartVault smartVault = new SmartVault(); authenticate(smartVault); String localFile = getLocalFile(); String remoteFolder = getRemoteFolder(smartVault); ... } catch (Exception e) { e.printStackTrace(); } }
Now let’s implement getRemoteFolder. SmartVault automatically creates an account for the user on signup containing a vault called My First Vault and a folder called My First folder. For this tutorial, let’s assume that we’re going to upload the file to My First folder. If you have changed the name of this vault or folder in your account, you’ll probably want to update them here to match.
This still doesn’t give us the account name, which is randomly generated on signup. But we can use our browsePath method to retrieve it.
private static String getRemoteFolder(SmartVault smartVault) throws Exception { NodeProto.NodeResponse rootNode = smartVault.browsePath("nodes/pth"); String account = rootNode.getMessage().getChildrenList().get(0).getName(); return String.format("/nodes/pth/%s/My First Vault/My First folder", account); }
Finally, we can actually upload the file using the uploadFile method we created earlier. Let’s do this in the main method.
public static void main(String[] args) { try { SmartVault smartVault = new SmartVault(); authenticate(smartVault); String localFile = getLocalFile(); String remoteFolder = getRemoteFolder(smartVault); System.out.println(String.format("\nUploading '%s' to '%s'", localFile, remoteFolder)); smartVault.uploadFile(localFile, remoteFolder); System.out.println("\nUpload complete"); } catch (Exception e) { e.printStackTrace(); } }
Finishing It Up
Let’s go ahead and add a prompt to have the user press the enter key to exit to prevent the console application from quitting so we can see the of end of the program’s output.
public static void main(String[] args) { try { SmartVault smartVault = new SmartVault(); authenticate(smartVault); String localFile = getLocalFile(); String remoteFolder = getRemoteFolder(smartVault); System.out.println(String.format("\nUploading '%s' to '%s'", localFile, remoteFolder)); smartVault.uploadFile(localFile, remoteFolder); System.out.println("\nUpload complete"); } 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); } public NodeProto.NodeResponse browsePath(String path) throws Exception { int children = 1; // Immediate contents only return _delegation.navigate(path, children); } public void uploadFile(String localFile, String remoteFolder) throws Exception { FileInputStream stream = new FileInputStream(localFile); UploadFileProto.UploadFileRequest.Builder builder = UploadFileProto.UploadFileRequest.newBuilder(); builder.setName(Paths.get(localFile).getFileName().toString()); _delegation.postFile(remoteFolder, builder.build(), stream); stream.close(); } }
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); String localFile = getLocalFile(); String remoteFolder = getRemoteFolder(smartVault); System.out.println(String.format("\nUploading '%s' to '%s'", localFile, remoteFolder)); smartVault.uploadFile(localFile, remoteFolder); System.out.println("\nUpload complete"); } 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); } private static String getLocalFile() { System.out.print("\nEnter the path to a file to upload. " + "(Hint: drag a file to the console window): "); String localFile = keyboard.nextLine(); return localFile.replace("\"", ""); // Remove quotes, if supplied } private static String getRemoteFolder(SmartVault smartVault) throws Exception { NodeProto.NodeResponse rootNode = smartVault.browsePath("nodes/pth"); String account = rootNode.getMessage().getChildrenList().get(0).getName(); return String.format("/nodes/pth/%s/My First Vault/My First folder", account); } }
Here’s What You’ll Need
We will be uploading files using pin-based authentication for this tutorial. Visit Pin-Based Authentication for the tutorial on performing pin-based authentication.
If you have not yet created a developer account or client ID, visit Creating a Developer Account.
Setting Up
You will also need to install the C# API wrapper library, begin communicating with SmartVault, and create a method to handle pin-based authentication. The following tutorial will guide you through this process:
Pin-Based Authentication
Browsing the Folder Structure
A very common task in SmartVault is browsing the folder structure. For generic integrations, this is done using the /nodes/pth structure. The root of this structure contains the user’s accounts. Accounts contain vaults, and vaults contain folders. Folders are where files are typically stored.
Let’s create a method called BrowsePath to implement browsing this structure in a simplified way. This method will take in a path to browse and output the response. The variable children controls how deep in the structure we want to traverse on each call. Setting this to 1 will make the response contain the immediate contents of the path retrieved.
public NodeResponse BrowsePath(string path) { int children = 1; // Immediate contents only return _delegation.Navigate(new AbsolutePath(path), children); }
Uploading Files
Let’s create a method called UploadFile to handle uploading files from the local computer to SmartVault. This method can take in a string containing the path to the file on the local machine, and the path to folder in SmartVault where we want to store it.
public void UploadFile(string localFile, string remoteFolder) { ... }
The first step with uploading a file is creating a Stream pointing to the file on the local computer. This stream will be read by the library and used to transmit the file’s data to SmartVault.
public void UploadFile(string localFile, string remoteFolder) { FileStream stream = new FileStream(localFile, FileMode.Open); ... }
Now we need to build an UploadFileRequest in order to upload the file. This contains the file’s metadata, including the file name in SmartVault. For this example, we will use the same filename as used for the original file on the local computer.
public void UploadFile(string localFile, string remoteFolder) { FileStream stream = new FileStream(localFile, FileMode.Open); UploadFileRequest.Builder builder = UploadFileRequest.CreateBuilder(); builder.Name = Path.GetFileName(localFile); ... }
Next, we need to actually upload the file, using a library call that takes in the request, the folder path to store it in, and the stream pointing to the file data.
public void UploadFile(string localFile, string remoteFolder) { FileStream stream = new FileStream(localFile, FileMode.Open); UploadFileRequest.Builder builder = UploadFileRequest.CreateBuilder(); builder.Name = Path.GetFileName(localFile); _delegation.PostFile(new AbsolutePath(remoteFolder), builder.Build(), stream); ... }
Finally, we’re going to want to close that stream.
public void UploadFile(string localFile, string remoteFolder) { FileStream stream = new FileStream(localFile, FileMode.Open); UploadFileRequest.Builder builder = UploadFileRequest.CreateBuilder(); builder.Name = Path.GetFileName(localFile); _delegation.PostFile(new AbsolutePath(remoteFolder), builder.Build(), stream); stream.Close(); }
Trying It Out
Setting Up
Now that we’ve got a nice wrapper class to handle some basic operations, let’s try it out! We’re going to make a simple console program that uploads a file to SmartVault.
Let’s start with a simple Main method.
class Program { static void Main(string[] args) { ... } }
Authenticating
Include the Authenticate method you created using the Pin-Based Authentication tutorial.
static void Main(string[] args) { try { SmartVault smartVault = new SmartVault(); Authenticate(smartVault); ... } catch (Exception e) { Console.WriteLine(e.Message); } }
Uploading a File
Before we can upload a file, we need two pieces of information: the path to the file on the local system, and the path in SmartVault where the file needs to be stored. Let’s call a new method called GetLocalFile to get the local file path from the user.
static void Main(string[] args) { try { SmartVault smartVault = new SmartVault(); Authenticate(smartVault); string localFile = GetLocalFile(); ... } catch (Exception e) { Console.WriteLine(e.Message); } }
Now let’s implement the GetLocalFile method. This will ask the user to input a file from the console.
private static string GetLocalFile() { Console.Write("\nEnter the path to a file to upload. " + "(Hint: drag a file to the console window): "); string localFile = Console.ReadLine(); return localFile.Replace("\"", ""); // Remove quotes, if supplied }
Let’s go back to our Main method and call a new method called GetRemoteFolder to determine where to store the file in SmartVault.
static void Main(string[] args) { try { SmartVault smartVault = new SmartVault(); Authenticate(smartVault); string localFile = GetLocalFile(); string remoteFolder = GetRemoteFolder(smartVault); ... } catch (Exception e) { Console.WriteLine(e.Message); } }
Now let’s implement GetRemoteFolder. SmartVault automatically creates an account for the user on signup containing a vault called My First Vault and a folder called My First folder. For this tutorial, let’s assume that we’re going to upload the file to My First folder. If you have changed the name of this vault or folder in your account, you’ll probably want to update them here to match.
This still doesn’t give us the account name, which is randomly generated on signup. But we can use our BrowsePath method to retrieve it.
private static string GetRemoteFolder(SmartVault smartVault) { var rootNode = smartVault.BrowsePath("/nodes/pth"); string account = rootNode.Message.ChildrenList[0].Name; return String.Format("/nodes/pth/{0}/My First Vault/My First folder", account); }
Finally, we can actually upload the file using the UploadFile method we created earlier. Let’s do this in the Main method.
static void Main(string[] args) { try { SmartVault smartVault = new SmartVault(); Authenticate(smartVault); string localFile = GetLocalFile(); string remoteFolder = GetRemoteFolder(smartVault); Console.WriteLine("\nUploading '{0}' to '{1}'", localFile, remoteFolder); smartVault.UploadFile(localFile, remoteFolder); Console.WriteLine("\nUpload complete"); ... } catch (Exception e) { Console.WriteLine(e.Message); } }
Finishing It Up
Let’s go ahead and add a prompt to have the user press the enter key to exit to prevent the console application from quitting so we can see the of end of the program’s output.
static void Main(string[] args) { try { SmartVault smartVault = new SmartVault(); Authenticate(smartVault); string localFile = GetLocalFile(); string remoteFolder = GetRemoteFolder(smartVault); Console.WriteLine("\nUploading '{0}' to '{1}'", localFile, remoteFolder); smartVault.UploadFile(localFile, remoteFolder); Console.WriteLine("\nUpload complete"); } 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 PublicClientProtocol _protocol; private DelegatedProtocol _delegation; public SmartVault() { string clientId = "CSharpTutorial"; // Change this to your client ID PublicClientCfg cfg = new PublicClientCfg(new Uri("https://rest.smartvault.com"), clientId); _protocol = new PublicClientProtocol(cfg); } public string RequestPin(string email) { return _protocol.GetPinRequestEndpoint(email); } public void Authenticate(string email, string pin) { _delegation = _protocol.CreateDelegatedProtocol(email, pin); } public NodeResponse BrowsePath(string path) { int children = 1; // Immediate contents only return _delegation.Navigate(new AbsolutePath(path), children); } public void UploadFile(string localFile, string remoteFolder) { FileStream stream = new FileStream(localFile, FileMode.Open); UploadFileRequest.Builder builder = UploadFileRequest.CreateBuilder(); builder.Name = Path.GetFileName(localFile); _delegation.PostFile(new AbsolutePath(remoteFolder), builder.Build(), stream); stream.Close(); } } }
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); string localFile = GetLocalFile(); string remoteFolder = GetRemoteFolder(smartVault); Console.WriteLine("\nUploading '{0}' to '{1}'", localFile, remoteFolder); smartVault.UploadFile(localFile, remoteFolder); Console.WriteLine("\nUpload complete"); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("\nPress any key to exit"); Console.ReadKey(); } private static void Authenticate(SmartVault smartVault) { // Pin-based authentication with manual pin entry Console.Write("Enter your email address: "); string email = Console.ReadLine(); Console.Write("Do you have a pin? [y/n]: "); string response = Console.ReadLine(); if (!response.ToLower().StartsWith("y")) { string url = smartVault.RequestPin(email); Process.Start(url); } Console.Write("Enter your pin: "); string pin = Console.ReadLine(); smartVault.Authenticate(email, pin); } private static string GetLocalFile() { Console.Write("\nEnter the path to a file to upload. " + "(Hint: drag a file to the console window): "); string localFile = Console.ReadLine(); return localFile.Replace("\"", ""); // Remove quotes, if supplied } private static string GetRemoteFolder(SmartVault smartVault) { var rootNode = smartVault.BrowsePath("/nodes/pth"); string account = rootNode.Message.ChildrenList[0].Name; return String.Format("/nodes/pth/{0}/My First Vault/My First folder", account); } } }
Web Application with ASP.NET MVC4 Using C#
Here’s What You’ll Need
If you have not yet created a developer account or client ID, visit Creating a Developer Account.(For OAuth Support, select User PIN 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 in the Models folder to handle communication with the SmartVault API. We will need to include the SmartVault library:
using SmartVault.Core; using SmartVault.Proto; using SmartVault.Rest; class SmartVault { . . . }
Opening the Connection
Let’s add three instance variables to our class to handle communication with SmartVault:
private PublicClientCfg _clientCfg; private PublicClientProtocol _protocol; private DelegatedProtocol _delegation;
The _clientCfg object created here will be used to store the connection information with SmartVault. The _protocol object will handle tasks on behalf of the client. In our case, this will be used to get the authorization URL. 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 _clientCfg and _protocol objects:
public SmartVault() { string clientId = "CSharpTutorial"; // Change this to your client ID _clientCfg = new PublicClientCfg(new Uri("https://rest.smartvault.com"), clientId); _protocol = new PublicClientProtocol(_clientCfg); }
NOTE: You will need to change the Client ID to the one you registered earlier using the SmartVault Portal.
Authentication
For this tutorial, we’re going to be using pin-based authentication with a callback. The way that this works is that the user will need to be directed to the SmartVault Portal to authorize our application. Once the user does this, he or she will be redirected back to our application. This callback includes the delegation token that we will use to authenticate all the user’s actions.
Requesting a pin
The SmartVault API has a call to get a URL from the server for the user to visit in order to authorize an application. We will need the user’s email address in order to do this.
Let’s start by creating a method called RequestPin 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 RequestPin:
public string RequestPin(string email) { return _protocol.GetPinRequestEndpoint(email); }
Authenticating with SmartVault
Once we have the delegation token, we can use it along with their email address to actually authenticate. Let’s create a method called AuthenticateWithToken to take care of this.
public void AuthenticateWithToken(string email, string token) { _delegation = _protocol.CreateDelegatedProtocol(email, pin); }
Using the email address and token, we will need to build a DelegationTokenResponse object that contains this information.
public void AuthenticateWithToken(string email, string token) { DelegationTokenResponse.Types.Message.Builder messageBuilder = new DelegationTokenResponse.Types.Message.Builder(); messageBuilder.SetToken(token); messageBuilder.SetUserEmail(email); DelegationTokenResponse.Builder responseBuilder = new DelegationTokenResponse.Builder(); responseBuilder.SetMessage(messageBuilder.Build()); . . . }
From there, we can create a UserCfg object containing all information to connect with SmartVault and authenticate as our user. We can now initialize the _delegation object to perform all the actions as this user.
public void AuthenticateWithToken(string email, string token) { DelegationTokenResponse.Types.Message.Builder messageBuilder = new DelegationTokenResponse.Types.Message.Builder(); messageBuilder.SetToken(token); messageBuilder.SetUserEmail(email); DelegationTokenResponse.Builder responseBuilder = new DelegationTokenResponse.Builder(); responseBuilder.SetMessage(messageBuilder.Build()); UserCfg cfg = new UserCfg(email, responseBuilder.Build(), _clientCfg); _delegation = new DelegatedProtocol(cfg); }
Browsing the Folder Structure
A very common task in SmartVault is browsing the folder structure. For generic integrations, this is done using the /nodes/pth structure. The root of this structure contains the user’s accounts. Accounts contain vaults, and vaults contain folders. Folders are where files are typically stored.
Let’s create a method called BrowsePath to implement browsing this structure in a simplified way. This method will take in a path to browse and output the response. The variable children controls how deep in the structure we want to traverse on each call. Setting this to 1 will make the response contain the immediate contents of the path retrieved.
public NodeResponse BrowsePath(string path) { int children = 1; // Immediate contents only return _delegation.Navigate(new AbsolutePath(path), children); }
Uploading Files
Let’s create a method called UploadFile to handle uploading files from the local computer to SmartVault. We will need three pieces of information to be able to upoad a file: a stream containing the file’s data, the path to a remote folder to put it in, and the filename as which we want to store it.
public void UploadFile(Stream fileData, string remoteFolder, string fileName) { . . . }
The first step with loading a file is building an UploadFileRequest. This contains the file’s metadata including the filename in SmartVault.
public void UploadFile(Stream fileData, string remoteFolder, string fileName) { UploadFileRequest.Builder builder = UploadFileRequest.CreateBuilder(); builder.Name = fileName; . . . }
Next, we need to actually upload the file using a library call that takes in the request, the folder path to store it in, and the stream pointing to the file data.
public void UploadFile(Stream fileData, string remoteFolder, string fileName) { UploadFileRequest.Builder builder = UploadFileRequest.CreateBuilder(); builder.Name = fileName; _delegation.PostFile(new AbsolutePath(remoteFolder), builder.Build(), fileData); . . . }
Finally, we’re going to want to close that stream.
public void UploadFile(Stream fileData, string remoteFolder, string fileName) { UploadFileRequest.Builder builder = UploadFileRequest.CreateBuilder(); builder.Name = fileName; _delegation.PostFile(new AbsolutePath(remoteFolder), builder.Build(), fileData); fileData.Close(); }
Trying It Out
Authorization
Now that we’ve got a nice wrapper class to handle some basic operations, let’s try it out! We’re going to make a very basic website that performs authentication.
Let’s create a Home view to get the user’s email address so they can authorize our application. This will contain a webpage called Index.cshtml.
Our webpage will have a field for the user to enter their email address, which will be passed to the controller as a string.
@model stringWelcome Welcome!
@using (Html.BeginForm()) { @Html.ValidationSummary(true) Enter your email address: @Html.EditorForModel(Model, "email") }
Now we’ll need a controller to actually make this do something. Let’s create one called HomeController.
public class HomeController : Controller { . . . }
We’ll need a method called Index, which will simply display our page.
public ActionResult Index() { return View(); }
Next we’ll need another method to handle the POST request from our page. This will take in the string containing the user’s email address.
[HttpPost] public ActionResult Index(string email) { . . . }
Now let’s use create an instance of the SmartVault model. We’re going to store the model in the session data so that we can reference it from other pages.
[HttpPost] public ActionResult Index(string email) { Models.SmartVault smartVault = new Models.SmartVault(); Session["smartVault"] = smartVault; . . . }
Next, we can use the SmartVault model to get the URL to authorize our application.
[HttpPost] public ActionResult Index(string email) { Models.SmartVault smartVault = new Models.SmartVault(); Session["smartVault"] = smartVault; string url = smartVault.RequestPin(email); . . . }
We’ll need to register our callback. This is done by tacking on a new parameter to the URL called redirect_uri. Once the user has authorized our application, SmartVault will redirect the user to this URL with a GET request. The request will contain parameters containing the user’s delegation token.
Let’s have SmartVault redirect the user to the URL in our application called Auth to handle the authentication.
[HttpPost] public ActionResult Index(string email) { Models.SmartVault smartVault = new Models.SmartVault(); Session["smartVault"] = smartVault; string url = smartVault.RequestPin(email); url += String.Format("&redirect_uri={0}/Auth", Request.Url.GetLeftPart(UriPartial.Authority)); . . . }
Finally, we can redirect the user to SmartVault to do the authorization.
[HttpPost] public ActionResult Index(string email) { Models.SmartVault smartVault = new Models.SmartVault(); Session["smartVault"] = smartVault; string url = smartVault.RequestPin(email); url += String.Format("&redirect_uri={0}/Auth", Request.Url.GetLeftPart(UriPartial.Authority)); return new RedirectResult(url); }
Authentication
Because of the callback we set up, SmartVault will redirect the user to the path /Auth in our application. Let’s create a controller called AuthController to handle this request and authenticate our user.
public class AuthController : Controller { . . . }
Let’s create an Index method that takes in the two parameters that SmartVault will return to us: access_token and email.
public ActionResult Index(string access_token, string email) { . . . }
Let’s get our SmartVault object we created earlier from the session data, and use the AuthenticateWithToken method that we created to authenticate.
public ActionResult Index(string access_token, string email) { Models.SmartVault smartVault = (Models.SmartVault)Session["smartVault"]; smartVault.AuthenticateWithToken(email, access_token); . . . }
Finally, let’s redirect the user to a new page at the path /UploadFile from which they will be able to upload a file.
public ActionResult Index(string access_token, string email) { Models.SmartVault smartVault = (Models.SmartVault)Session["smartVault"]; smartVault.AuthenticateWithToken(email, access_token); return Redirect("/UploadFile"); }
Uploading a File
Let’s create an UploadFile view to allow the user to upload a file. This will contain a webpage called Index.cshtml.
Index.cshtml will simply contain a form to allow the user to upload a file. Let’s also add a message that tells the user whether the upload was successful or not.
Upload File Upload File
@FileUpload.GetHtml( initialNumberOfFiles:1, allowMoreFilesToBeAdded:false, includeFormTag:true, uploadText:"Upload") @if (TempData["message"] != null) {@TempData["message"].ToString()} @if (TempData["message"] == null) {Error uploading file}
Now we need to create a controller class called UploadFileController to make this do something.
public class UploadFileController : Controller { ... }
Let’s add a method called Index to display our page and let the page now if the upload was a success.
public ActionResult Index() { . . . }
We will be passing a message to the view in order to determine whether the upload was a success. To do this, let’s create an instance of MyViewModel to save the success message.
public ActionResult Index() { MyViewModel model = new MyViewModel { Message = TempData["message"] as string, }; . . . }
We’ll need to implement the MyViewModel.
public class MyViewModel { public string Message { get; set; } }
Now we’re ready to display the page. We’ll need to pass the model in order to send the success status to the view.
public ActionResult Index() { MyViewModel model = new MyViewModel { Message = TempData["message"] as string, }; return View(model); }
Now we need to add a method to handle the POST request from our page.
[HttpPost] public ActionResult Index(int? id) { ... }
Next, we will need to get the file out of the request that the user sent us.
[HttpPost] public ActionResult Index(int? id) { Models.SmartVault smartVault = (Models.SmartVault)Session["smartVault"]; HttpPostedFileBase uploadedFile = Request.Files[0]; . . . }
If the request is not null, let’s use the SmartVault object to upload the file to SmartVault. Notice UploadFile uses a method called GetRemoteFolder that retrieves the path to a folder in which to store our file in SmartVault.
[HttpPost] public ActionResult Index(int? id) { Models.SmartVault smartVault = (Models.SmartVault)Session["smartVault"]; HttpPostedFileBase uploadedFile = Request.Files[0]; if (uploadedFile != null) { smartVault.UploadFile(uploadedFile.InputStream, GetRemoteFolder(smartVault), uploadedFile.FileName); . . . } }
Let’s implement GetRemoteFolder. SmartVault automatically creates an account for the user on signup containing a vault called My First Vault and a folder called My First folder. For this tutorial, let’s assume that we’re going to upload the file to My First folder. If you have changed the name of this vault or folder in your account, you’ll probably want to update them here to match.
This still doesn’t give us the account name, which is randomly generated on signup. But we can use our BrowsePath method to retrieve it.
public string GetRemoteFolder(Models.SmartVault smartVault)
{
var rootNode = smartVault.BrowsePath(“/nodes/pth”);
string account = rootNode.Message.ChildrenList[0].Name;
return String.Format(“/nodes/pth/{0}/My First Vault/My First folder”, account);
}
Now let’s store the entire path to the file in SmartVault in the session data and create a success message.
[HttpPost] public ActionResult Index(int? id) { Models.SmartVault smartVault = (Models.SmartVault)Session["smartVault"]; HttpPostedFileBase uploadedFile = Request.Files[0]; if (uploadedFile != null) { smartVault.UploadFile(uploadedFile.InputStream, GetRemoteFolder(smartVault), uploadedFile.FileName); Session["remoteFile"] = GetRemoteFolder(smartVault) + "/" + uploadedFile.FileName; TempData["message"] = "File uploaded successfully."; . . . } }
Finally, let’s redirect the user to a new page from which they can download their file. Also remember to set the message as null in the case that the request was empty.
[HttpPost] public ActionResult Index(int? id) { Models.SmartVault smartVault = (Models.SmartVault)Session["smartVault"]; HttpPostedFileBase uploadedFile = Request.Files[0]; if (uploadedFile != null) { smartVault.UploadFile(uploadedFile.InputStream, GetRemoteFolder(smartVault), uploadedFile.FileName); Session["remoteFile"] = GetRemoteFolder(smartVault) + "/" + uploadedFile.FileName; TempData["message"] = "File uploaded successfully."; return RedirectToAction("index"); } TempData["message"] = null; return RedirectToAction("index"); }
Putting It Together
Home View – Index.cshtml
@model stringWelcome Welcome!
@using (Html.BeginForm()) { @Html.ValidationSummary(true) Enter your email address: @Html.EditorForModel(Model, "email") }
Upload File View – Index.cshtml
Upload File Upload File
@FileUpload.GetHtml( initialNumberOfFiles:1, allowMoreFilesToBeAdded:false, includeFormTag:true, uploadText:"Upload") @if (TempData["message"] != null) {@TempData["message"].ToString()} @if (TempData["message"] == null) {Error uploading file}
SmartVault.cs
using System; using SmartVault.Core; using SmartVault.Proto; using SmartVault.Rest; using System.IO; namespace ASPNET_MVC_HelloWorldSVRest.Models { public class SmartVault { private readonly PublicClientProtocol _protocol; private DelegatedProtocol _delegation; private readonly PublicClientCfg _clientCfg; public SmartVault() { const string clientId = "CSharpTutorial"; // Change this to your client ID _clientCfg = new PublicClientCfg(new Uri("https://rest.smartvault.com"), clientId); _protocol = new PublicClientProtocol(_clientCfg); } public string RequestPin(string email) { return _protocol.GetPinRequestEndpoint(email); } public void AuthenticateWithToken(string email, string token) { DelegationTokenResponse.Types.Message.Builder messageBuilder = new DelegationTokenResponse.Types.Message.Builder(); messageBuilder.SetToken(token); messageBuilder.SetUserEmail(email); DelegationTokenResponse.Builder responseBuilder = new DelegationTokenResponse.Builder(); responseBuilder.SetMessage(messageBuilder.Build()); UserCfg cfg = new UserCfg(email, responseBuilder.Build(), _clientCfg); _delegation = new DelegatedProtocol(cfg); } public NodeResponse BrowsePath(string path) { const int children = 1; // Immediate contents only return _delegation.Navigate(new AbsolutePath(path), children); } public void UploadFile(Stream localFile, string remoteFolder, string fileName) { UploadFileRequest.Builder builder = UploadFileRequest.CreateBuilder(); builder.Name = fileName; _delegation.PostFile(new AbsolutePath(remoteFolder), builder.Build(), localFile); localFile.Close(); } public string GetDownloadLink(string remoteFile) { NodeResponse fileNode = BrowsePath(remoteFile); return fileNode.Message.DownloadLinkUri; } } }
HomeController.cs
using System; using System.Web.Mvc; namespace ASPNET_MVC_HelloWorldSVRest.Controllers { public class HomeController : Controller { // // GET: /Home/ public ActionResult Index() { return View(); } [HttpPost] public ActionResult Index(string email) { Models.SmartVault smartVault = new Models.SmartVault(); string url = smartVault.RequestPin(email); if (Request.Url != null) { url += String.Format("&redirect_uri={0}/Auth", Request.Url.GetLeftPart(UriPartial.Authority)); } Session["smartVault"] = smartVault; return new RedirectResult(url); } } }
AuthController.cs
using System.Web.Mvc; namespace ASPNET_MVC_HelloWorldSVRest.Controllers { public class AuthController : Controller { // // GET: /Auth/ public ActionResult Index(string access_token, string email) { Models.SmartVault smartVault = (Models.SmartVault)Session["smartVault"]; smartVault.AuthenticateWithToken(email, access_token); return Redirect("/UploadFile"); } } }
UploadFileController.cs
using System; using System.Web; using System.Web.Mvc; namespace ASPNET_MVC_HelloWorldSVRest.Controllers { public class UploadFileController : Controller { // // GET: /UploadFile/ public class MyViewModel { public string Message { get; set; } } public ActionResult Index() { MyViewModel model = new MyViewModel { Message = TempData["message"] as string, }; return View(model); } [HttpPost] public ActionResult Index(int? id) { Models.SmartVault smartVault = (Models.SmartVault)Session["smartVault"]; HttpPostedFileBase uploadedFile = Request.Files[0]; if (uploadedFile != null) { smartVault.UploadFile(uploadedFile.InputStream, GetRemoteFolder(smartVault), uploadedFile.FileName); Session["remoteFile"] = GetRemoteFolder(smartVault) + "/" + uploadedFile.FileName; TempData["message"] = "File uploaded successfully."; return RedirectToAction("index"); } TempData["message"] = null; return RedirectToAction("index"); } public string GetRemoteFolder(Models.SmartVault smartVault) { var rootNode = smartVault.BrowsePath("/nodes/pth"); string account = rootNode.Message.ChildrenList[0].Name; return String.Format("/nodes/pth/{0}/My First Vault/My First folder", account); } } }
Leave A Comment?