Quantcast
Viewing all articles
Browse latest Browse all 10

Storing Connection String Information in the Secure Store Service

As a SharePoint developer, i’ve been tasked a few times with pulling data from an external database into SharePoint. More often than not, that data is secured SQL data and needs to be accessed using a SQL account, which means I’m going to have to access that data using a connection string. Generally that’s a pretty straight forward task, however you must decide where to store the connection string credentials…

Within ASP.NET you generally have a few options:

  • Store the credentials in your code (terrible idea!)
  • Store the credentials in some web.config file
  • Store the credentials in the registry

Honestly I’m not crazy about any of these methods. If I had to choose I would go with the web.config option, however you are still storing the information as plain text, which I don’t like. And I suppose you can encrypt the data somehow, but that just seems like more work than its worth to me.

So then what? Well if you’re using SharePoint 2010 and up, you can actually store your credentials in the Secure Store Service, then programatically access as needed using the SharePoint Object Model. Life changing, I know…so lets get started…

In this example we’ll create a simple Web Part which accesses the stored credentials and displays them within the Web Part. With this proof of concept you would just alter the code so that instead of displaying the credentials, you would put the string values in your connection string, and you’ll be good to go.

The first thing we need to do is create a new Secure Store Target Application. To that follow these steps:

  • Log into SharePoint 2010 Central Administration
  • Click Manage service applications
  • Click Secure Store Service
  • Click New
  • Enter a Target Application ID (some unique identifier which generally contains the name of the target application)
  • Enter a Display Name
  • Enter a Contact Email
  • Set Target Application Type to Group and click Next
  • Change the Field Names so that the word Windows is replaced with SQL (not necessary, just me being nit picky)
  • Change the first Field Type to User Name
  • Change the second Field Type to Password and click Next
  • Add yourself to both Administrators and Members and click OK

The second and final thing we need to do is a little coding. Follow these steps:

  • Fire up Visual Studio and create a new Blank SharePoint Project that is scoped as a Farm level solution
  • Add a reference to Microsoft.BusinessData.dll by browsing to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI (Assuming a standard installation of SharePoint)
  • Add a reference to Microsoft.Office.SecureStoreService.dll by browsing to C:\Windows\assembly\GAC_MSIL\Microsoft.Office.SecureStoreService\14.0.0.0__71e9bce111e9429c
  • Right click the project, go to Add, and select New Item
  • Select Web Part (not Visual Web Part), specify some name, and click Add
  • Add the following Using statements to your Web Part file
  • using Microsoft.SharePoint.Administration;
    using Microsoft.BusinessData.Infrastructure.SecureStore;
    using Microsoft.Office.SecureStoreService.Server;
    using System.Security;
    using System.Runtime.InteropServices;
  • Update your class with the following code:
  • private TextBox tbxAppID;
    private Button btnGetCreds;
    private Label lblUserID, lblPassword;
     
    protected override void CreateChildControls()
    {
        tbxAppID = new TextBox();
        btnGetCreds = new Button();
        btnGetCreds.Text = "Get Credentials";
        btnGetCreds.Click += new EventHandler(btnGetCreds_Click);
        lblUserID = new Label();
        lblPassword = new Label();
        
        this.Controls.Add(tbxAppID);
        this.Controls.Add(btnGetCreds);
        this.Controls.Add(new LiteralControl("<br />"));
        this.Controls.Add(lblUserID);
        this.Controls.Add(new LiteralControl("<br />"));
        this.Controls.Add(lblPassword);
    }
     
    private void btnGetCreds_Click(object sender, EventArgs e)
    {
        try
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                // Get the CA site URI
                SPAdministrationWebApplication adminWebApp = SPAdministrationWebApplication.Local;
                Uri adminSiteUri = adminWebApp.GetResponseUri(SPUrlZone.Default);
     
                /* Using statement to access the Central Administration site */
                using (SPSite site = adminWebApp.Sites[adminSiteUri.AbsoluteUri])
                {
                    // Get the Secure Store Service Context
                    ISecureStoreProvider provider = SecureStoreProviderFactory.Create();
                    ISecureStoreServiceContext providerContext = provider as ISecureStoreServiceContext;
                    providerContext.Context = SPServiceContext.GetContext(site);
     
                    using (SecureStoreCredentialCollection credentials = provider.GetCredentials(tbxAppID.Text))
                    {
                        /* Loop each credential in the current credential collection */
                        foreach (SecureStoreCredential credential in credentials)
                        {
                            if (credential.CredentialType == SecureStoreCredentialType.UserName)
                                lblUserID.Text = String.Format("User ID: {0}", GetStringFromSecureString(credential.Credential));
                            else if (credential.CredentialType == SecureStoreCredentialType.Password)
                                lblPassword.Text = String.Format("Password: {0}", GetStringFromSecureString(credential.Credential));
                        }
                    }
                }
            });
        }
        catch (Exception ex)
        {
            lblUserID.Text = ex.ToString();
        }
    }
     
    private static string GetStringFromSecureString(SecureString secStr)
    {
        if (secStr == null)
        {
            return null;
        }
     
        IntPtr pPlainText = IntPtr.Zero;
        try
        {
            pPlainText = Marshal.SecureStringToBSTR(secStr);
            return Marshal.PtrToStringBSTR(pPlainText);
        }
        finally
        {
            if (pPlainText != IntPtr.Zero)
            {
                Marshal.FreeBSTR(pPlainText);
            }
        }
    }
  • Then just build and deploy your solution

If you look at the code above we’re essentially accessing the Central Admin site, grabbing the Secure Store Context, accessing the SecureStoreCredentialCollection by the ID, looping each credential, decoding the credential, and finally outputting to the Web Part.

So to use the Web Part, just pull up the site you deployed it to, add the Web Part, type in the Target Application ID, and click Get Credentials.

And just like that, you’ll never have to store a connection string in the web.config again when using SharePoint.

References:
http://msdn.microsoft.com/en-us/library/ff394459(v=office.14).aspx

Updates:

1. In this post I am running a chunk of my code with Elevated privileges in order to ensure that users accessing the site will have access to the Secure Store Service. This does assume that the service account associated with the Web Application does have access to manage the Secure Store Target Application that we created.
2. Also, I like the idea of using the Property Bag, so I expect to be posting about that soon. Thanks for the suggestions Mostafa!

The post Storing Connection String Information in the Secure Store Service appeared first on MetroStar Systems Blog.


Viewing all articles
Browse latest Browse all 10

Trending Articles