Getting Authentication failed for user on running owasp ZAP scanAsuserAPI - owasp

I have used ZAP Desktop using form based authentication, zap runs perfectly fine on Desktop app. However as the web application i am using also has _csrf_token is passed along with username and Password I chose to automate it with manual authentication using selenium.
Below is the error that i am getting -
1112496 [ZAP-ProxyThread-473] INFO org.zaproxy.zap.users.User - Authentication failed for user: abc
1112601 [ZAP-ProxyThread-481] INFO org.zaproxy.zap.users.User - Authenticating user: abc
1112602 [ZAP-ProxyThread-481] INFO org.zaproxy.zap.users.User - Authentication failed for user: abc
1112624 [ZAP-ProxyThread-470] INFO org.zaproxy.zap.users.User - Authenticating user: abc
1112624 [ZAP-ProxyThread-470] INFO org.zaproxy.zap.users.User - Authentication failed for user: abc
1112648 [ZAP-ProxyThread-482] INFO org.zaproxy.zap.users.User - Authenticating user: abc
1112648 [ZAP-ProxyThread-482] INFO org.zaproxy.zap.users.User - Authentication failed for user: abc
1117079 [ZAP-ProxyThread-488] INFO org.zaproxy.zap.users.User - Authenticating user: abc
1117080 [ZAP-ProxyThread-488] INFO org.zaproxy.zap.users.User - Authentication failed for user: abc
1117082 [ZAP-ProxyThread-485] INFO org.zaproxy.zap.users.User - Authenticating user: abc
1117088 [ZAP-ProxyThread-485] INFO org.zaproxy.zap.users.User - Authentication failed for user: abc
1119534 [ZAP-ProxyThread-489] INFO org.zaproxy.zap.users.User - Authenticating user: abc
1119535 [ZAP-ProxyThread-489] INFO org.zaproxy.zap.users.User - Authentication failed for user: abc
1120768 [ZAP-ProxyThread-490] INFO org.zaproxy.zap.users.User - Authenticating user: abc
1120768 [ZAP-ProxyThread-490] INFO org.zaproxy.zap.users.User - Authentication failed for user: abc
1120770 [ZAP-ProxyThread-491] INFO org.zaproxy.zap.users.User - Authenticating user: abc
1120770 [ZAP-ProxyThread-491] INFO org.zaproxy.zap.users.User - Authentication failed for user: abc
1124677 [ZAP-ProxyThread-500] INFO org.zaproxy.zap.users.User - Authenticating user: abc
1124682 [ZAP-SpiderInitThread-4] INFO org.zaproxy.zap.extension.spider.SpiderThread - Starting spidering scan on https://****/web at 2021-10-21T19:12:37.019+0530
1124682 [ZAP-SpiderInitThread-4] INFO org.zaproxy.zap.spider.Spider - Spider initializing...
1124707 [ZAP-SpiderInitThread-4] INFO org.zaproxy.zap.spider.Spider - Starting spider...
1124709 [ZAP-SpiderInitThread-4] INFO org.zaproxy.zap.spider.Spider - Scan will be performed from the point of view of User: abc
1124714 [ZAP-SpiderThreadPool-4-thread-1] INFO org.zaproxy.zap.users.User - Authenticating user: abc
1124715 [ZAP-SpiderThreadPool-4-thread-1] INFO org.zaproxy.zap.users.User - Authentication failed for user: abc
1125460 [ZAP-SpiderThreadPool-4-thread-1] INFO org.zaproxy.zap.spider.Spider - Spidering process is complete. Shutting down...
1125462 [ZAP-SpiderShutdownThread-4] INFO org.zaproxy.zap.extension.spider.SpiderThread - Spider scanning complete: true on https://****/web at 2021-10-21T19:12:37.799+0530
My code looks like below -
#Test
public void zapScanOnTest(String jsonContextsFileName, String testCaseFile, String scanType, String scanPolicyName) throws InterruptedException {
SoftAssert softassert = new SoftAssert();
boolean login = loginPage.login(UsrName, Pwd);
softassert.assertTrue(login, "zapScanTest : Logged in");
Thread.sleep(10000);
runScanAsUserOnURLs(jsonContextsFileName,"abc_"+HostIP, "after_login_url", UsrName,scanType,scanPolicyName);
}
public void runScanAsUserOnURLs(String jsonContextsFileName, String zapContextName, String nodeName,
String UserName, String scanType, String scanPolicyName){
List<ApiResponse> listOfContext;
try {
listOfContext = ((ApiResponseList) clientApi.context.contextList()).getItems();
String contextID = setAndGetContextID(listOfContext, zapContextName);
log.info("Checking if the User already exists in Context if not Add the user to the context");
String userID = setAndGetUserID(UserName, contextID);
log.info("Fetching Json file path and reading all the URL's mentioned in JSON File");
List<String> urlLists = readJsonFileConvertUrlsToList(jsonContextsFileName, nodeName);
includeAllURLSToContext(urlLists, contextID, zapContextName);
spiderCrawlScanAsUser(contextID,userID,urlLists);
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch (ClientApiException e) {
e.printStackTrace();
}
}
public String setAndGetContextID(List<ApiResponse> listOfContext, String contextName) throws ClientApiException {
String contextID = null;
if (listOfContext.isEmpty() || isContextPresent(listOfContext, contextName) == false) {
ApiResponse newContext = clientApi.context.newContext(contextName);
contextID = newContext.toString();
log.info("Context is Created and the ID is : " + contextID);
} else {
Context context = new Context((ApiResponseSet) clientApi.context.context(contextName));
contextID = context.getId();
log.info("ID of existing Context is : " + contextID);
}
listOfContext = ((ApiResponseList) clientApi.context.contextList()).getItems();
return contextID;
}
public boolean isContextPresent(List<ApiResponse> listOfContext, String contextName) {
boolean isPresent = false;
String str = "Context is not available in list : " + listOfContext + " let's create a new context";
log.info("Checking if provided context name " + contextName + " is already present in list of context");
for (int i = 0; i < listOfContext.size(); i++) {
String zapContext = listOfContext.get(i).toString();
if (zapContext.equals(contextName)) {
isPresent = true;
str = "Context Name Already Exists : No need to create a Context again : " + listOfContext;
}
}
log.info(str);
return isPresent;
}
public String setAndGetUserID(String mcUser, String contextID) throws ClientApiException {
String userID = null;
List<ApiResponse> usersListInContext = ((ApiResponseList) clientApi.users.usersList(contextID)).getItems();
if (usersListInContext.isEmpty() || isUserPresentInContext(usersListInContext, mcUser, contextID) == false) {
userID = clientApi.users.newUser(contextID, mcUser).toString();
log.info("User is added to the Context and the user ID is : " + userID);
log.info("Enabling the User");
ApiResponse setUserEnabled = clientApi.users.setUserEnabled(contextID, userID, "true");
log.info("User is Enabled and the status is : " + setUserEnabled);
log.info("Setting Forced User");
ApiResponse setForcedUser = clientApi.forcedUser.setForcedUser(contextID, userID);
log.info("User is set as Forced User and the status is : " + setForcedUser);
log.info("Enabling Forced User Mode");
ApiResponse setForcedUserModeEnabled = clientApi.forcedUser.setForcedUserModeEnabled(true);
log.info("Enabled Forced User Mode and the status is : " + setForcedUserModeEnabled);
} else {
for (ApiResponse userListResponse : usersListInContext) {
String userList = userListResponse.toString(0);
boolean userPresentInContextList = userList.contains("name = " + mcUser);
boolean contextIDPresent = userList.contains("contextId = " + contextID);
if (userPresentInContextList == true && contextIDPresent == true) {
userID = userList.substring(userList.indexOf("id = ") + 5, userList.indexOf("enabled"));
log.info("User ID is : " + userID);
log.info("Enabling the User");
ApiResponse setUserEnabled = clientApi.users.setUserEnabled(contextID, userID, "true");
log.info("User is Enabled and the status is : " + setUserEnabled);
log.info("Setting Forced User");
ApiResponse setForcedUser = clientApi.forcedUser.setForcedUser(contextID, userID);
log.info("User is set as Forced User and the status is : " + setForcedUser);
log.info("Enabling Forced User Mode");
ApiResponse setForcedUserModeEnabled = clientApi.forcedUser.setForcedUserModeEnabled(true);
log.info("Enabled Forced User Mode and the status is : " + setForcedUserModeEnabled);
break;
}
}
}
return userID;
}
public boolean isUserPresentInContext(List<ApiResponse> usersListInContext, String mcUser, String contextID) {
boolean isPresent = false;
String str = "User is not available in Context List let's add the user";
log.info("Checking if provided User name " + mcUser + " is already present in list of context");
for (ApiResponse userListResponse : usersListInContext) {
String userList = userListResponse.toString(0);
boolean userPresentInContextList = userList.contains("name = " + mcUser);
boolean contextIDPresent = userList.contains("contextId = " + contextID);
if (userPresentInContextList == true && contextIDPresent == true) {
isPresent = true;
str = "User is already added to the context, no need to add the user again";
}
}
log.info(str);
return isPresent;
}
public List<String> readJsonFileConvertUrlsToList(String jsonContextsFileName, String nodeName) {
String filePath = readJsonFile.getJsonFilePath(jsonContextsFileName);
log.info("File Path is : " + filePath);
FileInputStream fis;
List<String> urlList = new ArrayList<>();
try {
fis = new FileInputStream(filePath);
JSONTokener tokener = new JSONTokener(fis);
JSONObject jsonObject = new JSONObject(tokener);
JSONArray contextJsonArray = jsonObject.getJSONArray("contexts");
for (int i = 0; i < contextJsonArray.length(); i++) {
JSONObject testJsonObject = contextJsonArray.getJSONObject(i);
JSONArray urlJsonArray = testJsonObject.getJSONArray(nodeName);
log.info("Running ZAP Scan on " + urlJsonArray.length() + " URL's");
for (int j = 0; j < urlJsonArray.length(); j++) {
String urlEndPoints = urlJsonArray.get(j).toString();
urlList.add(mcHostUrl + urlEndPoints);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return urlList;
}
public void includeAllURLSToContext(List<String> listOfURL, String contextID, String contextName) {
try {
log.info("Going to include URLs to context : " + contextName);
List<ApiResponse> includeContextRegex = ((ApiResponseList) clientApi.context.includeRegexs(contextName)).getItems();
for (int i = 0 ; i< listOfURL.size();i++) {
String zapTargetURL = listOfURL.get(i);
if (includeContextRegex.isEmpty() || isContextRegexPresent(includeContextRegex, zapTargetURL) == false)
clientApi.context.includeInContext(contextName, zapTargetURL);
log.info("Included Context Regex to Context : " + contextName);
}
} catch (ClientApiException e) {
e.printStackTrace();
}
}
public void spiderCrawlScanAsUser(String contextID, String userID,List<String> urlList)
throws InterruptedException, ClientApiException {
for (int i = 0 ; i< urlList.size();i++) {
String zapTargetURL = urlList.get(i);
log.info("PREPARING FOR SPIDER CRAWL ON TARGET HOST :" + zapTargetURL);
log.info("Starting Spider Scan");
ApiResponse apiResponse = clientApi.spider.scanAsUser(contextID, userID, zapTargetURL, "500",
"true", "true");
int progress;
String scanId = ((ApiResponseElement) apiResponse).getValue();
do {
Thread.sleep(5000);
progress = Integer.parseInt(((ApiResponseElement) clientApi.spider.status(scanId)).getValue());
log.info("Scan progress: {}{}", progress, "%");
} while (progress < 100);
log.info("Spider scan completed");
List<ApiResponse> spiderResults = ((ApiResponseList) clientApi.spider.results(scanId)).getItems();
log.info("spider results {}", spiderResults);
}
}
Am I missing anything in the above code? I am not able to authenticate the user at all.

To be honest I wouldnt recommend configuring ZAP that way.
I recommend testing everything in the desktop, making sure its all working and then exporting the context - you can then import that via the API.
I also notices that you are using Forced User Mode - thats really there for manual testing so I wouldnt use that for automation either. Instead specify the user when you run the spiders and active scanner.
We will bee adding more authentication docs soon and enhancing the Automation Framework to support authentication - those 2 things should make things easier.

Related

OPC-DA AddGroup not working by using "TitaniumAS.Opc.Client" c# library

I'm getting a NULL reference error while adding the group. ie: in line -> opcDaGroup = server.AddGroup("Group");
Please help me out what's the issue and how to overcome the same.
whether this is the DCOM access issue.
Code:
public OpcDaGroup opcDaGroup;
private void StartConnection(string Cls_Id, string Machine_IpAddress)
{
try
{
log.Debug("START - Starting the connection");
Uri url = UrlBuilder.Build(Cls_Id, Machine_IpAddress);
server = new OpcDaServer(url);
server.Connect();
log.Debug("END - Starting the connection");
}
catch (Exception e)
{
log.Error("Could not connect to the OPC server for the IpAddress: {0}", e);
}
}
public OpcDaAdapterThreadImpl(string Cls_Id, string Machine_IpAddress, string name, ICollection<TagConfigurationModel> tags)
{
this.Cls_Id = Cls_Id;
this.Machine_IpAddress = Machine_IpAddress;
this.name = name;
this.AdapterReady = true;
Tags = tags;
var group = tags.GroupBy(c => new { ItemName = c.TagName }).Select(c => c.Key).Distinct();
grouptags = group.Select(c => new TagConfigurationModel { TagName = c.ItemName }).ToList();
opcTagItems = grouptags.Select(c => new OpcDaItemDefinition { ItemId = c.TagName, IsActive = true }).ToList();
// Connection Initializing
StartConnection(Cls_Id, Machine_IpAddress);
if (server.IsConnected)
{
// Add group to the server
opcDaGroup = server.AddGroup("Group");
opcDaGroup.IsActive = true;
// Add Items to group
opcDaGroup.AddItems(opcTagItems);
}
}

Getting access token for SharePoint through http request via proxy server

I am able to get access token for SharePoint from accounts.accesscontrol.windows.net while I am running my application on a machine which is allowed to connect to external URL.
But when I am running my application on an environment where I can only go via a proxy server, its giving me 401: Permission denied (connect failed) even through I have added the proxy code. I am given a ProxyServer URL and port; its of type http.
Please find my code for direct hit below. This is working absolutely fine in open env:
private String getToken(String tenant_id,String client_id, String client_secret, String domain)
{
String resultToken=null;
try {
// AccessToken url
String wsURL = "https://accounts.accesscontrol.windows.net/"+ tenant_id+"/tokens/OAuth/2";
URL url = new URL(wsURL);
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) connection;
// Set header
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
String jsonParam = "grant_type=client_credentials"
+ "&client_id="+client_id+"#"+tenant_id
+ "&client_secret="+client_secret
+ "&resource=00000003-0000-0ff1-ce00-000000000000/" +domain+".com#"+tenant_id;
System.out.println("TokenRequestString : " + jsonParam);
// Send Request
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(jsonParam);
wr.flush();
wr.close();
// Read the response.
InputStreamReader isr = null;
if (httpConn.getResponseCode() == 200) {
isr = new InputStreamReader(httpConn.getInputStream());
} else {
isr = new InputStreamReader(httpConn.getErrorStream());
}
BufferedReader in = new BufferedReader(isr);
String responseString = "";
String outputString = "";
// Write response to a String.
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
// Extracting accessToken from string, here response
// (outputString)is a Json format string
if (outputString.indexOf("access_token\":\"") > -1) {
int i1 = outputString.indexOf("access_token\":\"");
String str1 = outputString.substring(i1 + 15);
int i2 = str1.indexOf("\"}");
String str2 = str1.substring(0, i2);
accessToken = str2;
}
} catch (Exception e) {
accessToken = "Error: " + e.getMessage();
}
return accessToken;
}
Below is my code where I am trying to achieve the same thing through proxy server. This is throwing Permission Denied (401)
private String getToken(String tenant_id,String client_id, String client_secret, String domain)
{
String resultToken=null;
try {
// AccessToken url
String wsURL = "https://accounts.accesscontrol.windows.net/"+ tenant_id+"/tokens/OAuth/2";
URL url = new URL(wsURL);
// via Proxy
Proxy webProxy
= new Proxy(Proxy.Type.HTTP, new InetSocketAddress("internet.xyz.com", 83);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(webProxy);
// Set header
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
String jsonParam = "grant_type=client_credentials"
+ "&client_id="+client_id+"#"+tenant_id
+ "&client_secret="+client_secret
+ "&resource=00000003-0000-0ff1-ce00-000000000000/" +domain+".com#"+tenant_id;
System.out.println("TokenRequestString : " + jsonParam);
// Send Request
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(jsonParam);
wr.flush();
wr.close();
// Read the response.
InputStreamReader isr = null;
if (httpConn.getResponseCode() == 200) {
isr = new InputStreamReader(httpConn.getInputStream());
} else {
isr = new InputStreamReader(httpConn.getErrorStream());
}
BufferedReader in = new BufferedReader(isr);
String responseString = "";
String outputString = "";
// Write response to a String.
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
// Extracting accessToken from string, here response
// (outputString)is a Json format string
if (outputString.indexOf("access_token\":\"") > -1) {
int i1 = outputString.indexOf("access_token\":\"");
String str1 = outputString.substring(i1 + 15);
int i2 = str1.indexOf("\"}");
String str2 = str1.substring(0, i2);
accessToken = str2;
}
} catch (Exception e) {
accessToken = "Error: " + e.getMessage();
}
return accessToken;
}

Web API Returns Wrong Values after being Published to IIS

Please help me. The API I created works fine when I launch it with Visual Studio but (the POST methods) has issues I deployed to IIS.
It returns wrong values and sometimes, null values. If i go back to test it in debug mode it works well.
THIS IS WHERE I'M CALLING THE API
try
{
string apiToken = "DEFAULTAPI";
EmployeeObject EmployeeObject = new EmployeeObject()
{
username = "John Doe"
password = "12345"
apiToken = apiToken
};
var emp = JsonConvert.SerializeObject(EmployeeObject);
string url = "http://localhost/PublishVersion/api/Company";
//the url variable holds the published version link
var response = client.PostAsync(url, new StringContent(emp, Encoding.UTF8, "application/json"));
response.Wait();
var result = response.Result;
if (result.IsSuccessStatusCode)
{
Uri employeeUrl = result.Headers.Location;
var statusMessage = result.Content.ReadAsStringAsync().Result;
if (statusMessage == "yes")
{
status = true;
}
else if (statusMessage == "no")
{
status = false;
}
}
return status;
}
AND THIS IS THE API
public string Post([FromBody] Employees employees)
{
string message = "no";
if (employees != null)
{
string emp = employees.username;
string password = employees.password
string apiToken = employees.apiToken
APIToken token = _dbContext.MyTable.Where(x => x.apitoken == apitoken).FirstOrDefault();
//APIToken is a table which has properties company and boss (both string)
if (token != null)
{
string company = token.company;
string boss = token.boss;
return message = "yes" + " " + company + "" + boss;
}
else
{
return message = "invalid token";
}
}
return message + employee.username;
}
The api returns "no John Doe" to the caller, which shouldn't be that way, since it displayed the username value which shows that the employee object is not null. Why doesn't it go into the block of code since it passed the null check? This issue only comes up when I deploy the API project to the IIS (version 10). Works fine in Visual Studio debug mode.
Also, the API and Winsform(where i'm calling it from) are on the same machine.
Thank you.

Not receive notification with azure notification hub when using tag

I'm new to this. The example of android is from
GetStartedFirebase
Below are the steps:
1) I install the android to my phone
2) I followed this example to create my web api
https//learn.microsoft.com/en-us/azure/notification-hubs/notification-hubs-aspnet-backend-gcm-android-push-to-user-google-notification
3) i comment out the AuthenticationTestHandler class
4)i call the below code from fiddle
The DeviceRegistration object
{
"Platform": "gcm",
"Handle": "regid i get from android",
"Tags": [
"1",
"2"
]
}
// This creates or updates a registration (with provided channelURI) at the specified id
public async Task<HttpResponseMessage> Put(string id, DeviceRegistration deviceUpdate)
{
RegistrationDescription registration = null;
switch (deviceUpdate.Platform)
{
case "mpns":
registration = new MpnsRegistrationDescription(deviceUpdate.Handle);
break;
case "wns":
registration = new WindowsRegistrationDescription(deviceUpdate.Handle);
break;
case "apns":
registration = new AppleRegistrationDescription(deviceUpdate.Handle);
break;
case "gcm":
registration = new GcmRegistrationDescription(deviceUpdate.Handle);
break;
default:
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
registration.RegistrationId = id;
var username = "test";
string[] userTag = new string[1];
userTag[0] = "username:" + username;
registration.Tags = new HashSet<string>(userTag);
try
{
await hub.CreateOrUpdateRegistrationAsync(registration);
}
catch (MessagingException e)
{
ReturnGoneIfHubResponseIsGone(e);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
5) Then i call to send the push notification
http://localhost:4486/api/Notifications?pns=gcm&to_tag=test
public async Task<HttpResponseMessage> Post(string pns, [FromBody]string message, string to_tag)
{
var user = "test";
message = "msg";
string[] userTag = new string[1];
userTag[0] = "username:" + to_tag;
Microsoft.Azure.NotificationHubs.NotificationOutcome outcome = null;
HttpStatusCode ret = HttpStatusCode.InternalServerError;
switch (pns.ToLower())
{
case "wns":
// Windows 8.1 / Windows Phone 8.1
var toast = #"<toast><visual><binding template=""ToastText01""><text id=""1"">" +
"From " + user + ": " + message + "</text></binding></visual></toast>";
outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag);
break;
case "apns":
// iOS
var alert = "{\"aps\":{\"alert\":\"" + "From " + user + ": " + message + "\"}}";
outcome = await Notifications.Instance.Hub.SendAppleNativeNotificationAsync(alert, userTag);
break;
case "gcm":
// Android
var notif = "{ \"data\" : {\"message\":\"" + "From " + user + ": " + message + "\"}}";
outcome = await Notifications.Instance.Hub.SendGcmNativeNotificationAsync(notif, userTag);
break;
}
if (outcome != null)
{
if (!((outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Abandoned) ||
(outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Unknown)))
{
ret = HttpStatusCode.OK;
}
}
return Request.CreateResponse(ret);
}
No error returned but i do not receive any notification.
I try to remove usertag as below:
outcome = await Notifications.Instance.Hub.SendGcmNativeNotificationAsync(notif);
I am able to receive the notification.
Why the tag doesn't work ?
Any help appreciated.
var allRegistrations = await Notifications.Instance.Hub.GetAllRegistrationsAsync(0);
Check your tag in allRegistrations. If it is there then it should work.
You can check test notification from http://pushtry.com
I'm confused - JSON from Fiddler shows that the registration has "1" and "2" tags, but everywhere in the code you are using "username:test" tag. Can you get this registration from the hub and make sure that it has correct tags?
You can use GetRegistrationAsync<TRegistrationDescription>(String) [1], GetRegistrationsByChannelAsync(String, Int32) [2] or GetAllRegistrationsAsync(Int32) [3] methods to get the registration.
[1] https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.notificationhubs.notificationhubclient#Microsoft_Azure_NotificationHubs_NotificationHubClient_GetRegistrationAsync__1_System_String_
[2] https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.notificationhubs.notificationhubclient#Microsoft_Azure_NotificationHubs_NotificationHubClient_GetRegistrationsByChannelAsync_System_String_System_Int32_
[3] https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.notificationhubs.notificationhubclient#Microsoft_Azure_NotificationHubs_NotificationHubClient_GetAllRegistrationsAsync_System_Int32_

Ado.net Update Command is successful but database is not updated

The following code executes successfully and the return value of cmd.ExecuteNonQuery returns 1 indicating the row was successfully updated but the database is not truly updated. How could that be? I'm using sqlserver2008.
public string updatePost(string id, string head, string body)
{
connection = new SqlConnection(connString);
string cmdStr = "update News set Header = '"+head+"' , [Text] = '"+body+"' where Id = "+int.Parse(id)+"";
string msg = String.Empty;
try
{
connection.Open();
SqlCommand cmd = new SqlCommand(cmdStr, connection);
int effected = cmd.ExecuteNonQuery();
msg += "The 'News Post - id:"+id+"' was successfully updated. Rows effected:"+effected+"";
}
catch (Exception ex)
{
msg = "The attempt to update the 'News Post - id'" + id + " failed with message: " + ex.Message;
}
finally
{
connection.Close();
}
return msg;
}
Try this, this fixes some problems (like sql-injection), perhaps also your update issue:
public string UpdatePost(string id, string head, string body)
{
string msg = "";
string cmdStr = "update News set Header = #header, [Text] = #body where Id = #id";
using (var con = new SqlConnection(connString))
{
try
{
con.Open();
using (var cmd = new SqlCommand(cmdStr, con))
{
cmd.Parameters.AddWithValue("#header", head);
cmd.Parameters.AddWithValue("#body", body);
cmd.Parameters.AddWithValue("#id", int.Parse(id));
int effected = cmd.ExecuteNonQuery();
msg += "The 'News Post - id:" + id + "' was successfully updated. Rows effected:" + effected + "";
}
} catch (Exception ex)
{
msg = "The attempt to update the 'News Post - id'" + id + " failed with message: " + ex.Message;
}
}
return msg;
}