How to: Use the Secure Store Service from within a .NET Connectivity Assembly

Applies to: SharePoint Server 2010

In this article
No-Code Approach to Using Secure Store in a .NET Connectivity Assembly
Code Approach to Using Secure Store in a .NET Connectivity Assembly
Summary

Database, web service, and Windows Communication Foundation (WCF) service connectors all use only one external system. Microsoft Business Connectivity Services (BCS) can connect to these external systems and natively supports Secure Store integration for these connectors. However, for a Microsoft .NET Framework assembly connector, the .NET assembly code can use zero, one, or many external systems. Because Business Connectivity Services cannot determine what the .NET assembly code does, it does not support Secure Store integration natively for the .NET assembly connector. However, Business Connectivity Services provides two different mechanisms to use the Secure Store within a .NET connectivity assembly.

In the first mechanism (no-code approach), Business Connectivity Services performs the necessary operations to read the credentials from the Secure Store. In the second mechanism (code approach), the .NET connectivity assembly performs the necessary operations. This topic describes both mechanisms.

No-Code Approach to Using Secure Store in a .NET Connectivity Assembly

As the name suggests, your .NET connectivity assembly does not directly interact with the Secure Store. Through filters, it can use Business Connectivity Services to read the credentials from the Secure Store and get the credentials as input parameters to the method. This approach is not unique to the .NET assembly connector and can be used with database connectors, Web service connectors, and WCF connectors.

When writing the method in the .NET connectivity assembly, you must have input parameters for the credentials. The following example shows the GetEntity method with input parameters for username and password and other parameters.

public SampleEntity GetEntity(string username, string password, int id)
{ 
    // Parameters username and password 
    // contain the credentials.
}

To get the credentials in the username and password parameters, you must use the UsernameFilter and PasswordFilter filters. In the metadata model, you must define the SecondarySsoApplicationId and SsoProviderImplementation properties for the LobSystemInstance and associate the filters to appropriate input parameters of the method. When Business Connectivity Services encounters filters, it uses the SecondarySsoApplicationId and SsoProviderImplementation properties for the Secure Store target application ID and Secure Store provider, respectively.

<LobSystemInstance ...> 
  <Properties> 
    <!-- Other properties omitted. –> 
    <Property Name="SecondarySsoApplicationId" 
        Type="System.String">MyLobAppId</Property> 
    <Property Name="SsoProviderImplementation" Type="System.String"> 
        Microsoft.Office.SecureStoreService.Server.SecureStoreProvider, Microsoft.Office.SecureStoreService, 
        Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Property> 
  </Properties> 
</LobSystemInstance> 

Now let us define the two filters for the method.

<Method Name="GetEntity"> 
  <FilterDescriptors> 
    <FilterDescriptor Type="Username" Name="UserNameFilter"/> 
    <FilterDescriptor Type="Password" Name="PasswordFilter"/> 
  </FilterDescriptors> 
</Method>

Now that the filters defined for the method, the following example shows how to associate the two filters to the input parameters of the method.

<Parameter Direction="In" Name="username">  
    <TypeDescriptor TypeName="System.String" Name="username" 
        AssociatedFilter="UserNameFilter"/> 
</Parameter> 
<Parameter Direction="In" Name="password">  
    <TypeDescriptor TypeName="System.String" Name="password" 
        AssociatedFilter="PasswordFilter"/> 
</Parameter>

This is all you need to use Secure Store in .NET connectivity assembly. When Business Connectivity Services executes the method, it reads the credentials from the Secure Store and sets the credentials in the input parameters of the method.

Code Approach to Using Secure Store in a .NET Connectivity Assembly

Before writing code for using the Secure Store, you should understand how Business Connectivity Services uses the Secure Store in other connectors. In Business Connectivity Services, other connectors rely on the metadata model for the information they require about the Secure Store and the target application ID. The connectors use this information to retrieve credentials for authenticating with the external system. For example, for the database connector, the properties for LobSystemInstance in the metadata model appear as shown in the following example.

<LobSystemInstance ...> 
  <Properties> 
    <!-- Other properties omitted. –> 
    <Property Name="SsoApplicationId" 
        Type="System.String">MyLobAppId</Property> 
    <Property Name="SsoProviderImplementation" Type="System.String"> Microsoft.Office.SecureStoreService.Server.SecureStoreProvider, Microsoft.Office.SecureStoreService, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Property> 
  </Properties> 
</LobSystemInstance>

The database connector reads the metadata model and determines that it requires credentials to connect to the database and the credentials can be obtained from the specified Secure Store provider. After the database connector has the necessary information for the Secure Store provider, it reads the credentials from the provider and impersonates the user for database connection.

The following sections explain how to read the metadata model properties within your .NET assembly code and use the Secure Store APIs to read user credentials.

Reading Metadata Model Properties in the .NET Connectivity Assembly

To read metadata model properties in the .NET connectivity assembly, code in .NET assembly must implement the IContextProperty interface. The following code shows a sample implementation of the IContextProperty interface.

Sample Implementation of IContextProperty

using IContextProperty = Microsoft.BusinessData.SystemSpecific.IContextProperty; 
public class SampleConnector : IContextProperty 
{ 
    private IMethodInstance methodInstance; 
    private ILobSystemInstance lobSystemInstance; 
    private IExecutionContext executionContext;
    #region IContextProperty implementation 
    public IMethodInstance MethodInstance 
    { 
        get { return this.methodInstance; } 
        set { this.methodInstance = value; } 
    }
    public ILobSystemInstance LobSystemInstance 
    { 
        get { return this.lobSystemInstance; } 
        set { this.lobSystemInstance = value; } 
    } 
    public IExecutionContext ExecutionContext 
    { 
        get { return this.executionContext; } 
        set { this.executionContext = value; } 
    } 
        #endregion 
        // Unrelated code removed for brevity. 
} 

When the .NET connectivity assembly class implements the IContextProperty interface, the Business Connectivity Services runtime automatically initializes IContextProperty properties.

At runtime, the code has the context (method instance and LobSystem Instance) in which it executes; a method that is implemented in the code can read the properties from the metadata model. The following code shows how LobSystemInstance properties are read.

public SampleEntity GetEntity(int id) 
{ 
    // Read the LobSystemInstance property defined in the metadata model. 
    string provider =  
        LobSystemInstance.GetProperties()["ssoProviderImplementation"] 
        as string; 
    // Unrelated code removed for brevity. 
} 

Interacting with the Secure Store Service

When the .NET connectivity assembly requires reading one credential from the Secure Store, use the following property names.

  • ssoProviderImplementation   Secure Store provider

  • SecondarySsoApplicationId   Target application for the Secure Store

The ssoProviderImplementation and SecondarySsoApplicationId properties are supported for modeling .NET assembly connector models in Microsoft SharePoint Designer 2010. If the .NET connectivity assembly requires reading more than one credential from the Secure Store, choose a property name that makes the most sense for your scenario.

Sample Implementation for Reading Credentials from the Secure Store

The first step is to instantiate the Secure Store provider from the provider implementation. In your code, ensure that the provider implements the ISecureStoreProvider interface. The following example shows a simple implementation for instantiating the Secure Store provider.

private ISecureStoreProvider GetSecureStoreProvider() 
{
    // Error checking removed for brevity.
string provider = this.LobSystemInstance.GetProperties()  
    ["ssoProviderImplementation"] as string; 
Type providerType = Type.GetType(provider); 
return Activator.CreateInstance(providerType)  
    as ISecureStoreProvider;
} 

After the Secure Store provider is instantiated, get the credentials from the Secure Store. The Secure Store returns a SecureStoreCredentialCollection for the user and a target ID, which contains a collection of credentials. The ISecureStoreCredential interface defines the credentials type and value.

The following example shows how the credentials are read from the Secure Store. These credentials can be used for authentication to an external system.

private void ReadCredentialsFromSecureStore() 
{ 
    // Error checking removed for brevity. 
    string targetId = 
        LobSystemInstance.GetProperties()["SecondarySsoApplicationId"]  
        as string; 
    ISecureStoreProvider provider = GetSecureStoreProvider();
    // Get the credentials for the user on whose behalf the code 
    // is executing. 
    using(SecureStoreCredentialCollection credentials =      
        provider.GetRestrictedCredentials(targetId)) 
    { 
        SecureString secureUsername; 
        SecureString securePassword; 
         // Look for username and password in credentials. 
        foreach (ISecureStoreCredential credential in credentials) 
        { 
            switch (credential.CredentialType) 
            { 
                case SecureStoreCredentialType.UserName: 
                case SecureStoreCredentialType.WindowsUserName: 
                    secureUsername = credential.Credential; 
                    break; 
                case SecureStoreCredentialType.Password: 
                case SecureStoreCredentialType.WindowsPassword: 
                    securePassword = credential.Credential; 
                    break; 
                default: 
                    break; 
            } 
        } 
        // Username and password have been read. 
        // Use them as necessary.  
    } 
     // NOTE:  Because we are getting the credentials in the using block,  
    // all the credentials that we get will be disposed after the 
    // using block. If you need to cache the credentials,  do not use 
    // a using block but dispose the credentials when you are done 
     // with them.
} 

Summary

Depending on your scenario, you can choose the no-code approach or the code approach to use the Secure Store in your .NET connectivity assembly. Table 1 summarizes the differences between these two approaches.

Table 1. Summary of differences in no-code and code approaches

Area

No-Code Approach

Code Approach

Interaction with Secure Store API required

No

Yes

Exclusive to .NET assembly connector

No

Yes

SharePoint Designer support

Yes

Partial

Impacts method signature

Yes

No

Read from multiple Secure Stores

No

Yes

Can credentials be set at LobSystemInstance level

No

Yes