SharePoint And ADFS: SecurityTokenException – The issuer of the token is not a trusted issuer

This is a pretty common ADFS error, and there are all sorts of reasons that it could happen.

The stack trace will be this:

[code]

Microsoft.SharePoint.IdentityModel.SPTrustedIssuerNameRegistry.GetIssuerName(SecurityToken securityToken)

   at Microsoft.SharePoint.IdentityModel.SPPassiveIssuerNameRegistry.GetIssuerName(SecurityToken securityToken)

   at Microsoft.IdentityModel.Tokens.Saml11.Saml11SecurityTokenHandler.CreateClaims(SamlSecurityToken samlSecurityToken)

   at Microsoft.IdentityModel.Tokens.Saml11.Saml11SecurityTokenHandler.ValidateToken(SecurityToken token)

   at Microsoft.IdentityModel.Web.TokenReceiver.AuthenticateToken(SecurityToken token, Boolean ensureBearerToken, String endpointUri)

   at Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.SignInWithResponseMessage(HttpRequest request)

   at Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs args)

   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()

   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

[/code]

At the end of the day though, don’t sit around and fiddle with the SharePoint trusted authorities and yada yada yada, it boils down to a certificate problem. Basically the one that was specified as the signing certificate, when exported during the ADFS setup, is either malformed (the certificate chain is incomplete) or plainwrong wrong when the trusted issuer was being built up in SharePoint ala powershell. So to get around the error follow two pretty basic steps.

  1. Verify the appropriate certificate chain is present on the SharePoint server in both the trusted root authorities as well as in the SharePoint folder within the Certificate MMC snap-in. Never ever, ever delete the self issued ones that SharePoint provisioned within that folder. You will cause a Micheal Bay-spolosion. To verify the chain, just popup open the certificate details within some interface (like, the MMC :) ) doesn’t really matter what and verify that the chain is trusted and existent.
  2. Next, verify that you actually used the right certificate when specifying the certificate path when building the System.Security.Cryptography.X509Certificates.X509Certificate2 object to pass into your SPTrustedIdentityTokenIssuer. This is pretty easy to mess up when troubleshooting if you are swapping certs all over the place.

Both of these are in place, then that error will go away. Not that another won’t popup :)

Share

Using Telerik RadUpload Control with SharePoint Document Libraries Silverlight

Having examined the RadUpload control now from the ASP.NET perspective in this post, it is time to investigate the other platform of interest, Silverlight. This is a little bit trickier then working with the ASP.NET port of the control since it requires developing a HTTP handler to manage the upload, and, constructing the stream to push into SharePoint requires a temporary location on the server to host the file pre-upload operation into the SharePoint Document Library. So essentially, the file goes from client, to physically on the server, then to SharePoint, with subsequent removal of the file physically off the server. I was not able to build a direct stream successfully without problems, but would be interested if others have explored this route.

From the Silverlight perspective, the handler needs to be explicitly specified when invoking the RadUpload object. In general, the URL itself is constructed ala a configuration value in order to ease environment transitions in a normal ALM cycle. I am going to use a URI object since I am interested in a replacement token to a common WCF directory that contains my ASHX file and I only want the host value. This is useful if you are using the variable throughout the software.

[csharp]
Uri uri = new Uri(You configuration read goes here);
string newUrl = uri.Host;
string value = string.Format(“http://{0}/_wcf/UploadHandler.ashx”, newUrl);
Uploader.UploadServiceUrl = value;
[/csharp]

As you can see, we are setting the RadUpload.UploadServiceUrl property to my custom handler path. Now, onto the handler itself! The part to pay close attention to is that I am also demonstrating passing a dynamic parameter to hydrate the SharePoint Document Library SPFile with metadata.

[csharp]
namespace UploadHandler
{
public class UploadHandler : RadUploadHandler
{
public string MyParam;
public override bool SaveChunkData(string filePath, long position, byte[] buffer, int contentLength, out int savedBytes)
{
MyParam = GetQueryParameter(“Param”);
return base.SaveChunkData(filePath, position, buffer, contentLength, out savedBytes);
}

public override void ProcessStream()
{
base.ProcessStream();
for (int i = 0; i < Request.Files.Count; i++) { HttpPostedFile file = Request.Files[i]; string fileName = GetFileName(); string fullPath = string.Format("{0}\\_wcf\\TempFiles\\", HttpContext.Current.Server.MapPath(HttpContext.Current.Request.ApplicationPath)); string filename = fullPath + Path.GetFileName(file.FileName); string path = fullPath + fileName; if (file.ContentLength != 0) { file.SaveAs(filename); string requestUrl = WebConfigurationManager.AppSettings["RootSite"]; FileStream stream = new FileStream(filename, FileMode.Open); SPSite site = new SPSite(requestUrl); using (SPSite elevatedSite = new SPSite(requestUrl, site.SystemAccount.UserToken)) { using (SPWeb web = elevatedSite.OpenWeb()) { Hashtable hashtable = new Hashtable(); hashtable.Add("Param", MyParam); Hashtable properties = hashtable; web.AllowUnsafeUpdates = true; SPDocumentLibrary library = (SPDocumentLibrary) web.Lists["Document Library"]; SPFolder rootFolder = library.RootFolder; rootFolder.Files.Add(string.Format("{0}/{1}", rootFolder.Url, fileName), stream, properties, true); stream.Close(); } } File.Delete(path); File.Delete(filename); } } } } } [/csharp] The two overridden methods, SaveChunkData and ProcessStream basically are there because the handler manages the upload stream in variable size chunks. That’s the behavior you want to override. First thing we are doing is hydrating the class level parameter field so that we can have it available later when we want to push it into a HashTable for metadata support on the SPFile object. Within the ProcessSteam method where the meat of the application resides, we are getting all the posted files in the control since it support a mutable amount, and moving them onto the server. Subsequently when the file is constructed on the server, we are going to make it a stream and throw it into the RootFolder of the SPDocumentLibrary. Simple in theory, a pain in the ass to figure out!

Share