User login from desktop application to Website best practice (.NET) - json

UPDATE: I looked back at what I wrote up and there are too many communication layers. I am going to move forward and handle all authentication in Windows Form, generate a token there, and use it to open up the web app locally. I just need to figure out how to open a website within windows forms that can accept a model. Right now I can do, but I can only pass 1 object:
string endpointURL = "https://localhost:44318/api/login?token=" + tokenstring;
I would rather post a model, and then trigger that to open the webpage by hitting this controller endpoint in the web app
[HttpPost]
public ActionResult SecureLogin([FromBody]AuthenticateModel model)
{
return RedirectToAction("MainView", "Home", model.userID);
}
END UPDATE
I am developing a .NET Core web application. The users will login from a installed Windows Forms app I am also making. I have not done this specific way of logging in so I am looking for some advice on best practice. Here is my current process that works in development:
Desktop App accepts credentials
Once credentials are accepted a request will be sent to the web app server using a json login request
string url = "https://localhost:44318/api/TestPostData";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
httpWebRequest.Accept = "application/json; charset=utf-8";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string loginjson = new JavaScriptSerializer().Serialize(new
{
Username = "postTest",
Password = "password"
});
streamWriter.Write(loginjson);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
Web app hears the login request, verifies with DB credentials are good
If credentials are good, the server will generate a JSON Web Token.
The token will be saved to the DB as a temporary login permission tied to that userID
The token is sent back to the local client, and put in the URL to open the web application
The web app sees this token being used to access the platform, verifies it is good and outputs the data ties to the userID

A few thoughts:
The beauty of Json web tokens is that because they are cryptographically signed, you don’t need to store them in your database. Put the username in the payload, along with other useful data like the IP, and then check their validity directly, saving yourself some db overhead.
Guard against leaked tokens by limiting the validity of the token, both in terms of an expiry time and to one IP address.
Securely hash passwords as near to the user as possible, depending on how your authentication backend works.
Json web tokens are best put in an http authorization header using the bearer mechanism.
When implementing this, stick to using implementations based on trusted and well-maintained libraries. Avoid rolling-your-own to the maximum extent possible. The devil is usually in the details.

Related

How to sent GET request with some parameters?

I am new in the web dev. And have some questions. I hope someone can help me.
when I send a get request from an external device to my django server I do it like that:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1" , 8000))
s.sendall(b'GET / \n\n')
s.recv(100)
s.close
How can I see an address of a machine which sends a GET request to my web server (everything in the local network)?
How can I send some data back to the same machine after receiving the GET request?
I also would like to be able to send a get request with some message what the device needs so the view in django can proccess it. How can I from the GET request with a additional message?
I use django, server and external devices are connected to the same network
thank you in advance,
Check the following stack overflow link to get the IP address: How do I get user IP address in django?
The web server(The Django development server/ Nginx/ Apache) will handle the connections to your web application. They will help to send the response back to the same client(same IP) who send the request.
So you need to write a view function which will return render/HttpResponse/Some other kind of response.
eg:
def index(request):
some_dict = {'ip': '192.168.1.1', }
return render(request, 'polls/index.html', some_dict)
#return HttpResponse()

CSRF Tokens in Yii2 REST API with cookie stored tokens

I have one server running Yii2 with only API endpoints, and one server with a single-page application that fetches all data from the Yii server.
I'm storing a JWT-Token in a cookie on successful login by the application, and I have a custom AuthMethod based on this.
My issue is CSRF Protection that have to be in place when cookies are used for authentication. The yii application automatically sets a _csrf cookie, but it does not do much at the moment.
As far as I can understand, I need to provide this csrf token to the frontend application on login, so that it can be stored in local storage and send in the headers for all subsequent requests.
I've implemented a check for the csrf token using Yii::$app->request->csrfTokenFromHeader and sending the token in X-CSRF-Token http header.
I'm unable to extract the same value as the one stored in the cookie inside the application. Yii::$app->request->getCsrfToken() and Yii::$app->request->csrfToken both return a different token than the one stored in the _csrf-cookie.
This is from my login endpoint:
$token = $model->setCookie(); // Sets the JWT-Token HttpOnly Cookie
$response = [
'message' => 'Login successful',
'csrf-token' => Yii::$app->request->getCsrfToken() // This does not match the _csrf cookie
];
After reading some more in the source code, I discovered that the token needs to be unmasked. This is done in Request->validateCsrfTokenInternal() that are called with Request->validateCsrfToken().
I added the following line to my AuthMethod:
if (!\Yii::$app->request->validateCsrfToken()) throw new HttpException(401, 'Invalid CSRF Token');
And that automatically checks the X-CSRF-Token-header.
I'm leaving the question in case anyone else have the same problem.

How do I add additional JSON pairs in RAD Studio/Delphi in conjunction with FDBatchMoveJsonWriter?

I'm using an HTML client, and have the following situation:
Using Embarcadero's RAD Server's built-in method for authentication, I have successfully logged in a user and would like to now pass the session token back and forth in such a fashion that the connection is RESTful. The problem lies in the fact that for some reason, I have no clue as to how to track said session token within RAD Server. Embarcadero themselves have been secretive, telling our company that we can do it with Sencha/ExtJS, but we'd prefer not to have to buy even more software. The overall structure is as follows:
Login POSTs username and password (working) to RAD Server (still working) and receives response complete with session token. At this point, I want to open up another HTML file and maintain that session token AS I show data, such that with every JSON request, I send that session token. But in RAD Studio, as far as I can tell, I cannot manually add JSON data to an already-constructed JSON object to feed to the FDBatchMoveJsonWriter component. Any suggestions/examples anyone has done regarding this, if it is even possible?
I've not yet used RAD Server, but post to many REST services. Might RAD Server support Authentication additions in the header? I connect a THTTPBasicAuthenticator to my TRESTClient and in the OnAuthenticate event add token data.
procedure TCLTSProcessor.RESTAuthenticatorAuthenticate(ARequest: TCustomRESTRequest; var ADone: Boolean);
begin
ARequest.AddAuthParameter('token', userToken, pkHTTPHEADER);
end;
Another method I use is connecting a TOAuth2Authenticator to the REST client and set the TokenType to ttBEARER and set the AccessToken property.

Play Framework Secure Module: Login for JSON response interface

I'm using the secure module that is provided by the play framework. Now im trying to access a controller method that is protected by the secure module to get a JSON response. Is there a way to access this method without using the provided login form? e.g. with username and password as url parameter
Thanks, joe
Not directly, no. The Secure module is designed for UI based authentication. That said, building security around a controller using HTTP Authentication is pretty trivial.
There are a number of options, which depend on your use case on how to make this work. If you are building RESTful web services, then using HTTP Auth may be the way to go, but if you are using AJAX, that has already used the login page, then checking the cookie may be you answer.
If you look at the Http.Request object, you will see that it contains both a username and password fields. These are specifically used for HTTP authentication. So, you could have an action that does the following
public static void myJSONAction() {
if ("secretuser".equals(request.user) && "secret".equals(request.password)) {
// do some JSON
}
else {
// tell them they are not authorised to this content
unauthorized( "Secret Realm" );
}
}
Alternatively, if your JSON is used as AJAX on a website, I would be tempted to just check the secure module's cookie (take a look at the source to find the name of the cookie) to determine who the logged in user is.

How can I access auth-only Twitter API methods from a web application

I have a web application for iPhone, which will ultimately run within a PhoneGap application - but for now I'm running it in Safari.
The application needs to access tweets from Twitter friends, including private tweets. So I've implemented OAuth using the Scribe library. I successfully bounce users to Twitter, have them authenticate, then bounce back.
At this point the web app has oAuth credentials (key and token) which it persists locally. From here on I'd like it to user the Twitter statuses/user_timeline.json method to grab tweets for a particular user. I have the application using JSONP requests to do this with unprotected tweets successfully; when it accesses the timeline of a private Twitter feed, an HTTP basic authentication dialog appears in the app.
I believe that I need to provide the OAuth credentials to Twitter, so that my web application can identify and authenticate itself. Twitter recommends doing so through the addition of an HTTP Authorization header, but as I'm using JSONP for the request I don't think this is an option for me. Am I right in assuming this?
My options therefore appear to either be putting the oAuth credentials as query-string parameters (which Twitter recommends against, but documentation suggests still supports); or proxying all the Tweets through an intermediate server. I'd rather avoid the latter.
I access the Twitter API using URLs of the form
http://api.twitter.com/1/statuses/user_timeline.json?user_id=29191439&oauth_nonce=XXXXXXXXXXX&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1272323042&oauth_consumer_key=XXXXXXXXXX&oauth_signature=XXXXXXXXXX&oauth_version=1.0
When user_id is a public user, this works fine. When user_id is a private user, I get that HTTP Basic Auth dialog. Any idea what I'm doing wrong? I'm hoping it's something embarrassingly simple like "forgetting an important parameter"...
The oAuth stanza needs to be exact, as per http://dev.twitter.com/pages/auth#auth-request - I ended up building an Authorization: header that I could first check with curl.
I built it using the really helpful interactive request checker at http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/
Here's a friends API request for a protected user:
curl -v -H 'Authorization: OAuth realm="https://api.twitter.com/1/friends/ids.json", oauth_consumer_key="XXXXXXXXXXXXXXXX", oauth_token="XXXXXXXXXXXXXXXX", oauth_nonce="XXXXXXXXXXXXXXXX", oauth_timestamp="1300728665", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="XXXXXXXXXXXXXXXX%3D"' https://api.twitter.com/1/friends/ids.json?user_id=254723679
It's worth re-iterating that as you've tried to do, instead of setting the Authorization header via e.g. jquery's beforeSend function, that for cross-domain JSONP requests (which can't add HTTP headers) you can make oAuth requests by putting all the relevant key/value pairs in the GET request. This should hopefully help out various other questioners, e.g
Set Headers with jQuery.ajax and JSONP?
Modify HTTP Headers for a JSONP request
Using only JQuery to update Twitter (OAuth)
Your request looks like it has a couple of problems; it's missing the user's oauth_token plus the oauth_signature doesn't look like it has been base64 encoded (because it's missing a hex encoded = or ==, %3 or %3D%3D respectively).
Here's my GET equivalent using oAuth encoded querystring params, which you can use in a cross-domain JSONP call:
https://api.twitter.com/1/friends/ids.json?user_id=254723679&realm=https://api.twitter.com/1/friends/ids.json&oauth_consumer_key=XXXXXXXXXXXXXXXX&oauth_token=XXXXXXXXXXXXXXXX&oauth_nonce=XXXXXXXXXXXXXXXX&oauth_timestamp=1300728665&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=XXXXXXXXXXXXXXXX%3D
I was struggling with similar problem of making JSONP requests from Jquery, the above answer helped just to add what I did to achieve my solution.
I am doing server to server oauth and then I send oauth token, secret, consumer key and secret (this is temporary solution by the time we put a proxy to protect consumer secret). You can replace this to token acquiring code at client.
Oauth.js and Sha1.js download link!
Once signature is generated.
Now there are 2 problems:
JSONP header cannot be edited
Signed arguments which needs to be sent as part of oauth have problem with callback=? (a regular way of using JSONP).
As above answer says 1 cannot be done.
Also, callback=? won't work as the parameter list has to be signed and while sending the request to remote server Jquery replace callback=? to some name like callback=Jquery1232453234. So a named handler has to be used.
function my_twitter_resp_handler(data){
console.log(JSON.stringify(data));
}
and getJSON did not work with named function handler, so I used
var accessor = {
consumerSecret: XXXXXXXXXXXXXXXXXXXXXX,
tokenSecret : XXXXXXXXXXXXXXXXXXXXXX
};
var message = { action: "https://api.twitter.com/1/statuses/home_timeline.json",
method: "GET",
parameters: []
};
message.parameters.push(['realm', "https://api.twitter.com/1/statuses/home_timeline.json"]);
message.parameters.push(['oauth_version', '1.0']);
message.parameters.push(['oauth_signature_method', 'HMAC-SHA1']);
message.parameters.push(['oauth_consumer_key', XXXXXXXXXXXXXXXX]);
message.parameters.push(['oauth_token', XXXXXXXXXXXXXXX]);
message.parameters.push(['callback', 'my_twitter_resp_handler']);
OAuth.completeRequest(message, accessor);
var parameterMap = OAuth.getParameterMap(message.parameters);
Create url with base url and key value pairs from parameterMap
jQuery.ajax({
url: url,
dataType: "jsonp",
type: "GET",
});