Skip to content

Instantly share code, notes, and snippets.

@hawjeh
Created December 4, 2023 04:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hawjeh/3658cc6a6c0e62df4872a54e367f31ed to your computer and use it in GitHub Desktop.
Save hawjeh/3658cc6a6c0e62df4872a54e367f31ed to your computer and use it in GitHub Desktop.
Sitefinity Azure AD SAML SSO Login Integration
public void CreateUserFromSaml(Guid userId, string userEmail)
{
try
{
var user = userManager.GetUser(userId);
if (user != null)
{
var firstName = Cache.GetData(userEmail + AuthConstant.FirstNameKey).ToString();
var lastName = Cache.GetData(userEmail + AuthConstant.LastNameKey).ToString();
var userProfile = userProfileManager.GetUserProfile<SitefinityProfile>(user);
if (userProfile != null)
{
userProfileManager.Provider.SuppressSecurityChecks = true;
userProfile.FirstName = firstName;
userProfile.LastName = lastName;
userProfileManager.SaveChanges();
userProfileManager.Provider.SuppressSecurityChecks = false;
}
var role = Cache.GetData(userEmail + AuthConstant.RoleKey).ToString();
if (!role.IsNullOrEmpty())
{
var roleExists = roleManager.RoleExists(role);
var userRole = roleManager.GetRole(role);
if (userRole != null && roleExists)
{
roleManager.Provider.SuppressSecurityChecks = true;
roleManager.AddUserToRole(user, userRole);
roleManager.SaveChanges();
roleManager.Provider.SuppressSecurityChecks = false;
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
using System;
using Telerik.Microsoft.Practices.Unity;
using Telerik.Sitefinity.Abstractions;
using Telerik.Sitefinity.Authentication;
using Telerik.Sitefinity.Security.Events;
using Telerik.Sitefinity.Services;
namespace SitefinityWebApp
{
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
AuthenticationModule.Initialized += this.AuthenticationModule_Initialized;
Bootstrapper.Bootstrapped += Bootstrapper_Bootstrapped;
}
private void AuthenticationModule_Initialized(object sender, EventArgs e)
{
ObjectFactory.Container.RegisterType<AuthenticationProvidersInitializer, SamlAuthenticationProvidersInitializer>(new ContainerControlledLifetimeManager());
}
private void Bootstrapper_Bootstrapped(object sender, EventArgs e)
{
// Assign role and update user upon saml login
EventHub.Subscribe<UserCreated>(evt => UserCreatedEventHandler(evt));
}
private void UserCreatedEventHandler(UserCreated eventInfo)
{
var isSaml2p = eventInfo.ExternalProviderName == AuthConstant.SamlAuthenticationType;
if (isSaml2p)
{
var userServices = new UserServices();
userServices.CreateUserFromSaml(eventInfo.UserId, eventInfo.Email);
}
}
}
}
using IdentityModel;
using Owin;
using Sustainsys.Saml2;
using Sustainsys.Saml2.Configuration;
using Sustainsys.Saml2.Metadata;
using Sustainsys.Saml2.Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Telerik.Microsoft.Practices.EnterpriseLibrary.Caching;
using Telerik.Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
using Telerik.Sitefinity.Authentication;
using Telerik.Sitefinity.Authentication.Configuration.SecurityTokenService.ExternalProviders;
using Telerik.Sitefinity.Security.Claims;
using Telerik.Sitefinity.Services;
namespace SitefinityWebApp
{
public class SamlAuthenticationProvidersInitializer : AuthenticationProvidersInitializer
{
public virtual ICacheManager Cache
{
get
{
return SystemManager.GetCacheManager(CacheManagerInstance.Global);
}
}
public override Dictionary<string, Action<IAppBuilder, string, AuthenticationProviderElement>> GetAdditionalIdentityProviders()
{
var additionalProviders = base.GetAdditionalIdentityProviders();
additionalProviders[AuthConstant.SamlAuthenticationType] = (IAppBuilder app, string signInAsType, AuthenticationProviderElement config) =>
{
var authServicesOptions = new Saml2AuthenticationOptions(false)
{
SPOptions = new SPOptions
{
EntityId = new EntityId(config.GetParameter(AuthConstant.SpEntityIdParameterName)),
},
SignInAsAuthenticationType = signInAsType,
AuthenticationType = AuthConstant.SamlAuthenticationType,
Caption = config.Title,
Notifications = new Saml2Notifications
{
AcsCommandResultCreated = (result, response) =>
{
var claimsIdentity = result.Principal.Identity as ClaimsIdentity;
var email = GetEmailFromIdentity(claimsIdentity);
claimsIdentity.AddClaim(new Claim(SitefinityClaimTypes.ExternalUserEmail, email));
var name = GetNameFromIdentity(claimsIdentity);
claimsIdentity.AddClaim(new Claim(SitefinityClaimTypes.ExternalUserName, name));
var firstName = GetLastNameFromIdentity(claimsIdentity);
var lastName = GetFirstNameFromIdentity(claimsIdentity);
var role = GetRoleFromIdentity(claimsIdentity);
// Add custom cache for account provision use
Cache.Add(email + AuthConstant.FirstNameKey, firstName, CacheItemPriority.Normal, null, new AbsoluteTime(TimeSpan.FromMinutes(2)));
Cache.Add(email + AuthConstant.LastNameKey, lastName, CacheItemPriority.Normal, null, new AbsoluteTime(TimeSpan.FromMinutes(2)));
Cache.Add(email + AuthConstant.RoleKey, role, CacheItemPriority.Normal, null, new AbsoluteTime(TimeSpan.FromMinutes(2)));
},
LogoutCommandResultCreated = commandResult =>
{
// Post logout URL
commandResult.Location = new Uri("/", UriKind.Relative);
}
},
};
authServicesOptions.IdentityProviders.Add(new IdentityProvider(new EntityId(config.GetParameter(AuthConstant.IdpEntityIdParameterName)), authServicesOptions.SPOptions)
{
MetadataLocation = config.GetParameter(AuthConstant.IdpMetadataUrlParameterName),
LoadMetadata = true,
});
app.UseSaml2Authentication(authServicesOptions);
};
return additionalProviders;
}
private string GetNameFromIdentity(ClaimsIdentity claimsIdentity)
{
string name = null;
var nameClaim = claimsIdentity.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name);
if (nameClaim != null)
{
name = nameClaim.Value;
}
else
{
var firstName = GetFirstNameFromIdentity(claimsIdentity);
var lastName = GetLastNameFromIdentity(claimsIdentity);
name = firstName + lastName;
}
if (name.IsNullOrEmpty())
{
name = GetEmailFromIdentity(claimsIdentity);
}
return name;
}
private string GetFirstNameFromIdentity(ClaimsIdentity claimsIdentity)
{
var firstName = "";
var userFirstNameClaim = claimsIdentity.Claims.FirstOrDefault(x => x.Type == ClaimTypes.GivenName);
if (userFirstNameClaim != null)
{
firstName = userFirstNameClaim.Value;
}
return firstName;
}
private string GetLastNameFromIdentity(ClaimsIdentity claimsIdentity)
{
var lastName = "";
var userLastNameClaim = claimsIdentity.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Surname);
if (userLastNameClaim != null)
{
lastName = userLastNameClaim.Value;
}
return lastName;
}
private string GetEmailFromIdentity(ClaimsIdentity claimsIdentity)
{
var email = "";
var userEmailClaim = claimsIdentity.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Email);
if (userEmailClaim != null)
{
email = userEmailClaim.Value;
}
else
{
var jwtEmailClaim = claimsIdentity.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Email);
if (jwtEmailClaim != null)
{
email = jwtEmailClaim.Value;
}
else
{
throw new ArgumentException("Email claim not found");
}
}
return email;
}
private string GetRoleFromIdentity(ClaimsIdentity claimsIdentity)
{
var role = "";
var userRoleClaim = claimsIdentity.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role);
if (userRoleClaim != null)
{
role = userRoleClaim.Value;
}
return role;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment