I am facing an error when requesting to WEBPageMethod using jquery and get 401 Unauthorized response and here is code for that
function SaveFile(type) {
var prmList = '';
prmList += '{"Title":"' + $("#txtTitleAudio").val() + '",';
prmList += '"Tag":"' + $("#txtAudioTag").val() + '",';
prmList += '"IsEnable":"' + $('input[name=chkrepost]').is(':checked') + '"}';
$.ajax({
type: "POST",
url: "AudioDairy.aspx/SaveAudio",
data: prmList,
contentType: "application/json",
dataType: "json",
success: function (msg) {
},
error: AjaxFailed
});
}
and Server Side Code Is
[WebMethod]
public string SaveAudios(string Title, string Tag, string IsEnable)
{
//lblSelectedDate.Text = DateTime.Now.ToShortDateString();
return "try Later.";
// }
}
So Please do the needful.
This seems like a security/authentication issue with your ASP.NET App. Check out these tips from the ASP.NET Forum
There are several things you need to verify.
Does the web service you are trying to access allow Anonymous
Access? Authentication can be tricky
for web-to-web calls
What is the web application running under, IWAM_xxx or IUSR_xxx?
Or are you using an
application pool running under a specific identity?
You may want to make sure your web application server's ASPNET or NETWORK
SERVICE
accounts can access your web service server.
Hope that helps...
Related
I am new to mobile development. My project is build using asp.net. For authentication I am using build it UserManager & User.Identity.
I have bunch of existing web apis and I wish to use them from mobile app.
I know , I could pass a secret hash to web api after authenticating, but that would involve a huge code refactoring.
I been wondering if there other ways to handle authentication & authorization with nativescript & asp.net .
Do you know any useful resources for this topic?
Many thanks for your help!
It depends quite heavily on your API structure, but I would recommend somethign like this:
Firstly you would need to use the Nativescript Http module. An implementation to get a an HTTP GET calls returned header might look like this:
http.request({ url: "https://httpbin.org/get", method: "GET" }).then(function (response) {
//// Argument (response) is HttpResponse!
//for (var header in response.headers) {
// console.log(header + ":" + response.headers[header]);
//}
}, function (e) {
//// Argument (e) is Error!
});
So your backend might return a JSON Web Token as a header. In which case on the success callback you would probably want to store your token in the applications persistent memory. I would use the Application Settings module, which would look something like:
var appSettings = require("application-settings");
appSettings.setString("storedToken", tokenValue);
Then before you make an API call for a new token you can check if there is a stored value:
var tokenValue = appSettings.getString("storedToken");
if (tokenValue === undefined {
//do API call
}
Then with your token, you would want to make an API call, e.g. this POST and add the token as a header:
http.request({
url: "https://httpbin.org/post",
method: "POST",
headers: { "Content-Type": "application/json", "Auth": tokenValue },
content: JSON.stringify({ MyVariableOne: "ValueOne", MyVariableTwo: "ValueTwo" })
}).then(function (response) {
// result = response.content.toJSON();
// console.log(result);
}, function (e) {
// console.log("Error occurred " + e);
});
Your backend would need to check the Auth header and validate the JWT to decide whether to accept or reject the call.
Alternatively, there some nice plugins for various Backends-as-a-Service, e.g. Azure and Firebase
I am trying for a while to figure out how to solve SSO (Single Sign On) with Thinktecture IdentityServer v3 for a legacy webforms application. Unfortunately I am stacked.
The infrastructure is like this:
A WebForm App which need authentication and Authorization (possibly
cookie or bearer token)
A javascript lightweight app (once the user is authenticated) makes requests to an WebApi (which is on separate domain)
I am having the following questions which hopefully will help me to bring things up:
I can't make the legacy webforms application to redirect to IdentityServer, even with set in the Web.Config. I have in the Startup.cs the app.UseCookieAuthentication(....) and app.UseOpenIdConnectAuthentication(....) correctly set ( I guess ). For MVC the [Authorize] attribute force the redirection to the IdentityServer. How this should be done for webforms?
Is there a way once the user is logged in, to reuse the token stored in the cookie as bearer token to the WebApi calls, made from the javascript client. I just want to do the requests to the WebApi on behalf on currently logged user (once again the webforms app and the webapi are on different domains)
Any help will be much appreciated.
Thanks!
I'm currently working on the same type of project. This is what I have found out so far.
There is 4 Separate Concerns.
Identity Server - Maintains Authenticating Users / Clients / Scope
WebApi - Consumes Token generated by Identity Server for Authorization & Identity Information of User.
WebForms / JQuery - For my project currently handles authentication for existing functionality redirects to the new WebApi.
HTML using Javascript - Strictly uses WebApi for Information.
The custom grant below is for a user currently logged in through the WebForm as a membership object & I do not want to ask the user again to relogin via Identity Server.
For direct oAuth Authentication check out the sample here..
Sample Javascript Client
Configuring the Javascript an Implicit Flow would work just fine. Save the token connect with the api.
Identity Server v3
I had to configured using
Custom Grant w IUserService
Custom Grants
These will show how to configure a custom grant validation. With the user service you can have the Identity Service query existing users & customize claims.
There is alot of configuration to the Identity Server to make it your own. this is al very well documented on the IdentityServer website I wont go in how to set the basics up.
Ex: Client Configuration
return new List<Client>
{
new Client
{
ClientName = "Custom Grant Client",
Enabled = true,
ClientId = "client",
ClientSecrets = new List<ClientSecret>
{
new ClientSecret("secret".Sha256()),
},
Flow = Flows.Custom,
CustomGrantTypeRestrictions = new List<string>
{
"custom"
}
}
};
WebApi - Resource
Example
WebApi Client Sample
Need to have the Nuget package
Thinktecture.IdentityServer.AccessTokenValidation
Startup.cs
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
//Location of your identity server
Authority = "https://localhost:44333/core"
});
WebForms
BackEnd WebForms Call
Need Nuget Package
Thinktecture.IdentityModel.Client
[WebMethod]
[ScriptMethod(ResponseFormat.Json)]
public static string AuthorizeClient()
{
var client = new OAuth2Client(
//location of identity server, ClientId, ClientSecret
new Uri("http://localhost:44333/core/connect/token"),
"client",
"secret");
//ClientGrantRestriction, Scope (I have a Client Scope of read), Listing of claims
var result = client.RequestCustomGrantAsync("custom", "read", new Dictionary<string, string>
{
{ "account_store", "foo" },
{ "legacy_id", "bob" },
{ "legacy_secret", "bob" }
}).Result;
return result.AccessToken;
}
These are generic claim for this example however I can generate my own claim objects relating to the user to send to the Identity Server & regenerate an Identity for the WebApi to consume.
WebForms / JQuery
using
JQuery.cookie
$('#btnTokenCreate').click(function (e) {
//Create Token from User Information
Ajax({
url: "Default.aspx/AuthorizeClient",
type: "POST"
},
null,
function (data) {
sendToken = data.d;
//Clear Cookie
$.removeCookie('UserAccessToken', { path: '/' });
//Make API Wrap Info in Stringify
$.cookie.json = true;
//Save Token as Cookie
$.cookie('UserAccessToken', sendToken, { expires: 7, path: '/' });
});
JQuery WebAPI Ajax
Sample Ajax Method - Note the beforeSend.
function Ajax(options, apiToken, successCallback) {
//Perform Ajax Call
$.ajax({
url: options.url,
data: options.params,
dataType: "json",
type: options.type,
async: false,
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
//Before Sending Ajax Perform Cursor Switch
beforeSend: function (xhr) {
//Adds ApiToken to Ajax Header
if (apiToken) {
xhr.withCredentials = true;
xhr.setRequestHeader("Authorization", " Bearer " + apiToken);
}
},
// Sync Results
success: function (data, textStatus, jqXHR) {
successCallback(data, textStatus, jqXHR);
},
//Sync Fail Call back
error: function (jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
}
});
}
AngularJS
This has same idea as the JQuery using the
module.run(function($http) {
//Make API Wrap Info in Stringify
$.cookie.json = true;
//Save Token as Cookie
var token = $.cookie('UserAccessToken');
$http.defaults.headers.common.Authorization = 'Bearer ' + token });
This makes the assumption your using the same domain as the WebForm. Otherwise I would use a Query string for a redirect to the Angular page with the token.
For CORS support need to make sure the WebApi has Cors configured for proper functionality. using the
Microsoft.AspNet.WebApi.Cors
Hope this sheds some light on the subject of how to approach this
I am getting an error from a service which works on local system and on other domains (uploaded separately on each domain.) It returns the error:
"SyntaxError: JSON.parse: unexpected character"
The same service with same methods works on other domains.
Is there any issue regarding folder rights? If yes, can anyone tell what to change?
It is not a cross-browser issue as it is uploaded on same server from where I am accessing.
If I call this service from code behind by addding web reference then it works fine.
function GetHints(keyword, domain_id) {
var dataString = "{keyword: '" + keyword + "',domain_id: '" + domain_id + "'}";
$.ajax({
type: "POST",
url: "/test.asmx/GetKeywordSearch?" + (new Date()).getTime() + "",
data: dataString,
contentType: "application/json; charset=utf-8",
dataType: "json",
cache: false,
success: function (msg) {
var str = msg.d;
alert(str);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("An error has occurred making the request: " + errorThrown);
}
});
}
The Reason that service was not working is web.config. i Was missing web.config service settings. Handlers for service that are mostly added by Visual studio. But it missed that. After addition of handlers it works fine
I am trying to communicate to database from JavaScript using AJAX.
I have followed one article A beginner’s guide for consuming a WCF service in JavaScript using ASP.NET AJAX to understand about this functionality. I have done everything like exactly shown in the article. But, I couldn't understand how to set up the communication from JavaScript file.
Please note that as per my project requirement I can use only the second technique explained in the article: Using a Service Interface Defined in the Class Library.
Can anybody please suggest me how to do this?
Follow these steps
1) Creat a WCF service in your application.
2) Then add reference to your WCF Service.
3) Then add wcf service to the script manager control of your page
4) Now you can access the wcf service on your page.
Step by Step tutorial using VB.NET
http://v4.ajaxtutorials.com/tutorials/javascript/expose-wcf-service-to-javascript-in-asp-net-4-0-vb/
I used the following JavaScript code to get data from the database over AJAX:
$(function () {
var search = $("#<%=txtAccountNo.ClientID%>");
search.watermark('Enter Account No');
search.autocomplete({
source: function (request, response) {
$.ajax({
url: '<%=ResolveUrl("~/") %>AutoCompleteService.asmx/GetAccountNo',
data: "{'prefixText':'" + search.val() + "','count':'10','contextKey':''}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
if (data.d != null) {
response($.map(data.d, function (item) {
return {
value: item
}
}))
}
},
error: function (XMLHttpRequest, textStatus, error) {
//alert(textStatus);
}
});
},
minLength: 1
});
});
I am using the following code to post data from a asp.net 2.0 site to an asp.net 2.0 web service that post the data to a server:
$.ajax({
type: "POST",
url: "SynchroniseCustomers.asmx/synchroniseCustomers",
data: JSON.stringify(customerObj),
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (xhr, status) {
// If not successfull
},
success: function (msg) {
deleteCustomer(customer.id);
}
});
I have a JavaScript function to check if I have connection or not, if I have I run the synchronisation (pulling data from web kit browser local database):
function checkConnection() {
var i = new Image();
i.onload = synchronise;
i.onerror = fail;
i.src = 'http://myurl.com/ping.gif?d=' + escape(Date());
setTimeout("checkConnection()", 60000); // Execute every minute
}
Thing is, if I run this locally and drop my internet connection the web service returns a 500 error (like I want it to do) and deleteCustomer(customer.id); is not called. However, on the live site if I drop my connection the web service does not return an error and deleteCustomer(customer.id); is called even if I don't have a connection to the internet (customer gets deleted from local database without being posted to the web server).
What's the reason for this? Please let me know if you need more code.
Thanks in advance.
You probably didn't wait a minute after dropping the connection.
There is a case that Ajax recall the cached data when you are ask for delete, and even if you are not connected to the net its get it from cache, so thats why its think that is all ok. The cache on jQuery Ajax is true by default.
So try with cache:false
$.ajax({
type: "POST",
url: "SynchroniseCustomers.asmx/synchroniseCustomers",
data: JSON.stringify(customerObj),
contentType: "application/json; charset=utf-8",
dataType: "json",
cache:false,
error: function (xhr, status) {
// If not successfull
},
success: function (msg) {
deleteCustomer(customer.id);
}
});
For the image call, its better to use Interval and not create memory again and again.
<img id="PingerImg" width="1" height="1" src="/spacer.gif?" onload="synchronise" onerror="fail" />
<script language="javascript" type="text/javascript">
var myImg = document.getElementById("PingerImg");
if (myImg){
window.setInterval(function(){myImg.src = myImg.src.replace(/\?.*$/, '?' + Math.random());}, 60000);
}
</script>
Update
The other solution is to really get a confirmation code form the server that you have delete the user, and only if you read that code , proceed to delete the user on remote.
success: function (msg) {
if(msg.confirm = true)
{
deleteCustomer(customer.id);
}
else
{
alert('Fail to delete user.');
}
}