I try to use ASP.Net's MembershipProvider to give access only to certain users. This is backed up by an ADAM instance.
I use some test-code which runs just fine:
public static DataTable getADValuesByParameter(string strFilter, string strLDAPUser, string strLDAPPath, string strLDAPPWD, string strLDAPProperties)
{
DataTable functionReturnValue = default(DataTable);
string[] arrLDAP = null;
DirectoryEntry rootEntry = new DirectoryEntry();
DirectorySearcher searcher = new DirectorySearcher();
SearchResultCollection results = default(SearchResultCollection);
DataTable dtExchangeUserData = new DataTable();
arrLDAP = strLDAPProperties.Split(new char[] { ',' });
rootEntry.Path = strLDAPPath;
rootEntry.Username = strLDAPUser;
rootEntry.Password = strLDAPPWD;
rootEntry.AuthenticationType = AuthenticationTypes.Secure;
searcher.SearchRoot = rootEntry;
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = strFilter;
searcher.PropertiesToLoad.AddRange(arrLDAP);
//var value = rootEntry.NativeObject;
results = searcher.FindAll();
Int16 si = default(Int16);
foreach (SearchResult result in results)
{
si = 0;
object[] arrKeyValue = new object[result.Properties.Count - 1];
// -2 weil property "adspath" nicht dazu gehört, und .count -1 weil 0 basierendes array
if ((result != null))
{
System.Collections.IEnumerator myEnumerator = arrLDAP.GetEnumerator();
while (myEnumerator.MoveNext())
{
foreach (string Key in result.Properties.PropertyNames)
{
if (Key != "adspath")
{
if (Key.Equals(((string)myEnumerator.Current).ToLower()))
{
if (dtExchangeUserData.Columns[Key] == null)
dtExchangeUserData.Columns.Add(Key);
if (Key.Equals("objectguid"))
{
arrKeyValue[si] = new Guid(((byte[])result.Properties[Key][0]));
}
else
{
arrKeyValue[si] = result.Properties[Key][0].ToString();
}
si++;
}
}
}
}
if (arrKeyValue.Length > 0)
dtExchangeUserData.Rows.Add(arrKeyValue);
}
}
functionReturnValue = dtExchangeUserData;
dtExchangeUserData.Dispose();
rootEntry.Close();
rootEntry.Dispose();
return functionReturnValue;
}
Here, I query the ADAM manually. Although the code is badly written, it works. Note how I use "AuthenticationTypes.Secure".
Now, when I try to do the same thing (same connectionPath, username, password and so on) with the ActiveDirectoryMembershipProvider, it gives me (roughly translated from German):
ConfigurationErrorsException: Can't
establish a secure connection over
SSL.
This happens when I call
Membership.ValidateUser()
Here are the relevant parts from the Web.config file:
<connectionStrings>
<add name="ADConnectionString" connectionString="LDAP://server.com/OU=users,DC=test,DC=adam"/>
</connectionStrings>
<authentication mode="Forms" >
<forms loginUrl="~/Login.aspx/Test/" timeout="2880" />
</authentication>
<authorization>
<deny users ="?" />
</authorization>
<!--<identity impersonate="true" />-->
<trust level="Full" />
<membership defaultProvider="MyMembershipProvider">
<providers>
<add name="MyMembershipProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="ADConnectionString"
connectionUsername="[domain]\[user]"
connectionPassword="[password]"
connectionProtection="Secure"
enableSearchMethods="true"
/>
</providers>
</membership>
It doesn't matter whether I use impersonation or not (to be honest, I don't really know what it does anyway). Trust-level doesn't change anything either.
When I use connectionProtection="None" instead, it gives me (again translated) "Wrong username or password". I get the same error when I use "AuthenticationTypes.None" in the manual example.
What am I doing wrong?
Thanks for your time...
Related
I am new to .NET Core. I have defined the connection string in appsettings.json like this:
"ConnectionStrings": {
"TestBD": "Server=localhost;Database=Test;Trusted_Connection=True;MultipleActiveResultSets=true"
}
I am not using Entity Framework. I need to connect to the database using this connection string from the Program.cs file.
Any help is really appreciated. Thanks
You refer the following sample code to use ADO.NET in Asp.net 6 program.cs:
//required using Microsoft.Data.SqlClient;
app.MapGet("/movies", () =>
{
var movies = new List<Movie>();
//to get the connection string
var _config = app.Services.GetRequiredService<IConfiguration>();
var connectionstring = _config.GetConnectionString("DefaultConnection");
//build the sqlconnection and execute the sql command
using (SqlConnection conn = new SqlConnection(connectionstring))
{
conn.Open();
string commandtext = "select MovieId, Title, Genre from Movie";
SqlCommand cmd = new SqlCommand(commandtext, conn);
var reader = cmd.ExecuteReader();
while (reader.Read())
{
var movie = new Movie()
{
MovieId = Convert.ToInt32(reader["MovieId"]),
Title = reader["Title"].ToString(),
Genre = reader["Genre"].ToString()
};
movies.Add(movie);
}
}
return movies;
});
The result like this:
In the process of getting a managed package reviewed by Salesforce and it has been flagged for Insecure Storage of Sensitive Data and they highlight the following xml.
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<customSettingsType>List</customSettingsType>
<enableFeeds>false</enableFeeds>
<fields>
<fullName>Client_Id__c</fullName>
<deprecated>false</deprecated>
<externalId>false</externalId>
<label>Client Id</label>
<length>100</length>
<required>false</required>
<trackTrending>false</trackTrending>
<type>Text</type>
<unique>false</unique>
</fields>
<fields>
<fullName>Client_Secret__c</fullName>
<deprecated>false</deprecated>
<externalId>false</externalId>
<label>Client Secret</label>
<required>false</required>
<trackTrending>false</trackTrending>
<type>TextArea</type>
</fields>
<label>ConnectedApp</label>
**<visibility>Public</visibility>**
</CustomObject>
Notes
Sensitive data like Client_Id__c and Client_Secret__c which is use in api call, should be stored in a protected custom setting or named credential.
Related Code
public class CRMA_AuthenticationCheck {
...
#AuraEnabled
public static ResponseWrapper authorizeCRMA(String session_id, String userId, String consumerSecret){
ResponseWrapper rw = new ResponseWrapper();
string successMsg;
string crmaUrl;
ConnectedApp__c conApp;
try{
Boolean isStaging = [SELECT Id, IsSandbox FROM Organization LIMIT 1].IsSandbox;
if(isStaging){
crmaUrl = 'https://salesforcestaging.mydummysite.com/index.php/logincb/';
}else{
crmaUrl = 'https://salesforce.mydummysite.com/index.php/logincb/';
}
conApp = ConnectedAppCreator.createConnectedApp(crmaUrl+userId);
Boolean isSuccess = false;
if(String.isBlank(consumerSecret)){
consumerSecret = conApp.Client_Secret__c;
}
if(String.isBlank(consumerSecret)){
rw.StatusCode = 120;
rw.ResponseMessage = 'Please Enter the Consumer Secret from Connected App with name Foo Connected App' ;
rw.toastType = 'dismissable';
return rw;
}else {
conApp.Client_Secret__c = consumerSecret;
}
if(conApp != null && String.isNotBlank(conApp.Client_Id__c)){
successMsg = ConnectedAppDetailsToCRMA.connectedAppDetails(conApp.Client_Id__c, consumerSecret,UserInfo.getOrganizationName(), userId, session_id);
if(successMsg == 'SUCCESSFUL'){
isSuccess = true;
}
}
...
}
...
return rw;
}
...
}
Given that the managed package is generated and we are not specifically defining ConnectedApp, don't see how we can modify the field visibility to private or protected. Any link or relevant samples are appreciated. Thank you !
I converted the IdPInitiatedController example code for my WebForms project. Although I don't get compiler or runtime error, I still cannot seem to get the manually created claims added to the Saml2AuthnResponse object after setting the claims identity. Is there another way to add attributes to the SAML response? The app uses forms authentication; and the credentials are in a SQL database. That's why I don't have Windows Identity.
' SSO CODE BEHIND
...
Dim binding = New Saml2PostBinding With {
.RelayState = String.Format("RPID={0}", Uri.EscapeDataString(serviceProviderRealm))
}
Dim config = New Saml2Configuration With {
.Issuer = "company.stage.app",
.SingleSignOnDestination = New Uri(ConfigurationManager.AppSettings.Get("appValue")),
.SigningCertificate = CertificateUtil.Load(X509Certificates.StoreName.TrustedPeople, X509Certificates.StoreLocation.LocalMachine, X509Certificates.X509FindType.FindByThumbprint, ConfigurationManager.AppSettings.Get("ThatKey")),
.SignatureAlgorithm = Saml2SecurityAlgorithms.RsaSha256Signature
}
Dim samlResponse = New Saml2AuthnResponse(config) With {
.Status = Saml2StatusCodes.Success
}
_ssoService.AddAttributes(samlResponse, currentUser)
binding.Bind(samlResponse) ' NO ATTRIBUTES WERE ADDED
Me.SAMLResponse.Value = binding.XmlDocument.InnerXml
Me.RelayState.Value = binding.RelayState
frmSSO.Action = config.SingleSignOnDestination.AbsoluteUri()
frmSSO.Method = "POST"
Public Sub AddAttributes(ByRef samlResponse As Saml2AuthnResponse, ByVal currentUser As CurrentUser)
Dim acctContact As CoveredInsuredDto = _coveragesService.GetAccountPointOfContact(currentUser.getControlNo())
If Not IsNothing(acctContact) Then
' Adding Attributes as claims
Dim claimIdentity = New ClaimsIdentity(Me.BuildClaims(currentUser, acctContact))
samlResponse.NameId = New IdentityModel.Tokens.Saml2NameIdentifier(acctContact.Name)
samlResponse.ClaimsIdentity = claimIdentity
End If
End Sub
Private Function BuildClaims(ByVal currentUser As CurrentUser, ByVal acctContact As CoveredInsuredDto) As IEnumerable(Of Claim)
Dim claims = New List(Of Claim)
If Not IsNothing(acctContact) Then
claims.Add(New Claim("FIRST_NAME", acctContact.FirstName))
claims.Add(New Claim("LAST_NAME", acctContact.LastName))
End If
Return claims.ToList()
End Function
The problem is that you have forgot the var token = response.CreateSecurityToken(appliesToAddress); line which is actually the line creating the token.
The ASP.NET Core IdP Initiated sample code:
public IActionResult Initiate()
{
var serviceProviderRealm = "https://some-domain.com/some-service-provider";
var binding = new Saml2PostBinding();
binding.RelayState = $"RPID={Uri.EscapeDataString(serviceProviderRealm)}";
var config = new Saml2Configuration();
config.Issuer = "http://some-domain.com/this-application";
config.SingleSignOnDestination = new Uri("https://test-adfs.itfoxtec.com/adfs/ls/");
config.SigningCertificate = CertificateUtil.Load(Startup.AppEnvironment.MapToPhysicalFilePath("itfoxtec.identity.saml2.testwebappcore_Certificate.pfx"), "!QAZ2wsx");
config.SignatureAlgorithm = Saml2SecurityAlgorithms.RsaSha256Signature;
var appliesToAddress = "https://test-adfs.itfoxtec.com/adfs/services/trust";
var response = new Saml2AuthnResponse(config);
response.Status = Saml2StatusCodes.Success;
var claimsIdentity = new ClaimsIdentity(CreateClaims());
response.NameId = new Saml2NameIdentifier(claimsIdentity.Claims.Where(c => c.Type == ClaimTypes.NameIdentifier).Select(c => c.Value).Single(), NameIdentifierFormats.Persistent);
response.ClaimsIdentity = claimsIdentity;
var token = response.CreateSecurityToken(appliesToAddress);
return binding.Bind(response).ToActionResult();
}
private IEnumerable<Claim> CreateClaims()
{
yield return new Claim(ClaimTypes.NameIdentifier, "some-user-identity");
yield return new Claim(ClaimTypes.Email, "some-user#domain.com");
}
I have this error, it gets thrown during registration on my mvc application. How do i fix this issue? Below is my Web.Config file for connectionString.
<connectionStrings>
<add name = "eNtsaOnlineRegistrationDB" connectionString = "Data Source=GcobaniM-L\SQLEXPRESS;AttachDbFilename=[DataDirectory]\eNtsaOnlineRegistra[enter image description here][1]tionDB.mdf;Initial Catalog=eNtsaOnlineRegistration; Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser() { UserName = model.UserName };
user.Email = model.Email;
user.ConfirmedEmail = false;
var result = await UserManager.CreateAsync(user, model.Password); ?/** Error thrown here and shown the screen shot image as attached.***/
if (result.Succeeded)
{
System.Net.Mail.MailMessage m = new System.Net.Mail.MailMessage(
new System.Net.Mail.MailAddress("ggcobani#gmail.com", "Web Registration"),
new System.Net.Mail.MailAddress(user.Email));
m.Subject = "Email confirmation";
m.Body = string.Format("Dear {0}<BR/>Thank you for your registration, please click on the below link to complete your registration: {1}", user.UserName, Url.Action("ConfirmEmail", "Account", new { Token = user.Id, Email = user.Email }, Request.Url.Scheme));
m.IsBodyHtml = true;
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.mydomain.com");
smtp.Credentials = new System.Net.NetworkCredential("ggcobani#gmail.com", "password");
smtp.EnableSsl = true;
smtp.Send(m);
return RedirectToAction("Confirm", "Account", new { Email = user.Email });
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
I have this error, on my project folder i have created _AppStart.mdf while the account on SQL Server from the Administration Service changed to local account on sql server. Now i am getting this exception each time i am trying to create new users to my database. What can i do to resolve this issue?
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser() { UserName = model.UserName };
user.Email = model.Email;
user.ConfirmedEmail = false;
var result = await UserManager.CreateAsync(user, model.Password); ?/** This throws an error line 88, each time new user is created. **/
if (result.Succeeded)
{
System.Net.Mail.MailMessage m = new System.Net.Mail.MailMessage(
new System.Net.Mail.MailAddress("ggcobani#gmail.com", "Web Registration"),
new System.Net.Mail.MailAddress(user.Email));
m.Subject = "Email confirmation";
m.Body = string.Format("Dear {0}<BR/>Thank you for your registration, please click on the below link to complete your registration: {1}", user.UserName, Url.Action("ConfirmEmail", "Account", new { Token = user.Id, Email = user.Email }, Request.Url.Scheme));
m.IsBodyHtml = true;
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.mydomain.com");
smtp.Credentials = new System.Net.NetworkCredential("ggcobani#gmail.com", "password");
smtp.EnableSsl = true;
smtp.Send(m);
return RedirectToAction("Confirm", "Account", new { Email = user.Email });
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
<connectionStrings>
<add name = "eNtsaOnlineRegistrationDB" connectionString = "Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\eNtsaOnlineRegistrationDB.mdf;Initial Catalog=eNtsaOnlineRegistration; Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
The issue was file was existing on the project folder. Under _AppStart.mdf
Re changed my connectionString as shown, the error is gone although its throwing a new one due to connected party.