DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Integration Security and Safety When Connecting With External Systems
  • Harnessing the Power of APIs: Shaping Product Roadmaps and Elevating User Experiences through Authentication
  • Data Governance – Data Privacy and Security – Part 1
  • Authorization: Get It Done Right, Get It Done Early

Trending

  • Introduction to Retrieval Augmented Generation (RAG)
  • Lambda-Driven API Design: Building Composable Node.js Endpoints With Functional Primitives
  • AI Paradigm Shift: Analytics Without SQL
  • No More Cheap Claude: 4 First Principles of Token Economics in 2026
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Implementing Single Sign-on Integration With SAML Providers Using C#

Implementing Single Sign-on Integration With SAML Providers Using C#

I provide a working example and step-by-step explanation on how to integrate using SAML 2.0 - the most popular integration protocol for SSO.

By 
Anton Yarkov user avatar
Anton Yarkov
DZone Core CORE ·
Mar. 23, 21 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
14.0K Views

Join the DZone community and get the full member experience.

Join For Free

What Is Single Sign-on at All?

Suppose you have a web application that people are using to do one thing X, but you are doing it great. For example, it would be a web store allowing to order a custom T-shirt printing by uploading some funny and pretty images found on the internet.

You are looking for ways to extend its functionality by adding some more capabilities for your users, but you don't want to lose the focus on this thing that you are doing best of all. 

One way would be to integrate your web application with other services, such as a cool image provider, a trends meter, a delivery service, etc. It would allow your users to seamlessly move between different services (for example: looking for a cool image, checking trends, and uploading this image to your custom printing service) and do multiple things using only your web application.

Single Sign-On simplifies authentication flow and allows your users to sign in only once (on your web application) with their login/password (or even more innovative mechanisms, like FIDO2, if you use such) and use more integrated services by simple clicks without the need to log in again and again. It allows you to extend the functionality of your product by adding more value with relatively low investments.

SAML 2.0

SAML is one of the standard ways of doing Single Sign-On. For a long time, extensive enterprise services use this mechanism as one of the most secure and proven methods to exchange sensitive authentication and authorization information, like logins, passwords, emails, user accounts, etc. But it's not that complicated to add this solution between smaller businesses and enable cool integrations.

SAML is one of the most secure ways to integrate with third-party among many other options. It allows parties to use asymmetric encryption (RSA) based on secure X.509 certificates. As of 2021, the standard is in version 2.

I should note that it might be better for you to trust one of many existing boxed solutions with a proven history and from vendors responsible for their code and overall solution. However, as a developer, I know that businesses may need much more flexibility and customization in their products, so I want to provide more details and working examples using C#, so you can easily reuse this with your ASP.NET application.

SAML Workflow

Usually, the 'classic' SAML workflow includes 3 parties: 

  • Service Provider — this is a third-party service you want to integrate with.
  • Identity Provider — this is some (enterprise) trusted authentication service, that is able to prove the user identify and tell the Service Provider that 'he is OK!'
  • User Agent — a browser with your Web Store opened by a user.

This "classic" scenario is suitable for the enterprise, and we are not going to stop for long here. You can see the workflow diagram below and it is explained in all details on Wikipedia.

Classic SAML

However, we are a small business, right? So, usually, we don't have complicated agreements with Enterprise-level Identity Providers, but we still need to integrate with third-party. Let's see how it should look like for us.

The First Step of The Integration

The first thing is an agreement with some service provider to have an integration with your service. This time we focus on SAML protocol specifically, but I know about tenish more custom integration algorithms used by many small and medium-sized services. They use custom HTTP API, REST, WCF, XML, and JSON-based data formats, JWTokens and OAuth, and sometimes even combine all things. Whatever option is used, they need to provide you with some configuration parameters to establish an initial test connection.

For SAML-based integrations, they will ask you to provide so-called "metadata information." That's a small XML file that contains information about your service. This file is being used by service providers representatives to automatically create a certification (aka test) endpoint that would allow you to test the connection, resolve all the roadblocks and certify everything before you go public.

The critical part here is the XML content of this file that must be signed with your private X.509 certificate (aka private key, in terms of RSA). Of course, you have to buy one. Some providers allow using self-signed credentials for testing purposes. That's a matter of your agreement with the service provider.

I've prepared some code that is open source and publicly available on my GitHub account. This small console application allows you to generate a Metadata.xml file and properly sign it with the private key.

Now, you should send your Public X.509 Certificate (as a *.crt file, or PEM text) and this Metadata.xml via a secure channel.

As soon as the service provider replies with some connection endpoints, the first part might be over.

Integration Workflow

You have a web application that implements some authentication workflow and allows users to sign in with their login and password. It means that you are the Identity Provider, and by doing this, you can eliminate some redundant steps and make a process simpler. So, imagine that we combine Identity Provider and your Web Store into one entity, like this:

Simple SAML scenario

It simplifies the overall picture. However, it's not that simple under the hood. What actually should happen in the end is we should have an XML document called SAMLResponse prepared and encoded in Base64. You have to send this document via an HTTP POST request to the service provider to authenticate the user and automatically redirect his browser to the third-party target service — see detailed steps in the diagram below.

Under the hood of SAML authentication

Again, I've prepared a set of utility classes written in C#, so you can easily see how to execute those steps in your web application.

Below, you can find my comments on every important aspect of that process. But I believe, it will be much easier to follow the steps in class SamlIntegrationSteps.cs > method BuildEncodedSamlResponse(...).

Step 1. Creating SAML assertion XML is not harder than creating a usual XML document. But you have to follow the SAML specification and documentation provided by your Service Provider to use the appropriate field names. A working example is here: SamlAssertionAlgorithms.cs.

C#
 




x
58


 
1
AssertionType assertion = new AssertionType
2
{
3
    ID = ...Assertion Id ...,
4
    IssueInstant = ...UTC Time...,
5
    Version = "2.0",
6
    Issuer = new NameIDType
7
    {
8
        Value = "...your Web Store URL here..."
9
    },
10
    Subject = new SubjectType
11
    {
12
        Items = new object[]
13
        {
14
            new NameIDType
15
            {
16
                Format = "urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress",
17
                Value = userData.GetUserEmail()
18
            },
19
            new SubjectConfirmationType
20
            {
21
                Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer",
22
                SubjectConfirmationData = new SubjectConfirmationDataType
23
                {
24
                    NotOnOrAfter = ...UTC Time....AddMinutes(3),
25
                    NotOnOrAfterSpecified = true,
26
                    Recipient = settings.Recipient
27
                }
28
            }
29
        }
30
    },
31
    Conditions = new ConditionsType
32
    {
33
        NotBefore = ...UTC Time...,
34
        NotBeforeSpecified = true,
35
        NotOnOrAfter = ...UTC Time....AddMinutes(3),
36
        NotOnOrAfterSpecified = true,
37
        Items = ...conditions that you need...
38
    },
39
    Items = new StatementAbstractType[]
40
    {
41
        new AttributeStatementType
42
        {
43
            // ReSharper disable once CoVariantArrayConversion
44
            Items = ...attributes array...
45
        },
46
        new AuthnStatementType
47
        {
48
            AuthnInstant = ...UTC Time...,
49
            SessionIndex = ...Assertion Id ...,
50
            AuthnContext = new AuthnContextType
51
            {
52
                ItemsElementName = new [] { ItemsChoiceType5.AuthnContextClassRef },
53
                Items = new object[] { "urn:federation:authentication:windows" }
54
            }
55
        }
56
    }
57
};
58

          



Step 2. The signing of the SAML assertion can be done as described in official Microsoft docs. A working example is here: SamlAssertionAlgorithms.cs.

Step 3. Encryption of the SAML assertion is implemented in SamlAssertionAlgorithms.cs using System.Security.Cryptography.xml.

C#
 




xxxxxxxxxx
1
29


 
1
X509Certificate2 x509 = ...get certificate...
2

          
3
xmlElement.SigningKey = x509.PrivateKey;
4
xmlElement.SignedInfo.CanonicalizationMethod = SamlSignedXml.XmlDsigExcC14NTransformUrl;
5

          
6
// Create a reference to be signed. 
7
Reference reference = new Reference
8
{
9
    Uri = "#" + referenceValue
10
};
11

          
12
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
13
reference.AddTransform(new XmlDsigExcC14NTransform());
14

          
15
// Add the reference to the SignedXml object. 
16
xmlElement.AddReference(reference);
17

          
18
// Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate). 
19
KeyInfo keyInfo = new KeyInfo();
20
keyInfo.AddClause(new KeyInfoX509Data(certificate));
21

          
22
xmlElement.KeyInfo = keyInfo;
23

          
24
// Compute the signature. 
25
xmlElement.ComputeSignature();
26

          
27
// Put the sign as the first child of main Request tag.
28
xmlAssertion?.InsertAfter(xmlElement, xmlAssertion.ChildNodes[0]);
29

          



Step 4. Adding the assertion document to the SAMLResponse is just about adding XML:

C#
 




xxxxxxxxxx
1
22


 
1
XmlDocument encryptedAssertion = new XmlDocument();
2

          
3
// Add namespaces
4
XmlDeclaration xmlDeclaration = encryptedAssertion.CreateXmlDeclaration("1.0", "UTF-8", null);
5
XmlElement encryptedRoot = encryptedAssertion.DocumentElement;
6
encryptedAssertion.InsertBefore(xmlDeclaration, encryptedRoot);
7

          
8
// Form Assertion element
9
XmlElement encryptedAssertionElement = encryptedAssertion.CreateElement("saml",
10
    "EncryptedAssertion", "urn:oasis:names:tc:SAML:2.0:assertion");
11
encryptedAssertion.AppendChild(encryptedAssertionElement);
12

          
13
// Add encrypted content
14
var encryptedDataNode = encryptedAssertion.ImportNode(encryptedData.GetXml(), true);
15
encryptedAssertionElement.AppendChild(encryptedDataNode);
16

          
17
// Form a document
18
var root = xmlDocument.DocumentElement;
19
var node = root.OwnerDocument.ImportNode(encryptedAssertionElement, true);
20
root.RemoveChild(xmlAssertionSource ?? throw new InvalidOperationException());
21
root.AppendChild(node);
22

          



Step 5. Signing the SAMLResponse is almost the same as signing the Assertion. A working example is here: SamlResponseAlgorithms.cs.

The End

Some service providers may avoid specific steps and do not require the signature or encryption. In this case, you may remove these parts of the code. Overall, feel free to use my examples in your apps, and I hope this will help you and your application engage users and grow the customer base.

Cheers!

Related Links

Examples of SAML responses.
Tips and Tricks on documenting custom API.

authentication security Integration csharp Web Service

Opinions expressed by DZone contributors are their own.

Related

  • Integration Security and Safety When Connecting With External Systems
  • Harnessing the Power of APIs: Shaping Product Roadmaps and Elevating User Experiences through Authentication
  • Data Governance – Data Privacy and Security – Part 1
  • Authorization: Get It Done Right, Get It Done Early

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook