Sitefinity can be setup to use Single Sign-On (SSO) combined with Windows Authentication, as described on http://docs.sitefinity.com/administration-set-up-sso-with-windows-authentication.
This article shows what is happening under the hood and how all the pieces fit together.
1) The Sitefinity site redirects to the STS site
Whenever users need to be authenticated, Sitefinity will redirect them to the STS site instead of displaying the standard login page. This step happens when the issuer property in web.config's <wsFederation> tag is set to something other than "http://localhost":
<
federatedAuthentication
>
<
wsFederation
passiveRedirectEnabled
=
"true"
issuer
=
"https://sts_site/mysts.ashx"
realm
=
"http://localhost"
requireHttps
=
"false"
/>
<
cookieHandler
requireSsl
=
"false"
/>
</
federatedAuthentication
>
As a result, Sitefinity will call a URL such as https://sts_site/mysts.ashx?realm=http://sitefinity_site&redirect_uri=%2fhome%3fsf-hru%3dtrue&deflate=true. The URL passes a few arguments:
- The realm, as set in the <wsFederation> tag: this is the return address the STS site should call back after authentication. If it is set to "http://localhost", Sitefinity will replace it with the site full URL, otherwise it will be passed as is
- redirect_uri: the relative URL to return to in Sitefinity once authentication has completed
- deflate=true: asks the STS site to compress the return data
2) The STS site authenticates the user and generates a token
Once called, the first thing the STS site does is to authenticate the user's Windows credentials. This is why this project's Authentication in IIS needs to be configured to use Windows Authentication.
Here is the code snippet inside SimpleWebTokenHandler.cs that is performing that authentication:
public
void
ProcessRequest(HttpContext context)
{
var winPrincipal = context.User
as
WindowsPrincipal;
if
(winPrincipal ==
null
|| !winPrincipal.Identity.IsAuthenticated)
throw
new
ConfigurationException(
"This web site is not correctly configured for Windows authentication."
);
The STS project will then create an access token, which contains information such as the Windows Domain and username of the user who has been authenticated as well as extra Windows domains information. It also contains the following arguments:
- TokenId: a newly generated Token ID that will be used by Sitefinity
- Issuer: tells the Sitefinity site what Security Token Issuer to use (more in the next section)
- Audience: set to the realm
- ExpiresOn: when does the token expires. It is by default set to 3600 seconds in the future, as defined by tokenLifeTime in SWTParser.cs.
These arguments are added to the access token inside the CreateToken() method in SimpleWebTokenHandler.cs:
sb
.AppendFormat(
"TokenId={0}&"
, HttpUtility.UrlEncode(Guid.NewGuid().ToString()))
.AppendFormat(
"Issuer={0}&"
, HttpUtility.UrlEncode(issuerName))
.AppendFormat(
"Audience={0}&"
, HttpUtility.UrlEncode(appliesTo))
.AppendFormat(
"ExpiresOn={0:0}"
, (issueDate -
new
DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds + SWTParser.tokenLifeTime);
This token will then be signed using a private key based on the realm, and the signature added to the access token:
var hmac =
new
HMACSHA256(key);
var sig = hmac.ComputeHash(Encoding.ASCII.GetBytes(unsignedToken));
string
signedToken = String.Format(
"{0}&HMACSHA256={1}"
,
unsignedToken,
HttpUtility.UrlEncode(Convert.ToBase64String(sig)));
The signature is generated using the HMAC algorithm in conjunction with SHA256, which is a reliable Message Authentication Code (MAC) by today's standards. It allows to detect any data tampering. The private key used for the signature will be the one defined in the STS web.config file for the proper realm - that is, the Sitefinity site that called the STS:
<?
xml
version
=
"1.0"
?>
<
configuration
>
<
appSettings
>
<
add
key
=
"http://sitefinity_site/"
value
=
"52ACD69BD85C96F08C74762ED247A4AAFD2174E6B3E7F700630C2DAC5E169D21"
/>
</
appSettings
>
Because deflate=true is passed to the STS URL, it will compress the access token for faster performance as it can be quite large.
3) The STS site redirects the user back to Sitefinity
Once the STS has authenticated the user and generated an access token, it redirects the user back to Sitefinity, using the realm parameter. Note that the STS site will only callback a site which is in its web.config appSettings list. This prevents a malicious URL from tricking a user into authenticating using a legitimate STS site but sending the resulting access token to a malicious Website.
The user will be redirected to a URL such as http://sitefinity_site/?sf-hru=true&wrap_deflated=true&wrap_access_token=...&wrap_access_token_expires_in=3600.
4) Sitefinity authenticates the user
Sitefinity will first look at the Issuer argument inside the access token to tell what Security Token Issuer to use. This information is accessible in Administration / Settings / Advanced / Security / SecurityTokenIssuers:
Sitefinity will use the issuer's key to verify the signature (the key should be the same as the one in the STS project's web.config). This ensures that the request comes from a legitimate STS site and has not been tampered with.
It will also use the MembershipProvider to know what provider to use to perform a user lookup (in the above screenshot, LdapUsers)
Note that at no point will the Sitefinity site receive the user password from the STS site. It trusts the STS site to have successfully authenticated the user. It will just verify that the user exists by performing a user lookup against the Membership Provider.
Enhancing security
One will notice that the access token sent back to Sitefinity is not encrypted. However, encrypting it would not enhance security. Indeed, someone who is able to eavesdrop on the network and capture network communications could steal credentials using several techniques, even if the access token was encrypted:
- Fake an STS authentication by sending again the access token to Sitefinity. Because it is legitimately signed, it is considered a valid access token
- After authentication, capture the user's token ID when it is sent by the client to Sitefinity as a cookie every time a new Web page is loaded
To prevent against these types of attacks, it is recommended to use HTTPS for your website as well as for any redirection between Sitefinity and the STS site.