Not able to access previous stored value in Keychain after update - c#

We’re having a problem to access a value we stored previously in keychain in a previous version of our app. We have updated our Xamarin.iOS version from 11.6.14 to 12.2.1.15 and our XCode version from 9.4.1 to 10.1.
We are not able to access that value anymore after the update.
I have read there are some changes in the security settings, but I’m not able to find the specifics about that. Is there anybody that had that problem before or has lot of experience with keychain? Thanks for your help!
bool WriteGenericPasswordValueToSecureKeychain(string service, string account, string value)
{
if (service == null || account == null || value == null)
{
throw new ArgumentNullException("Both arguments need a value and cannot be null");
}
var query = new SecRecord(SecKind.GenericPassword)
{
Service = service,
Account = account
};
var newRecord = new SecRecord(SecKind.GenericPassword)
{
Service = service,
Account = account,
ValueData = NSData.FromString(value, NSStringEncoding.UTF8)
};
SecStatusCode error;
var match = SecKeyChain.QueryAsRecord(query, out error);
if (error == SecStatusCode.Success)
{
error = SecKeyChain.Update(match, newRecord);
}
else
{
error = SecKeyChain.Add(newRecord);
}
if (error != SecStatusCode.Success && error != SecStatusCode.DuplicateItem)
{
return false;
}
return true;
}

Related

Add binding to IIS-site - NullReferenceException

I am trying to add bindings to a website in IIS with C# code. It seem to work on my local computer, but not on the hosting server (Windows Server 2022). Adding http-binding works, but commit after https causes NullReferenceException, and i am wondering if any of you can explain to me why?
My code is like this (i replaced my actual domainname with . "sitename" and "hostHttpsBinding" always exists with the certificate i want to use):
public static bool AddBindings(IConfiguration configuration, ILogger logger, string subdomain)
{
if (string.IsNullOrWhiteSpace(subdomain)) return false;
try
{
var server = new ServerManager();
var sitename = EnvironmentHelper.IsProd(configuration) ? "<domain>.no" : "test.<domain>.no";
var hostname = $"{subdomain.ToLowerInvariant().Trim()}.<domain>.no";
var site = server.Sites.FirstOrDefault(a => a.Name == sitename);
if (site == null) return false;
logger.LogInformation($"IIS: Sitename {sitename} found. Trying to add bindings...");
var hostHttpsBinding = site.Bindings.FirstOrDefault(a => a.BindingInformation == $"*:443:{sitename}");
var httpBinding = site.Bindings.FirstOrDefault(a => a.BindingInformation == $"*:80:{hostname}");
var httpsBinding = site.Bindings.FirstOrDefault(a => a.BindingInformation == $"*:443:{hostname}");
if (httpBinding != null && httpsBinding != null) return false;
if (httpBinding == null)
{
site.Bindings.Add($"*:80:{hostname}", "http");
logger.LogInformation($"IIS: Http-binding added for {hostname}");
}
if (httpsBinding == null)
{
logger.LogInformation($"SSLName: {hostHttpsBinding.CertificateStoreName}, Hash: {hostHttpsBinding.CertificateHash}");
site.Bindings.Add($"*:443:{hostname}", hostHttpsBinding.CertificateHash, hostHttpsBinding.CertificateStoreName, SslFlags.Sni);
logger.LogInformation($"IIS: Https-binding added for {hostname}");
}
server.CommitChanges();
server.Dispose();
return true;
}
catch (Exception e)
{
logger.LogError($"IIS: Something went wrong when adding bindings: {e.Message}, {e.InnerException.Message}");
return false;
}
}
This is my error message:
ERROR|Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer|Connection ID "16717361851964326032", Request ID "40000091-0008-e800-b63f-84710c7967bb": An unhandled exception was thrown by the application.|System.NullReferenceException: Object reference not set to an instance of an object.

Session value returned null in mvc5 asp.net

I have login controller and in this i get my session values
[HttpPost]
public ActionResult Login(Models.AdminUsers adminUsers)
{
try
{
if (Session["iUserId"] != null || GetCookie("iUserId") != null)
{
return Redirect("/Home/Index");
}
if (ModelState.IsValid)
{
using (Data.DataClassesDataContext dc = new Data.DataClassesDataContext())
{
var resultUsers =
(from tableAdminUsers in dc.AdminUsers
where
tableAdminUsers.cEmail == adminUsers.cEmail &&
tableAdminUsers.cPassaword == new Class.AesCryption().Encryption(adminUsers.cPassaword) &&
tableAdminUsers.iActive == 1
select new Models.AdminUsers
{
iUserId = tableAdminUsers.iUserId,
cEmail = tableAdminUsers.cEmail,
cUserName = tableAdminUsers.cUserName,
cUserSurname = tableAdminUsers.cUserSurname,
cImage = tableAdminUsers.cImage
}).FirstOrDefault();
if (resultUsers != null)
{
if (adminUsers.lBeniHatirla == false)
{
Session.Add("iUserId", resultUsers.iUserId);
Session.Add("cEmail", resultUsers.cEmail);
Session.Add("cUserName", new Class.TextLowerAndFirstUpper().Send(resultUsers.cUserName));
Session.Add("cUserSurname", resultUsers.cUserSurname.ToUpper());
Session.Add("cImage", resultUsers.cImage);
}
else
{
CreateCookie("iUserId", resultUsers.iUserId.ToString());
CreateCookie("cEmail", resultUsers.cEmail);
CreateCookie("cUserName", new Class.TextLowerAndFirstUpper().Send(resultUsers.cUserName));
CreateCookie("cUserSurname", resultUsers.cUserSurname.ToUpper());
CreateCookie("cImage", resultUsers.cImage);
}
return Redirect("/Home/Index");
}
else
{
ViewBag.iSonuc = -7;
}
}
}
else
{
ViewBag.iSonuc = -6;
}
}
catch (Exception Ex)
{
new Class.Log().Hata("AdminUsers", "AdminUsers_Post", Ex.Message);
}
return View();
}
And i want to control to session in another controller but my session value return null. My control like this :
if (Session["iUserId"] == null && GetCookie("iUserId") == null)
{
return Redirect("/AdminUsers/Login");
}
int iUserLogin = 0;
if (Session["iUserId"] != null && Convert.ToInt32(Session["iUserId"]) > 0)
{
iUserLogin = Convert.ToInt32(Session["iUserId"]);
}
else if (GetCookie("iUserId") != null && Convert.ToInt32(GetCookie("iUserId")) > 0)
{
iUserLogin = Convert.ToInt32(GetCookie("iUserId"));
}
if (Session["iUserId"] == null && GetCookie("iUserId") == null) this row return true and redict to login page again.But i getting cookie correctly Why session value return null?
Where am I making mistakes? Can you help me?
If it is a .net core, use httpcontext. You can solve it using a distribution cache such as Redis. https://learn.microsoft.com/tr-tr/aspnet/core/fundamentals/app-state?view=aspnetcore-5.0
If you want to develop a User Manager
Use a thirty part nuget like Jwt. What it does is sso logic gives you a token for the user you use it
Try using Session with HttpContext as below:-
HttpContext.Current.Session["iUserId"]=value;
Alternativly, you can try using TempData rather then Session.
TempData["iUserId"]=value;
There is a localization function that I use for language change, in this function I am changing the value of the culture using thread, I realized that this function resets my session value.

C# use field 1 value if field 2 empty

I am running through a set of records using a for each loop, and also doing simple checks to ensure that good data is inserted into a database table.
Sometimes the dataset can be missing the LegistarID value, the change I need to do in my code, is to add a check for LegistarItem,
if the value of LegistarID is missing, but the AgendaItem value is not, then assign the value of AgendaItem to LegistarID
if LegistarId is missing, and there is also no AgendaItem value, then return a message to the user, to let them know that these values need to be present in the dataset they are trying to import.
I know it does not sound complex, but I am having a hard time making this change successfully. I need a bit of help if possible, please.
Here is my code as I currently have it:
if (ModelState.IsValid)
{
using (Etities db = new Entities())
{
foreach (var i in meeting)
{
if (i.MeetingID == 0)
{
message = string.Format("This file is missing the Meeting ID value of at least 1 record. \n Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.", i.MeetingID);
return new JsonResult { Data = new { status = status, message = message } };
}
else
{
// development
var compositeKey = db.MeetingAgenda.Find(i.MeetingID, i.AgendaItem);
if (compositeKey == null)
{
// Add new
// development
db.MeetingAgenda.Add(i);
//
}
else
{
// Serves as an update, or addition of a previously imported dataset
db.Entry(compositeKey).CurrentValues.SetValues(i.MeetingID);
db.Entry(compositeKey).State = EntityState.Modified;
}
}
}
db.SaveChanges();
status = true;
}
}
else
{
message = string.Format("Please, verify that the file you are trying to upload is correctly formatted, and that the data it contains, meets the expected criteria, then click the upload button again. \n Thank you!");
return new JsonResult { Data = new { status = status, message = message } };
}
I think that part of the code I need is something like this:
else if (i.LegistarID == 0 and i.AgendaItem != 0)
{
i.LegistarID = i.AgendaItem
}
I just am unsure how in the current code place it.
I would check all rows before returning a result.
if (ModelState.IsValid) {
var errors = new List<string> ();
var rowCounter = 1;
using (Etities db = new Entities ()) {
foreach (var i in meeting) {
if (i.MeetingID == 0) {
// Let the user know this row is bad
errors.Add ($"Row {rowCounter}: This file is missing the Meeting ID. Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.");
}
// Check if LegistarID is missing
if (i.LegistarID == 0) {
// Check if Agenda Item is present
if (i.AgendaItem == 0) {
errors.Add ($"Row {rowCounter}: Meeting has no LegistarID and no Agenda Item. Please check data");
} else {
i.LegistarID = i.AgendaItem
}
}
// development
var compositeKey = db.MeetingAgenda.Find (i.MeetingID, i.AgendaItem);
if (compositeKey == null) {
// Add new
// development
db.MeetingAgenda.Add (i);
//
} else {
// Serves as an update, or addition of a previously imported dataset
db.Entry (compositeKey).CurrentValues.SetValues (i.MeetingID);
db.Entry (compositeKey).State = EntityState.Modified;
}
rowCounter++;
}
// If there are errors do not save and return error message
if (errors.Count > 0) {
return new JsonResult { Data = new { status = false, message = string.Join ("\n", errors) } };
}
db.SaveChanges ();
status = true;
}
} else {
message = string.Format ("Please, verify that the file you are trying to upload is correctly formatted, and that the data it contains, meets the expected criteria, then click the upload button again. \n Thank you!");
return new JsonResult { Data = new { status = status, message = message } };
}
The "if(i.MeetingID == 0)" else is redundant, because you are returning if the condition is met. So to avoid unneeded/confusing nesting I would rewrite the actual code (of the loop only) as:
foreach (var i in meeting)
{
if (i.MeetingID == 0)
{
message = string.Format("This file is missing the Meeting ID value of at least 1 record. \n Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.", i.MeetingID);
return new JsonResult { Data = new { status = status, message = message } };
}
// development
var compositeKey = db.MeetingAgenda.Find(i.MeetingID, i.AgendaItem);
if (compositeKey == null)
{
// Add new
// development
db.MeetingAgenda.Add(i);
//
}
else
{
// Serves as an update, or addition of a previously imported dataset
db.Entry(compositeKey).CurrentValues.SetValues(i.MeetingID);
db.Entry(compositeKey).State = EntityState.Modified;
}
}
Then, I would add the new condition in between the MeetingID = 0 check and the rest of the code, like this:
foreach (var i in meeting)
{
if (i.MeetingID == 0)
{
message = string.Format("This file is missing the Meeting ID value of at least 1 record. \n Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.", i.MeetingID);
return new JsonResult { Data = new { status = status, message = message } };
}
// *** New check on LegistarID and AgendaItem ***
if(i.LegistarID == 0)
{
// Is there a chance to fill LegistarID with AgendaItem?
if(i.AgendaItem != 0)
{
// Yes, fill it and then let the rest of the code flow peacefully.
i.LegistarID = i.AgendaItem
}
else
{
// No way: I must stop the procedure here and warn the user about this.
// return "these values need to be present in the dataset they are trying to import."
}
}
// development
var compositeKey = db.MeetingAgenda.Find(i.MeetingID, i.AgendaItem);
if (compositeKey == null)
{
// Add new
// development
db.MeetingAgenda.Add(i);
//
}
else
{
// Serves as an update, or addition of a previously imported dataset
db.Entry(compositeKey).CurrentValues.SetValues(i.MeetingID);
db.Entry(compositeKey).State = EntityState.Modified;
}
}

Microsoft Identity Platform - User Token Cache args.Account is always null

I have an MVC web application wanting to send emails from one email address using Office365. I am calling the API so that it shows up the microsoftonline login page for signing in. On successful sign in I am receiving the code back from API and generating Microsoft.Identity.Client.AuthenticationResult with the help of code and saving tokenresponse.UniqueId and tokenresponse.Account.HomeAccountId.Identifier in database.
I got to following page and signed in successfully and my database has the response saved.
After this I am trying to send emails using following code:
IConfidentialClientApplication mailer;
var mailerbuilder = ConfidentialClientApplicationBuilder
.Create(o365setpQry.ClientId))
.WithAuthority(AzureCloudInstance.AzurePublic, o365setpQry.Tenant)
.WithClientSecret(o365setpQry.ClientSecret);
mailerbuilder.WithRedirectUri(O365OAuthRedirectURL);
mailer = mailerbuilder.Build();
//user token cache.
mailer.UserTokenCache.SetAfterAccess((args) => {
Users user;
if **(args.Account == null)** user = null;
else user = _users.Table.Where(x => x.email_address == args.Account.Username).FirstOrDefault();
if (user == null)
{
var emsetp = _emsetp.Table.FirstOrDefault();
if (args.HasStateChanged || (emsetp.o365_GlobalTokenInfo == null))
{
emsetp.o365_GlobalTokenInfo = args.TokenCache.SerializeMsalV3();
}
}
else if (args.HasStateChanged || (user.o365_TokenInfo == null))
{
user.o365_TokenInfo = args.TokenCache.SerializeMsalV3();
_users.Update(user);
}
});
webEmailer.UserTokenCache.SetBeforeAccess((args) => {
Users user;
**if (args.Account == null)** user = null;
else user = _users.Table.Where(x => x.email_address == args.Account.Username).FirstOrDefault();
if (user == null)
{
args.TokenCache.DeserializeMsalV3(_emsetp.Table.FirstOrDefault().o365_GlobalTokenInfo);
}
else if (user.o365_TokenInfo != null)
{
args.TokenCache.DeserializeMsalV3(user.o365_TokenInfo);
}
});
var t = mailer.GetAccountAsync(emsetp.FirstOrDefault().o365_GlobalToken);
t.Wait();
Microsoft.Identity.Client.IAccount acct = t.Result;
The args.Account is returning null always.
var RequestClient = GraphClientFactory.Create(new DelegateAuthenticationProvider(new AuthenticateRequestAsyncDelegate((args) => {
var tokenRequest = mailer.AcquireTokenSilent(scopes, acct).ExecuteAsync();
tokenRequest.Wait();
args.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenRequest.Result.AccessToken);
return System.Threading.Tasks.Task.FromResult(0);
})));
var graphClient = new GraphServiceClient(RequestClient);
var t = graphClient.Me.SendMail(message, true).Request();
var u = t.PostAsync();
I made sure my redirect urls are matching and I am not getting any errors from the API calls to see what is wrong and what makes args.Account value null and thus am not able to send emails. If I request the sign in page again it still shows the account I am signed in with.

Windows explorer get unresponsive while application is calling web service

I have a .Net 3.5 application that I have running as a service. This application has a thread that calls a web service and stores that data in a SQLite database.
In development we never had any problems with this but in production the web service call takes up to 20 seconds to complete. When the application calls the web service and is waiting for the reply windows explorer because laggy and unresponsive. When the call returns windows explorer acts normal again until it calls the web service and waits for the reply.
The cpu usage of the process is very low and does not spike when calling the web service. I can see the I/O hit to the hard drive when it writes to the database but that all happens in a split second and surely cannot be the cause of the slowdown.
Any help would be greatly appreciated as I am at a loss for this problem right now.
Machine Specs
Windows XP SP3
Intel core i5 3.2GHz
3.5 GB RAM
Code
public void UpdateMembers()
{
var moreMembersToUpdate = true;
while (moreMembersToUpdate)
{
var response = GetMembersToUpdate();
if (response != null)
{
UpdateLicense(response.licensed);
if (response.memberResult == null || response.memberResult.recordsReturned == 0)
break;
}
else
break;
UpdateMemberCache(response.memberResult.memberList, response.memberResult.lastUpdate,
response.memberResult.lastMembersTransactionID);
moreMembersToUpdate = response.memberResult.recordsLeft;
}
}
public void UpdateLicense(bool licensed)
{
var list = DataMapper.GetMapper().QueryForList("Select.License", null);
if (list != null && list.Count > 0)
{
var isLicensed = (Boolean) list[0];
if(isLicensed != licensed)
{
DataMapper.GetMapper().Update("Update.License", licensed);
}
}
else
DataMapper.GetMapper().Insert("Insert.License", licensed);
}
public StoredValueResponse GetMembersToUpdate()
{
var token = new OperationToken
{
company = Settings.GetCompany(),
storeID = Settings.GetStoreID(),
operationID = Guid.NewGuid().ToString(),
batchSize = 3000,
password = Settings.GetPassword(),
userName = Settings.GetCompany()
};
var lastSync = GetLastMemberCacheSync();
return WebMethods.GetUpdatedMemberCache(token, lastSync.TransactionDetailID);
}
public MemberSyncRecord GetLastMemberCacheSync()
{
var lastMemberSync = DataMapper.GetMapper().QueryForList("Select.LastMemberUpdate", null);
if (lastMemberSync != null && lastMemberSync.Count > 0 && lastMemberSync[0] != null)
return (MemberSyncRecord)lastMemberSync[0];
var record = new MemberSyncRecord
{
LastMembersTransactionTime = new DateTime(1900, 1, 1),
TransactionDetailID = 0
};
return record;
}
public void UpdateMemberCache(SmallMemberInfo[] members, DateTime lastSyncTime, long transactionDetailID)
{
try
{
DataMapper.GetMapper().BeginTransaction();
foreach (var member in members)
{
DataMapper.GetMapper().Insert("Insert.MemberInfo", member);
}
DataMapper.GetMapper().CommitTransaction();
}
catch(Exception)
{
DataMapper.GetMapper().RollBackTransaction();
throw;
}
UpdateMemberCacheSyncHistory(lastSyncTime, members.Length, transactionDetailID);
}

Categories