Passing DataSnap Authentication Credentials with jquery and AJAX - delphi

I am attempting to build a Delphi XE2 DataSnap Rest server to be used as a 3rd party API for access to our DBMS.
I have extended the functionality of the sample methods provided when using the rest datasnap wizard in xe2 with authentication and authorization.
I can confirm that all the server methods I have written do pass back the data expected when accessed directly through the browser.
The issue comes from trying to authenticate to the server from a $.ajax() call.
When accessed from the browser address bar, you are prompted for the username and password and, when you enter "dev" for both, allows you to continue.
When setting the ajax() username and password params to "dev", I am getting a HTTP 401 response.
I think I am doing it correctly, but here is the code snippet:
$("#contentdiv").click(function(){
$.ajax({
type:"GET",
cache:"false",
username:"dev",
password:"dev",
url:"http://192.168.0.2:8080/datasnap/rest/TServerMethods1/methodname/",
dataType:"jsonp",
statusCode: {
200: function(data){
alert('success ');
}
}
});
});
If I turn off authentication, I can successfully get a HTTP 200 response (albeit with a syntax error in the JSON Delphi DataSnap is returning, but that is a question for a different time).
Also, what is worth know - if I log in manually and then run the ajax, it works - I am assuming that this is because the credentials are cached or some such.
Quite new to both these technologies, so be gentle.
If I've left something out that could be of import, let me know and I will get it up here.

Your Ajax code uses JSONP, the server uses basic authentification.
A comment on this answer says that JSONP cannot contain the USER / PWD headers which Basic Auth requires:
Basic Authentication with jQuery.ajax request and jsonp
The reason is (quote from the answer above):
JSONP works differently, it's a GET request via a tag include
to get the file, so you're not sending special headers or anything.

Related

AWS and Cognito

I'm a newbie to this stuff so downloaded the samples which is all fine and I thought I could see what was going on and what I needed to do. However, got a bit stuck for no obvious reason so I wondered if anyone could maybe give me some hints.
I'm trying to engineer Cognito authentication and identity into an old Apache Struts 1 legacy web application written in Java, so all the activity needs to be server-side. Using the Cognito https://xxx.auth.xxx.amazoncognito.com/login? URL I can successfully authenticate and get an auth code back using this URL providing my client id, redirect URI and response_type=code so all good thus far.
If I then create an HttpClient (as per the sample code in Github) and call the token URL https://xxx.auth.xxx.amazoncognito.com/oauth2/token and write various parameters to the request body (grant_type=authorization_code, client_id=as previously, redirect_uri=my URI and code=auth code just returned), I get an "unauthorized_client" message returned. But the code is valid albeit for authorization, and the client_id is correct because I used it previously.
My log:
Cognito following successful signin, continuing to url http:[redacted]/passport/CognitoHandlerSignIn.do?code=62eeb0b1-a76b-489b-bd28-e42023a497bd
(this was the /login succeeding)
Callback from Cognito received
(following is the log dump of the /oauth2/token URI called to)
Cognito token signin URL is https:[redacted].amazoncognito.com/oauth2/token
HTTP request header, added Authorization=Basic M29wcGR0azdpYzF2YjloNGd0OTQzNXYxcmI6MW9mMmFsaWNzZGR2dHZ1NmFkOHRuc2s4cnJ0cXEyYm0yc3RqbG1mcmkyamhkdXBubG1wMw==
HTTP request header, added Content-Type=application/x-www-form-urlencoded
HTTP request body, added grant_type=authorization_code
HTTP request body, added
redirect_uri=https%3A%2F%2F<redacted>%2Fpassport%2FCognitoHandlerSignIn.do
HTTP request body, added code=62eeb0b1-a76b-489b-bd28-e42023a497bd
HTTP request body, added client_id=[redacted]
HTTP request is sun.net.www.protocol.https.DelegateHttpsURLConnection:https:
[redacted].auth.eu-west-1.amazoncognito.com/oauth2/token
HTTP Json result=<{"error":"unauthorized_client"}>
org.json.JSONException: JSONObject not found.
at org.json.JSONObject.get(JSONObject.java:454)
at
What's wrong with this picture? I tried also adding client_id, code as URL parameters but I just get an "invalid_client" message instead.
I also tried using the /oauth2/token URI directly from the Struts app to provide a token but it returns the id_token using # rather than ? in the parameter list so it is client-side only and hence can't be intercepted by the Struts app and so will be a pain to forward to the server, but I could write some Javascript to do it if I had to. It doesn't seem the path of least resistance, though, as it seems wrong that the pure Java server side call doesn't work so I must be doing something wrong which isn't obvious to me.

Invalid authenticity token when POSTing to a Rails API

I have a web application that gets & stores some data through a Rails API.
When I try to "post" to the Rails API, I get an error ActionController::InvalidAuthenticityToken. I know one option is to simply disable the authenticity token requirement on my Rails controller.
Is it possible to have my web app providing a correct authenticity token when it calls the Rails API? How can I do this?
2 Part answer for you here.
First if you are going to be using Rails as an API I would recommend you use another way of validating that the user making the request is actually the user they say they are such as creating a unique token upon account creation or login that can be returned in the initial response and provided as a HTTP header in subsequent requests. If you are worried about the security of this you could optionally base64 encode the key plus some other value and decode it server side before comparison.
If you still wish to use the CSRF method baked in to Rails you can do so as long as the user is making a request from the webapp using AJAX or whatever. If you have the csrf_meta_tags ERB in the header of your layout file you can get the value and set it in the X-CSRF-Token HTTP header. Using jQuery it may look something like:
$.ajaxPrefilter(function(options, originalOptions, xhr) {
var token = $('meta[name="csrf-token"]').attr('content');
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
});
This would cause it to be added to every ajax request made using jQuery.

iOS - How to get form data for an HTTP post

When submitting an HTTP post using Objective-C to a server, the required form data entries include __VIEWSTATE, __EVENTVALIDATION, username, and password. I get the user's username and password programmatically through the iOS application, but I hard-code the __VIEWSTATE and __EVENTVALIDATION parameters by looking at their entries through Google Chrome Developer Tools. The problem is that once the __VIEWSTATE and __EVENTVALIDATION parameters change, my app is defunct.
Is it possible to get the __VIEWSTATE and __EVENTVALIDATION parameters programmatically, possibly by storing them in a cookie, or can I send a POST request without them? Do I need to integrate a JavaScript function into my Xcode project?
It's strongly related to your server-side logic because it's a deal of client and server applications how to use this parameters, but in in most cases VIEWSTATE paramater is given to you at previous request. You should not send it with first request. For example:
request1, authorization — sending username, password. This will (may) return you VIEWSTATE.
request2 — sending VIEWSTATE from request1 and other parameters. This will (may) return you new VIEWSTATE.
request3 — sending VIEWSTATE from request2 and other parameters. This will (may) return you new VIEWSTATE.
...
I'm not aware about __EVENTVALIDATION parameter but you can inspect actual traffic from browser using debugging proxy tool such as Fiddler and try to find out logic of it's usage.

trying to get a oauth token using fiddler

I've been following Scott Allen's ASP.NET MVC 5 Fundamentals on pluralsight, and can successfully request a token, using a simple HTML page, but now need to try and do this using fiddler. the reason I need to test it using fiddler, is that this is in essence the way my apu will be called. An ios device app is being written, and i have to do the api piece.
So, i enter the followdin in fiddler:
HEADER:
POST http://localhost:53140/token HTTP/1.1
Content-Type: application/json
Host: localhost:53140
Content-Length: 50
BODY:
grant_type=password:
{"userName":"something",
"password":"password"}
and I get a 400 - bad request.
i've changed the content type to : application/x-www-form-urlencoded but still a 400.
what am i doing wrong?
EDIT
Even tried "username=username&password=password" still no joy
EDIT
Whoops, had the grant_type in the wrong place. this needed to be in the body:
grant_type:password&username:username&password:password
Now i get username or password are not valid:
{"error":"invalid_grant","error_description":"The user name or
password is incorrect."}
i'll leave the post active, as this may be a red herring.
In fiddler, make sure after grant_type=password&username=username&password=password there is no space or line break.
I was troubleshooting the same error message
{"error":"invalid_grant","error_description":"The user name or password is incorrect."}
while trying this tutorial myself. It seems that the UserName being persisted onto the local database is actually the email address rather than the UserName provided in the JSON payload while invoking the /api/Account/Register Web API. You can verify this by running a T-SQL query against the [AspNetUsers] table. (If you are using LocalDb database, you can open the database located in the project’s App_Data using Show All Files.)
Please note that once the actual user name is confirmed as the email address, the email address (and possibly your password) has to be URL encoded when posting the /api/Token request.
For example:
grant_type=password&username=Alice%40yourdomain.com&password=_Password123
Hope this helps.
In fiddler you can write
Host: localhost:17271
Content-Length: 81
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
In RequestBody you can write
grant_type=password&username=Alice&password=password123&response_type=token
Hope to someone help it because my problem is solve by this type of requestbody
This is how I do it using Fiddler4 (this guide assumes you are starting from scratch):
Create a new MVC Web API 2 project in Visual Studio 2015
Ensure you set the Authentication to individual user accounts (assuming this is what you want)
Once the project has loaded build the project and start the Web Application to ensure it runs
You should get the default "ASP.NET Getting started..." page with the navigation links at the top "Home" and "API".
At this point I tend to change the "DefaultConnection" in my Web.config file to point to an actual SQL Server where I will host the ASP.NET Identity tables but you don't need to just use the localDb by default.
Fire up Fiddler4 and then click on the Composer tab on the right
Change the request type to 'POST' and then change the URL to that of your local website which you ran earlier (the VS Web API 2 project) e.g:
http://localhost:49598/api/Account/Register
Change the header text to the following:
User-Agent: Fiddler
Content-Type: application/json;charset=UTF-8
In the request body you need to compose your JSON data that will be the account you are registering for example:
{
"Email": "youremail#account.com",
"Password": "YourPassw0rd!",
"ConfirmPassword": "YourPassw0rd!"
}
With your website running hit the Execute button at the top right
If successful you should see a 200 response on the left hand side of Fiddler4 which confirms the Account Controller API action Register was called a new user was successfully registered.
Now you can test your user account by requesting an Authorization token. Clear the contents of the Request body in Fiddler4 and then change the type to POST if required.
Change the header text to the following again:
User-Agent: Fiddler
Content-Type: application/json;charset=UTF-8
In the request body paste the following (changing the values for your account obviously)
grant_type=password&username=your#account.com&password=Passw0rd!
Hit Execute again and you should see a 200 response on the left hand side of Fiddler4:
http://localhost:49598/Token
Double-click the response to open up the Inspector tab on the right hand side of Fiddler4 which should display the authorization information in JSON format (you can also see it as raw by click on the 'Raw' tab).
Look for the 'access_token=' line which will have the access token you need to make "bearer" type requests.
In layman terms this is what happens now:
a. You authenticate and get an auth token.
b. Any/All requests made to the API endpoints are done using the bearer token type and this is set in the header of your request.
c. You pass in the auth token you received and this is validated and your request is processed.
d. You should ensure your Web API 2 endpoints have the [Authorize] decoration on the methods and/or class to ensure those areas are secure.
e. If your auth token has expired (set in the App_Start\Startup.Auth.cs class 'AccessTokenExpireTimeSpan'...) then you will need to handle this for example my app calls a dumb method that requires authorization, if that fails the client side AngularJS code redirects the user to the login screen where a valid user can request another auth token by logging in.
*note: I keep the expiry times to 30 minutes for my auth tokens
Okay now to use that token in Fiddler4...
Start Fiddler4 and in the Composer tab on the right change the type to GET (Clear the contents of Request Body if you need to)
Change the header text to the following:
User-Agent: Fiddler
Host: localhost:49598
Authorization: Bearer your_very_long_auth_token_here
Change the url to the good old api/values endpoint:
http://localhost:49598/api/values
Hit the Execute button and if everything was successful you should see the 200 response on the left:
200 HTTP localhost:49598 /api/values
Double click this response and the inspector tab should open showing the JSON response
This concludes how to use Fiddler4 to test Oauth2 with Web API 2. Hope someone finds this useful if you spot any mistakes let me know in your comments and I will update this answer.
One issue I see is that it looks like you putting the username and password in the Request Body as a Json string. it should just be text with no quotes:
grant_type=password&username=UserName&password=PassWord
Then making sure you have the Content Type: application/x-www-form-urlencoded
I'm not familiar with Scott's course, but normally for OAuth2, you do a GET request to the authorization server with the credentials, which then gives you an AuthorizationCode which you then POST along with some other stuff to the token server to get your token.
I'm not aware of a shortcut where you can get a token by just passing the credentials to the token server.

asp.net mvc authentication when call from client app

I use asp.net mvc controller instead of Web Service in my project.
When I call the controller from my client app,there will be a authentication problem. If I use Web Service ,I can use SOAP Header , but now in asp.net mvc, There is no soap header.
Please help.
I am really know a little about the web security.
Normal way of doing this when you come to http services is to pass it in authorization header in following format (if you are doing request from fiddler)
Authorization: Basic user123:pass123
user123:pass123 string is normally base64 encoded and you have to decode it on server side, check it against user store and authenticate the user. One example can be found here
You have several options.
Use a request header to contain some security token.
Include security tokens in the message that you send in the request body.
If your application uses something like Forms Authentication, you can ask consumers to call a login action, then grab the Forms Auth cookie and include that cookie in subsequent calls.
Since you are not using soap. You may use a simple http way. Which means you start a HttpRequest and handle result via HttpResponse. Thus you have to simulate a authenticate action as signing in from web browser.
You need to get the security token or cookie from the reponse. And put them into your following request. Thus your controller will recognize the request's identity.

Resources