januari februari (2) maart (2) april (2) mei (2) juni (2) juli augustus september oktober november december
HTTP+HTML+Delphi authentication (how xxm does it)
2018-04-13 14:26 xxmauth [permalink]
→ Daraja Framework: HTTP+HTML form-based authentication
Jikes! This is strange. Yes you could go ahead and have a page with a login-form, that posts onto a handler that checks your password, and throws a 401 when it fails. But is that really what you need? I thought 401 is there to elicit the user's HTML-client (a.k.a. browser) to show a modal form asking for a password before re-posting the request. Just like xxm's Basic Authentication demo does, and it does this right at the center of the project, before your request is routed to any page or resource, so that all requests to the project need authentication. Also this way you don't need to code a check IsAuthenticated on every page or resource.
But — again — is this really what you need? The public nowadays doesn't respond well to systematic authentication like that, and also makes it impossible to do anything on the website while not being authenticated (yet). It's better form to welcome new users with a nice 'create new account' button (More about that here.) and perhaps more information on what's on offer, next to the logon form for existing users (with extra options like 'stay logged on on this station' and a 'forgot my password' link). There's an example in xxm's Session demo: The opening page has a log-on form, and
Login.xxm does the rest. It doesn't really check user-account and password here as it exceeds the purpose of the demo.
To show you a working demo, you should have a look at tx: It has a central redirect for any page request from a user that should authenticate first; the logon-form with extra options to show users as a normal web-page; checks the entered password agains a properly salted hash and then redirects you to the page you came in for originally...
And there's much more to tell about authenticating users. I've tried to make a list here (it's in Dutch though), and that doesn't even scratch OAuth(2) yet...
Before I forget, did I mention xxm comes under a permissive MIT license? So you don't need to buy a commercial license!
What do you think I should do?
2018-04-20 23:26 sendfile404 [permalink]
Dilemma, dilemma! What should I do? Sometimes, you need to have a certain URL in a web-project that just serves op the contents of a local file. You could try to have the file in a static section of the website, or even a sub-domain for static content (if your budget allows it), but then it's out there for anyone. Best is to have a request be processed dynamically, so you can do some server-side logic first, for example to do authentication control, or generate the file first (perhaps with a graphics library?). That's where the
SendFile method of the
IXxmContext comes in. The code that implements it is pretty straight-forward:
procedure TXxmGeneralContext.SendFile(const FilePath: WideString);
if State=ctHeaderNotSent then FSingleFileSent:=FilePath;
SendStream(TStreamAdapter.Create(TFileStream.Create(FilePath,fmOpenRead or fmShareDenyNone),soOwned));
If the request's header has not been sent already, the private value
FSingleFileSent is set to the file path, assuming the request is meant to have this file's data as response data. This is used for error handling and logging.
SendStream is called, which takes an
IStream pointer, so a
TStreamAdapter is used to wrap around a
TFileStream, with ownership so the last
IStream._Release will call the file stream's destructor.
One thing that's missing here perhaps is trying to figure out if the HTTP response header
Content-Type is set to some suitable MIME-type for the file, but this is so untrivial that it's best left to the developer. So give it a second of thought when you're coding a call to
So about this dilemma I'm having. Just imagine for a second you have this code in a project. Attention: this is very bad practice! It should be glaringly obvious to everybody that doing this opens the back door wide open and people with malicious intent can access any file they want on the machine, include system files, so please don't ever really do this:
Yikes. Very very bad! I feel dirty just for typing that, but just as an example, this code has a high probability of trying to open a file that doesn't exist, or otherwise have the
TFileStream.Create throw an
In that case, would it be better if xxm answers with a proper HTTP 404 (page not found) response? Now default exception handling kicks in, and left unhandled (hint) xxm will fashion a HTTP 500 response for you with the exception data. There's also a bit that will see if your local fragment registry can load a fragment for
'404.xxm' that lets you design a nicer 'page not found' page than the default, but I'm having a hard time to guess if that would be something unexpected for someone somewhat new to xxm, calling
SendFile on an inexistant file for the first time...
I'd love to hear from anyone on this, but for now I'll just let it be like this and let the normal exception play out, if any.
But wait, there's more. Deep burried within the dark corners of the Windows API, there's a thing called TransferFile. It basically lets you tell the system to take a file handle and a network handle and stream all the data from the one to the other, as much as possible right from the kernel. The way the friendly people over at Microsoft worked it out, and tied it to the running system so it would only work on Windows Server versions, makes it kind of unsuitable for where I want to take the xxm project.
But wait, there's more. You may have noticed the web-sphere is gripped with a frenzy for all things asynchronous. There are a few good things there, but it is mainly the best way to serve a magnitude more of concurrent requests by the same server. The short story is you try to avoid waiting on the system while it waits on network or disk. The long story envolves completion ports or libuv, but is in essence unfit to combine with what xxm is doing: having a separate DLL with code you just call to have a response generated for a request, since to do it properly every request to the operating system needs to be re-routed over your job/thread/task/fiber/yarn-management.
This shouldn't hold me back to get as close as possible to the middle ground between the two, where you have the option to build a response, but can hand over a (file)stream and have the HTTP server spool that as it sees fit, once the situation really is just that straightforward. But this may be what xxm 2.0 could be about, if there ever will be something like that.