|
836
|
meow auth by @moon | Stardance
|
moon
|
0
|
129.27
|
0
|
[]
|
[{"post_id": 76283, "ts": "202 [{"post_id": 76283, "ts": "2026-10-03T02:33:15Z", "hours": 10.1333, "text": "pew pew cabosh, wawah space birb is very sleepy. BREAKING NEWS, i added and changed a lot of things so i could make a delicious soup of changes that changed my old changed code that i yes. minimal frontend work called making the passkey section button go crazy with colors, authenticator icon (just search āaaguid explorerā, its not crazy work) and having a dialog telling āhi do you want to rename this, no? okayā. I also have collapsibles that hide info from your lil nonfluffy face when its useless. Now my crappy server knows from where you are connecting (who would have known that a server could know that) and where you live (oh no [its approximated from your ip]). THe latter only works when the instance is proxied under cloudflare (it even gets mad if a request doesnt have the headers it wants when you have enabled the āunder cloudflareā mode). the audit log single method to do everything⢠has been swapped with a builder (i love this), AND its info now includes that same ip and location (actor related [who did it]). all fields are now obligatory for⦠audit log purposes, because before i just pushed null on the db for things i didnt want to show the user MAKING a pretty stinker audit log that does not show who did what. i really dont know whata past me thought, because you can keep everything on the db and just show what you want to the user. idk, past me thinking in uhm not portals (yes). okay, more slurry of things. mah beautiful fix so the JWKS (signing keys used to⦠sign a jwt! [important for OpenID]) update when the database JWKS changed, spammed the hell out of the db and log as it polled instead of waiting for the db (or an instance) to say āI UPDATED IT GUYSS!1ā!1ā. This comes from the instances cacheāing JWKS instead of saying ācould you repeat thatā to the db (too many requests = blue elephant cry and explosions), so they need to know when the db changes or THEY WILL BE out of sync!! mr past me also thought that it was a good idea to store the oauth token code (used to get an access token) in plaintext in the muffing db, SMTH YOU SHOULDNT AT ALL DO. now its just hashed via hmac just like everything else. man i am GOOOD at this job of so called programming, having to go back to edit a thing i called done AND then HAVINGTO edit and edit and edit. this is so fun that I WILL BURST into FLAMES because of how stoopid i am meanwhile, you also have me deserving to be cooked with rice because I made a condition in the oauth token exchange that when SOMEONE somehow miss types or gets access to the oauth token code but has the wrong client_id, the temporary code gets deleted⦠and you know what i forgot? i forgot to commit the changes to the db, so the code never was deleted lol. i love these kind of stupid goofy pain errors that arent even errors. AALSO I reprettyfied the oauth helpers because after working on them a long time ago, i didnt know what were they doing and it wasnt fun nor funny >:( [i was mad {i am still mad, with that space birb⦠i want to sentence past moon to sad corner jail for 12 seconds}]. NOW teeny tiny additions!ā1 the ratelimiter now exposes a āRetry-Afterā per a hacker news old moldy article i found, plus exposes its headers on cors. the audit log now does its job even in more parts! now it also tracks the totp recovery code usage [i frankly forgot about it :(].Changing your email or name now requires sudo minus the name on register. AND the app startup has now a beautiful banner saying āmeow authā in cursive. its pretty :3, makes it stylishinning. I also moved and added to the service manager (the watcher) a way to have service names and to launch services from inside of it (for some reason i used a method that was outof place for ages lol). oh no my time has come nnonono, i give you permission to see my trashy work in screenshot format (so modern)⦠yet i shall push towards completion of this meowing meow meow authing meow auth server:"}, {"post_id": 65650, "ts": "2026-09-10T22:39:28Z", "hours": 11.2656, "text": "hi hello hiiii, stupid space birb back from long bed sleep break. CATCHING UP, i have swapped to resident passkeys, fixed jwk refresh feature not working, beautified toml settings, added 2fa replay protection and audit log beautification. alright.. prepare for a long boring devlog as always. I finally swapped to resident passkeys after thinking about it for days (hours)! That means.. NO MORE user enumeration problemo with passkeys, yippie. it wasnt really a pain in the feathered buttocks, like it was just enabling a crate flag and boomy boom (and it even works on the frontend!). also, i patched with scotch tape a stupid buggy bug about the email templates, becuase I used a lazylock to store the email templater engine stuffy, when SOME random goofy template or data was wrong for whatever reason, it would poison the lazylock and the next time it was used it would just say āoh noes, i am broken, poisoned my childs. GO HECK YOUR SELFā⦠i just fixed the template part by checking if tera likes them in the global state creation. i love scotch tape, it smells great. while doing that, i finally addressed the beautiful jwks not updating on all instances because in MY JOB QUEUE only one running server instance can eat the job. that means, if you have 2 instances running, the one that is the unfortunate one that didnt eat the job will have stale jwks until the next time it is restarted. fixed it with some beautiful blue elephant database screaming āHEY GUYS, THE JWKS HAVE BEEN UPDATEDā and the other instances will be like āoh, okay, i will update my beautiful jwks nowā. finally, 2fa, or as i like to call it, TOTP, has been taken cared like a baby and then thrown again to the battle field after giving it the power up of replay protection. That means, if you use a code, it will be marked as used and you cant use it again (this only works with valid codes). makes you wait more smh. THE SETTINGS got a layer of microscopic makeup because i was like āman, these setting name are weired? what if the settings file had comments to know what the heck is this beautiful knob named ādo_not_touch_thisāā. yes i did that. it was a big red booty pain as i had rerereremember how to do proc_macros and how the heck did i even update the toml files with new entries without making them implode with gibrish. AND WE ALL KNOW NOW that ādo_not_touch_thisā is a setting that if you set it to true, it will make this space birb implode in flames and become dust (yes, like a real firework going CHIRPAAAAAAAAAAAH pop ). and the final thing given some body work spray was the audit log. no more caveman moonbeeper style ālogā method with a thousand things. now we have the SAME thing but as a builder with a āsaveā method. it just makes the code easier to read and understand. also, the audit log now has a āwhat resourceĀæā and āwhat ip?ā and i removed the audit entry making from inside the auth helpers to outside. it was just an inconvenient place to put it, i dont evne know why would moonbeeper put it there⦠oh right i am moonbeeper. I DID IT BECAUSE it was a great place in those times. alright, HEREās your typical bad screenshots that are trashign and god i am sleepy:"}, {"post_id": 53541, "ts": "2026-08-24T04:13:41Z", "hours": 9.2344, "text": "hi hello this is space bird. i have eaten 9h hours of real world time in just making the dialog component. I mean, IT WAS for making the 2FA prompts for when you wanted to enable it or disable and bleh bluh.. atleast it does look great⦠and i still need to add icons. the prompt is just the typical 2fa enable that gives you a qr or the 2fa secret if you cant scan the qr. The dialog component was pretty much made in nothing, in air time (free :D). the thing that took a bit was just the styling BUT WAHT did take a BIG LOOOT of time was just making the 2FA dialogs. lik gha damn hecking ā2FA promptā and ābeep boop enabling dialogsā.. why?! becuase they are PACKED like a lasagna with forms, tanstack fetching, dialog steps and other stupid stuff to make it atleast not confusing for the user to navigate with tree sized buttons that dont work (becuase you are on the wrong step!!!!1 or already did everything lol). i mean, besides that custom stuff, it just reuses components like the pin or qr svg and⦠for now, also uses the spinner icon on the buttons you click to manage 2fa as i couldnt be asked to add real icons for now (leaving them for lasts). next up working work is more dialogs (for the passkey setup [so it isnt just a spinner without any āmagic guideanceā]), a collapsible comp to wrap the info items to show EVENTUALLY some metadata like, in the session items, browser, ip, what user was that did that thing and etc. Its just so i dont balloon the āinfo itemsā BECaUSE they are supposed to be some kind of āquick infoā. broom brroom, i love wasting time on these stupid things (and wiring them!) >:3. LEAVING that tiny goofy work that apparently took hours to do. I am thinking and WILL be doing a beautiful swap into using resident passkeys (the ones that dont require me to know the userās email in advance). yes, i know i said before that i dont wanted and ew ew resident. but man, its just easier for the end user to click a magical button to login directly. AND AND this even protects me from someone slapping the meowbackend with the email fish to see who is registered (with a passkey) by checking if the userās email makes the selector appear. still, some part of me still thinks this is really bad idea but i want to do it tho⦠what could go wrong hah! i might aswell go to the cooking pot already and make some uhh chicken soup made of space birb. thatās it, i still feel like i havent done anything. Hereās your beautiful video of showing the beautiful dialog going āhiā āgoodbyeā (the video shows me enabling 2fa, viewing recovery codes and disabling it [with a recovery code]):"}, {"post_id": 47860, "ts": "2026-08-16T02:59:32Z", "hours": 10.5872, "text": "would you look at that, 10h⦠i love wasting time. Now THIS thing fetches some bits of data like the audit log, my passkeys, adding those and even modifying the username (you are forced to do it)! BUT big buty, i had to add the mr /signup/complete where you set your prefered username, like moon (its a me!), or else the backend will straight up refuse anything you want to do. AFTER changing it, you can do everything else a normal user can [by Default the username is just the userās email AND THAT IS NOT PRETTY AT ALL >:(] FIRST OF all i grabbed my magic cup for tea and made the audit log page (it does not even have anything special)! .. oh right, for that i needed to know how the heck you even send requests with tanstack. so uhh,, blah bleh bluh wawa BOOM i now know how to call a method and get my data back AAnd even make infinite fetchers (IT kinda hates my way of giving data [its wrapped in {3} onion layers {request.data.data.data}, the ones that make you cry a bit]). i also synced my auth state with the tanstack client so it doesnt do two trips every time. okay now. TO make the audit log thingy, i did some beautiful matching so the type, creation and guy who did the action (probably the user) are actually human readable with a limit of 8 items (or else the /me page would be as long as this projectās crappy devlogs). When thereās more, a beautiful āview moreā button appears (separate page). For this, so called āview moreā page, i used the infinite queries. while at first i just puuushed the data into the dom with the #each (svelte thingy), chrome do be VERY very mad when thereās a lot of entries in there (The audit log, because it logs actions in your account, can get very huge. Because actions like the baddie Session action logs each time you log in or log out), SOO i did what someone whose browser is eating more than 10gb does, using a virtual list to render the it! (IT only renders items when they are visible, hidding [removing from the dom] non visible ones. this fixes the āOH gosh THOSE 200 things THAT I CANT EVEN SEE, ARE EATING MY precious ramā). OHh and you can press ESC to leave the page because i made a cool component that lets me plug in a callback for specific keyboard events :D. SECOND, the passkey stuff. yeah, pretty easy thanks to libraries like SimpleWebAuthn that do the hard work of telling the browser āhey, authenticate this guy pleaseā or āhiya, registrate this passkey pleaseā. its just querying what passkys you have to know⦠hwat passkeys you have and thatās it. BUT sadly, an actually sadly, my passkeys are non resident (I cant have a simple button to just login, I need you email before i can use the passkey). Thaaat means I havea teeny big tiny small user enumaration problemo becuase the backend can reveal that an user has a passkey registered and, in turn, we know that user is registered. a bad guy can just atack with āoh noes, your passkey has been stolen. pls give a undecillion of moneysā. third, i had to add the sudo page. It does what you think, reauthenticate to do sensitive operations like adding a passkey. Pretty simple, it redirects directly to an email code if the user does not have a passkey or totp enabled (email code is always enabled), if they have those, it just shows a selection screen. fourth, i had to fix up some stupid things with the api schema of the backend becuase I either forgot to put a body on the responses (like the passkey/webauthn routes) or just fix up a teeeeeny tiny setting thing that wasnt correct (its the webauthn/passkey rp_origin [allowed pages to register/use a passkey} becuase it jsut used the backend url and THAT is not correct). so tahatās it, shall you see some stupid screenshots and not even a video because i havent even finished everything:"}, {"post_id": 44382, "ts": "2026-08-10T02:59:15Z", "hours": 6.0403, "text": "well hello again. space birb presents you the next devlog. I cleaned up the forms a bit (they are a still bit TOO messy ugly but they do work), REDID the ugly flags class to be a more EEEASIER TO WROK WITH (i dont even know how it worked before lol) and FINALIZED the auth pages! RIGHT right, first frontend. I finally finalized the most basic and empty and everything pages of the frontend! wahoo mee :). these pages practically include the otp one and the 2fa one (+ recovery).. and i just realized that i forgot about the passkey one, great so now it isnt finished (fried space bird thingy). Redid the pin component so it works with my Input form component AND also fixed some weired quicks of the pin component in phones (for some reason, my phone, didnt respect the max lenght of the input. i just sliced the value of the input on my max length lol). And finally, the frontend now has the most precious bit of any⦠i dont know. i just added the typical dropdown componetn for the avatars (yes, this was important for me). while on the backend, because mr past moon made some weired decisions, the 2FA recovery code generator and giver of the code the state was a messy mess that I frankly dont know if I even tested it, because it accepted wrong codes? i dont even remember if it worked haha in the past BUT now it works as it should and its at least better readable with normal method names (not plainly ārecoveryā [⦠what does that mean anyway!?? you would need to look at the code to understand it! and thatās bad]). ah, the typical moment has arrived, the one i always repeat. HEREās your happily working auth pages for once, plus the āwant to retry the email sending?ā, the passkey one is still missing but thatās just slapping some paint (and painting my self) and boom (whhile this is practically the same as the past devlog, it just works better than the past devlog lol):"}, {"post_id": 43668, "ts": "2026-08-09T01:58:51Z", "hours": 10.3242, "text": "would you look at that! Finnaly some functional pages with forms, ALmost finalized components⦠oh they are just the login pagesā¦.. and its not even all of the auth pages, just selected ones so the auth flow barely works. BUT, THIS fLuffy (not fluffy) space bird has finalllizated converting (or thinks) the classes i had as global styles into beautiful svelte components with all those stars and happy things. happily, i am longer limited by having evertyhign in global space.. oh right, RIGHT. i wasnt even limited :). AND the coolest compponent of all of them is the spinner one because it spins. The first pages have been plugged into an outlet called SuperForms (not really super, mostly helping to validate)! thanks to that, we now have working forms that post to the backend! with all those classic things, red colors and form validation. but, how I THE unfluffy space bird is pushing envelopes with the form inside of it? by talking to my backend obviously! but not manually (doign every step each time manually), by using a library like the trusty openapi-fetch that eats the openapi schema of the server i used in the past iteration. BUT i trashed it into the.. trash because I was fed up by having to repeat a thousand times the same snippet of code in each form or even page (I could have used a service like class to make it easier tho!). it was swapped by Orval! Orval works with the same openapi schema BUT gives methods! No more repeating the same things, just use the method and boom. and also that openapi-fetch was mad that i used a more recent typescript version. ANND, finally, the auth context was upgraded with a leg made of clay so it can now parse the BITENUM flags of, for example, the user (UserFlags) that tell what is enabled and what is not, if you didnt remember. Its practically a generic class with everything that i considered necessary that must be extended to be able to use it. and thatās it. you may watch the shittiest video ever that just shows that it kinda works with the forms and logging in and thatās it with still mocked things:"}, {"post_id": 36040, "ts": "2026-07-27T21:16:15Z", "hours": 6.8131, "text": "haha 10 days later. no progress just me rambling and going in circles. I am a bad space birb. RIGHT! I just were converting the css stuff into svelte components using the style tag (and the preprocessor duh). Thatās actually it, quite literally. No progress at all. Wasted time on, still, falling on the loop of trying to get something that ālooks goodā, but i dont reall know what i want in reality. ofc i try to get āinspiratainionionā from other websites and try to mix them together to then dislike the result, undo and rinse and repeat (at this point my fur and feather soaked hard on water). YOu may imagine it as thinking that you ahve a finish line when you done even know where it is. i will just try to make the frontend work first without thinking about the design⦠AND i cant even promise THAT! because i will probbaly spiral into the same loop once again (saying oh this looks bad blah bleh bleh). god i am bad at making frontends or evne design or everything, but thats how people learn haha. it is a lesson that i should learn from now on.. i keep judging my work too harsly but i dont know. frontend is just harder for me. hereās the useless non functional three pages that atleast have something layout:"}, {"post_id": 30020, "ts": "2026-07-17T08:27:04Z", "hours": 1.9356, "text": "in the end i gave up in the design or well⦠can you even call it ādesignā when it was ugly even at teh start? yes, i tried my best at making it look āgoodā in my own eyes but i could not for the love of birds. it was bad anyways, like actually bad. I, to make it easy for my self and be able to copy how other people do it because i am a lazy bastard (stupid space birb that klanks its keyboard for nothing), will be using the typical two columns for each section. One for āwhat the heck is this section forā and the other for the actual content (wow). man, i hate how the frontend is where i struggle the most when the backend should be where i should have struggled the most, not with this dude. agh. I also hate HOW i thought the layout i wanted initially was the best one and that i look great when in reality it was an aberration that didnt even look good and it really threw to the trash the unused space bruh. it just wasnt for this job, maybe for something else.. idk haha, what I know is that I think it already looks better with the simple sutff ive done lol [thatās sad btw :)]. as you may see int eh screen shooting, the audit log section instead of having a table it uses a⦠placeholder for a button with the same content it has currently because I frankly i am scared of making tables because of the probable difficulty i will have (because I am already struggling with teh simplest of things!). ALSO, i need to stop making .scss files, compounded into a single css file using @layer and @use , to just use svelte components that use the style tag. it really doesnt change anything, but atleast i wont be doing āclass=āmeowāā each time i want something, just using āā is half better lol (doesnt really fix anything, I just want to give use the svelte components). finally, i am planning to use āservicesā.. they arent really services but more about wrappers around the openapi client. less manual labor for some shitty stuff that i wont need to do anymore. Still, its just a wrapper with nicer method names and namespaces. (also, ill be adding profile pictures. didnt think i would be adding them tho) hereās the typical dumb screenshot of what i think that looks āgoodā without doing that much work:"}, {"post_id": 28705, "ts": "2026-07-15T03:47:05Z", "hours": 8.9958, "text": "i am ashamed. i am that bad or⦠well ive gotten to the point of real badness and what some call āskill issueā because I CANT make this hecking frontend. its just too hard, i am just way more slower than before and what i though i was. i hate that i am not usign tailwindcss and isntead I am building my own scss styles IN @layer when i could have been using svelte components with the style tag but ugh bad decisions that can be still reverted i guess. For the layout of the settings, i even tried copying how I did it in the last iteration of this frontend (past server, not named meow auth).. i just did not like it because using a sidebar for this teeny tiny amount of information is wasteful (like this tiny [not really tiny] space birb). Like the content is just the typical name, email, auditlog, 2fa, passkeys, sessions, oauth authorizations and user created oauth apps AND lets not forget about the admin panel. i am practically suffering with mundane crap that anyone can have done in probably 10 minutes by asking mr claude or even chatgpt OR even just copying an already made layout, but here i am suffering trying to make stuff my own way, telling my self that this was the worst decision iāve made goddamit⦠at this point i will really become a hotpot space birb soup.. i just need one layout made and then it should be an easy job to then copy and paste to other tabs. then the enxt step is to wire it up the forms and have it communicate to the backend which should be an easy task (i think [⦠oh god please be easy])⦠i know this entries of the frontend will make my project go into deflation mode and stuff, and i even broken a promise that ive made my self to not make devlogs that are more than 5h long because of a review someone made of my project when i submitted it unfinished to flavourtown (yes, flavortown) which is sad but it is what is. you cant be perfect, thatās why i have a shit hecking design. i am just bad, a bad space bird i guess. i already rambled too much in this suppossedly simple devlog. hereās your half crap āinspirationā that I used to (quite literally did a C&P of the page) of my past proyect using a sidebar (not what i want with this iteration) and the current state of art of my REALLY REALLY SHITTY curernt state page:"}, {"post_id": 25277, "ts": "2026-07-09T13:32:20Z", "hours": 10.9092, "text": "hi hello. oh, ive been 10 hours doing the same thing!!1 god. So, I was doing the frontend design without using figma and uhh yes. And also removed the ability to use your login to.. login to the app. You just use your email (otp, and passkeys). First, I forgot how to use figma, I only remember some shortcuts. I was going to use it (for frontend and logos) but seeing how struggled to make simple things, I only used it to swap the colors of the logo of MEOW AUTH, hmm yes, very meow. . The frontend stuff⦠I frankly ALSO do not remember anything.. or well I do now remember some things thanks to me fighting to uncenter a div hah. The stack is practically svelte, as always, client rendered and scss (sassy :o) for the styling. In the start I was just going to use the same styling and structure of my first iteration of this project, beepauth (ew), and after doing all of that I thought āgod, this looks pretty badā, soo I then tried to make it look a bit better WITHOUT starting from zero again. And I did style it a bit better but I didnāt even like it. Like it felt like I hadnt even advanced at all, like if the same shitty fricking backend was the same from the past (probably noone would care because probably uhh noone cares.) [brains a weired and even more mine i guess, wawa]. So, naturally, i did the less sane thing, REDOING EVERYTHING again. Had to watch tutorials to relearn how use sass and picked up also some new css stuff that I wont even use (minus the layers! that pretty cool!!). And from that css stuff I discovered Oklch.. yes i swapped my whole color palette to that using their harmonizer that uses the equivalent of WCAG, APCA (contrast bg to text!). At least the frontend now looks decent (or the first blocks fo the website). sadly the only frcking shitting heckign parts ive made are the login (and register BUT THATS THE SAME). AWIT WAIT WAWA, I also swapped some gears in the BACKEND! I removed the login (username) entirely, now its just demoted to a non unique display name (for openid!). you must be asking why, because I changed it to use the login not long ago. Well, because I donāt have to force a user to give me a username AND their email on signup. Its easier to just give the email. And if you already have an account and hit, without knowing (our typical autopilot mode), the signup page, I can silently make a AuthChallenge for login instead of signup because both handlers return the same result. Then, after registering, I just force you to set a display name (by default its just the email, i could leave it like that but currently I want it to force you set a custom display name for OPENID). By doing that, I practically removed the āvectorsā (ooh hackiry stuffiry) for user enumeration [those vectors were the endpoints to see if a login (username) or email was already taken] (I also made so the login endpoint gives you a fake challenge id when the email doesnt exist {This works thanks to having the auth exchange handlers return āinvalid codeā even if the challenge doesnt even exist}). hereās your screenshot of a login page that looks exactly like very other login page, maybe even shittier (sorry i am bad doing these kinds of things.) [also you have the logo colors, i went with purple because it looks cool and its a cool color] {the āPsst, over hereā its just a random greeting, just like the ones i have in the emails} [[sorry for wasting 10 hours doing nothing]]:"}, {"post_id": 23063, "ts": "2026-07-05T20:02:59Z", "hours": 0.3025, "text": "a. hi there mr svelte! I was wondering if I should be drafting first a design in figma but meh. I like to suffer and make bad designs that progress very slowly to look mediocre at best! yay!1!! anyways, ill be using scss as always (i frankly done even remember anything about it lol) and sveltekit. HEREāS YOUR stupid āhello worldā from slevetkt (reaaly useful devlog):"}, {"post_id": 22522, "ts": "2026-07-05T01:24:44Z", "hours": 0.3122, "text": "oopsy. shoooort one, sorry. I added the forgotten oauth error StatusCodes and Descriptions. thereās not much to it lol, I just forgot about it. as always, hereās your even uselesser screenshot with code taht you can already see in the guthub:"}, {"post_id": 22514, "ts": "2026-07-05T00:59:48Z", "hours": 1.7131, "text": "right, its a me! the teeny tiny waist sized space birb that is here to tell you that I added the ratelimiter! It works just as iāve explained in the last entry, it uses the IP of the user to limit the amount of requests via a ticket bucket. THe bucket is stored in memory, as again said before, so if the instance is restarted, goodbye ratelimits. EAch request eats 1 ticket AND the bucket tickets and refill rate can be set via the⦠middleware. who would have known wow. It always adds the typical āx-ratelimit-limitā bleh bleh bleh with all the info you can like that is useless BUT hey, its there for you. I like making my own stuffies because its cool. THe root has a limit of 500 requests, refilling after 1 second. While the auth routes have a limit of 10 (sudo) and 20 (auth flows) requests, refilling after 1 minute. The other routes are just uhh protected under the umbrella of the root ratelimiter lol, no need for having to add a ratelimiter to every single route (god). thatās it. thereās no more devlog. Now what i gotta start doing is the frontend. I will cry a bit because I am VERY very VEEERY rustified in the typescript department like I never touch it but meh I MUST do a frontend or else this is incomplete⦠and i will do be crying if i send it off in a incomplete state. THE frontend will be in svelte kit, because its cool and ive already used it in the last iteration and it left me with a good taste in my forked tongue (hahaha, i am space birb) AND thanks that Ive been using from the start utoipa to add an openapi schema, I can use it easily to make requests from the frontend! and i didnt need to suffer adding them after everything was done just like in the past iteration! hereās your useless screenshot showing teh ratelimiter working and the headers and stuffies⦠god i am a mediocre at best writting long hecking devlogs for nothing:"}, {"post_id": 22325, "ts": "2026-07-04T18:52:19Z", "hours": 1.4481, "text": "wow. thatās a long time doing nothing. I just updated the deps, tera had a change on its templating because it was rewritten from the ground up. pretty cool, now it kinda looks like jsx and at the same time not. I also tried or well⦠I am thinking about making my own ratelimiter but was like, ugh. I was practically mega blocked on the idea of wanting a ratelimiter that used the IP + UserId. Both are easy but for some goddamn reason I kept going circles and circles and honestly I dont even remember why anymore, like huh!? In the end I will only be doing ratelimits via IP because they are the easiest AND THEY DO NOT NEED TO be stored in the database. yes database, you read it right. IN this version of my backend I wanted to use the least things AAANd the oNly thing required is just the database to make everything. Adding redis would be waste (and waste of ram) for just storing the ratelimiter. Redis would be required if I wanted to run more than 1 instance of my application AND IF i wanted to distribute the info about āoh this guy is grounded, no entering the meow auth realm for 5 minutesā to all other running instances. BUTTT, as you might not see, I dont want to run more than instance nor want to distribute it to more instances if it were the case that I wnted to run more than 1 instance. Soo, I went in circles in my crapppy bird brain because to add ratelimits via the user id I would have to store the info somewhere that wouldnt be erased (like in the in-memmory storing that i will be using) or else the ratelimits would be useless because⦠THEY WOULD BE ERASED from this whole realm when the instance is restarted (memory goes boom to the void, so does the ratelimiter). Thatās why I want to just implement the Ip based one, its the easiest one and the only one that I donāt care about loosing the information about the ratelimits when the instance is restarted. Also, i need to implement it yet lol i was just scrambling my head nuts and bolts hearing them clank while trying to ratchet them. ALSO², i need to redo the email stuff because my brain has came up with a cool design lol but first gotta do the frontend to make it uhh look good before suffering making the email components. I also started to hate the tera zed language extension. its crap. bad crap the worst one. ALSO, hereās your really useless screenshot this time showing code that you can already see on the github page (yay!1):"}, {"post_id": 20456, "ts": "2026-07-02T01:37:49Z", "hours": 5.1653, "text": "hello again, its a me, a random space birb that is here to tell you that I completly forgot about the ratelimiting stuff. BUUT, I added the admin methods and UserFlags to be able to set⦠flags. not much rodeo this time. had to think how i wanted the audit logs to work for the admin stuff. I first though about just having a bool saying āah yeah adminā but meh, I think its better to have also an āactor_idā, the who did it user id, and boom. In the user side handlers for the audit log I just return the typical plain response of āyeah this was changedā (not sql joins, cheaper [?]) but in the admin side, I return the actor_id with some other things like the user login of the actor AND the user login of the user that was changed (cause why not!? its jsut another join statement in sql). Works wonderfully and even better now because before I had setup the user audit log to fetch AAAL the entries form the db and pee pee poo poo no, now that i have my paginated stuff, no way! SOO, the admin methods are just the typical ones, see what the user has changed or an admin changed from an user via its audit logs, the oauth applications and authorizations management and thatās it. I will probably also add a way to know globally what the heck is being changed but idk about that, seems a big sql query (that is tiny but very costly in db terms) and I frankly want to avoid that⦠and even more avoid using redis because i hate it and that SOMEHOW i have better some beautiful organized code vs the first version of this backend where I used the typical DB+redis aaand it was ugly . i hate that. I also added the UserFlags to be able to set flags like āis the user an admin?ā or āis this user allowed to manage its oauth applications?ā and so on. Pretty cool. BUUT as always, I had to C&P some code (almost all of it) from past handlers to make the admin handlers work lol. I would really want to make a central place to put all the common handler code but meh. IT WORKS! and thatās what matters. THe next things are just making the ratelimiting WHICCHC probably will be only inside the instance the user is reaching and thatās it. I would like to have global ratelimiting using the IP of the user or its account id but that would (i think) require redis⦠I really need to think about this because someone with a crappy toaster can make explode my poor baby vps. ps. god do I really take that much time doing stuff? god i am slow at coding. i am bad goddamit. thatās it. shallllll you see my shiitty api docs with the admin stuff and admin auditlogs becuase why not:"}, {"post_id": 16949, "ts": "2026-06-27T14:57:54Z", "hours": 2.2208, "text": "hi and welcome to my unreadable journals. I added those oauth authorized applications management handlers that I forgot to add yesterday, like the typical āoh let me see what scopes does this thing use⦠OH GOD IT CAN SEE MY fur color I MUST revoke it NOW!11ā. Then I moved AAAL the handlers that touched ME user data to the.. obvious /me route so its prettier and doesnt pollute the air of the real auth related things. and did some cleanup in the http error department by merging some repeated errors. god this is one of the shorter entries iāve made i think. next up is doing ratelimting, probably roles or just an admin api and the āhey your account has been locked because of repeated tries to loginā. i dont even know what will it take to make tests work god. hereās your shitty screenshot showing my only progress, the oauth management bleh bleh bleh:"}, {"post_id": 16427, "ts": "2026-06-26T18:44:11Z", "hours": 3.4175, "text": "hi, hello i am space birb in the sad corner and i am here to tell you that i added the the typical oauth management handlers that everything has. I also added a generic paginated database thingy to be able to make⦠pages when thereās more than 20 items (rows). firstly, everything was easy. yes, no rocks not nothing that could set me on fire⦠minus that I HAD TO MAKE a paginated database thingy. WHY did i make it? idk man, i wanted because my bad coder brain thought that maybe someone could have more than 1 oauth application created (like a thousand) and thatās pretty bad for mr blue elephant database becuase that means eating 1000 rows in one go (and blue elephant doesnt like that, AND EVEN less if my vps has 1vcore and not really that much ram). SO, the best course of action was to make pagination to be able to cut in pieces the data and make it easier to load and handle.. even though the loaded rows are hardcoded (its 20 plus 1). The pagination practically works by seeing if thereās more data after 20 items (thatās why it has a āplus 1ā!), if so, we take the LAST itemās id (using a trait to access it, because you canāt really know in what form or what id will be used in any database model) in those same 20 items to set the ānextā param. That ānextā param is used to.. quite literally say āhi, uh could you give me the next rows after this id pretty please?ā and boom works and i didnt set my self on fire but i did ruffle my feathers a bit because of. Ill probably implement it to more places because the only places that use it are the oauth applications and user sessions because i am a bit lazy haha (i mean, its just C&P the current find_many* and use the pagination stuff and caboosh). oh god, i forgot about the oauth consent management. great job me, NOW IT ISNT COMPLETE āeverythingā great coder i am great big bird brain. My next plans are just to do some general cleanup with the openapi schema, add comments to the code and then start doing the frontend in mr sveltekit.. although i am too rusty in ts land and i will have to learn some stuff again and touch again scss and stuffies and god, i am going to get cooked in the sun and roasted like the space birb i am because of me no longer touching anything javascript. hereās your really useless screenshots showing the INCOMPLETE oauth management handlers and the pagination thingy working:"}, {"post_id": 15504, "ts": "2026-06-25T06:20:57Z", "hours": 1.2603, "text": "I made the User Info handler for the open id stuff. thatās the end of it. It works, wahoo my self yay good job, even though you had pretty much bad scrambled code, you did it hahaha. It practically, as the openid spec says, returns the claims used also on the id_token. Soo, because its sooo close to the id_token, iāve decided to just eat the that same id_token but spit out a converted version with things I want. I also added the typical OauthManager and RequiresOauth. the latter one not having a param to decide what scopes you want because, whhy would you want that?! its just a one liner and it may change for each hecking endpoint or even the data the endpoint returns. its just over complicating it with wrapped trash. ⦠and about my devlogs, i realized that mine are pretty bad and not interesting like other peopleās devlogs. i simply write weird and long ones. but i donāt want to write a simple āI did this, commits, hardness of implementing, whateverā in bullet points like other people do. i dunno it feels flat like this devlog. Hereās you typical SINGLE screenshot showing that the user info works, thatās it:"}, {"post_id": 15052, "ts": "2026-06-24T13:25:06Z", "hours": 6.1178, "text": "oh hi, did not know that you are really reading this. I added the openid stuff! Well not all of it, I still need to do the āuserinfoā endpoint but meh, it works as it should. I also added the cool JWK (the secret key [ES256] that is used to sign the JWTs) rotation stuff, which I can say that I tried at first over complicating it to then end up simplifying it because it was A HELL to use like you had to call a thousand hecking things or in one method give a thousand arguments (its an overestimation, probs not real [shy of 5, it wasnt generic, it was attached to the token flow] :3), it was a pain to use and IT EVEN GAVE ME a burn mark. As I said, I just redoād everything and boom, simplified thigny you just call from the global state and boom, we do be working! The JWKs are rotated every 2 months, and the old one is retired at the same time. After 1 month, the retired one is deleted. So, at any given time, thereās a maximum of 2 keys, the current one and the retired one. The retired one, as the name implies, is not used to sign new tokens but is still valid to verify old token. And all of this is fetched at startup and then via a scheduled job it is updated. AND as you might have (NOT) guessed the JWKs are stored in the database, so if you have multiple instances of mah meow meow server running, they all share the same JWKs and rotate⦠OH GOD THEY DO NOT ROTATE THEM AT THE SAME TIME GODDAMIT AAAGH.. the intention was there okay? I did that to, in one part, give more use to my job manager and, to let all isntances update at the same time but big brain me did not think that a job is always locked to the instance that picks it up. also the token endpoint now supports using openid and spitting out a āid_tokenā with the user info (some claims are gatekeept behind the scopes [like āprofileā or āemailā duh]). thatās it actually, like i started really pulling my hair, fluff, feathers whatever because I was trying to overcomplicate it a lot and i really dunno why. like, for another example, i kept swapping from the ājsonwebtokensā and ācompact_jwtā crates because I wanted to use ES256 but didnt want the other because i never used it but then ended up using the latter because it was easier, and then that I wanted to use EC25519 which is apparently not really talked about in the rfcs (thatās why i ended up with ES256! [also supported on compact_jwt]). AH! and also in the job queue, for the JWK rotation, I wanted first to add cron job for that but⦠why tho, I donāt really need it, I just need a way to NOT run a job until a specific time and then reschedule it inside the same worker. hereās the shitty screenshots showing the oh wow āopenid configurationā, oh wowie āit does output tokens and id_tokenā, oh thats nice āit does give out a valid jwt with valid claims that the programmer didnāt even do themselves because they used a library called compact_jwtā and wow āit does have a job that tries to autorotate if the current key is older than two monthsā:"}, {"post_id": 13022, "ts": "2026-06-21T09:21:29Z", "hours": 1.6031, "text": "you know? i love debugging my code when the error was the entire time in the db. great job me!!!! Iāve made the token handler. again, as other devlogs, thatās all folks. Stupid me couldnt figure out why client secret was always bad, why the mr code verifier was always bad when it was the same as the stored one aaand why the heck scopes werent showing. i really do love that my code, practically, worked first try (MY CODE >:3). But did NOT love that i am still stupid and forgot that i had a database that works as the house for the data that my app ingests. god i am smart. time to go suffer with openid i guess. i have to touch jwt and stuff, eugh.. i like my opaque tokens more than jwts, because IF you want to revoke one of them you still HAVE TO STORE A LIST OF IDS⦠that defeats the whole hecking purpose dude, not worth it (or thatās what i think for now, smh i am just a space birb claking at keys). hereās your video that shows that it does work and gives the bearer opaque token and creates the db entry:"}, {"post_id": 12940, "ts": "2026-06-21T05:37:44Z", "hours": 4.6994, "text": "yayy! the first step of making oauth2 alive has been made. I rewrote the tiny part of the authorization handler of the oauth2 flow⦠thereās not much to it! It did took a while to reunderstand it because of how long I wrote it (2 months ago) and that I wrote it in a rush (and didnāt even make it work). Basically, the same as always, traceback to try to understand what past me wanted to do, to then rework everything (or at least try) to unspaghettify those radiative peaces of code. So, practically it only the authorization method was half done and ugly, it was a big BIG monolithic method that did everything in a way that either past me or current me like at all because it takes a whole lotta things to work (8 to 9 argumentos lol). In the end i just splitted the big MONOLITHIC (thick) method into two of the same kind but with at least clear and defined and bleh jobs. One when the user has already authorized the client and the other when he has never touched it in its life. I also did some qol for my self (or i think i did, probs not because it was already bad and rushed and stuff⦠i already said it at the start) with the oauth helpers and stuff by also prettifying them and simplying parts that I really donāt know why I added. Like I added mr āOauthResponseā which, as the name implies, makes the oauth response (redirect, plain error, error with redirect) instead of the 3 different methods I had to use to do the same thing, easier is better (and even understandable!). Ah, and i even tried to use strum but nope, it do not cut the job (it tries to cut the wall instead of the thing i want). NOW, sHALl the work continue to make the token making handler and then the OpenID stuff that may be a bit difficult because, with my shitty reading, i think ill have to juggle making jwks and stuffies to server correctly the food for the picky openid. hereās the video that shows, confusingly, that indeed the handler works (It does a āhi, oh you want to authenticate with āpoopā, let me create a pending authentication. Oh! you accepted the consent, let me delete the pending one and create the actual lasting consent for āpoopā.). god, i am so bad at coding or whatever the this is:"}, {"post_id": 11753, "ts": "2026-06-19T04:14:50Z", "hours": 2.2278, "text": "AAAH, sorry, did i startle you? I added audit logs, a health handler (a simple āOK YES i am alive ) and a root info thingy that tells you āokay, so my name is this, mmh yes, and this is my version and my build stuffiesā¦). the audit log thing was not really a pain to add. At first i was thinking of using my job queue (because ITS only use is for emails⦠and i put my sweat and tears to making it pretty to then not being used lol) but.. why tho, like IF you see how was the code before the audit log adavancement (yes, cement) you can se HOW every action runs already a postgresql transaction. So, why not bundle the audit log adding magic into that same transaction? and so i did. Now, we donāt have to track our selves with pencil (i dont like pens) and paper the actions we do, we just let the application do it for us⦠leaving a paper trail of our desastrous actions. yay⦠now that i said that, i should add a random chance of also adding another audit log entry that is just a random āhi, i am your audit log talkingā. hah that would be funny. btw, strum is not cool. I thought i could use hte EnumString thingy to make it implement automagaicallytationally the Display trait to snake_case but NOPE, it is used backwards. You give it a string and it gives out the enum variant. what a pee pee poo poo dude, imagine having a big monstrous enum and having to implement Display for each variant⦠just like the monolithic error enum of the http site⦠ew. to use it you just sprinkle the audit::log() and boom, done. AAAAAAH, did i scare you again, no? yay. I almost forgot (<- totally) to say that⦠i think THIS IS really the last thingyes before the oauth stuff. i really think i am going to burst into flames and become a cooked space birb⦠kfa (i hope you get it [its a acronym of a whole word {also, hi and thank you for reading this long journals that may be very boring or unnecessary to read}])"}, {"post_id": 11100, "ts": "2026-06-18T04:45:50Z", "hours": 4.8661, "text": "ah, beautiful api docs. I reworked the api docs (because they were a messy mess because of my past laziness [not understandable!!]) and now they are organized in pretty folders (tags) with correct descriptions and titles. now its even helpful to read the api docs to understand how to use a api handler, not having to dig into the code [noone does that :(] right, I DID THE EMAIL CHANGE THING and LOGIN tooo wohoooā¦. yeah it isnāt that amazing lol. at the start i was just thinking about using the typical chacha encryption that ive used for the TOTP stuff but for a random token nanoidād⦠you just donāt, hMAc is fine. Ended up with a dual like verification flow where both the old email AND the new email get a token link (well, now it just the token string because, ahem, i dont have a frontend). both have to be verified before the change goes through. sooo, no more āoh noes, not again, someone got into my account and changed the mail to their own, smhā. then you just get the notif saying āhey, your email has been changedā. SEEECOND, login (your username) changing magic that is way simpler because I just check if you have sudo enabled and that you havent changed it in the last 24 days (why not). Just like with the email stuff, you get a notification saying āyay, you changed it!ā. and I think thatās the last of the tiny stuff i wanted to do before the BIG and PAINFUL oauth stuff. i think i am going to burst into flames and go boom and the floor is covered with dust and feathers. OH wait, i sitll need to do account deletion⦠whatever its just a simple āhya you need sudoā, āare you sure about thisā, āok, byeā flow. meh. i also need profile pictures⦠heh backblaze or maybe cloudflare idk i like backblaze more but uhh I GOTTA RESEARCH OKAY!?! shall you see the probabaly useless screenshots that atleast show the tiny progress that i always do. great"}, {"post_id": 3935, "ts": "2026-06-07T02:04:58Z", "hours": 3.2119, "text": "beep bwap. firstly, what a waste of argon2. I was using it for encrypting the otp codes and.. dude, thatās like its just 6 characters. I just swapped to the typical hmac256. I also made a common cookies helper method to not have 2 (or more) instances of the same cookie making method. uhh, also I adde dhte forgotten passkey management handlers⦠and thatās it. OH WAIT, i also added validation! I mean, its pretty rough and very bad but it works for what I want! I, in theory, was going to use Garde for the validation with axum-valid to provide me with the base stuff. I DID NOT WORK, like I had (and still have) to make a wrapper around their sutff so I can send out my own error messages and not some plaintext like before i handled them. right, it did not work because of something called the āContextā ⦠I tried everything to make it work, but I just could not, not even doing workarounds and C&P examples directly and stuffies, it just would not work like it wanted the global context to have a trait implemented, which I did, but it still would not work. I guess its because to use my global context inside axum, i wrap it around an Arc and maybe it didnt like that? or whatever meh wa. I just swapped to using Validate, and ta-da works as it should. HEREās your badly made screenshot showing the crappy validation messages (they just say: āthis field is bad :(ā)"}, {"post_id": 3560, "ts": "2026-06-06T15:40:12Z", "hours": 0.8356, "text": "added a better way to handle required authentication!⦠middleware. yup, i am very creative. itās practically a qol improvement in the development side, making code look a bit nicer without seeing in every single protected route the same 3 lines to check if the user is authenticated. now i can āenforceā it when I want the user to be reallly unauthenticated to use a route. to use it, you just āadd the middleware and maybe move one flagā and thatās it⦠goddamit I should have had that before to not write a heck ton of āif not authenticated or if authenticatedā¦ā. i am trying to delay the inevitable.. the need of making the oauth side and the frontend ;D"}, {"post_id": 3518, "ts": "2026-06-06T14:25:42Z", "hours": 3.6319, "text": "I started using a master key for everything and fixed the server returning a plain text message when parsing goes wrong. FIRST, I have seen the future and the future says that I WILL be suffering if I have more than 2 secret keys to manage when I can just derivate them from a single master key. AND EVEN rails does that! its just blake3ās key derivation with a xor to fill the remaining bytes that some libraries require. it works pretty great. neat. SECOND, this was a problemo that one of the flavourtown (yes flavour not flavor) reviewers made me notice. When you send a malformed json body, like a new line on a field that really doesnāt expect a new line, the server would plainly return a error message in plain text, which is really bad for the client to handle and even for looks. Sooo, I tried fixing it trying to strap a error handler to axum⦠yes I dont even know if that even exists bruh. In the end i just created a newtype that wraps the original Json extractor from axum to catch its errors and THEN and only then wrap those with my own error messages. And bobās your dad, the server now return a json error message like every other route error. shall you see the useless screen recording (its cropped by stardanceās ui, great)"}]...
|
Title: meow auth by @moon | Stardance
Devlogs:
I Title: meow auth by @moon | Stardance
Devlogs:
I started using a master key for everything and fixed the server returning a plain text message when parsing goes wrong. FIRST, I have seen the future and the future says that I WILL be suffering if I have more than 2 secret keys to manage when I can just derivate them from a single master key. AND EVEN rails does that! its just blake3ās key derivation with a xor to fill the remaining bytes that some libraries require. it works pretty great. neat. SECOND, this was a problemo that one of the flavourtown (yes flavour not flavor) reviewers made me notice. When you send a malformed json body, like a new line on a field that really doesnāt expect a new line, the server would plainly return a error message in plain text, which is really bad for the client to handle and even for looks. Sooo, I tried fixing it trying to strap a error handler to axum⦠yes I dont even know if that even exists bruh. In the end i just created a newtype that wraps the original Json extractor from axum to catch its errors and THEN and only then wrap those with my own error messages. And bobās your dad, the server now return a json error message like every other route error. shall you see the useless screen recording (its cropped by stardanceās ui, great)
added a better way to handle required authentication!⦠middleware. yup, i am very creative. itās practically a qol improvement in the development side, making code look a bit nicer without seeing in every single protected route the same 3 lines to check if the user is authenticated. now i can āenforceā it when I want the user to be reallly unauthenticated to use a route. to use it, you just āadd the middleware and maybe move one flagā and thatās it⦠goddamit I should have had that before to not write a heck ton of āif not authenticated or if authenticatedā¦ā. i am trying to delay the inevitable.. the need of making the oauth side and the frontend ;D
beep bwap. firstly, what a waste of argon2. I was using it for encrypting the otp codes and.. dude, thatās like its just 6 characters. I just swapped to the typical hmac256. I also made a common cookies helper method to not have 2 (or more) instances of the same cookie making method. uhh, also I adde dhte forgotten passkey management handlers⦠and thatās it. OH WAIT, i also added validation! I mean, its pretty rough and very bad but it works for what I want! I, in theory, was going to use Garde for the validation with axum-valid to provide me with the base stuff. I DID NOT WORK, like I had (and still have) to make a wrapper around their sutff so I can send out my own error messages and not some plaintext like before i handled them. right, it did not work because of something called the āContextā ⦠I tried everything to make it work, but I just could not, not even doing workarounds and C&P examples directly and stuffies, it just would not work like it wanted the global context to have a trait implemented, which I did, but it still would not work. I guess its because to use my global context inside axum, i wrap it around an Arc and maybe it didnt like that? or whatever meh wa. I just swapped to using Validate, and ta-da works as it should. HEREās your badly made screenshot showing the crappy validation messages (they just say: āthis field is bad :(ā)
ah, beautiful api docs. I reworked the api docs (because they were a messy mess because of my past laziness [not understandable!!]) and now they are organized in pretty folders (tags) with correct descriptions and titles. now its even helpful to read the api docs to understand how to use a api handler, not having to dig into the code [noone does that :(] right, I DID THE EMAIL CHANGE THING and LOGIN tooo wohoooā¦. yeah it isnāt that amazing lol. at the start i was just thinking about using the typical chacha encryption that ive used for the TOTP stuff but for a random token nanoidād⦠you just donāt, hMAc is fine. Ended up with a dual like verification flow where both the old email AND the new email get a token link (well, now it just the token string because, ahem, i dont have a frontend). both have to be verified before the change goes through. sooo, no more āoh noes, not again, someone got into my account and changed the mail to their own, smhā. then you just get the notif saying āhey, your email has been changedā. SEEECOND, login (your username) changing magic that is way simpler because I just check if you have sudo enabled and that you havent changed it in the last 24 days (why not). Just like with the email stuff, you get a notification saying āyay, you changed it!ā. and I think thatās the last of the tiny stuff i wanted to do before the BIG and PAINFUL oauth stuff. i think i am going to burst into flames and go boom and the floor is covered with dust and feathers. OH wait, i sitll need to do account deletion⦠whatever its just a simple āhya you need sudoā, āare you sure about thisā, āok, byeā flow. meh. i also need profile pictures⦠heh backblaze or maybe cloudflare idk i like backblaze more but uhh I GOTTA RESEARCH OKAY!?! shall you see the probabaly useless screenshots that atleast show the tiny progress that i always do. great
AAAH, sorry, did i startle you? I added audit logs, a health handler (a simple āOK YES i am alive ) and a root info thingy that tells you āokay, so my name is this, mmh yes, and this is my version and my build stuffiesā¦). the audit log thing was not really a pain to add. At first i was thinking of using my job queue (because ITS only use is for emails⦠and i put my sweat and tears to making it pretty to then not being used lol) but.. why tho, like IF you see how was the code before the audit log adavancement (yes, cement) you can se HOW every action runs already a postgresql transaction. So, why not bundle the audit log adding magic into that same transaction? and so i did. Now, we donāt have to track our selves with pencil (i dont like pens) and paper the actions we do, we just let the application do it for us⦠leaving a paper trail of our desastrous actions. yay⦠now that i said that, i should add a random chance of also adding another audit log entry that is just a random āhi, i am your audit log talkingā. hah that would be funny. btw, strum is not cool. I thought i could use hte EnumString thingy to make it implement automagaicallytationally the Display trait to snake_case but NOPE, it is used backwards. You give it a string and it gives out the enum variant. what a pee pee poo poo dude, imagine having a big monstrous enum and having to implement Display for each variant⦠just like the monolithic error enum of the http site⦠ew. to use it you just sprinkle the audit::log() and boom, done. AAAAAAH, did i scare you again, no? yay. I almost forgot (<- totally) to say that⦠i think THIS IS really the last thingyes before the oauth stuff. i really think i am going to burst into flames and become a cooked space birb⦠kfa (i hope you get it [its a acronym of a whole word {also, hi and thank you for reading this long journals that may be very boring or unnecessary to read}])
yayy! the first step of making oauth2 alive has been made. I rewrote the tiny part of the authorization handler of the oauth2 flow⦠thereās not much to it! It did took a while to reunderstand it because of how long I wrote it (2 months ago) and that I wrote it in a rush (and didnāt even make it work). Basically, the same as always, traceback to try to understand what past me wanted to do, to then rework everything (or at least try) to unspaghettify those radiative peaces of code. So, practically it only the authorization method was half done and ugly, it was a big BIG monolithic method that did everything in a way that either past me or current me like at all because it takes a whole lotta things to work (8 to 9 argumentos lol). In the end i just splitted the big MONOLITHIC (thick) method into two of the same kind but with at least clear and defined and bleh jobs. One when the user has already authorized the client and the other when he has never touched it in its life. I also did some qol for my self (or i think i did, probs not because it was already bad and rushed and stuff⦠i already said it at the start) with the oauth helpers and stuff by also prettifying them and simplying parts that I really donāt know why I added. Like I added mr āOauthResponseā which, as the name implies, makes the oauth response (redirect, plain error, error with redirect) instead of the 3 different methods I had to use to do the same thing, easier is better (and even understandable!). Ah, and i even tried to use strum but nope, it do not cut the job (it tries to cut the wall instead of the thing i want). NOW, sHALl the work continue to make the token making handler and then the OpenID stuff that may be a bit difficult because, with my shitty reading, i think ill have to juggle making jwks and stuffies to server correctly the food for the picky openid. hereās the video that shows, confusingly, that indeed the handler works (It does a āhi, oh you want to authenticate with āpoopā, let me create a pending authentication. Oh! you accepted the consent, let me delete the pending one and create the actual lasting consent for āpoopā.). god, i am so bad at coding or whatever the this is:
you know? i love debugging my code when the error was the entire time in the db. great job me!!!! Iāve made the token handler. again, as other devlogs, thatās all folks. Stupid me couldnt figure out why client secret was always bad, why the mr code verifier was always bad when it was the same as the stored one aaand why the heck scopes werent showing. i really do love that my code, practically, worked first try (MY CODE >:3). But did NOT love that i am still stupid and forgot that i had a database that works as the house for the data that my app ingests. god i am smart. time to go suffer with openid i guess. i have to touch jwt and stuff, eugh.. i like my opaque tokens more than jwts, because IF you want to revoke one of them you still HAVE TO STORE A LIST OF IDS⦠that defeats the whole hecking purpose dude, not worth it (or thatās what i think for now, smh i am just a space birb claking at keys). hereās your video that shows that it does work and gives the bearer opaque token and creates the db entry:
oh hi, did not know that you are really reading this. I added the openid stuff! Well not all of it, I still need to do the āuserinfoā endpoint but meh, it works as it should. I also added the cool JWK (the secret key [ES256] that is used to sign the JWTs) rotation stuff, which I can say that I tried at first over complicating it to then end up simplifying it because it was A HELL to use like you had to call a thousand hecking things or in one method give a thousand arguments (its an overestimation, probs not real [shy of 5, it wasnt generic, it was attached to the token flow] :3), it was a pain to use and IT EVEN GAVE ME a burn mark. As I said, I just redoād everything and boom, simplified thigny you just call from the global state and boom, we do be working! The JWKs are rotated every 2 months, and the old one is retired at the same time. After 1 month, the retired one is deleted. So, at any given time, thereās a maximum of 2 keys, the current one and the retired one. The retired one, as the name implies, is not used to sign new tokens but is still valid to verify old token. And all of this is fetched at startup and then via a scheduled job it is updated. AND as you might have (NOT) guessed the JWKs are stored in the database, so if you have multiple instances of mah meow meow server running, they all share the same JWKs and rotate⦠OH GOD THEY DO NOT ROTATE THEM AT THE SAME TIME GODDAMIT AAAGH.. the intention was there okay? I did that to, in one part, give more use to my job manager and, to let all isntances update at the same time but big brain me did not think that a job is always locked to the instance that picks it up. also the token endpoint now supports using openid and spitting out a āid_tokenā with the user info (some claims are gatekeept behind the scopes [like āprofileā or āemailā duh]). thatās it actually, like i started really pulling my hair, fluff, feathers whatever because I was trying to overcomplicate it a lot and i really dunno why. like, for another example, i kept swapping from the ājsonwebtokensā and ācompact_jwtā crates because I wanted to use ES256 but didnt want the other because i never used it but then ended up using the latter because it was easier, and then that I wanted to use EC25519 which is apparently not really talked about in the rfcs (thatās why i ended up with ES256! [also supported on compact_jwt]). AH! and also in the job queue, for the JWK rotation, I wanted first to add cron job for that but⦠why tho, I donāt really need it, I just need a way to NOT run a job until a specific time and then reschedule it inside the same worker. hereās the shitty screenshots showing the oh wow āopenid configurationā, oh wowie āit does output tokens and id_tokenā, oh thats nice āit does give out a valid jwt with valid claims that the programmer didnāt even do themselves because they used a library called compact_jwtā and wow āit does have a job that tries to autorotate if the current key is older than two monthsā:
I made the User Info handler for the open id stuff. thatās the end of it. It works, wahoo my self yay good job, even though you had pretty much bad scrambled code, you did it hahaha. It practically, as the openid spec says, returns the claims used also on the id_token. Soo, because its sooo close to the id_token, iāve decided to just eat the that same id_token but spit out a converted version with things I want. I also added the typical OauthManager and RequiresOauth. the latter one not having a param to decide what scopes you want because, whhy would you want that?! its just a one liner and it may change for each hecking endpoint or even the data the endpoint returns. its just over complicating it with wrapped trash. ⦠and about my devlogs, i realized that mine are pretty bad and not interesting like other peopleās devlogs. i simply write weird and long ones. but i donāt want to write a simple āI did this, commits, hardness of implementing, whateverā in bullet points like other people do. i dunno it feels flat like this devlog. Hereās you typical SINGLE screenshot showing that the user info works, thatās it:
hi, hello i am space birb in the sad corner and i am here to tell you that i added the the typical oauth management handlers that everything has. I also added a generic paginated database thingy to be able to make⦠pages when thereās more than 20 items (rows). firstly, everything was easy. yes, no rocks not nothing that could set me on fire⦠minus that I HAD TO MAKE a paginated database thingy. WHY did i make it? idk man, i wanted because my bad coder brain thought that maybe someone could have more than 1 oauth application created (like a thousand) and thatās pretty bad for mr blue elephant database becuase that means eating 1000 rows in one go (and blue elephant doesnt like that, AND EVEN less if my vps has 1vcore and not really that much ram). SO, the best course of action was to make pagination to be able to cut in pieces the data and make it easier to load and handle.. even though the loaded rows are hardcoded (its 20 plus 1). The pagination practically works by seeing if thereās more data after 20 items (thatās why it has a āplus 1ā!), if so, we take the LAST itemās id (using a trait to access it, because you canāt really know in what form or what id will be used in any database model) in those same 20 items to set the ānextā param. That ānextā param is used to.. quite literally say āhi, uh could you give me the next rows after this id pretty please?ā and boom works and i didnt set my self on fire but i did ruffle my feathers a bit because of. Ill probably implement it to more places because the only places that use it are the oauth applications and user sessions because i am a bit lazy haha (i mean, its just C&P the current find_many* and use the pagination stuff and caboosh). oh god, i forgot about the oauth consent management. great job me, NOW IT ISNT COMPLETE āeverythingā great coder i am great big bird brain. My next plans are just to do some general cleanup with the openapi schema, add comments to the code and then start doing the frontend in mr sveltekit.. although i am too rusty in ts land and i will have to learn some stuff again and touch again scss and stuffies and god, i am going to get cooked in the sun and roasted like the space birb i am because of me no longer touching anything javascript. hereās your really useless screenshots showing the INCOMPLETE oauth management handlers and the pagination thingy working:
hi and welcome to my unreadable journals. I added those oauth authorized applications management handlers that I forgot to add yesterday, like the typical āoh let me see what scopes does this thing use⦠OH GOD IT CAN SEE MY fur color I MUST revoke it NOW!11ā. Then I moved AAAL the handlers that touched ME user data to the.. obvious /me route so its prettier and doesnt pollute the air of the real auth related things. and did some cleanup in the http error department by merging some repeated errors. god this is one of the shorter entries iāve made i think. next up is doing ratelimting, probably roles or just an admin api and the āhey your account has been locked because of repeated tries to loginā. i dont even know what will it take to make tests work god. hereās your shitty screenshot showing my only progress, the oauth management bleh bleh bleh:
hello again, its a me, a random space birb that is here to tell you that I completly forgot about the ratelimiting stuff. BUUT, I added the admin methods and UserFlags to be able to set⦠flags. not much rodeo this time. had to think how i wanted the audit logs to work for the admin stuff. I first though about just having a bool saying āah yeah adminā but meh, I think its better to have also an āactor_idā, the who did it user id, and boom. In the user side handlers for the audit log I just return the typical plain response of āyeah this was changedā (not sql joins, cheaper [?]) but in the admin side, I return the actor_id with some other things like the user login of the actor AND the user login of the user that was changed (cause why not!? its jsut another join statement in sql). Works wonderfully and even better now because before I had setup the user audit log to fetch AAAL the entries form the db and pee pee poo poo no, now that i have my paginated stuff, no way! SOO, the admin methods are just the typical ones, see what the user has changed or an admin changed from an user via its audit logs, the oauth applications and authorizations management and thatās it. I will probably also add a way to know globally what the heck is being changed but idk about that, seems a big sql query (that is tiny but very costly in db terms) and I frankly want to avoid that⦠and even more avoid using redis because i hate it and that SOMEHOW i have better some beautiful organized code vs the first version of this backend where I used the typical DB+redis aaand it was ugly . i hate that. I also added the UserFlags to be able to set flags like āis the user an admin?ā or āis this user allowed to manage its oauth applications?ā and so on. Pretty cool. BUUT as always, I had to C&P some code (almost all of it) from past handlers to make the admin handlers work lol. I would really want to make a central place to put all the common handler code but meh. IT WORKS! and thatās what matters. THe next things are just making the ratelimiting WHICCHC probably will be only inside the instance the user is reaching and thatās it. I would like to have global ratelimiting using the IP of the user or its account id but that would (i think) require redis⦠I really need to think about this because someone with a crappy toaster can make explode my poor baby vps. ps. god do I really take that much time doing stuff? god i am slow at coding. i am bad goddamit. thatās it. shallllll you see my shiitty api docs with the admin stuff and admin auditlogs becuase why not:
wow. thatās a long time doing nothing. I just updated the deps, tera had a change on its templating because it was rewritten from the ground up. pretty cool, now it kinda looks like jsx and at the same time not. I also tried or well⦠I am thinking about making my own ratelimiter but was like, ugh. I was practically mega blocked on the idea of wanting a ratelimiter that used the IP + UserId. Both are easy but for some goddamn reason I kept going circles and circles and honestly I dont even remember why anymore, like huh!? In the end I will only be doing ratelimits via IP because they are the easiest AND THEY DO NOT NEED TO be stored in the database. yes database, you read it right. IN this version of my backend I wanted to use the least things AAANd the oNly thing required is just the database to make everything. Adding redis would be waste (and waste of ram) for just storing the ratelimiter. Redis would be required if I wanted to run more than 1 instance of my application AND IF i wanted to distribute the info about āoh this guy is grounded, no entering the meow auth realm for 5 minutesā to all other running instances. BUTTT, as you might not see, I dont want to run more than instance nor want to distribute it to more instances if it were the case that I wnted to run more than 1 instance. Soo, I went in circles in my crapppy bird brain because to add ratelimits via the user id I would have to store the info somewhere that wouldnt be erased (like in the in-memmory storing that i will be using) or else the ratelimits would be useless because⦠THEY WOULD BE ERASED from this whole realm when the instance is restarted (memory goes boom to the void, so does the ratelimiter). Thatās why I want to just implement the Ip based one, its the easiest one and the only one that I donāt care about loosing the information about the ratelimits when the instance is restarted. Also, i need to implement it yet lol i was just scrambling my head nuts and bolts hearing them clank while trying to ratchet them. ALSO², i need to redo the email stuff because my brain has came up with a cool design lol but first gotta do the frontend to make it uhh look good before suffering making the email components. I also started to hate the tera zed language extension. its crap. bad crap the worst one. ALSO, hereās your really useless screenshot this time showing code that you can already see on the github page (yay!1):
right, its a me! the teeny tiny waist sized space birb that is here to tell you that I added the ratelimiter! It works just as iāve explained in the last entry, it uses the IP of the user to limit the amount of requests via a ticket bucket. THe bucket is stored in memory, as again said before, so if the instance is restarted, goodbye ratelimits. EAch request eats 1 ticket AND the bucket tickets and refill rate can be set via the⦠middleware. who would have known wow. It always adds the typical āx-ratelimit-limitā bleh bleh bleh with all the info you can like that is useless BUT hey, its there for you. I like making my own stuffies because its cool. THe root has a limit of 500 requests, refilling after 1 second. While the auth routes have a limit of 10 (sudo) and 20 (auth flows) requests, refilling after 1 minute. The other routes are just uhh protected under the umbrella of the root ratelimiter lol, no need for having to add a ratelimiter to every single route (god). thatās it. thereās no more devlog. Now what i gotta start doing is the frontend. I will cry a bit because I am VERY very VEEERY rustified in the typescript department like I never touch it but meh I MUST do a frontend or else this is incomplete⦠and i will do be crying if i send it off in a incomplete state. THE frontend will be in svelte kit, because its cool and ive already used it in the last iteration and it left me with a good taste in my forked tongue (hahaha, i am space birb) AND thanks that Ive been using from the start utoipa to add an openapi schema, I can use it easily to make requests from the frontend! and i didnt need to suffer adding them after everything was done just like in the past iteration! hereās your useless screenshot showing teh ratelimiter working and the headers and stuffies⦠god i am a mediocre at best writting long hecking devlogs for nothing:
oopsy. shoooort one, sorry. I added the forgotten oauth error StatusCodes and Descriptions. thereās not much to it lol, I just forgot about it. as always, hereās your even uselesser screenshot with code taht you can already see in the guthub:
a. hi there mr svelte! I was wondering if I should be drafting first a design in figma but meh. I like to suffer and make bad designs that progress very slowly to look mediocre at best! yay!1!! anyways, ill be using scss as always (i frankly done even remember anything about it lol) and sveltekit. HEREāS YOUR stupid āhello worldā from slevetkt (reaaly useful devlog):
hi hello. oh, ive been 10 hours doing the same thing!!1 god. So, I was doing the frontend design without using figma and uhh yes. And also removed the ability to use your login to.. login to the app. You just use your email (otp, and passkeys). First, I forgot how to use figma, I only remember some shortcuts. I was going to use it (for frontend and logos) but seeing how struggled to make simple things, I only used it to swap the colors of the logo of MEOW AUTH, hmm yes, very meow. . The frontend stuff⦠I frankly ALSO do not remember anything.. or well I do now remember some things thanks to me fighting to uncenter a div hah. The stack is practically svelte, as always, client rendered and scss (sassy :o) for the styling. In the start I was just going to use the same styling and structure of my first iteration of this project, beepauth (ew), and after doing all of that I thought āgod, this looks pretty badā, soo I then tried to make it look a bit better WITHOUT starting from zero again. And I did style it a bit better but I didnāt even like it. Like it felt like I hadnt even advanced at all, like if the same shitty fricking backend was the same from the past (probably noone would care because probably uhh noone cares.) [brains a weired and even more mine i guess, wawa]. So, naturally, i did the less sane thing, REDOING EVERYTHING again. Had to watch tutorials to relearn how use sass and picked up also some new css stuff that I wont even use (minus the layers! that pretty cool!!). And from that css stuff I discovered Oklch.. yes i swapped my whole color palette to that using their harmonizer that uses the equivalent of WCAG, APCA (contrast bg to text!). At least the frontend now looks decent (or the first blocks fo the website). sadly the only frcking shitting heckign parts ive made are the login (and register BUT THATS THE SAME). AWIT WAIT WAWA, I also swapped some gears in the BACKEND! I removed the login (username) entirely, now its just demoted to a non unique display name (for openid!). you must be asking why, because I changed it to use the login not long ago. Well, because I donāt have to force a user to give me a username AND their email on signup. Its easier to just give the email. And if you already have an account and hit, without knowing (our typical autopilot mode), the signup page, I can silently make a AuthChallenge for login instead of signup because both handlers return the same result. Then, after registering, I just force you to set a display name (by default its just the email, i could leave it like that but currently I want it to force you set a custom display name for OPENID). By doing that, I practically removed the āvectorsā (ooh hackiry stuffiry) for user enumeration [those vectors were the endpoints to see if a login (username) or email was already taken] (I also made so the login endpoint gives you a fake challenge id when the email doesnt exist {This works thanks to having the auth exchange handlers return āinvalid codeā even if the challenge doesnt even exist}). hereās your screenshot of a login page that looks exactly like very other login page, maybe even shittier (sorry i am bad doing these kinds of things.) [also you have the logo colors, i went with purple because it looks cool and its a cool color] {the āPsst, over hereā its just a random greeting, just like the ones i have in the emails} [[sorry for wasting 10 hours doing nothing]]:
i am ashamed. i am that bad or⦠well ive gotten to the point of real badness and what some call āskill issueā because I CANT make this hecking frontend. its just too hard, i am just way more slower than before and what i though i was. i hate that i am not usign tailwindcss and isntead I am building my own scss styles IN @layer when i could have been using svelte components with the style tag but ugh bad decisions that can be still reverted i guess. For the layout of the settings, i even tried copying how I did it in the last iteration of this frontend (past server, not named meow auth).. i just did not like it because using a sidebar for this teeny tiny amount of information is wasteful (like this tiny [not really tiny] space birb). Like the content is just the typical name, email, auditlog, 2fa, passkeys, sessions, oauth authorizations and user created oauth apps AND lets not forget about the admin panel. i am practically suffering with mundane crap that anyone can have done in probably 10 minutes by asking mr claude or even chatgpt OR even just copying an already made layout, but here i am suffering trying to make stuff my own way, telling my self that this was the worst decision iāve made goddamit⦠at this point i will really become a hotpot space birb soup.. i just need one layout made and then it should be an easy job to then copy and paste to other tabs. then the enxt step is to wire it up the forms and have it communicate to the backend which should be an easy task (i think [⦠oh god please be easy])⦠i know this entries of the frontend will make my project go into deflation mode and stuff, and i even broken a promise that ive made my self to not make devlogs that are more than 5h long because of a review someone made of my project when i submitted it unfinished to flavourtown (yes, flavortown) which is sad but it is what is. you cant be perfect, thatās why i have a shit hecking design. i am just bad, a bad space bird i guess. i already rambled too much in this suppossedly simple devlog. hereās your half crap āinspirationā that I used to (quite literally did a C&P of the page) of my past proyect using a sidebar (not what i want with this iteration) and the current state of art of my REALLY REALLY SHITTY curernt state page:
in the end i gave up in the design or well⦠can you even call it ādesignā when it was ugly even at teh start? yes, i tried my best at making it look āgoodā in my own eyes but i could not for the love of birds. it was bad anyways, like actually bad. I, to make it easy for my self and be able to copy how other people do it because i am a lazy bastard (stupid space birb that klanks its keyboard for nothing), will be using the typical two columns for each section. One for āwhat the heck is this section forā and the other for the actual content (wow). man, i hate how the frontend is where i struggle the most when the backend should be where i should have struggled the most, not with this dude. agh. I also hate HOW i thought the layout i wanted initially was the best one and that i look great when in reality it was an aberration that didnt even look good and it really threw to the trash the unused space bruh. it just wasnt for this job, maybe for something else.. idk haha, what I know is that I think it already looks better with the simple sutff ive done lol [thatās sad btw :)]. as you may see int eh screen shooting, the audit log section instead of having a table it uses a⦠placeholder for a button with the same content it has currently because I frankly i am scared of making tables because of the probable difficulty i will have (because I am already struggling with teh simplest of things!). ALSO, i need to stop making .scss files, compounded into a single css file using @layer and @use , to just use svelte components that use the style tag. it really doesnt change anything, but atleast i wont be doing āclass=āmeowāā each time i want something, just using āā is half better lol (doesnt really fix anything, I just want to give use the svelte components). finally, i am planning to use āservicesā.. they arent really services but more about wrappers around the openapi client. less manual labor for some shitty stuff that i wont need to do anymore. Still, its just a wrapper with nicer method names and namespaces. (also, ill be adding profile pictures. didnt think i would be adding them tho) hereās the typical dumb screenshot of what i think that looks āgoodā without doing that much work:
haha 10 days later. no progress just me rambling and going in circles. I am a bad space birb. RIGHT! I just were converting the css stuff into svelte components using the style tag (and the preprocessor duh). Thatās actually it, quite literally. No progress at all. Wasted time on, still, falling on the loop of trying to get something that ālooks goodā, but i dont reall know what i want in reality. ofc i try to get āinspiratainionionā from other websites and try to mix them together to then dislike the result, undo and rinse and repeat (at this point my fur and feather soaked hard on water). YOu may imagine it as thinking that you ahve a finish line when you done even know where it is. i will just try to make the frontend work first without thinking about the design⦠AND i cant even promise THAT! because i will probbaly spiral into the same loop once again (saying oh this looks bad blah bleh bleh). god i am bad at making frontends or evne design or everything, but thats how people learn haha. it is a lesson that i should learn from now on.. i keep judging my work too harsly but i dont know. frontend is just harder for me. hereās the useless non functional three pages that atleast have something layout:
would you look at that! Finnaly some functional pages with forms, ALmost finalized components⦠oh they are just the login pagesā¦.. and its not even all of the auth pages, just selected ones so the auth flow barely works. BUT, THIS fLuffy (not fluffy) space bird has finalllizated converting (or thinks) the classes i had as global styles into beautiful svelte components with all those stars and happy things. happily, i am longer limited by having evertyhign in global space.. oh right, RIGHT. i wasnt even limited :). AND the coolest compponent of all of them is the spinner one because it spins. The first pages have been plugged into an outlet called SuperForms (not really super, mostly helping to validate)! thanks to that, we now have working forms that post to the backend! with all those classic things, red colors and form validation. but, how I THE unfluffy space bird is pushing envelopes with the form inside of it? by talking to my backend obviously! but not manually (doign every step each time manually), by using a library like the trusty openapi-fetch that eats the openapi schema of the server i used in the past iteration. BUT i trashed it into the.. trash because I was fed up by having to repeat a thousand times the same snippet of code in each form or even page (I could have used a service like class to make it easier tho!). it was swapped by Orval! Orval works with the same openapi schema BUT gives methods! No more repeating the same things, just use the method and boom. and also that openapi-fetch was mad that i used a more recent typescript version. ANND, finally, the auth context was upgraded with a leg made of clay so it can now parse the BITENUM flags of, for example, the user (UserFlags) that tell what is enabled and what is not, if you didnt remember. Its practically a generic class with everything that i considered necessary that must be extended to be able to use it. and thatās it. you may watch the shittiest video ever that just shows that it kinda works with the forms and logging in and thatās it with still mocked things:
well hello again. space birb presents you the next devlog. I cleaned up the forms a bit (they are a still bit TOO messy ugly but they do work), REDID the ugly flags class to be a more EEEASIER TO WROK WITH (i dont even know how it worked before lol) and FINALIZED the auth pages! RIGHT right, first frontend. I finally finalized the most basic and empty and everything pages of the frontend! wahoo mee :). these pages practically include the otp one and the 2fa one (+ recovery).. and i just realized that i forgot about the passkey one, great so now it isnt finished (fried space bird thingy). Redid the pin component so it works with my Input form component AND also fixed some weired quicks of the pin component in phones (for some reason, my phone, didnt respect the max lenght of the input. i just sliced the value of the input on my max length lol). And finally, the frontend now has the most precious bit of any⦠i dont know. i just added the typical dropdown componetn for the avatars (yes, this was important for me). while on the backend, because mr past moon made some weired decisions, the 2FA recovery code generator and giver of the code the state was a messy mess that I frankly dont know if I even tested it, because it accepted wrong codes? i dont even remember if it worked haha in the past BUT now it works as it should and its at least better readable with normal method names (not plainly ārecoveryā [⦠what does that mean anyway!?? you would need to look at the code to understand it! and thatās bad]). ah, the typical moment has arrived, the one i always repeat. HEREās your happily working auth pages for once, plus the āwant to retry the email sending?ā, the passkey one is still missing but thatās just slapping some paint (and painting my self) and boom (whhile this is practically the same as the past devlog, it just works better than the past devlog lol):
would you look at that, 10h⦠i love wasting time. Now THIS thing fetches some bits of data like the audit log, my passkeys, adding those and even modifying the username (you are forced to do it)! BUT big buty, i had to add the mr /signup/complete where you set your prefered username, like moon (its a me!), or else the backend will straight up refuse anything you want to do. AFTER changing it, you can do everything else a normal user can [by Default the username is just the userās email AND THAT IS NOT PRETTY AT ALL >:(] FIRST OF all i grabbed my magic cup for tea and made the audit log page (it does not even have anything special)! .. oh right, for that i needed to know how the heck you even send requests with tanstack. so uhh,, blah bleh bluh wawa BOOM i now know how to call a method and get my data back AAnd even make infinite fetchers (IT kinda hates my way of giving data [its wrapped in {3} onion layers {request.data.data.data}, the ones that make you cry a bit]). i also synced my auth state with the tanstack client so it doesnt do two trips every time. okay now. TO make the audit log thingy, i did some beautiful matching so the type, creation and guy who did the action (probably the user) are actually human readable with a limit of 8 items (or else the /me page would be as long as this projectās crappy devlogs). When thereās more, a beautiful āview moreā button appears (separate page). For this, so called āview moreā page, i used the infinite queries. while at first i just puuushed the data into the dom with the #each (svelte thingy), chrome do be VERY very mad when thereās a lot of entries in there (The audit log, because it logs actions in your account, can get very huge. Because actions like the baddie Session action logs each time you log in or log out), SOO i did what someone whose browser is eating more than 10gb does, using a virtual list to render the it! (IT only renders items when they are visible, hidding [removing from the dom] non visible ones. this fixes the āOH gosh THOSE 200 things THAT I CANT EVEN SEE, ARE EATING MY precious ramā). OHh and you can press ESC to leave the page because i made a cool component that lets me plug in a callback for specific keyboard events :D. SECOND, the passkey stuff. yeah, pretty easy thanks to libraries like SimpleWebAuthn that do the hard work of telling the browser āhey, authenticate this guy pleaseā or āhiya, registrate this passkey pleaseā. its just querying what passkys you have to know⦠hwat passkeys you have and thatās it. BUT sadly, an actually sadly, my passkeys are non resident (I cant have a simple button to just login, I need you email before i can use the passkey). Thaaat means I havea teeny big tiny small user enumaration problemo becuase the backend can reveal that an user has a passkey registered and, in turn, we know that user is registered. a bad guy can just atack with āoh noes, your passkey has been stolen. pls give a undecillion of moneysā. third, i had to add the sudo page. It does what you think, reauthenticate to do sensitive operations like adding a passkey. Pretty simple, it redirects directly to an email code if the user does not have a passkey or totp enabled (email code is always enabled), if they have those, it just shows a selection screen. fourth, i had to fix up some stupid things with the api schema of the backend becuase I either forgot to put a body on the responses (like the passkey/webauthn routes) or just fix up a teeeeeny tiny setting thing that wasnt correct (its the webauthn/passkey rp_origin [allowed pages to register/use a passkey} becuase it jsut used the backend url and THAT is not correct). so tahatās it, shall you see some stupid screenshots and not even a video because i havent even finished everything:
hi hello this is space bird. i have eaten 9h hours of real world time in just making the dialog component. I mean, IT WAS for making the 2FA prompts for when you wanted to enable it or disable and bleh bluh.. atleast it does look great⦠and i still need to add icons. the prompt is just the typical 2fa enable that gives you a qr or the 2fa secret if you cant scan the qr. The dialog component was pretty much made in nothing, in air time (free :D). the thing that took a bit was just the styling BUT WAHT did take a BIG LOOOT of time was just making the 2FA dialogs. lik gha damn hecking ā2FA promptā and ābeep boop enabling dialogsā.. why?! becuase they are PACKED like a lasagna with forms, tanstack fetching, dialog steps and other stupid stuff to make it atleast not confusing for the user to navigate with tree sized buttons that dont work (becuase you are on the wrong step!!!!1 or already did everything lol). i mean, besides that custom stuff, it just reuses components like the pin or qr svg and⦠for now, also uses the spinner icon on the buttons you click to manage 2fa as i couldnt be asked to add real icons for now (leaving them for lasts). next up working work is more dialogs (for the passkey setup [so it isnt just a spinner without any āmagic guideanceā]), a collapsible comp to wrap the info items to show EVENTUALLY some metadata like, in the session items, browser, ip, what user was that did that thing and etc. Its just so i dont balloon the āinfo itemsā BECaUSE they are supposed to be some kind of āquick infoā. broom brroom, i love wasting time on these stupid things (and wiring them!) >:3. LEAVING that tiny goofy work that apparently took hours to do. I am thinking and WILL be doing a beautiful swap into using resident passkeys (the ones that dont require me to know the userās email in advance). yes, i know i said before that i dont wanted and ew ew resident. but man, its just easier for the end user to click a magical button to login directly. AND AND this even protects me from someone slapping the meowbackend with the email fish to see who is registered (with a passkey) by checking if the userās email makes the selector appear. still, some part of me still thinks this is really bad idea but i want to do it tho⦠what could go wrong hah! i might aswell go to the cooking pot already and make some uhh chicken soup made of space birb. thatās it, i still feel like i havent done anything. Hereās your beautiful video of showing the beautiful dialog going āhiā āgoodbyeā (the video shows me enabling 2fa, viewing recovery codes and disabling it [with a recovery code]):
hi hello hiiii, stupid space birb back from long bed sleep break. CATCHING UP, i have swapped to resident passkeys, fixed jwk refresh feature not working, beautified toml settings, added 2fa replay protection and audit log beautification. alright.. prepare for a long boring devlog as always. I finally swapped to resident passkeys after thinking about it for days (hours)! That means.. NO MORE user enumeration problemo with passkeys, yippie. it wasnt really a pain in the feathered buttocks, like it was just enabling a crate flag and boomy boom (and it even works on the frontend!). also, i patched with scotch tape a stupid buggy bug about the email templates, becuase I used a lazylock to store the email templater engine stuffy, when SOME random goofy template or data was wrong for whatever reason, it would poison the lazylock and the next time it was used it would just say āoh noes, i am broken, poisoned my childs. GO HECK YOUR SELFā⦠i just fixed the template part by checking if tera likes them in the global state creation. i love scotch tape, it smells great. while doing that, i finally addressed the beautiful jwks not updating on all instances because in MY JOB QUEUE only one running server instance can eat the job. that means, if you have 2 instances running, the one that is the unfortunate one that didnt eat the job will have stale jwks until the next time it is restarted. fixed it with some beautiful blue elephant database screaming āHEY GUYS, THE JWKS HAVE BEEN UPDATEDā and the other instances will be like āoh, okay, i will update my beautiful jwks nowā. finally, 2fa, or as i like to call it, TOTP, has been taken cared like a baby and then thrown again to the battle field after giving it the power up of replay protection. That means, if you use a code, it will be marked as used and you cant use it again (this only works with valid codes). makes you wait more smh. THE SETTINGS got a layer of microscopic makeup because i was like āman, these setting name are weired? what if the settings file had comments to know what the heck is this beautiful knob named ādo_not_touch_thisāā. yes i did that. it was a big red booty pain as i had rerereremember how to do proc_macros and how the heck did i even update the toml files with new entries without making them implode with gibrish. AND WE ALL KNOW NOW that ādo_not_touch_thisā is a setting that if you set it to true, it will make this space birb implode in flames and become dust (yes, like a real firework going CHIRPAAAAAAAAAAAH pop ). and the final thing given some body work spray was the audit log. no more caveman moonbeeper style ālogā method with a thousand things. now we have the SAME thing but as a builder with a āsaveā method. it just makes the code easier to read and understand. also, the audit log now has a āwhat resourceĀæā and āwhat ip?ā and i removed the audit entry making from inside the auth helpers to outside. it was just an inconvenient place to put it, i dont evne know why would moonbeeper put it there⦠oh right i am moonbeeper. I DID IT BECAUSE it was a great place in those times. alright, HEREās your typical bad screenshots that are trashign and god i am sleepy:
pew pew cabosh, wawah space birb is very sleepy. BREAKING NEWS, i added and changed a lot of things so i could make a delicious soup of changes that changed my old changed code that i yes. minimal frontend work called making the passkey section button go crazy with colors, authenticator icon (just search āaaguid explorerā, its not crazy work) and having a dialog telling āhi do you want to rename this, no? okayā. I also have collapsibles that hide info from your lil nonfluffy face when its useless. Now my crappy server knows from where you are connecting (who would have known that a server could know that) and where you live (oh no [its approximated from your ip]). THe latter only works when the instance is proxied under cloudflare (it even gets mad if a request doesnt have the headers it wants when you have enabled the āunder cloudflareā mode). the audit log single method to do everything⢠has been swapped with a builder (i love this), AND its info now includes that same ip and location (actor related [who did it]). all fields are now obligatory for⦠audit log purposes, because before i just pushed null on the db for things i didnt want to show the user MAKING a pretty stinker audit log that does not show who did what. i really dont know whata past me thought, because you can keep everything on the db and just show what you want to the user. idk, past me thinking in uhm not portals (yes). okay, more slurry of things. mah beautiful fix so the JWKS (signing keys used to⦠sign a jwt! [important for OpenID]) update when the database JWKS changed, spammed the hell out of the db and log as it polled instead of waiting for the db (or an instance) to say āI UPDATED IT GUYSS!1ā!1ā. This comes from the instances cacheāing JWKS instead of saying ācould you repeat thatā to the db (too many requests = blue elephant cry and explosions), so they need to know when the db changes or THEY WILL BE out of sync!! mr past me also thought that it was a good idea to store the oauth token code (used to get an access token) in plaintext in the muffing db, SMTH YOU SHOULDNT AT ALL DO. now its just hashed via hmac just like everything else. man i am GOOOD at this job of so called programming, having to go back to edit a thing i called done AND then HAVINGTO edit and edit and edit. this is so fun that I WILL BURST into FLAMES because of how stoopid i am meanwhile, you also have me deserving to be cooked with rice because I made a condition in the oauth token exchange that when SOMEONE somehow miss types or gets access to the oauth token code but has the wrong client_id, the temporary code gets deleted⦠and you know what i forgot? i forgot to commit the changes to the db, so the code never was deleted lol. i love these kind of stupid goofy pain errors that arent even errors. AALSO I reprettyfied the oauth helpers because after working on them a long time ago, i didnt know what were they doing and it wasnt fun nor funny >:( [i was mad {i am still mad, with that space birb⦠i want to sentence past moon to sad corner jail for 12 seconds}]. NOW teeny tiny additions!ā1 the ratelimiter now exposes a āRetry-Afterā per a hacker news old moldy article i found, plus exposes its headers on cors. the audit log now does its job even in more parts! now it also tracks the totp recovery code usage [i frankly forgot about it :(].Changing your email or name now requires sudo minus the name on register. AND the app startup has now a beautiful banner saying āmeow authā in cursive. its pretty :3, makes it stylishinning. I also moved and added to the service manager (the watcher) a way to have service names and to launch services from inside of it (for some reason i used a method that was outof place for ages lol). oh no my time has come nnonono, i give you permission to see my trashy work in screenshot format (so modern)⦠yet i shall push towards completion of this meowing meow meow authing meow auth server:...
|
1792738089.8583465
|
1793342889.8583465
|