Hi, I'm learning the SAML standard and I'm trying to implement it in my software.
Here is a part of my code
public class UserAuthentication : IUserAuthentication
{
private readonly LogSplitter _logger;
private HttpRequest _request;
private string _serviceProviderEntityId;
private string _returnUrl;
private string _identityProviderEntityId;
private string _identityProviderMetadataLocation;
private string _organizationCode;
public UserAuthentication(LogSplitter logger)
{
_logger = logger;
}
public void Configuration(IAppBuilder app, AuthParams parameters)
{
_serviceProviderEntityId = parameters["ServiceProviderEntityId"];
_returnUrl = parameters["ReturnUrl"];
_identityProviderEntityId = parameters["IdentityProviderEntityId"];
_identityProviderMetadataLocation = parameters["IdentityProviderMetadataLocation"];
_organizationCode = parameters["OrganizationCode"];
app.UseSaml2Authentication(CreateSamlOptions());
}
private Saml2AuthenticationOptions CreateSamlOptions()
{
var samlOptions = new Saml2AuthenticationOptions(false) // "false" to specify that the module should not work as active
{
SPOptions = new Sustainsys.Saml2.Configuration.SPOptions
{
EntityId = new EntityId(_serviceProviderEntityId),
ReturnUrl = new Uri(_returnUrl), // Should match the ACS endpoint
// The certificate used for signing SAML requests.
},
AuthenticationType = "Saml2",
SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
AuthenticationMode = AuthenticationMode.Active
};
//samlOptions.SPOptions.ServiceCertificates.Add(new X509Certificate2("C:\\temp\\cert.pfx", "prova"));
var idp = new IdentityProvider(new EntityId(_identityProviderEntityId), samlOptions.SPOptions)
{
// Set up the Identity Provider options as needed
MetadataLocation = _identityProviderMetadataLocation, // Metadata URL
LoadMetadata = true,
// Configure more IdP options as needed, e.g., bindings, signing certificates
};
idp.SigningKeys.AddConfiguredKey(new X509Certificate2("C:\\temp\\cert.pfx", "prova"));
// Add the identity provider to the samlOptions
samlOptions.IdentityProviders.Add(idp);
return samlOptions;
}
private AuthUserRequestInfo GetUserInfo(HttpContext context)
{
try
{
// Retrieve SAML attributes from the context
var samlAttributes = context.Items["Saml2Attributes"] as Dictionary<string, string>;
AuthUserRequestInfo userInfo;
bool identificationCodeExists = samlAttributes.TryGetValue("IdentificationCode", out string identificationCode);
userInfo = new AuthUserRequestInfo()
{
ProviderAuthentication = System.Reflection.Assembly.GetExecutingAssembly().FullName,
IdentificationCode = identificationCode,
OrganizationCode = _organizationCode
};
return userInfo;
}
catch(Exception ex)
{
_logger.Error("", $"Error during SAML2 authentication: {ex.Message}");
return new AuthUserRequestInfo();
}
}
public async Task<bool> SetClaims(HttpContext context, IAuthenticationManager authenticationManager, Func<string, string, string, bool, Task<UserDto>> getUser, UserApplication applicationType)
{
AuthUserRequestInfo userInfo = GetUserInfo(context);
var useUserIdObjectOnly = false;
// Fetch user credentials from the database
UserDto user = await getUser(String.Empty, userInfo.IdentificationCode, userInfo.OrganizationCode, useUserIdObjectOnly);
if (user == null) return false;
// Verify credentials
var profile = ProfileFilter.GetAuthority(applicationType, ((UserProfile)user.ProfileId).GetName());
if (user.IsForbidden || profile == UserProfile.None) return false;
var identity = new ClaimsIdentity(
new[]
{
new Claim("UserId", user.UserId.ToString()),
new Claim("FullName", user.FullName),
new Claim("OrganizationCode", user.OrganizationCode),
new Claim("Institute", user.Institute),
new Claim("UserName", user.UserName),
new Claim(ClaimTypes.Role, ((UserProfile)user.ProfileId).GetName()),
new Claim("RoleCode", user.ProfileId.ToString())
},
DefaultAuthenticationTypes.ApplicationCookie);
authenticationManager.SignIn(new AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = false
}, identity);
return true;
}
public void SignIn(HttpContext context, IAuthenticationManager authenticationManager)
{
// Trigger the SAML2 authentication process
var properties = new AuthenticationProperties
{
RedirectUri = _returnUrl
};
// Challenge the SAML2 authentication
try
{
// Challenge the SAML2 authentication
authenticationManager.Challenge(properties, "Saml2");
//authenticationManager.AuthenticateAsync("Saml2");
_logger.Info("", () => "SAML2 sign-in challenge triggered.");
}
catch (Exception ex)
{
_logger.Error("", $"Error during SAML2 sign-in: {ex.Message}");
throw;
}
}
public void SignOut(IAuthenticationManager authenticationManager)
{
authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
}
}
In the SignIn method is it correct to call authenticationManager.Challenge(properties, "Saml2"); ? It doesn't redirect me to the IdP login page and I don't understand how to get logs/informations on what's happening.
Hi, I'm learning the SAML standard and I'm trying to implement it in my software. Here is a part of my code public class UserAuthentication : IUserAuthentication { private readonly LogSplitter _logger; private HttpRequest _request; private string _serviceProviderEntityId; private string _returnUrl; private string _identityProviderEntityId; private string _identityProviderMetadataLocation; private string _organizationCode;
}
In the SignIn method is it correct to call authenticationManager.Challenge(properties, "Saml2"); ? It doesn't redirect me to the IdP login page and I don't understand how to get logs/informations on what's happening.
Thanks