So while I was considering a redesign to TI-Trek's login system, it occurred to me that the key-based login system is something that was scalable in the event that recent developments in usb/networking in the toolchain lead to more networked services. So I endeavored to design a credential-less single-sign-on system that could be embedded into said programs/services. I decided to name this service TInyAuth, a euphemism for TI as well as the word Tiny, suggesting that it is a simplified version of the system on which it is based, Oauth.
TInyAuth works by having users sign up on the web interface. Once you sign up, a token is generated for your user account. I use the term "token" loosely... it is actually just a nonce that is generated, the token generation occurs during keyfile creation.
Once you generate your token (actually nonce), you can request a keyfile download. This keyfile contains: (1) A file type identifier string, (2) an account identifier, (3) a digitally-signed authentication token (more on this later).
To generate the token, the password and a salt are passed through pbkdf2_hmac and the resulting hash is signed using hmac_sha256. The signing key is a private key generated by openssl, maintained by the server, and it cycles annually, meaning that all keys issued by the server expire after 1 year. Additionally, a user can expire all keys themselves by refreshing their token.
While at present only the account creating, login, token refresh, and key retrieval are implemented, I plan to release a static library for use client-side loading TInyAuth keyfiles, as well as a Python API for connecting to the TInyAuth service for key validation (aside: the service will run over SSL).
Further, I plan to try to support an ECDSA signature instead of the current hmac one as well as enhance security of the system further in whatever ways are suggested that I can feasibly implement.
The UI and API are works in progress, so expect breakage of certain things if you're messing with it at present. Also it is an eventual plan to just use oauth or some other similar backend to handle authentication, if I can figure out a way to handle syncing the api with stuff the calculator can work with.
I'm obliged to post here because the first half of this project's name is the first half of my name as well 👀
This does seem like an interesting project though, and I'm excited to see how it progresses and evolves in the future. Any plans for integration with other projects, like TI-Trek?
TIny_Hacker wrote:
I'm obliged to post here because the first half of this project's name is the first half of my name as well 👀
This does seem like an interesting project though, and I'm excited to see how it progresses and evolves in the future. Any plans for integration with other projects, like TI-Trek?
Yes, the point is the ability to integrate with anything that wants to use it.
Also while I'm using the project to "self-implement" for the sake of a learning experience, I also know you're really not supposed to when it comes to stuff like cryptography, thus I'm also working on figuring out an actual oauth backend for token generation and authentication. I've been poking around with Oauth.io as a backend to use, but if anyone has experience with other APIs they think may be better, let me know.
I have a dilemma I could use some feedback on.
Given the purpose tinyauth was going to serve, it would seem to suggest that, if I am using an (or serving my own) oauth service, then I should be running a server for auth token grant. Then it further occurred to me, that since a multitude of public oauth services exist, as well as libraries for many languages to query those services, there really is no need for tinyauth.
Unless of course people wouldn't mind a service like this targeting the calculator directly that implements similar mechanics to oauth, but in a bit of a less secure fashion.
Further it has been suggested that I wait until networking becomes more standardized and then see what the community winds up needing more before deciding which way to go. I think I will follow that advice for now.
So I decided to do some work on getting TInyAuth working as I initially intended. Obviously if you're writing a service of your own, you can probably just use Oauth directly (and it undoubtedly would be more secure), but I wanted to mess around with generating (and maintaining) secure keyfiles, and writing an authentication service for them to learn how it's done and perhaps over time get the security of it...pretty decent.
So TInyAuth works by allowing you to sign up like you would for any other account. Once registered, a secret is maintained by your account. At your request, that secret is converted into a token that is then signed using ECDSA, and both your username and the signature are dumped into a keyfile that is then auto-downloaded.
Authentication works by having whatever service (like a game) you are connecting to request your credentials (username, signed token). Those are then sent to TInyAuth via a GET request over HTTPS. The response is a JSON object that has a success field (true or false) and an error field that contains an error string denoting if some error occurred.
Users can revoke any previously-issued keyfiles by refreshing the account secret (causing all keys to no longer validate against that secret). Additionally, users can optionally secure their keyfiles with a passphrase. The passphrase is per-keyfile, meaning you can use different passwords for every keyfile. The passphrase is converted into an encryption key via PBKDF2, and then that is used for AES-CTR-256 encryption of the username/token data of the key. In this case, an additional \0xec byte is embedded into the keyfile, indicating it is encrypted, followed by the PBKDF2 salt and the AES initialization vector and then the encrypted data. Users can use CryptX on their device to reverse the encryption when they need to send credentials to some service.
Update
Another update to TInyAuth.
The keyfiles generated are encoded using DER in one of two formats depending on if the keyfile is passphrase protected or not.
Code:
Keyfile ::= SEQUENCE {
EncryptedFlag BOOLEAN,
Credentials ::= SEQUENCE {
Username IA5STRING,
EcdsaSig OCTET STRING
}
}
Code:
KeyfileEncrypted ::= SEQUENCE {
EncryptedFlag BOOLEAN,
KDFSalt OCTET STRING,
EncryptedData OCTET STRING,
Tag OCTET STRING
}
EncryptedData, Tag = Cipher(AES-256-GCM, Credentials ::= SEQUENCE {
Username IA5STRING,
EcdsaSig OCTET STRING
})
I also provide a static library for decoding the keyfiles that developers looking to make use of the system can utilize. API documented here: https://tinyauth.cagstech.com/portions/apidoc.php
https://pastebin.com/qpuqgUAu
Update
There is a small back-end feature being added (still incomplete, WIP). The overview of recent attempts to authenticate with your keys will now be filtered by IP and will list hits, success, fail, and error. There will also be a blacklist button there, for use if a certain host appears to be sending floods with your keys. Enabling this will cause any further attempt to authenticate your account using one of your keys to fail, even if a valid key is supplied. This also will cause the service itself to begin monitoring the behavior of that host more closely.
Additionally, users will have the ability to "subscribe" to the blacklist. What this means is that once a user blacklists an IP, the subscribed user has that IP blacklisted as well.
The "Phoenix" Update
This is a bit of a double-edged update because it comes with a bit of sad news and a bit of good news.
Last week, an applied update rendered the server hosting this resource unbootable. I reflashed the disk assuming I had a backup. The NFS network share had in fact not been mounting for some time and I had practically no backup copy of TInyAuth and TI-Trek's website. I have the benefit of having TI-Trek's code in repositories, but TInyAuth needed to be rewritten completely from scratch--both site and application/API.
I dub this the "Phoenix" update because, like a phoenix rising from the ashes, TInyAuth 2.0 rises from the ashes of my stupidity and incompetence. And also because much like another Phoenix in Minecraft, it fell from a high place and then respawned (and will probably do it again). The website has been completely redesigned, borrowing some inspiration from common designs for tech sites. The landing page now has a graphic describing the project's features, the login/dashboard page is in it's own place. I also added a popup showing current compliance statistics for the server (fun fact, it scores a 90% for CIS Server Level 1 and 82% for CIS Server Level 2). I also audit the code for the TInyAuth repo with Snyk (as suggested by TKB_Studios).
Site and API once more WIP so if things don't work, give it some time.
I'm really sorry to hear that. It's quite impressive you persevered and recreated it all! I'm sure the new code is even better with all your new experience. Best of luck with future backups!
ACagliano wrote:
The "Phoenix" Update
This is a bit of a double-edged update because it comes with a bit of sad news and a bit of good news.
Last week, an applied update rendered the server hosting this resource unbootable. I reflashed the disk assuming I had a backup. The NFS network share had in fact not been mounting for some time and I had practically no backup copy of TInyAuth and TI-Trek's website. I have the benefit of having TI-Trek's code in repositories, but TInyAuth needed to be rewritten completely from scratch--both site and application/API.
I dub this the "Phoenix" update because, like a phoenix rising from the ashes, TInyAuth 2.0 rises from the ashes of my stupidity and incompetence. And also because much like another Phoenix in Minecraft, it fell from a high place and then respawned (and will probably do it again). The website has been completely redesigned, borrowing some inspiration from common designs for tech sites. The landing page now has a graphic describing the project's features, the login/dashboard page is in it's own place. I also added a popup showing current compliance statistics for the server (fun fact, it scores a 90% for CIS Server Level 1 and 82% for CIS Server Level 2). I also audit the code for the TInyAuth repo with Snyk (as suggested by TKB_Studios).
Site and API once more WIP so if things don't work, give it some time.
Lol I can confirm that it was pretty sad when you said that too me in DM 💀 For new people: always do backups on Direct Attached Storage (DAS) to prevent NFS problems 💀
But TInyAuth looks good at first glance and I hope it'll continue like that
I'm really glad that this project is still going after all those years even with setbacks like the above data loss. Nice work
DJ Omnimaga wrote:
after all those years
I think you're thinking about Trek. TI-Trek is the one that's been ongoing for years. This one has been a few months only.
TI-Trek has seen some progress recently too.
Update
TInyAuth has seen a few more minor updates and revisions, partly for security, flood protection, better UI, and communication with end-users.
First a bit of a look at the TInyAuth API from within a (my) logged-in account:
First the secret refresh date. When the secret is freshly generated, the date is coded in green text. As the secret begins to age to a point where regenerating it is encouraged, the color changes to orange. When the secret has reached lifespan, the color changes to red.
Next the authentication attempts interface. That panel shows all hosts that have attempted to log into your account using your keyfiles, how many times the host has tried, and how many succeeded/failed. If a host seems to be using (and failing) your keys a lot, you may choose to block it. You can also strike entries from your account's log if you choose.
The API now requires that hosts fill out an origin field with the IP of the client the key was used from. If you fail to do this, your API request fails and the "hit" goes against the querying service instead of the actual source so don't leave this out.
Lastly, lockout. Actually I decided to implement this a bit differently than what is shown in the image, so stay tuned. Basically if a host fails an authentication for your account a certain number of times, you will receive an email alerting you to this and advising you to take action from your Dashboard. There will also be a fail2ban jail watching for potentially abusive services that seemed explicitly designed to just try different keys from spoofed IPs.
Last but not least, I am still toying with the implementation of 2FA. I do know that technically a utility like this requires 2FA to be "secure". But I am struggling with the necessity of annoying users with that on an authentication utility.... for a calculator.
Update
TInyAuth continues to see backend improvements and security enhancements.
Users can subscribe or unsubscribe to various email triggers (signing key reset cannot be unsubscribed).
Additionally the API request by a querying server now requires either the
origin field or the
X-Forwarded-For header set to the origin (client ip) using the keyfile. X-Forwarded-For always takes precedence and also allows for client rate limiting.
The service rate limits querying hosts to 50 queries per minute.
There is also an origin rate limit of 5 key attempts per minute at which point, that origin begins to be greylisted for increasing intervals of time (via iptables string pattern match of X-forwarded-for).
Additionally I may also implement where a larger number of incorrect key auth attempts for an account locks the account, requiring input from the legitimate owner before any key can be successfully authenticated.
I've also been wondering about the necessity of utilizing 2FA on this system. In theory I could implement it with every login attempts, with logins via web browser only, or least intrusively, only for account unlock or password reset. Thoughts?
UPDATE -- 2FA Now Supported (WIP)
A major step up in security possible with TInyAuth, Two-Factor Authentication is now possible on most actions you would do with your account.
2FA will not be enforced---this is a calculator it is targeting, and most people do not care about security for a calculator game or something like that. That being said, it is being made available for those who would like to use it.
The current 2FA method is TOTP. I have tested it with the FreeOTP client and Google Authenticator. From your dashboard simply scan the QR code that you see under 2FA Settings or input the secret manually (it is printed near the bottom of that dialog). It's 6 digits and each OTP lasts 30 seconds. Because I currently do not know how to do the conventional popup for entering the OTP yet, right now the OTP field is part of any forms where it may be required. If the database lookup for your account shows a particular action requires 2FA it will yell at you if not provided. Otherwise, it proceeds without it.
Users can enable 2FA for Dashboard login, for password reset, and for keyfile authentication (the client-side library has seen a minor edit to serialize an OTP into the payload sent to the server, and an OTP field will now be an optional part of the server->TInyAuth payload. That part of things is still WIP. Like with everything else, if your account indicates 2FA for keyfiles is required and it is not part of the payload, keyfile authentication will fail.
Significant API changes to TInyAuth
You read this right. After some discussion with others and consideration, I have arrived at what I believe to be a better way to deal with credentialing. Please note that portions of this new API haven't been decided on and are just brainstorming.
Most interfacing with TInyAuth directly will now occur on the calculator via this utility. Now closer than ever to SSH public key authentication's functionality, the user can use the key management functionality to generate a random key, or to store a password directly. This information will be logged into a database that is encrypted with a password the user supplies.
For the purposes of credentialing, the user can choose to generate a public key from a key record using the CryptX elliptic curves module. The public key would then proceed to be uploaded to an authentication keyserver as configured in the program (this would require an active connection to that server through IP or bridged usb/serial or the upload will fail). TInyAuth's web portal would now display an API key for keyfile operations which must be configured within the keyserver data and is required for any operation involving a key. Upon successful public key upload, TInyAuth will sign the payload with its own private key and return that to the user. That key is a revocation key that can be used to revoke the credential.
It's worth note that for those who don't want to go through the trouble of setting up the requisites for connecting the calculator, the web UI will provide an interface for dealing with this.
Users can export a key object for authentication or for usage. Usage is a user saying "I need to use password #3 stored in the database". There is also a specialized TInyAuth dump that does specific things.
The TInyAuth authentication export contains the user's identity and the public key to authenticate against, encrypted with the API secret specific to authentication This can also be obtained from the web interface.