using System.Collections.Generic; using System.IdentityModel; using System.IdentityModel.Configuration; using System.IdentityModel.Protocols.WSTrust; using System.IdentityModel.Tokens; using System.Linq; using System.Security.Claims; using System.Security.Cryptography.X509Certificates; using Coscine.Api.LegacySTS.ModelingObjects; namespace Coscine.Api.LegacySTS.Security { public class CustomSecurityTokenService : SecurityTokenService { private static readonly string[] SupportedWebApps = { }; private UserObject _userObject; public CustomSecurityTokenService(SecurityTokenServiceConfiguration securityTokenServiceConfiguration, UserObject userObject) : base(securityTokenServiceConfiguration) { _userObject = userObject; } private static void ValidateAppliesTo(EndpointReference appliesTo) { if (SupportedWebApps == null || SupportedWebApps.Length == 0) return; var validAppliesTo = SupportedWebApps.Any(x => appliesTo.Uri.Equals(x)); if (!validAppliesTo) { throw new InvalidRequestException(string.Format("The 'appliesTo' address '{0}' is not valid.", appliesTo.Uri.OriginalString)); } } protected override Scope GetScope(ClaimsPrincipal principal, RequestSecurityToken request) { ValidateAppliesTo(request.AppliesTo); var scope = new Scope(request.AppliesTo.Uri.OriginalString, SecurityTokenServiceConfiguration.SigningCredentials); // TODO maybe set? var encryptionCertificate = ""; if (!string.IsNullOrEmpty(encryptionCertificate)) { // Important note on setting the encrypting credentials. // In a production deployment, you would need to select a certificate that is specific to the RP that is requesting the token. // You can examine the 'request' to obtain information to determine the certificate to use. var encryptingCertificate = GetCertificate();// encryptionCertificate); var encryptingCredentials = new X509EncryptingCredentials(encryptingCertificate); scope.EncryptingCredentials = encryptingCredentials; } else { // If there is no encryption certificate specified, the STS will not perform encryption. // This will succeed for tokens that are created without keys (BearerTokens) or asymmetric keys. scope.TokenEncryptionRequired = false; } scope.ReplyToAddress = request.ReplyTo; if(request.ReplyTo == "") { scope.ReplyToAddress = request.Context; } if (scope.ReplyToAddress.Contains(",")) { scope.ReplyToAddress = scope.ReplyToAddress.Substring(0, scope.ReplyToAddress.IndexOf(",")); } return scope; } protected override ClaimsIdentity GetOutputClaimsIdentity(ClaimsPrincipal principal, RequestSecurityToken request, Scope scope) { var claims = new List<Claim>() { new Claim(System.IdentityModel.Claims.ClaimTypes.Name, _userObject.DisplayName), new Claim(System.IdentityModel.Claims.ClaimTypes.Surname, _userObject.DisplayName.Contains(" ") ? _userObject.DisplayName.Split(' ')[0] : _userObject.DisplayName), new Claim(System.IdentityModel.Claims.ClaimTypes.GivenName, _userObject.DisplayName.Contains(" ") ? _userObject.DisplayName.Split(' ')[1] : ""), new Claim(System.IdentityModel.Claims.ClaimTypes.NameIdentifier, _userObject.Id.ToString()), }; if (_userObject.EmailAddress != null) { claims.Add(new Claim(System.IdentityModel.Claims.ClaimTypes.Email, _userObject.EmailAddress)); } var identity = new ClaimsIdentity(claims); return identity; } public static X509Certificate2 GetCertificate() { var pfx = Program.Configuration.GetAndWait("coscine/global/sts/pfx"); var passwordString = Program.Configuration.GetStringAndWait("coscine/global/sts/pfxpassword"); X509Certificate2 x509Certificate2 = new X509Certificate2(pfx, passwordString); return x509Certificate2; } } }