Hi!
We have recently been working on federated login using SAML.
Our approach is to make a redirect to a STS when a user attempt to log on. After the user have authenticated with the STS and is redirected back to the DNN-site, we inspect the claims and log the user in based on the username.
We have successfully achieved that with some simple code, see below. This was tested adding the code to Default.aspx.
To implement this function we want to intercept the request at the HTTP level but this is producing an error related to AntiForgery. Some help or ideas here would be greatly appreciated.
Code
protected void Application__AuthenticateRequest(Object source, EventArgs e)
{
HttpContext currentHttpContext = HttpContext.Current;
UserInfo objUserInfo = UserController.Instance.GetCurrentUserInfo();
int currentUserId = objUserInfo.UserID;
if (currentUserId < 1)
{
// sam is configured in web.config
var sam = FederatedAuthentication.SessionAuthenticationModule;
// fam is not
var fam = new WSFederationAuthenticationModule();
fam.FederationConfiguration = FederatedAuthentication.FederationConfiguration;
var request = new HttpContextWrapper(currentHttpContext).Request;
// is this the response from the STS
if (!fam.IsSignInResponse(request))
{
// no
// the STS
fam.Issuer = sam.FederationConfiguration.WsFederationConfiguration.Issuer;
// the return address
fam.Realm = currentHttpContext.Request.Url.AbsoluteUri;
var req = fam.CreateSignInRequest(string.Empty, null, false);
// go to STS
currentHttpContext.Response.Redirect(req.WriteQueryString());
}
else
{
// yes
EventLog.WriteEntry("NoSignInResponse,", EventLogEntryType.Information, 1000);
EventLog.WriteEntry("Realm=" + currentHttpContext.Request.Url.AbsoluteUri, EventLogEntryType.Information, 1000);
// get the SAML token
var securityToken = fam.GetSecurityToken(request);
var config = new SecurityTokenHandlerConfiguration
{
CertificateValidator = System.IdentityModel.Selectors.X509CertificateValidator.None,
IssuerNameRegistry = new CustomIssuerNameRegistry()
};
config.AudienceRestriction.AudienceMode = System.IdentityModel.Selectors.AudienceUriMode.Never;
var tokenHandler = new SamlSecurityTokenHandler
{
CertificateValidator = System.IdentityModel.Selectors.X509CertificateValidator.None,
Configuration = config
};
// validate the token and get the ClaimsIdentity out of it
var identity = tokenHandler.ValidateToken(securityToken);
var principal = new ClaimsPrincipal(identity);
var token = sam.CreateSessionSecurityToken(principal, string.Empty,
DateTime.Now.ToUniversalTime(), DateTime.Now.AddMinutes(20).ToUniversalTime(), false);
LoginDNNUser(principal);
}
}
}
Error message when running this code as HTTPmodule.
InnerStackTrace:
at System.Web.Helpers.AntiXsrf.ClaimUidExtractor.GetUniqueIdentifierParameters(ClaimsIdentity claimsIdentity, String uniqueClaimTypeIdentifier)
at System.Web.Helpers.AntiXsrf.ClaimUidExtractor.ExtractClaimUid(IIdentity identity)
at System.Web.Helpers.AntiXsrf.TokenValidator.GenerateFormToken(HttpContextBase httpContext, IIdentity identity, AntiForgeryToken cookieToken)
at System.Web.Helpers.AntiXsrf.AntiForgeryWorker.GetTokens(HttpContextBase httpContext, AntiForgeryToken oldCookieToken, AntiForgeryToken& newCookieToken, AntiForgeryToken& formToken)
at System.Web.Helpers.AntiXsrf.AntiForgeryWorker.GetFormInputElement(HttpContextBase httpContext)
at System.Web.Helpers.AntiForgery.GetHtml()
at DotNetNuke.Framework.ServicesFrameworkImpl.RegisterAjaxAntiForgery(Page page) in C:\VS2013_v4.5\DotNetNuke\DNN_DNN742Source\DNN Platform\Library\Framework\ServicesFrameworkImpl.cs:line 52
at DotNetNuke.Framework.PageBase.OnPreRender(EventArgs e) in C:\VS2013_v4.5\DotNetNuke\DNN_DNN742Source\DNN Platform\Library\Framework\PageBase.cs:line 341
at DotNetNuke.Framework.DefaultPage.OnPreRender(EventArgs evt) in c:\VS2013_v4.5\DotNetNuke\DNN_DNN742Source\Website\Default.aspx.cs:line 803