diff --git a/.github/vale/styles/config/vocabularies/FusionAuth/accept.txt b/.github/vale/styles/config/vocabularies/FusionAuth/accept.txt new file mode 100644 index 0000000000..5fc83f0ea7 --- /dev/null +++ b/.github/vale/styles/config/vocabularies/FusionAuth/accept.txt @@ -0,0 +1,114 @@ +[Aa]utoscaling +Aiven +anonymization +API +authorizer +Bachman +Basecamp +[Bb]crypt +boolean +CAPTCHA +[Cc]yberattack +[Cc]ybercriminal +[Cc]ybersecurity +Cognito +CRM +cron +crypto +CSP +cutover +CVE +datacenter +datastore +[Dd]ev +deprovision +deserialize +Dockerfile +Equifax +Erlich +esport +failover +Fastly +FIDO +FusionAuth +gameplay +Guice +HAProxy +Hashicorp +Hooli +hostname +Hubspot +Id +Infosec +initializer +interoperate +Inversoft +ISP +Istio +JMeter +JWT +Kaspersky +Kerberos +Keycloak +keypair +Laravel +Linkerd +Linode +lossy +middleware +minifier +namespace +nginx +ngrok +npm +OAuth +Okta +onboarded +[Oo]ffboarding +[Oo]nboarding +Packagist +passcode +pentesting +performant +Pinterest +plaintext +Postgres +[Pp]asswordless +pseudocode +pseudonymization +pseudonymize +Psyonix +Pulumi +[Qq]uickstart +reauthenticate +reauthentication +repo +[Rr]eindex +[Rr]elicensing +[Rr]oadmap +SDK +SHA +Shopify +signup +SLA +[Ss]crypt +SSD +[Ss]erverless +[Ss]harding +Supabase +Twilio +URI +virtualized +VPN +Vue +WebAuthn +webview +Wordpress +WUPHF +[Ww]ebapp +Xbox +Xcode +xkcd +Yubico +YubiKey +Zendesk diff --git a/.github/vale/styles/write-good/Cliches.yml b/.github/vale/styles/write-good/Cliches.yml new file mode 100644 index 0000000000..c95314387b --- /dev/null +++ b/.github/vale/styles/write-good/Cliches.yml @@ -0,0 +1,702 @@ +extends: existence +message: "Try to avoid using clichés like '%s'." +ignorecase: true +level: warning +tokens: + - a chip off the old block + - a clean slate + - a dark and stormy night + - a far cry + - a fine kettle of fish + - a loose cannon + - a penny saved is a penny earned + - a tough row to hoe + - a word to the wise + - ace in the hole + - acid test + - add insult to injury + - against all odds + - air your dirty laundry + - all fun and games + - all in a day's work + - all talk, no action + - all thumbs + - all your eggs in one basket + - all's fair in love and war + - all's well that ends well + - almighty dollar + - American as apple pie + - an axe to grind + - another day, another dollar + - armed to the teeth + - as luck would have it + - as old as time + - as the crow flies + - at loose ends + - at my wits end + - avoid like the plague + - babe in the woods + - back against the wall + - back in the saddle + - back to square one + - back to the drawing board + - bad to the bone + - badge of honor + - bald faced liar + - ballpark figure + - banging your head against a brick wall + - baptism by fire + - barking up the wrong tree + - bat out of hell + - be all and end all + - beat a dead horse + - beat around the bush + - been there, done that + - beggars can't be choosers + - behind the eight ball + - bend over backwards + - benefit of the doubt + - bent out of shape + - best thing since sliced bread + - bet your bottom dollar + - better half + - better late than never + - better mousetrap + - better safe than sorry + - between a rock and a hard place + - beyond the pale + - bide your time + - big as life + - big cheese + - big fish in a small pond + - big man on campus + - bigger they are the harder they fall + - bird in the hand + - bird's eye view + - birds and the bees + - birds of a feather flock together + - bit the hand that feeds you + - bite the bullet + - bite the dust + - bitten off more than he can chew + - black as coal + - black as pitch + - black as the ace of spades + - blast from the past + - bleeding heart + - blessing in disguise + - blind ambition + - blind as a bat + - blind leading the blind + - blood is thicker than water + - blood sweat and tears + - blow off steam + - blow your own horn + - blushing bride + - boils down to + - bolt from the blue + - bone to pick + - bored stiff + - bored to tears + - bottomless pit + - boys will be boys + - bright and early + - brings home the bacon + - broad across the beam + - broken record + - brought back to reality + - bull by the horns + - bull in a china shop + - burn the midnight oil + - burning question + - burning the candle at both ends + - burst your bubble + - bury the hatchet + - busy as a bee + - by hook or by crook + - call a spade a spade + - called onto the carpet + - calm before the storm + - can of worms + - can't cut the mustard + - can't hold a candle to + - case of mistaken identity + - cat got your tongue + - cat's meow + - caught in the crossfire + - caught red-handed + - checkered past + - chomping at the bit + - cleanliness is next to godliness + - clear as a bell + - clear as mud + - close to the vest + - cock and bull story + - cold shoulder + - come hell or high water + - cool as a cucumber + - cool, calm, and collected + - cost a king's ransom + - count your blessings + - crack of dawn + - crash course + - creature comforts + - cross that bridge when you come to it + - crushing blow + - cry like a baby + - cry me a river + - cry over spilt milk + - crystal clear + - curiosity killed the cat + - cut and dried + - cut through the red tape + - cut to the chase + - cute as a bugs ear + - cute as a button + - cute as a puppy + - cuts to the quick + - dark before the dawn + - day in, day out + - dead as a doornail + - devil is in the details + - dime a dozen + - divide and conquer + - dog and pony show + - dog days + - dog eat dog + - dog tired + - don't burn your bridges + - don't count your chickens + - don't look a gift horse in the mouth + - don't rock the boat + - don't step on anyone's toes + - don't take any wooden nickels + - down and out + - down at the heels + - down in the dumps + - down the hatch + - down to earth + - draw the line + - dressed to kill + - dressed to the nines + - drives me up the wall + - dull as dishwater + - dyed in the wool + - eagle eye + - ear to the ground + - early bird catches the worm + - easier said than done + - easy as pie + - eat your heart out + - eat your words + - eleventh hour + - even the playing field + - every dog has its day + - every fiber of my being + - everything but the kitchen sink + - eye for an eye + - face the music + - facts of life + - fair weather friend + - fall by the wayside + - fan the flames + - feast or famine + - feather your nest + - feathered friends + - few and far between + - fifteen minutes of fame + - filthy vermin + - fine kettle of fish + - fish out of water + - fishing for a compliment + - fit as a fiddle + - fit the bill + - fit to be tied + - flash in the pan + - flat as a pancake + - flip your lid + - flog a dead horse + - fly by night + - fly the coop + - follow your heart + - for all intents and purposes + - for the birds + - for what it's worth + - force of nature + - force to be reckoned with + - forgive and forget + - fox in the henhouse + - free and easy + - free as a bird + - fresh as a daisy + - full steam ahead + - fun in the sun + - garbage in, garbage out + - gentle as a lamb + - get a kick out of + - get a leg up + - get down and dirty + - get the lead out + - get to the bottom of + - get your feet wet + - gets my goat + - gilding the lily + - give and take + - go against the grain + - go at it tooth and nail + - go for broke + - go him one better + - go the extra mile + - go with the flow + - goes without saying + - good as gold + - good deed for the day + - good things come to those who wait + - good time was had by all + - good times were had by all + - greased lightning + - greek to me + - green thumb + - green-eyed monster + - grist for the mill + - growing like a weed + - hair of the dog + - hand to mouth + - happy as a clam + - happy as a lark + - hasn't a clue + - have a nice day + - have high hopes + - have the last laugh + - haven't got a row to hoe + - head honcho + - head over heels + - hear a pin drop + - heard it through the grapevine + - heart's content + - heavy as lead + - hem and haw + - high and dry + - high and mighty + - high as a kite + - hit paydirt + - hold your head up high + - hold your horses + - hold your own + - hold your tongue + - honest as the day is long + - horns of a dilemma + - horse of a different color + - hot under the collar + - hour of need + - I beg to differ + - icing on the cake + - if the shoe fits + - if the shoe were on the other foot + - in a jam + - in a jiffy + - in a nutshell + - in a pig's eye + - in a pinch + - in a word + - in hot water + - in the gutter + - in the nick of time + - in the thick of it + - in your dreams + - it ain't over till the fat lady sings + - it goes without saying + - it takes all kinds + - it takes one to know one + - it's a small world + - it's only a matter of time + - ivory tower + - Jack of all trades + - jockey for position + - jog your memory + - joined at the hip + - judge a book by its cover + - jump down your throat + - jump in with both feet + - jump on the bandwagon + - jump the gun + - jump to conclusions + - just a hop, skip, and a jump + - just the ticket + - justice is blind + - keep a stiff upper lip + - keep an eye on + - keep it simple, stupid + - keep the home fires burning + - keep up with the Joneses + - keep your chin up + - keep your fingers crossed + - kick the bucket + - kick up your heels + - kick your feet up + - kid in a candy store + - kill two birds with one stone + - kiss of death + - knock it out of the park + - knock on wood + - knock your socks off + - know him from Adam + - know the ropes + - know the score + - knuckle down + - knuckle sandwich + - knuckle under + - labor of love + - ladder of success + - land on your feet + - lap of luxury + - last but not least + - last hurrah + - last-ditch effort + - law of the jungle + - law of the land + - lay down the law + - leaps and bounds + - let sleeping dogs lie + - let the cat out of the bag + - let the good times roll + - let your hair down + - let's talk turkey + - letter perfect + - lick your wounds + - lies like a rug + - life's a bitch + - life's a grind + - light at the end of the tunnel + - lighter than a feather + - lighter than air + - like clockwork + - like father like son + - like taking candy from a baby + - like there's no tomorrow + - lion's share + - live and learn + - live and let live + - long and short of it + - long lost love + - look before you leap + - look down your nose + - look what the cat dragged in + - looking a gift horse in the mouth + - looks like death warmed over + - loose cannon + - lose your head + - lose your temper + - loud as a horn + - lounge lizard + - loved and lost + - low man on the totem pole + - luck of the draw + - luck of the Irish + - make hay while the sun shines + - make money hand over fist + - make my day + - make the best of a bad situation + - make the best of it + - make your blood boil + - man of few words + - man's best friend + - mark my words + - meaningful dialogue + - missed the boat on that one + - moment in the sun + - moment of glory + - moment of truth + - money to burn + - more power to you + - more than one way to skin a cat + - movers and shakers + - moving experience + - naked as a jaybird + - naked truth + - neat as a pin + - needle in a haystack + - needless to say + - neither here nor there + - never look back + - never say never + - nip and tuck + - nip it in the bud + - no guts, no glory + - no love lost + - no pain, no gain + - no skin off my back + - no stone unturned + - no time like the present + - no use crying over spilled milk + - nose to the grindstone + - not a hope in hell + - not a minute's peace + - not in my backyard + - not playing with a full deck + - not the end of the world + - not written in stone + - nothing to sneeze at + - nothing ventured nothing gained + - now we're cooking + - off the top of my head + - off the wagon + - off the wall + - old hat + - older and wiser + - older than dirt + - older than Methuselah + - on a roll + - on cloud nine + - on pins and needles + - on the bandwagon + - on the money + - on the nose + - on the rocks + - on the spot + - on the tip of my tongue + - on the wagon + - on thin ice + - once bitten, twice shy + - one bad apple doesn't spoil the bushel + - one born every minute + - one brick short + - one foot in the grave + - one in a million + - one red cent + - only game in town + - open a can of worms + - open and shut case + - open the flood gates + - opportunity doesn't knock twice + - out of pocket + - out of sight, out of mind + - out of the frying pan into the fire + - out of the woods + - out on a limb + - over a barrel + - over the hump + - pain and suffering + - pain in the + - panic button + - par for the course + - part and parcel + - party pooper + - pass the buck + - patience is a virtue + - pay through the nose + - penny pincher + - perfect storm + - pig in a poke + - pile it on + - pillar of the community + - pin your hopes on + - pitter patter of little feet + - plain as day + - plain as the nose on your face + - play by the rules + - play your cards right + - playing the field + - playing with fire + - pleased as punch + - plenty of fish in the sea + - point with pride + - poor as a church mouse + - pot calling the kettle black + - pretty as a picture + - pull a fast one + - pull your punches + - pulling your leg + - pure as the driven snow + - put it in a nutshell + - put one over on you + - put the cart before the horse + - put the pedal to the metal + - put your best foot forward + - put your foot down + - quick as a bunny + - quick as a lick + - quick as a wink + - quick as lightning + - quiet as a dormouse + - rags to riches + - raining buckets + - raining cats and dogs + - rank and file + - rat race + - reap what you sow + - red as a beet + - red herring + - reinvent the wheel + - rich and famous + - rings a bell + - ripe old age + - ripped me off + - rise and shine + - road to hell is paved with good intentions + - rob Peter to pay Paul + - roll over in the grave + - rub the wrong way + - ruled the roost + - running in circles + - sad but true + - sadder but wiser + - salt of the earth + - scared stiff + - scared to death + - sealed with a kiss + - second to none + - see eye to eye + - seen the light + - seize the day + - set the record straight + - set the world on fire + - set your teeth on edge + - sharp as a tack + - shoot for the moon + - shoot the breeze + - shot in the dark + - shoulder to the wheel + - sick as a dog + - sigh of relief + - signed, sealed, and delivered + - sink or swim + - six of one, half a dozen of another + - skating on thin ice + - slept like a log + - slinging mud + - slippery as an eel + - slow as molasses + - smart as a whip + - smooth as a baby's bottom + - sneaking suspicion + - snug as a bug in a rug + - sow wild oats + - spare the rod, spoil the child + - speak of the devil + - spilled the beans + - spinning your wheels + - spitting image of + - spoke with relish + - spread like wildfire + - spring to life + - squeaky wheel gets the grease + - stands out like a sore thumb + - start from scratch + - stick in the mud + - still waters run deep + - stitch in time + - stop and smell the roses + - straight as an arrow + - straw that broke the camel's back + - strong as an ox + - stubborn as a mule + - stuff that dreams are made of + - stuffed shirt + - sweating blood + - sweating bullets + - take a load off + - take one for the team + - take the bait + - take the bull by the horns + - take the plunge + - takes one to know one + - takes two to tango + - the more the merrier + - the real deal + - the real McCoy + - the red carpet treatment + - the same old story + - there is no accounting for taste + - thick as a brick + - thick as thieves + - thin as a rail + - think outside of the box + - third time's the charm + - this day and age + - this hurts me worse than it hurts you + - this point in time + - three sheets to the wind + - through thick and thin + - throw in the towel + - tie one on + - tighter than a drum + - time and time again + - time is of the essence + - tip of the iceberg + - tired but happy + - to coin a phrase + - to each his own + - to make a long story short + - to the best of my knowledge + - toe the line + - tongue in cheek + - too good to be true + - too hot to handle + - too numerous to mention + - touch with a ten foot pole + - tough as nails + - trial and error + - trials and tribulations + - tried and true + - trip down memory lane + - twist of fate + - two cents worth + - two peas in a pod + - ugly as sin + - under the counter + - under the gun + - under the same roof + - under the weather + - until the cows come home + - unvarnished truth + - up the creek + - uphill battle + - upper crust + - upset the applecart + - vain attempt + - vain effort + - vanquish the enemy + - vested interest + - waiting for the other shoe to drop + - wakeup call + - warm welcome + - watch your p's and q's + - watch your tongue + - watching the clock + - water under the bridge + - weather the storm + - weed them out + - week of Sundays + - went belly up + - wet behind the ears + - what goes around comes around + - what you see is what you get + - when it rains, it pours + - when push comes to shove + - when the cat's away + - when the going gets tough, the tough get going + - white as a sheet + - whole ball of wax + - whole hog + - whole nine yards + - wild goose chase + - will wonders never cease? + - wisdom of the ages + - wise as an owl + - wolf at the door + - words fail me + - work like a dog + - world weary + - worst nightmare + - worth its weight in gold + - wrong side of the bed + - yanking your chain + - yappy as a dog + - years young + - you are what you eat + - you can run but you can't hide + - you only live once + - you're the boss + - young and foolish + - young and vibrant diff --git a/.github/vale/styles/write-good/E-Prime.yml b/.github/vale/styles/write-good/E-Prime.yml new file mode 100644 index 0000000000..fdc47a0a52 --- /dev/null +++ b/.github/vale/styles/write-good/E-Prime.yml @@ -0,0 +1,31 @@ +extends: existence +message: "Try to avoid using '%s'." +ignorecase: true +level: suggestion +tokens: + - am + - are + - aren't + - be + - been + - being + - he's + - here's + - here's + - how's + - i'm + - is + - isn't + - she's + - that's + - there's + - they're + - was + - wasn't + - we're + - were + - weren't + - what's + - where's + - who's + - you're diff --git a/.github/vale/styles/write-good/Illusions.yml b/.github/vale/styles/write-good/Illusions.yml new file mode 100644 index 0000000000..b4f1321859 --- /dev/null +++ b/.github/vale/styles/write-good/Illusions.yml @@ -0,0 +1,11 @@ +extends: repetition +message: "'%s' is repeated!" +level: warning +alpha: true +action: + name: edit + params: + - truncate + - " " +tokens: + - '[^\s]+' diff --git a/.github/vale/styles/write-good/Passive.yml b/.github/vale/styles/write-good/Passive.yml new file mode 100644 index 0000000000..f472cb9049 --- /dev/null +++ b/.github/vale/styles/write-good/Passive.yml @@ -0,0 +1,183 @@ +extends: existence +message: "'%s' may be passive voice. Use active voice if you can." +ignorecase: true +level: warning +raw: + - \b(am|are|were|being|is|been|was|be)\b\s* +tokens: + - '[\w]+ed' + - awoken + - beat + - become + - been + - begun + - bent + - beset + - bet + - bid + - bidden + - bitten + - bled + - blown + - born + - bought + - bound + - bred + - broadcast + - broken + - brought + - built + - burnt + - burst + - cast + - caught + - chosen + - clung + - come + - cost + - crept + - cut + - dealt + - dived + - done + - drawn + - dreamt + - driven + - drunk + - dug + - eaten + - fallen + - fed + - felt + - fit + - fled + - flown + - flung + - forbidden + - foregone + - forgiven + - forgotten + - forsaken + - fought + - found + - frozen + - given + - gone + - gotten + - ground + - grown + - heard + - held + - hidden + - hit + - hung + - hurt + - kept + - knelt + - knit + - known + - laid + - lain + - leapt + - learnt + - led + - left + - lent + - let + - lighted + - lost + - made + - meant + - met + - misspelt + - mistaken + - mown + - overcome + - overdone + - overtaken + - overthrown + - paid + - pled + - proven + - put + - quit + - read + - rid + - ridden + - risen + - run + - rung + - said + - sat + - sawn + - seen + - sent + - set + - sewn + - shaken + - shaven + - shed + - shod + - shone + - shorn + - shot + - shown + - shrunk + - shut + - slain + - slept + - slid + - slit + - slung + - smitten + - sold + - sought + - sown + - sped + - spent + - spilt + - spit + - split + - spoken + - spread + - sprung + - spun + - stolen + - stood + - stridden + - striven + - struck + - strung + - stuck + - stung + - stunk + - sung + - sunk + - swept + - swollen + - sworn + - swum + - swung + - taken + - taught + - thought + - thrived + - thrown + - thrust + - told + - torn + - trodden + - understood + - upheld + - upset + - wed + - wept + - withheld + - withstood + - woken + - won + - worn + - wound + - woven + - written + - wrung diff --git a/.github/vale/styles/write-good/README.md b/.github/vale/styles/write-good/README.md new file mode 100644 index 0000000000..3edcc9b376 --- /dev/null +++ b/.github/vale/styles/write-good/README.md @@ -0,0 +1,27 @@ +Based on [write-good](https://github.com/btford/write-good). + +> Naive linter for English prose for developers who can't write good and wanna learn to do other stuff good too. + +``` +The MIT License (MIT) + +Copyright (c) 2014 Brian Ford + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` diff --git a/.github/vale/styles/write-good/TooWordy.yml b/.github/vale/styles/write-good/TooWordy.yml new file mode 100644 index 0000000000..275701b196 --- /dev/null +++ b/.github/vale/styles/write-good/TooWordy.yml @@ -0,0 +1,221 @@ +extends: existence +message: "'%s' is too wordy." +ignorecase: true +level: warning +tokens: + - a number of + - abundance + - accede to + - accelerate + - accentuate + - accompany + - accomplish + - accorded + - accrue + - acquiesce + - acquire + - additional + - adjacent to + - adjustment + - admissible + - advantageous + - adversely impact + - advise + - aforementioned + - aggregate + - aircraft + - all of + - all things considered + - alleviate + - allocate + - along the lines of + - already existing + - alternatively + - amazing + - ameliorate + - anticipate + - apparent + - appreciable + - as a matter of fact + - as a means of + - as far as I'm concerned + - as of yet + - as to + - as yet + - ascertain + - assistance + - at the present time + - at this time + - attain + - attributable to + - authorize + - because of the fact that + - belated + - benefit from + - bestow + - by means of + - by virtue of + - by virtue of the fact that + - cease + - close proximity + - commence + - comply with + - concerning + - consequently + - consolidate + - constitutes + - demonstrate + - depart + - designate + - discontinue + - due to the fact that + - each and every + - economical + - eliminate + - elucidate + - employ + - endeavor + - enumerate + - equitable + - equivalent + - evaluate + - evidenced + - exclusively + - expedite + - expend + - expiration + - facilitate + - factual evidence + - feasible + - finalize + - first and foremost + - for all intents and purposes + - for the most part + - for the purpose of + - forfeit + - formulate + - have a tendency to + - honest truth + - however + - if and when + - impacted + - implement + - in a manner of speaking + - in a timely manner + - in a very real sense + - in accordance with + - in addition + - in all likelihood + - in an effort to + - in between + - in excess of + - in lieu of + - in light of the fact that + - in many cases + - in my opinion + - in order to + - in regard to + - in some instances + - in terms of + - in the case of + - in the event that + - in the final analysis + - in the nature of + - in the near future + - in the process of + - inception + - incumbent upon + - indicate + - indication + - initiate + - irregardless + - is applicable to + - is authorized to + - is responsible for + - it is + - it is essential + - it seems that + - it was + - magnitude + - maximum + - methodology + - minimize + - minimum + - modify + - monitor + - multiple + - necessitate + - nevertheless + - not certain + - not many + - not often + - not unless + - not unlike + - notwithstanding + - null and void + - numerous + - objective + - obligate + - obtain + - on the contrary + - on the other hand + - one particular + - optimum + - overall + - owing to the fact that + - participate + - particulars + - pass away + - pertaining to + - point in time + - portion + - possess + - preclude + - previously + - prior to + - prioritize + - procure + - proficiency + - provided that + - purchase + - put simply + - readily apparent + - refer back + - regarding + - relocate + - remainder + - remuneration + - requirement + - reside + - residence + - retain + - satisfy + - shall + - should you wish + - similar to + - solicit + - span across + - strategize + - subsequent + - substantial + - successfully complete + - sufficient + - terminate + - the month of + - the point I am trying to make + - therefore + - time period + - took advantage of + - transmit + - transpire + - type of + - until such time as + - utilization + - utilize + - validate + - various different + - what I mean to say is + - whether or not + - with respect to + - with the exception of + - witnessed diff --git a/.github/vale/styles/write-good/Weasel.yml b/.github/vale/styles/write-good/Weasel.yml new file mode 100644 index 0000000000..e29391444b --- /dev/null +++ b/.github/vale/styles/write-good/Weasel.yml @@ -0,0 +1,207 @@ +extends: existence +message: "'%s' is a weasel word!" +ignorecase: true +level: warning +tokens: + - absolutely + - accidentally + - additionally + - allegedly + - alternatively + - angrily + - anxiously + - approximately + - awkwardly + - badly + - barely + - beautifully + - blindly + - boldly + - bravely + - brightly + - briskly + - bristly + - bubbly + - busily + - calmly + - carefully + - carelessly + - cautiously + - cheerfully + - clearly + - closely + - coldly + - completely + - consequently + - correctly + - courageously + - crinkly + - cruelly + - crumbly + - cuddly + - currently + - daily + - daringly + - deadly + - definitely + - deliberately + - doubtfully + - dumbly + - eagerly + - early + - easily + - elegantly + - enormously + - enthusiastically + - equally + - especially + - eventually + - exactly + - exceedingly + - exclusively + - extremely + - fairly + - faithfully + - fatally + - fiercely + - finally + - fondly + - few + - foolishly + - fortunately + - frankly + - frantically + - generously + - gently + - giggly + - gladly + - gracefully + - greedily + - happily + - hardly + - hastily + - healthily + - heartily + - helpfully + - honestly + - hourly + - hungrily + - hurriedly + - immediately + - impatiently + - inadequately + - ingeniously + - innocently + - inquisitively + - interestingly + - irritably + - jiggly + - joyously + - justly + - kindly + - largely + - lately + - lazily + - likely + - literally + - lonely + - loosely + - loudly + - loudly + - luckily + - madly + - many + - mentally + - mildly + - monthly + - mortally + - mostly + - mysteriously + - neatly + - nervously + - nightly + - noisily + - normally + - obediently + - occasionally + - only + - openly + - painfully + - particularly + - patiently + - perfectly + - politely + - poorly + - powerfully + - presumably + - previously + - promptly + - punctually + - quarterly + - quickly + - quietly + - rapidly + - rarely + - really + - recently + - recklessly + - regularly + - remarkably + - relatively + - reluctantly + - repeatedly + - rightfully + - roughly + - rudely + - sadly + - safely + - selfishly + - sensibly + - seriously + - sharply + - shortly + - shyly + - significantly + - silently + - simply + - sleepily + - slowly + - smartly + - smelly + - smoothly + - softly + - solemnly + - sparkly + - speedily + - stealthily + - sternly + - stupidly + - substantially + - successfully + - suddenly + - surprisingly + - suspiciously + - swiftly + - tenderly + - tensely + - thoughtfully + - tightly + - timely + - truthfully + - unexpectedly + - unfortunately + - usually + - very + - victoriously + - violently + - vivaciously + - warmly + - waverly + - weakly + - wearily + - weekly + - wildly + - wisely + - worldly + - wrinkly + - yearly diff --git a/.github/vale/styles/write-good/meta.json b/.github/vale/styles/write-good/meta.json new file mode 100644 index 0000000000..a115d2886a --- /dev/null +++ b/.github/vale/styles/write-good/meta.json @@ -0,0 +1,4 @@ +{ + "feed": "https://github.com/errata-ai/write-good/releases.atom", + "vale_version": ">=1.0.0" +} diff --git a/.github/workflows/vale.yml b/.github/workflows/vale.yml new file mode 100644 index 0000000000..77868e7a44 --- /dev/null +++ b/.github/workflows/vale.yml @@ -0,0 +1,13 @@ +name: reviewdog +on: [pull_request] + +jobs: + vale: + name: runner / vale + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: errata-ai/vale-action@reviewdog + with: + files: '["astro/src/content"]' + fail_on_error: false diff --git a/.vale.ini b/.vale.ini new file mode 100644 index 0000000000..13be19eb30 --- /dev/null +++ b/.vale.ini @@ -0,0 +1,24 @@ +StylesPath = .github/vale/styles + +Vocab = FusionAuth +MinAlertLevel = error + +[formats] +mdx = md +astro = md + +[*.md] +BasedOnStyles = Vale, write-good +BlockIgnores = ]+)?/> +TokenIgnores = (?m)^import .+ from [^\n]+$, \ +(?m)^export const .+, \ +]+)?>, \ +, \ +[^<]+<\/InlineField>, \ +[^<]+<\/InlineUIElement>, \ +]+)?/>, \ +]+)?/>, \ +]+)?/>, \ +]+)?/>, \ +]+)?>[^<]+<\/APIField>, \ +]+)?>[^<]+<\/APIURI> diff --git a/DocsDevREADME.md b/DocsDevREADME.md index 9385f02027..ffc4cae981 100644 --- a/DocsDevREADME.md +++ b/DocsDevREADME.md @@ -441,6 +441,54 @@ Quickstarts are any pages that are going under /docs/quickstarts that are not on See https://github.com/FusionAuth/fusionauth-example-template/blob/master/QUICKSTART-INSTRUCTIONS.md for instructions on building out a quickstart. + +## Linting + +We're using [Vale](https://vale.sh/) to find misspellings and to standardize terms. + +The main configuration file is located at [`.vale.ini`](./.vale.ini), where we specify file extensions to parse (besides the default `.md` one), some custom filters to ignore Astro components and which rules we'll use. + +### Rules + +- The rules _(or, as Vale calls them, "styles")_ are located at [`.github/vale/styles`](./.github/vale/styles). +- Right now, we're using [`write-good`](./.github.vale/styles/write-good), a collection of simple rules to avoid common mistakes and awkward sentences. +- We also have a custom vocabulary at [`.github/vale/styles/config/vocabularies/FusionAuth/accept.txt`](./.github/vale/styles/config/vocabularies/FusionAuth/accept.txt) with known words. + - Note that this file can use regular expressions to match words in a case-insensitive manner, as described [in their docs](https://vale.sh/docs/topics/vocab/). + +### GitHub Actions + +There's [a GitHub Action](./.github/workflows/vale.yml) that runs Vale on added/modified files when opening a pull request. It'll only cover files located at `astro/src/content`, but it won't block merging the PR, as we currently have lots of errors to fix. So, use it as a guide to improve what you are writing. + +### Running locally + +If you have Docker installed, you can lint files by running the command below. + +```shell +$ cd fusionauth-site +$ docker run --rm -v "$(pwd)/.vale.ini:/etc/.vale.ini" -v "$(pwd)/.github:/etc/.github" -v "$(pwd)/astro:/docs" -w /docs jdkato/vale --config /etc/.vale.ini src/content/path/to/folder/or/file +``` + +If you whether choose to [install Vale locally](https://vale.sh/docs/vale-cli/installation/), make sure you're at the root folder for this repository and run: + +```shell +$ cd fusionauth-site +$ vale astro/path/to/folder/or/file +``` + +If you want to filter by specific rules, you can also pass a `--filter` argument: + +```shell +$ vale --filter=".Name == 'Vale.Spelling'" astro/path/to/file +``` + +### What to do with linting errors + +Whenever you receive an error, you need to determine if you should: + +- Actually fix the word (e.g. if you received an error like _"Use 'Id' instead of 'ID'."_); or +- Add a known word to [`the vocabulary`](./.github/vale/styles/config/vocabularies/FusionAuth/accept.txt) if it's a language, library, company name, etc. But make sure you have the correct capitalization to avoid having duplicates there; or +- In case of custom Astro components, you'd probably need to add a new `TokenIgnores` item in [`.vale.ini`](./.vale.ini). + ## Pull request review process * If a piece of content is technical, it needs a technical review by engineering or devrel. diff --git a/astro/src/content/articles/authentication/developer-benefits-single-sign-on.md b/astro/src/content/articles/authentication/developer-benefits-single-sign-on.md index f5cbb22296..2a535ca1e1 100644 --- a/astro/src/content/articles/authentication/developer-benefits-single-sign-on.md +++ b/astro/src/content/articles/authentication/developer-benefits-single-sign-on.md @@ -16,7 +16,7 @@ This tutorial will lead you through SSO, including what it is, why it’s necess ## What Is SSO and How Does It Work? -[Single sign-on](/features/single-sign-on) is an authentication method that enables users to log in to multiple linked applications or systems by using one ID and password. In the workplace, it is common for users to log onto their Microsoft Windows account and then have access to all the Microsoft Office products that their company uses (Outlook, Excel, etc.) as well as having access to their company’s HR portal without having to log in again. This creates a seamless experience for the user and also eliminates the need for remembering multiple passwords. +[Single sign-on](/features/single-sign-on) is an authentication method that enables users to log in to multiple linked applications or systems by using one Id and password. In the workplace, it is common for users to log onto their Microsoft Windows account and then have access to all the Microsoft Office products that their company uses (Outlook, Excel, etc.) as well as having access to their company’s HR portal without having to log in again. This creates a seamless experience for the user and also eliminates the need for remembering multiple passwords. Another common occurrence of SSO that almost everyone has seen is when you try to create an account on a website. Most companies now allow you to create an account with a username and password or give you the option to create it using your credentials from Google, Facebook, or other SSO providers. diff --git a/astro/src/content/articles/authentication/how-sso-works.mdx b/astro/src/content/articles/authentication/how-sso-works.mdx index a2b19122ff..343bf645b7 100644 --- a/astro/src/content/articles/authentication/how-sso-works.mdx +++ b/astro/src/content/articles/authentication/how-sso-works.mdx @@ -100,7 +100,7 @@ FusionAuth provides an [open source library for Java](https://github.com/FusionA ## Why Use SAML -Why would you pick SAML over the OIDC flow mentioned above? Widespread support. SAML has been around since 2005 and many many commercial off the shelf and open source applications support it. +Why would you pick SAML over the OIDC flow mentioned above? Widespread support. SAML has been around since 2005 and many commercial off the shelf and open source applications support it. When evaluating your identity provider solution, think about what kinds of applications you need to support. diff --git a/astro/src/content/articles/authentication/multi-factor-authentication.md b/astro/src/content/articles/authentication/multi-factor-authentication.md index 8bed490019..9b2be74af5 100644 --- a/astro/src/content/articles/authentication/multi-factor-authentication.md +++ b/astro/src/content/articles/authentication/multi-factor-authentication.md @@ -32,7 +32,7 @@ Each of these methods of proof is called a 'factor'. Factors must be kept secure Multi-factor authentication is best understood as requiring two or more factors in order to authenticate a user. MFA is a superset of two factor authentication (2FA). With MFA an arbitrary number of factors of proof can be required. With 2FA, the number of factors is limited to two. -Multi-factor authentication isn't just for online user accounts, though. If you are accessing a safe deposit box in a bank, you need a key (something you have) and a signature (something you are) or an id (another thing you have). However, this article will focus on online MFA. +Multi-factor authentication isn't just for online user accounts, though. If you are accessing a safe deposit box in a bank, you need a key (something you have) and a signature (something you are) or an Id (another thing you have). However, this article will focus on online MFA. The majority of user accounts have a password as a factor. You might be working in such a system right now. As engineering teams become more aware of the problem of user account hijacking and its real world consequences, more are allowing or requiring additional factors of authentication. @@ -169,7 +169,7 @@ The more factors you require, the more secure access is. No online system, howev Solution availability, security and user experience all play a role in determining what solution is best for your users. When you are incorporating MFA into your application, consider how widely deployed options are among your users or potential audience. -Below is a diagram displaying estimated relative deployment and security attributes of various factors. When deciding which is right for your application, think about security needs as well as what your users have accessible and can use, unless you will be providing all your users with a factor such as a Yubikey. You can also allow multiple factors and let users select one that works for them. +Below is a diagram displaying estimated relative deployment and security attributes of various factors. When deciding which is right for your application, think about security needs as well as what your users have accessible and can use, unless you will be providing all your users with a factor such as a YubiKey. You can also allow multiple factors and let users select one that works for them.
Secure, sure, but is it available? @@ -243,7 +243,7 @@ Physical devices, such as Yubikeys, can be used for authentication too. These de These devices differ from the other factors in this category because they cost money. This makes them acceptable for administrators, technical users, or high value accounts. It also makes this factor problematic for a broad user base; they will likely not have such devices. -As a developer, to use this factor, you need to build in support for the device using an SDK or a standard which the device is compatible with, such as WebAuthN. Your users need to ensure they don't lose it and have it available whenever they authenticate. +As a developer, to use this factor, you need to build in support for the device using an SDK or a standard which the device is compatible with, such as WebAuthn. Your users need to ensure they don't lose it and have it available whenever they authenticate. ### Knowledge: What You Know @@ -303,9 +303,9 @@ To implement authentication using biometric factors, first choose a solution. Ma You could also use biometrics integrated into an operating system. All major operating systems for both mobile phones and computers have some level of biometrics support: * Android has the [Biometric library](https://developer.android.com/jetpack/androidx/releases/biometric). -* iOS supports [Face ID and Touch ID](https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/authentication/). +* iOS supports [Face Id and Touch Id](https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/authentication/). * Windows has [Windows Hello](https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/windows-hello), which integrates with hardware such as a fingerprint scanner. -* MacOS has [Touch ID](https://support.apple.com/guide/mac-help/touch-id-mchl16fbf90a/mac). +* MacOS has [Touch Id](https://support.apple.com/guide/mac-help/touch-id-mchl16fbf90a/mac). If you are building web applications, use the [WebAuthn W3C standard](https://www.w3.org/TR/webauthn-2/), which lets the browser access the operating systems biometric implementations. We'll cover this standard in more detail below. @@ -378,7 +378,7 @@ Don't forget to talk to your end users, or at least a subset of them. The factor If shared secrets need to be captured at authentication or registration, build or buy solutions which allow you to do so. These could be questions and answers, a seed for a TOTP solution, or even registering a physical device. -Plan for a minimum level of MFA, but allow users who want more to go beyond that. Many security conscious users will want to enable MFA for their accounts; allow them to do so. By building this in, you allow users to self select the level of security which makes sense for them. For example, one person may run their entire life through their gmail account, while another may use it only occasionally as a throwaway email account. In the former case, MFA makes sense; in the latter it does not. +Plan for a minimum level of MFA, but allow users who want more to go beyond that. Many security conscious users will want to enable MFA for their accounts; allow them to do so. By building this in, you allow users to self select the level of security which makes sense for them. For example, one person may run their entire life through their Gmail account, while another may use it only occasionally as a throwaway email account. In the former case, MFA makes sense; in the latter it does not. Your MFA policies and configuration should be flexible. You can store MFA requirements in a central location in your application, such as your identity provider, a specialized datastore, or in a configuration file. Be aware that these requirements will evolve as technology and your applications do. New features will be built and some of them may require step up. Different kinds of users may start using the system. This policy configuration should itself be protected and only allow privileged users access. diff --git a/astro/src/content/articles/authentication/types-of-kubernetes-auth.md b/astro/src/content/articles/authentication/types-of-kubernetes-auth.md index 1ed5060d33..3d21b8fe41 100644 --- a/astro/src/content/articles/authentication/types-of-kubernetes-auth.md +++ b/astro/src/content/articles/authentication/types-of-kubernetes-auth.md @@ -24,7 +24,7 @@ This is the authentication and authorization discussed in [the Kubernetes docume As outlined there: -> API requests are tied to either a normal user or a service account, or are treated as anonymous requests. This means every process inside or outside the cluster, from a human user typing kubectl on a workstation, to kubelets on nodes, to members of the control plane, must authenticate when making requests to the API server, or be treated as an anonymous user. +> API requests are tied to either a normal user or a service account, or are treated as anonymous requests. This means every process inside or outside the cluster, from a human user typing `kubectl` on a workstation, to kubelets on nodes, to members of the control plane, must authenticate when making requests to the API server, or be treated as an anonymous user. So any API request that needs to read from, add to, or modify Kubernetes configuration must be authenticated (unless the request is available to anonymous users). The Kubernetes documentation outlines all supported options for both service accounts and user accounts, so this article won't cover them in detail. @@ -51,7 +51,7 @@ Here's a [tutorial on setting up Kubernetes RBAC with FusionAuth](/blog/2022/02/ When you have containers running on Kubernetes, there are another two types of auth entirely different from the infrastructure auth outlined above. -![Diagram of todo application in kubernetes." class="img-fluid](/img/articles/types-kubernetes-auth/todo-application-diagram.png) +![Diagram of todo application in Kubernetes." class="img-fluid](/img/articles/types-kubernetes-auth/todo-application-diagram.png) For instance, if you are running a todo application like the one diagrammed above, you need to make sure a user Alice has access to Alice's todos and a user Bob has access to Bob's todos, but neither Alice nor Bob should have access to the other's data. @@ -68,7 +68,7 @@ You want to lock down communication between the constituent parts of your applic Suppose the reminder service from the application above needs information from the todo service. There's a new feature being built. The reminder service will send an email to every user who has a todo with a due date falling in the next 24 hours. Therefore the reminder service needs to query the todo service. -![Diagram of service to service communication application in kubernetes." class="img-fluid](/img/articles/types-kubernetes-auth/todo-application-service-to-service.png) +![Diagram of service to service communication application in Kubernetes." class="img-fluid](/img/articles/types-kubernetes-auth/todo-application-service-to-service.png) When building this feature, you'll want to ensure: diff --git a/astro/src/content/articles/authentication/webauthn-explained.md b/astro/src/content/articles/authentication/webauthn-explained.md index f04f5bf446..4c82d34679 100644 --- a/astro/src/content/articles/authentication/webauthn-explained.md +++ b/astro/src/content/articles/authentication/webauthn-explained.md @@ -40,12 +40,12 @@ What does an authentication ceremony look like? At a high level, the flow of int 5. The website verifies the authenticator response 6. The user is logged in -Whenever the user authenticates against the relevant authenticator, that is an "authorization gesture". It's a gesture because it requires physical interaction. This could be biometric like Touch ID, using a PIN, or any other method that an authenticator offers. An authenticator requires a user to be present with the device. +Whenever the user authenticates against the relevant authenticator, that is an "authorization gesture". It's a gesture because it requires physical interaction. This could be biometric like Touch Id, using a PIN, or any other method that an authenticator offers. An authenticator requires a user to be present with the device. There are two types of authenticators: 1. Cross-platform authenticators, such as YubiKeys, which can move between different devices -2. Platform authenticators, built into the operating system, such as Apple's Face ID or Touch ID, which are tied to a given device +2. Platform authenticators, built into the operating system, such as Apple's Face Id or Touch Id, which are tied to a given device Authenticators store public/private keypairs securely. The purpose of an authenticator is to create and hold such keypairs. It also needs to expose the public key. The entire credential, which includes the public key and associated metadata, is often called a "passkey". Further, the authenticator must be able to sign content with the private key. @@ -471,7 +471,7 @@ If you are using an authenticator in this way, you want to distinguish between u User presence is when someone is there behind the authenticator who gave permission, but you don't know who. All it proves is that you have access to the authenticator. An example of this is when you press a button on a YubiKey. Every authenticator must support checking user presence, as it is part of the specification. -User verification, on the other hand, is when the user provides proof that they are who they say they are. The authenticator could require a PIN, known only to the user. It could be a Face ID or Touch ID challenge. In any case, verification allows you to tie a specific user to the authentication ceremony. +User verification, on the other hand, is when the user provides proof that they are who they say they are. The authenticator could require a PIN, known only to the user. It could be a Face Id or Touch Id challenge. In any case, verification allows you to tie a specific user to the authentication ceremony. Of the two types, user verification is more common with platform authenticators than with cross platform authenticators. And user presence is more useful as a second factor. When not used for MFA, you will typically want user verification. @@ -507,7 +507,7 @@ To build a WebAuthn compatible server, you can use any server-side language you ## Summing Up -WebAuthn lets consumers have the security of biometric authentication methods, such as Touch ID and Face ID, without requiring additional expensive hardware. +WebAuthn lets consumers have the security of biometric authentication methods, such as Touch Id and Face Id, without requiring additional expensive hardware. WebAuthn is supported by every browser and can bring a safer, more secure, more easily usable means of authentication to all your users. diff --git a/astro/src/content/articles/ciam/auth-facade-pattern.md b/astro/src/content/articles/ciam/auth-facade-pattern.md index ae232344cd..76e80b89a0 100644 --- a/astro/src/content/articles/ciam/auth-facade-pattern.md +++ b/astro/src/content/articles/ciam/auth-facade-pattern.md @@ -104,7 +104,7 @@ When evaluating auth facade solutions, make sure you can deploy the system into Being able to support air gapped or isolated networks is a strong competitive differentiator for your application, especially if it accesses sensitive data. -Ensure your application and the auth facade system are deployable as a unit. Depending on customers' needs, you may want to deploy in a unix friendly package such as an RPM or DEB, a generic software package like a zip file, or, for the clients using Kubernetes, a containerized solution. +Ensure your application and the auth facade system are deployable as a unit. Depending on customers' needs, you may want to deploy in a Unix-friendly package such as an RPM or DEB, a generic software package like a zip file, or, for the clients using Kubernetes, a containerized solution. Since auth is a necessary part of your application, but not a differentiator, an auth system that fades into the background is best. This should happen both in the literal sense, with a user interface that matches your applications look and feel, and the figurative sense, so your engineers minimize time spent maintaining or troubleshooting it. diff --git a/astro/src/content/articles/ciam/unlocking-growth-low-friction-signup-process.md b/astro/src/content/articles/ciam/unlocking-growth-low-friction-signup-process.md index b3bf5c6f0c..6200e762db 100644 --- a/astro/src/content/articles/ciam/unlocking-growth-low-friction-signup-process.md +++ b/astro/src/content/articles/ciam/unlocking-growth-low-friction-signup-process.md @@ -51,7 +51,7 @@ Keep in mind your expected audience when considering what types of sign-ups to s Also important is building accessibility into your signup process. Differences in physical and cognitive abilities must be taken into consideration. For example, memory impairments might be a challenge. For this, you can provide password recovery options or simplified login workflows to ensure that users can successfully sign up and log in. Accounting for differences pays dividends in ensuring your product is inclusive and accessible by all. -Webauthn is an exciting development in the authentication world that adds yet another option for login flexibility. It is a standard that enables users to authenticate themselves using biometrics, such as facial recognition or fingerprint scanning, or a physical security key. The best part about it? It can be used to completely replace a password. Now that Apple, Google, and Microsoft have all added WebAuthn support into their products, passwordless authentication, which once seemed futuristic, is becoming a reality. +WebAuthn is an exciting development in the authentication world that adds yet another option for login flexibility. It is a standard that enables users to authenticate themselves using biometrics, such as facial recognition or fingerprint scanning, or a physical security key. The best part about it? It can be used to completely replace a password. Now that Apple, Google, and Microsoft have all added WebAuthn support into their products, passwordless authentication, which once seemed futuristic, is becoming a reality. ### Lack of transparency @@ -69,7 +69,7 @@ It can’t be overstated how important security is as a part of your sign up flo Some examples of good security practices: - - Use MFA. Webauthn and TOTP are more secure than SMS or magic links. + - Use MFA. WebAuthn and TOTP are more secure than SMS or magic links. - Serve pages over SSL - Allow a user to choose single a login mechanism that aligns best with their security posture - If the user has their account managed centrally, they should use single sign-on diff --git a/astro/src/content/articles/gaming-entertainment/best-practices-spiky-registration.md b/astro/src/content/articles/gaming-entertainment/best-practices-spiky-registration.md index f38bcf1ad2..ccde422ad0 100644 --- a/astro/src/content/articles/gaming-entertainment/best-practices-spiky-registration.md +++ b/astro/src/content/articles/gaming-entertainment/best-practices-spiky-registration.md @@ -89,7 +89,7 @@ This tip is just as important for better user experience as it is for preserving Implementing authentication and authorization can be tricky, and if it’s not handled properly, you could face an information leak or full-blown database hack. If you decide to implement your own authentication and authorization service, think carefully about how you store user details. You should also make sure you use appropriate hashing algorithms and that the passwords are effectively salted before being stored in the database. You can read a bit about the underlying math [in this article](/articles/security/math-of-password-hashing-algorithms-entropy). -Explore using a third-party user authentication and authorization service. It helps you focus on what makes your game unique, and it’s especially useful when you want to implement SSO, and social auth. Depending on your platform, you may want to allow a user to log in with a gaming network login, such as the XBox or PlayStation Network. An auth server can help with this integration. +Explore using a third-party user authentication and authorization service. It helps you focus on what makes your game unique, and it’s especially useful when you want to implement SSO, and social auth. Depending on your platform, you may want to allow a user to log in with a gaming network login, such as the Xbox or PlayStation Network. An auth server can help with this integration. Using an external auth server ensures that if the gameplay code breaks, the registration continues working, so you can reach out to registered users once the game comes back online. One option for third-party auth is [FusionAuth](/). It keeps your user data secure and provides all the social login integrations your game might need. diff --git a/astro/src/content/articles/gaming-entertainment/cross-platform-game-accounts.md b/astro/src/content/articles/gaming-entertainment/cross-platform-game-accounts.md index 3a12dc6718..4845ca767e 100644 --- a/astro/src/content/articles/gaming-entertainment/cross-platform-game-accounts.md +++ b/astro/src/content/articles/gaming-entertainment/cross-platform-game-accounts.md @@ -349,7 +349,7 @@ Here is an explanation of some of the variables in the above code. - `apiKey` is the credential key required to authorize API requests from your app to FusionAuth. - `applicationId` is your Application Id, which is used to associate your API request to a specific FusionAuth application. > **Tips for Securing the API Key for Production** -> - Use [flutter_dotenv](https://pub.dev/packages/flutter_dotenv) to secure and read the API keys from a .env file. +> - Use [`flutter_dotenv`](https://pub.dev/packages/flutter_dotenv) to secure and read the API keys from a .env file. > - Store the keys in the backend and retrieve them when the app launches. diff --git a/astro/src/content/articles/gaming-entertainment/oauth-device-grant-gaming.md b/astro/src/content/articles/gaming-entertainment/oauth-device-grant-gaming.md index f3e4eec05d..43021ec3ba 100644 --- a/astro/src/content/articles/gaming-entertainment/oauth-device-grant-gaming.md +++ b/astro/src/content/articles/gaming-entertainment/oauth-device-grant-gaming.md @@ -99,7 +99,7 @@ This CORS configuration is only necessary because the game is running in the bro Next, configure and run the demo app project downloaded from the GitHub repository. -Open the project with an editor of your choosing (for example, Visual Studio Code or Sublime), then go to the `main.js` file and modify the `clientId` to match the clientId of your `test Grant` application on FusionAuth. +Open the project with an editor of your choosing (for example, Visual Studio Code or Sublime), then go to the `main.js` file and modify the `clientId` to match the Client Id of your `test Grant` application on FusionAuth. ```javascript var baseFusionAuthURL = 'http://localhost:9011/oauth2/device_authorize'; diff --git a/astro/src/content/articles/gaming-entertainment/securing-game-account.md b/astro/src/content/articles/gaming-entertainment/securing-game-account.md index c074d5cc80..1419d18218 100644 --- a/astro/src/content/articles/gaming-entertainment/securing-game-account.md +++ b/astro/src/content/articles/gaming-entertainment/securing-game-account.md @@ -51,9 +51,9 @@ Using MFA, you can request one of three types of additional information from use * Something the user knows, such as the account password or PIN * Something the user has, such as a verified digital badge, PC, smartphone, or digital game console -* Something the user is, such as a biometric ID +* Something the user is, such as a biometric Id -What kind of additional factor makes sense for your users depends on their demographic and device. You should also make varying kinds of factors available, as the casual game player might want something easy to use like SMS whereas the professional esport player, with a more valuable account, will want a more secure factor such as a biometric ID tied to their phone. +What kind of additional factor makes sense for your users depends on their demographic and device. You should also make varying kinds of factors available, as the casual game player might want something easy to use like SMS whereas the professional esport player, with a more valuable account, will want a more secure factor such as a biometric Id tied to their phone. Learn more about [Multi-Factor Authentication](/articles/authentication/multi-factor-authentication). diff --git a/astro/src/content/articles/identity-basics/complete-authentication-system.md b/astro/src/content/articles/identity-basics/complete-authentication-system.md index 7401b532cd..4a7e7eceb3 100644 --- a/astro/src/content/articles/identity-basics/complete-authentication-system.md +++ b/astro/src/content/articles/identity-basics/complete-authentication-system.md @@ -23,7 +23,7 @@ The first and probably most common type of authentication system is the DIY appr When taking the DIY approach, it is important to note that your team will be responsible for managing the security of the solution and mitigating vulnerabilities, which third-party vendors would otherwise handle when using a more managed provider. There are some rather attractive benefits to rolling your own solution, which is why so many teams do it. First of all, you have the freedom to build whatever you need, how you need it. You also get the benefit of not having any additional ongoing fees as you would with third-party providers. -These benefits can be a huge plus for small teams, startups, and hobbyists but as mentioned above, tend not to scale so well as teams, products, and problems grow in size and scope. On the other hand, any additional functionality that you want will need to be manually implemented. For example, if you want to support Single-Sign-On (SSO) with your DIY solution, you would have to manually implement your preferred SSO standard. Although this is a well-known process, it still takes time, money, and effort to do it right, and the same is true for any other authentication-related features you want to bring to your application, such as Multi-factor Authentication or WebAuthN. +These benefits can be a huge plus for small teams, startups, and hobbyists but as mentioned above, tend not to scale so well as teams, products, and problems grow in size and scope. On the other hand, any additional functionality that you want will need to be manually implemented. For example, if you want to support Single-Sign-On (SSO) with your DIY solution, you would have to manually implement your preferred SSO standard. Although this is a well-known process, it still takes time, money, and effort to do it right, and the same is true for any other authentication-related features you want to bring to your application, such as Multi-factor Authentication or WebAuthn. ### Drop-In Script diff --git a/astro/src/content/articles/identity-basics/due-diligence-authentication-vendors.md b/astro/src/content/articles/identity-basics/due-diligence-authentication-vendors.md index ba6efaa369..b5239111e0 100644 --- a/astro/src/content/articles/identity-basics/due-diligence-authentication-vendors.md +++ b/astro/src/content/articles/identity-basics/due-diligence-authentication-vendors.md @@ -35,7 +35,7 @@ Authentication providers should have strong guardrails to protect your users' co 1. Ask your vendor to fill out a questionnaire. This is a standard practice to understand security policies established by authentication providers. These questions should cover all security details, for example, how often are passwords reset? How are credentials stored? Where are they stored? 1. Ask for an encryption policy. It should have guidance on hashing, digital signature policy, and cryptography topics, and these policies should align with your internal security standards. For TLS, the standard is to use [128-bit, 192-bit, or 256-bit encryption](https://www.clickssl.net/blog/128-bit-ssl-encryption-vs-256-bit-ssl-encryption) to prevent unauthorized access to data in transit. Does your authentication provider offer encryption of data at rest? 1. CVEs happen. How does your vendor respond when a CVE occurs. How quickly is a fix released and how do they communicate the security issues to you? -1. Understand who will own responsibility in case of a cyber attack. Lawsuits arise when responsibilities are not well understood, so take particular care here. You should have a workflow diagram labeling each section with _vendor's name_ or _your company's name_ to indicate each party's areas of responsibility. +1. Understand who will own responsibility in case of a cyberattack. Lawsuits arise when responsibilities are not well understood, so take particular care here. You should have a workflow diagram labeling each section with _vendor's name_ or _your company's name_ to indicate each party's areas of responsibility. 1. During the procurement process, obtain all required security policy documents applicable to your industry or business. Ensure security policies cover [PII](https://www.dol.gov/general/ppii#:~:text=Personal%20Identifiable%20Information%20(PII)%20is%20defined%20as%3A&text=DOL%20internal%20policy%20specifies%20the,to%20which%20they%20have%20access), [HIPAA](https://www.hhs.gov/hipaa/index.html), and [GDPR, Article 33](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation) standards if your business falls under specific industry criteria. You should also obtain [SOC2](https://www.aicpa.org/interestareas/frc/assuranceadvisoryservices/aicpasoc2report.html) reports from any potential AaaS. This auditing procedure ensures that data and privacy are securely managed to protect the interests of your organization and the privacy of your clients. Of course, we could dive deeper into security due diligence, but the items above should be a minimum place to start. diff --git a/astro/src/content/articles/identity-basics/open-source-vs-commercial.md b/astro/src/content/articles/identity-basics/open-source-vs-commercial.md index 69c58eae46..ba0da607d0 100644 --- a/astro/src/content/articles/identity-basics/open-source-vs-commercial.md +++ b/astro/src/content/articles/identity-basics/open-source-vs-commercial.md @@ -49,7 +49,7 @@ Always review the license for any solution. In a true open-source solution, the "community" is responsible for submitting fixes they want to see included in the project. Feature requests from the community tend to need to be contributed to by the community itself, meaning you as the customer bear more of the maintenance burden. The amount of testing done for a new release varies based on the effort the community puts forth. -On the flip side, it could mean you have more say in the product roadmap if you're able to contribute fixes in a way that is acceptable to the community. Heck, you could even pay a developer to spend most of their day writing code for this system, which would buy you a lot of influence. Consider how much bandwidth your team has to contribute to this process; it might be a dealbreaker. +On the flip side, it could mean you have more say in the product roadmap if you're able to contribute fixes in a way that is acceptable to the community. Heck, you could even pay a developer to spend most of their day writing code for this system, which would buy you a lot of influence. Consider how much bandwidth your team has to contribute to this process; it might be a deal-breaker. You can also, if you need to, make a change in your own version of the project. You can then submit it to the maintainers. If it meets their quality standards and goal for the project, it can be integrated; this is also known as upstreaming. However, if it doesn't get incorporated, you are stuck supporting a critical feature and making sure that future releases don't break it. @@ -119,7 +119,7 @@ However, some commercial software offers free tiers with limited support. For ex Another item to consider is the pricing structure of the commercial solution. Some commercial products may prove cost-effective to large corporations, with high usage, but terribly improbable for a startup wanting a lowering buy-in point. Or more commonly, commercial providers provide different tiers depending on usage. This may make some use cases untenable as your product scales. -Depending on what stage your company is in, this monetary expense can either be something you can absorb or a dealbreaker. You should weigh this cost against the time and effort needed to maintain an open source solution. +Depending on what stage your company is in, this monetary expense can either be something you can absorb or a deal-breaker. You should weigh this cost against the time and effort needed to maintain an open source solution. ## The Final Showdown diff --git a/astro/src/content/articles/identity-basics/registration-best-practices.md b/astro/src/content/articles/identity-basics/registration-best-practices.md index 3115527d44..ebfec29e1c 100644 --- a/astro/src/content/articles/identity-basics/registration-best-practices.md +++ b/astro/src/content/articles/identity-basics/registration-best-practices.md @@ -92,7 +92,7 @@ Avoid complicated password validation rules. Allow users to use a password manag Obtain proper user consent. What this is depends on your plans for the requested information and what regulatory regime applies. Different levels of informed consent may be required. For example, if you are in the USA and are dealing with a child's personal information, you'll want to make sure you get parental consent because of COPPA. -Ensure new users enter sensitive data correctly. If there are any critical fields, such as a government ID, provide a confirmation field asking for the data to be re-entered to ensure the data is typed correctly. This is an exception to the rule of asking for less data. If the stakes of incorrect data entry are high, the additional work is worth the inconvenience. +Ensure new users enter sensitive data correctly. If there are any critical fields, such as a government Id, provide a confirmation field asking for the data to be re-entered to ensure the data is typed correctly. This is an exception to the rule of asking for less data. If the stakes of incorrect data entry are high, the additional work is worth the inconvenience. If you need more than a few pieces of information on registration, consider splitting the sign up form into steps and using a registration stepper, also known as a multi-step form or a wizard. A stepper is a user interface element which shows how many steps are required to complete an action: @@ -126,13 +126,13 @@ When collecting sensitive data, keep it secure throughout the multi-page process * Don't ask for this information until the last step. Since the registration form will be sent over TLS, the sensitive data is then secure. * Once submitted on any step, keep it in the server side session until the form is complete. -* Encrypt and store the form data in localstorage. +* Encrypt and store the form data in `localStorage`. * After sensitive data submission, store it in a hidden form field, but encrypt it first. Each of these options has tradeoffs. If you wait to ask for any sensitive information until the last step, you are limiting the flexibility of your form design. If more than one piece of sensitive data is needed, you're forced to put all of them on the last page. Keeping the value in the session means increasing the size of your user sessions. You will also be forced to use sticky sessions, hindering the scalability of your application. -Storing the data in localstorage is risky, due to malicious code running in the browser. If you encrypt it, make sure the encryption happens on the server, otherwise the same code may be able to decrypt the data. +Storing the data in `localStorage` is risky, due to malicious code running in the browser. If you encrypt it, make sure the encryption happens on the server, otherwise the same code may be able to decrypt the data. Encrypting the data and storing it in a hidden form field means additional processing. If you choose this, use a symmetric key stored only on the server side. Since you'll be decrypting the form field in the security of your server environment, the browser shouldn't need to read the data after the step on which it is submitted. diff --git a/astro/src/content/articles/identity-basics/what-is-identity-proofing.md b/astro/src/content/articles/identity-basics/what-is-identity-proofing.md index 87f9c0ca1c..db3877219d 100644 --- a/astro/src/content/articles/identity-basics/what-is-identity-proofing.md +++ b/astro/src/content/articles/identity-basics/what-is-identity-proofing.md @@ -57,9 +57,9 @@ Identity proofing provides several ways to verify a user’s identity, such as p ### Identity Document Verification -Identity document verification can be a physical process or done digitally. Physical identity proofing occurs when a customer performs a face-to-face transaction at a company location and presents identity documents such as an ID card, passport, or driver’s license. A company employee compares the photograph on the documents with the person standing in front of them and validates the information supplied against an authoritative source, such as government or credit records. Once identity is established, documents are copied and physically stored. +Identity document verification can be a physical process or done digitally. Physical identity proofing occurs when a customer performs a face-to-face transaction at a company location and presents identity documents such as an Id card, passport, or driver’s license. A company employee compares the photograph on the documents with the person standing in front of them and validates the information supplied against an authoritative source, such as government or credit records. Once identity is established, documents are copied and physically stored. -Businesses needing to establish real-world identity with online users can verify documentation using a scan of a valid passport or ID along with other verifiable personal information, like an address or phone number. To ensure that scanned documents aren’t stolen, businesses sometimes ask users to submit a selfie of themselves holding the documents. +Businesses needing to establish real-world identity with online users can verify documentation using a scan of a valid passport or Id along with other verifiable personal information, like an address or phone number. To ensure that scanned documents aren’t stolen, businesses sometimes ask users to submit a selfie of themselves holding the documents. ### Knowledge-Based Authentication diff --git a/astro/src/content/articles/oauth/differences-between-oauth-2-oauth-2-1.md b/astro/src/content/articles/oauth/differences-between-oauth-2-oauth-2-1.md index 4e6cf2c700..9b1b0d778d 100644 --- a/astro/src/content/articles/oauth/differences-between-oauth-2-oauth-2-1.md +++ b/astro/src/content/articles/oauth/differences-between-oauth-2-oauth-2-1.md @@ -10,9 +10,9 @@ icon: /img/icons/difference-oauth2-2.1.svg darkIcon: /img/icons/difference-oauth2-2.1-dark.svg --- -OAuth 2.1 is consolidating best practices learned over the eight years since Oauth 2 was published. The original OAuth 2.0 specification was released in October 2012 as [RFC 6749](https://tools.ietf.org/html/rfc6749) and [RFC 6750](https://tools.ietf.org/html/rfc6750). It replaced OAuth 1.0, released in April 2010. There have been a number of extensions and modifications to OAuth 2 over the subsequent years. +OAuth 2.1 is consolidating best practices learned over the eight years since OAuth 2 was published. The original OAuth 2.0 specification was released in October 2012 as [RFC 6749](https://tools.ietf.org/html/rfc6749) and [RFC 6750](https://tools.ietf.org/html/rfc6750). It replaced OAuth 1.0, released in April 2010. There have been a number of extensions and modifications to OAuth 2 over the subsequent years. -A new OAuth specification has been proposed and is currently under discussion. At this time, the specification was most recently updated on July 30, 2020. If approved, [OAuth 2.1](https://tools.ietf.org/html/draft-ietf-oauth-v2-1-00) will obsolete certain parts of Oauth 2.0 and mandate security best practices. The rest of the OAuth 2.0 specification will be retained. +A new OAuth specification has been proposed and is currently under discussion. At this time, the specification was most recently updated on July 30, 2020. If approved, [OAuth 2.1](https://tools.ietf.org/html/draft-ietf-oauth-v2-1-00) will obsolete certain parts of OAuth 2.0 and mandate security best practices. The rest of the OAuth 2.0 specification will be retained. That bears repeating. Nothing new will be added. This is an explicit design goal of OAuth 2.1. @@ -68,7 +68,7 @@ Whew, that's a lot. Let's examine each of these in turn. But before we do, let's * A `client` is a piece of code that the user is interacting with; browsers, native apps or single-page applications are all clients. * An `OAuth server` implements OAuth specifications. It has or can obtain information about which resources are available to clients. In the RFCs this application is called an Authorization Server. This is also known as an Identity Provider. Most users call it "the place I sign in". -* An `application server` doesn’t have any authentication functionality but instead delegates login requests to an OAuth server. It has an id which allows the OAuth server to identify it. +* An `application server` doesn’t have any authentication functionality but instead delegates login requests to an OAuth server. It has an Id which allows the OAuth server to identify it. ### OAuth 2.1 change: The Authorization Code grant requires PKCE @@ -102,7 +102,7 @@ However, allowing wildcard matching for the redirect URI is a security risk. If > The Implicit grant ("response_type=token") is omitted from this specification as per Section 2.1.2 of [OAuth 2.0 Security Best Current Practices](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-14) -The Implicit grant is inherently insecure when used in a single-page application (SPA). If you use this grant, your access token is exposed to any JavaScript running in the browser alongside your SPA. If you aren't careful, you'll get an access token that is in the URL fragment, stored in localstorage, or put in a non HttpOnly cookie. In all cases, an attacker gaining an access token is allowed to access resources as if they were the original user. This is not a good situation. +The Implicit grant is inherently insecure when used in a single-page application (SPA). If you use this grant, your access token is exposed to any JavaScript running in the browser alongside your SPA. If you aren't careful, you'll get an access token that is in the URL fragment, stored in `localStorage`, or put in a non `HttpOnly` cookie. In all cases, an attacker gaining an access token is allowed to access resources as if they were the original user. This is not a good situation. Access tokens are not necessarily one-time use, and can live from minutes to days depending on how the OAuth server is configured. If they are stolen, the resources they protect are no longer secure. You may think "well, I don’t have any malicious JavaScript on my site." Are you sure? Have you audited all your code, and its dependencies, and their dependencies, and their dependencies? Do you audit your code automatically? Extensive dependency trees can lead to unforeseen security issues: someone took over an [open source node library](https://snyk.io/blog/malicious-code-found-in-npm-package-event-stream/) and added malicious code that was downloaded millions of times. diff --git a/astro/src/content/articles/oauth/modern-guide-to-oauth.mdx b/astro/src/content/articles/oauth/modern-guide-to-oauth.mdx index 636d89b637..8bbd95adef 100644 --- a/astro/src/content/articles/oauth/modern-guide-to-oauth.mdx +++ b/astro/src/content/articles/oauth/modern-guide-to-oauth.mdx @@ -374,10 +374,10 @@ Here are definitions of the standard scopes in the OpenID Connect specification: * `openid` - tells the OAuth server to use OpenID Connect for the handling of the OAuth workflow. This additionally will tell the OAuth server to return an Id token from the Token endpoint (covered below). * `offline_access` - tells the OAuth server to generate and return a refresh token from the Token endpoint (covered below). -* `profile` - tells the OAuth server to include all of the standard OpenID Connect claims in the returned tokens (access and/or id tokens). -* `email` - tells the OAuth server to include the user's email in the returned tokens (access and/or id tokens). -* `address` - tells the OAuth server to include the user's address in the returned tokens (access and/or id tokens). -* `phone` - tells the OAuth server to include the user's phone number in the returned tokens (access and/or id tokens). +* `profile` - tells the OAuth server to include all of the standard OpenID Connect claims in the returned tokens (access and/or Id tokens). +* `email` - tells the OAuth server to include the user's email in the returned tokens (access and/or Id tokens). +* `address` - tells the OAuth server to include the user's address in the returned tokens (access and/or Id tokens). +* `phone` - tells the OAuth server to include the user's phone number in the returned tokens (access and/or Id tokens). In order to properly implement the handling for the `state`, PKCE, and `nonce` parameters, we need to save these values off somewhere. They must be persisted across browser requests and redirects. There are two options for this: @@ -1083,9 +1083,9 @@ function buildClickHandler() { } ``` -Since the `refresh_token` is an HTTPOnly cookie, JavaScript can't call a refresh endpoint to get a new access token. Our client side JavaScript would have to have access to the refresh token value to do so, but we don't allow that because of cross site scripting concerns. Instead, the client calls a server-side route, which will then try to refresh the tokens using the cookie value; it has access to that value. After that, the server will send down the new values as cookies, and the browser code can retry the API calls. +Since the `refresh_token` is an `HTTPOnly` cookie, JavaScript can't call a refresh endpoint to get a new access token. Our client side JavaScript would have to have access to the refresh token value to do so, but we don't allow that because of cross site scripting concerns. Instead, the client calls a server-side route, which will then try to refresh the tokens using the cookie value; it has access to that value. After that, the server will send down the new values as cookies, and the browser code can retry the API calls. -Here's the `refresh` server side route, which accesses the refresh token and tries to, well, refresh the access and id tokens. +Here's the `refresh` server side route, which accesses the refresh token and tries to, well, refresh the access and Id tokens. ```javascript @@ -1572,7 +1572,7 @@ Let’s take a look at these concepts. ### Scopes -A scope is a method of restricting access. A user may want to allow an application to access Wuphf to read posts, but not to post. Scopes can help with this. +A scope is a method of restricting access. A user may want to allow an application to access WUPHF to read posts, but not to post. Scopes can help with this. Instead of giving applications full access to a user's account, it enables apps to request a limited, well, scope of what they can do on the user's behalf. For example, some apps use OAuth2 to identify users and therefore only require a user Id and basic profile information. Other applications may require access to more sensitive data, like the user's birthdate or the ability to post data on the user's behalf. Scopes can represent these different levels of access. They are presented at the initial request of the Client, and then parsed and displayed to the user at the Authorization Server. @@ -1590,7 +1590,7 @@ Access tokens must be kept private, both in transit and at rest. Passing the tok ### Client Ids -OAuth 2.0 typically requires static, out of band initial configuration. For example, before an application can call the Wuphf API to retrieve information on behalf of a user, it must first receive approval from Wuphf. This process is called "Client Registration" and can be done manually or, in certain circumstances, programmatically. +OAuth 2.0 typically requires static, out of band initial configuration. For example, before an application can call the WUPHF API to retrieve information on behalf of a user, it must first receive approval from Wuphf. This process is called "Client Registration" and can be done manually or, in certain circumstances, programmatically. During Client registration, the third party application provides information like the client type, a redirect URL where the authorization code can be sent, and other related information including a website and description. The Authorization Server then generates a client Id and a client secret. @@ -1611,7 +1611,7 @@ Compare that to a homegrown authorization protocol, which has none of these adva We hope this guide has been a useful overview of the real-world uses of OAuth 2.0 and provided insights into implementation and the future of the OAuth protocol. Again, you can view working [code in this guide in the accompanying GitHub repository](https://github.com/FusionAuth/fusionauth-example-modern-guide-to-oauth). -If you notice any issues, bugs, or typos in the Modern Guide to OAuth, please submit a Github issue or pull request on [this repository](https://github.com/FusionAuth/fusionauth-site). +If you notice any issues, bugs, or typos in the Modern Guide to OAuth, please submit a GitHub issue or pull request on [this repository](https://github.com/FusionAuth/fusionauth-site). Thanks for reading and happy coding! diff --git a/astro/src/content/articles/oauth/oauth-device-authorization.mdx b/astro/src/content/articles/oauth/oauth-device-authorization.mdx index c46076f034..1ee168e31b 100644 --- a/astro/src/content/articles/oauth/oauth-device-authorization.mdx +++ b/astro/src/content/articles/oauth/oauth-device-authorization.mdx @@ -49,7 +49,7 @@ Let's go over the steps in quickly as well. 1. The App backend redirects the browser over to FusionAuth's OAuth v2 Device Authorization page 1. The browser requests FusionAuth's OAuth v2 Device Authorization page 1. FusionAuth responds with the HTML & CSS for the page -1. The user enters the the code they were provided on the TV and hist submit +1. The user enters the code they were provided on the TV and hits "Submit" 1. At this point, FusionAuth redirects the user to the standard OAuth v2 login workflow where the user can log into their Nerd Stuff on Demand account as normal 1. After the user has successfully logged in, FusionAuth redirects them to a success page 1. As mentioned above, the Nerd Stuff on Demand app on the Roku has been polling this entire time. Now that the user has completed the workflow, the next time the app polls FusionAuth's token endpoint, it will succeed diff --git a/astro/src/content/articles/oauth/value-standards-compliant-authentication.md b/astro/src/content/articles/oauth/value-standards-compliant-authentication.md index e071b6573c..417ccbd332 100644 --- a/astro/src/content/articles/oauth/value-standards-compliant-authentication.md +++ b/astro/src/content/articles/oauth/value-standards-compliant-authentication.md @@ -36,7 +36,7 @@ When you use a standardized protocol, you have the peace of mind that comes with What would happen if every time you built a new system's authentication system, you had to create it from scratch? You would have to learn the nitty-gritty details of authentication over and over again. -This would lead to a scenario where you couldn't leverage your hardwon knowledge between projects and employers. If you instead use a ubiquitous protocol like OAuth, there may be subtle differences, but you'll understand the general authentication architecture. If you know how standardized protocols work and what use cases they solve, you can bring that knowledge to other projects and companies. +This would lead to a scenario where you couldn't leverage your hard-won knowledge between projects and employers. If you instead use a ubiquitous protocol like OAuth, there may be subtle differences, but you'll understand the general authentication architecture. If you know how standardized protocols work and what use cases they solve, you can bring that knowledge to other projects and companies. The same applies when teaching and onboarding new engineers to your team. If you are using a standardized auth protocol, then your new team members are likely to already know about OAuth, SAML, or other standardized protocols. It will be much easier to get these new team members up and running and contributing to these relevant areas of your system. @@ -100,7 +100,7 @@ You've seen that OAuth is a great way to gain access to resources. But it doesn' ![OIDC tokens build on OAuth tokens.](/img/articles/value-standards/oidc-extends-oauth.png) -OIDC adds an "ID token" to be returned from the final OAuth request in the flow. This confirms the user was in fact authenticated (unlike the access token, as discussed previously) and also gives you a way to access identity-specific information about the current user. +OIDC adds an "Id token" to be returned from the final OAuth request in the flow. This confirms the user was in fact authenticated (unlike the access token, as discussed previously) and also gives you a way to access identity-specific information about the current user. Beyond these basic features, OIDC can also enable more advanced features such as [session management](https://openid.net/specs/openid-connect-session-1_0.html), [log-out ability](https://openid.net/specs/openid-connect-rpinitiated-1_0.html), [user registration standard](https://openid.net/specs/openid-connect-prompt-create-1_0.html), and more. @@ -126,7 +126,7 @@ SAML is a great tool for larger organizations to further enhance their users' se ### FIDO -FIDO stands for "Fast Identity Online." It's a set of protocols created by the [FIDO Alliance](https://fidoalliance.org/), a nonprofit group seeking to expunge the use of passwords. In general, the FIDO protocols allow users to authenticate themselves via special devices or applications that use fingerprint readers, facial recognition, or external devices such as special USB dongles. Many websites are also now supporting [webauthn](https://fidoalliance.org/fido2/fido2-web-authentication-webauthn/), which is a protocol that enables website logins with FIDO. +FIDO stands for "Fast Identity Online." It's a set of protocols created by the [FIDO Alliance](https://fidoalliance.org/), a nonprofit group seeking to expunge the use of passwords. In general, the FIDO protocols allow users to authenticate themselves via special devices or applications that use fingerprint readers, facial recognition, or external devices such as special USB dongles. Many websites are also now supporting [WebAuthn](https://fidoalliance.org/fido2/fido2-web-authentication-webauthn/), which is a protocol that enables website logins with FIDO. FIDO works much like SSH keys. Your device will have a FIDO-enabled "authenticator" application that can generate private and public keys between your device and other services. Your device keeps a private key for that service and sends it a public key. Whenever the device reads your fingerprint, for example, the device's authenticator application will verify you are _you_ and then use public key cryptography to authenticate you to that other service. @@ -136,7 +136,7 @@ This means that attackers can't steal your password. It's also much more conveni FIDO is a great choice for larger organizations that want to keep their users and devices very secure. If an organization chooses to use some type of specialized hardware, such as a [Yubico device](https://www.yubico.com/solutions/passwordless/), that can be a substantial cost. Not only must the devices be purchased, but they must be delivered when employees are onboarded and retrieved when they leave, incurring additional logistical complexity. -However, with growing support for webauthn and built-in facial recognition and fingerprint readers on modern PCs, many cloud-based tools are allowing FIDO-based authentication for their websites, lowering the overall cost of using FIDO. Thanks to FIDO's strong security, you'll often see FIDO used in government, insurance, and healthcare. +However, with growing support for WebAuthn and built-in facial recognition and fingerprint readers on modern PCs, many cloud-based tools are allowing FIDO-based authentication for their websites, lowering the overall cost of using FIDO. Thanks to FIDO's strong security, you'll often see FIDO used in government, insurance, and healthcare. ## Conclusion diff --git a/astro/src/content/articles/security/breached-password-detection.md b/astro/src/content/articles/security/breached-password-detection.md index 65a8fa733b..c4c4844473 100644 --- a/astro/src/content/articles/security/breached-password-detection.md +++ b/astro/src/content/articles/security/breached-password-detection.md @@ -50,7 +50,7 @@ In the same vein, [NIST, an American government agency](https://pages.nist.gov/8 > > * Passwords obtained from previous breach corpuses. > * Dictionary words. -> * Repetitive or sequential characters (e.g. ‘aaaaaa’, ‘1234abcd’). +> * Repetitive or sequential characters (e.g. `aaaaaa`, `1234abcd`). > * Context-specific words, such as the name of the service, the username, and derivatives thereof. > > If the chosen secret is found in the list, the CSP or verifier SHALL advise the subscriber that they need to select a different secret, SHALL provide the reason for rejection, and SHALL require the subscriber to choose a different value. @@ -73,7 +73,7 @@ You can also include lists of common words and character sequences in your datas ![Password strength](/img/articles/breached-password-detection/password-strength.png) -Whatever you do, please ensure you include 'correcthorsebatterystaple' ([image courtesy of xkcd](https://xkcd.com/license.html)). +Whatever you do, please ensure you include `correcthorsebatterystaple` ([image courtesy of xkcd](https://xkcd.com/license.html)). Make sure you are researching these providers and datasets on a regular schedule, since new breaches happen and new providers may appear. You'll also want to comply with any licensing or other requirements the data providers have. Some providers offer these datasets for free, while others may charge or ask for a donation. Make sure you set aside budget for this. @@ -116,7 +116,7 @@ You should enable checks on the first three events to prevent known compromised The last one deserves a bit of explanation. Suppose a user signs up on Example.com with a great password. Then they come to your site and sign up with the same great password. They continue to use your site for months, but forget about Example.com. -Then, Example.com is breached. They may send out a notice, but your user may not receive it or may not change their password. This [study from 2020 (PDF)](https://www.ieee-security.org/TC/SPW2020/ConPro/papers/bhagavatula-conpro20.pdf) covers a small dataset, approximately 250 users over two years. It found that of the approximatly 60 users who had accounts on breached domains, only 13% changed their password within three months of the breach announcement. +Then, Example.com is breached. They may send out a notice, but your user may not receive it or may not change their password. This [study from 2020 (PDF)](https://www.ieee-security.org/TC/SPW2020/ConPro/papers/bhagavatula-conpro20.pdf) covers a small dataset, approximately 250 users over two years. It found that of the approximately 60 users who had accounts on breached domains, only 13% changed their password within three months of the breach announcement. If you only check for compromise when the password is created at registration or modified by the end user, you'll end up with users who have credentials that have been leaked by breaches external to your system after account creation. The Example.com breach affected your system through the vector of the reused password. Detect breached passwords whenever a user logs in. diff --git a/astro/src/content/articles/security/guide-to-user-data-security.mdx b/astro/src/content/articles/security/guide-to-user-data-security.mdx index e6cccb9dd6..dda10ee260 100644 --- a/astro/src/content/articles/security/guide-to-user-data-security.mdx +++ b/astro/src/content/articles/security/guide-to-user-data-security.mdx @@ -39,11 +39,11 @@ There are two parts to the guide: Server Security and Application Security. We d ## TLDR -If you would rather not read our entire security guide (though we suggest you do), check out the Github project created around this guide. This project contains a set of scripts you can execute from your local computer to secure a remote server. The scripts perform most of the steps listed in this guide. The Github project also contains full configuration files based on the configuration detailed below that are deployed to the server by the scripts. +If you would rather not read our entire security guide (though we suggest you do), check out the GitHub project created around this guide. This project contains a set of scripts you can execute from your local computer to secure a remote server. The scripts perform most of the steps listed in this guide. The GitHub project also contains full configuration files based on the configuration detailed below that are deployed to the server by the scripts. -In addition to setup scripts and configuration, we also added a Chef cookbook to the Github repository. Chef is a great way to provision new servers and ensure they are setup exactly how you want them. There are a number of other systems similar to Chef, but we use Chef for all of our servers and thought we would share our Chef recipe with everyone. +In addition to setup scripts and configuration, we also added a Chef cookbook to the GitHub repository. Chef is a great way to provision new servers and ensure they are setup exactly how you want them. There are a number of other systems similar to Chef, but we use Chef for all of our servers and thought we would share our Chef recipe with everyone. -Find our Github project here: https://github.com/FusionAuth/security-scripts +Find our GitHub project here: https://github.com/FusionAuth/security-scripts **NOTE:** That is only half of the equation, so you will still want to read the Application Security section of the guide. @@ -378,7 +378,7 @@ Identify users that can access to the server Since we are going for über security, let's get crazy and add one more layer of authentication to your remote access. We will add two-factor authentication to the server. This will require users to type in a 6-digit code from their mobile phone in order to log in. Even if a user's private key is compromised, two-factor authentication ensures a hacker would still need the user's mobile phone to log into the server. -First, you will need to install a two-factor app on your mobile phone. There are many two-factor applications available for iOS and Android. I personally like the Authy app because it has slick icons for different services like AWS and Github. Next, install the Google Authenticator two-factor PAM module on the server by executing this command in the root user terminal: +First, you will need to install a two-factor app on your mobile phone. There are many two-factor applications available for iOS and Android. I personally like the Authy app because it has slick icons for different services like AWS and GitHub. Next, install the Google Authenticator two-factor PAM module on the server by executing this command in the root user terminal: ```bash $ apt-get install libpam-google-authenticator @@ -418,7 +418,7 @@ To install this package, type this command: ```bash $ apt-get install ntp ``` -Now restart the SSH service to pick up all of our changes changes like this: +Now restart the SSH service to pick up all of our changes like this: ```bash $ service ssh restart @@ -1479,7 +1479,7 @@ This creates our user and then allows the user to perform the standard SQL data Most modern applications use a combination of server-side code and client-side code. These two layers of code communicate with each other via APIs. Often, JSON data is sent between the client and server using AJAX requests. This new model of application development adds a lot of flexibility, but also opens up a lot of security risks. -After a user logs in, the application will need the user id in order to look up additional data for the user as well as ensure the user has the correct permissions to take actions. This user id will also be used when the user modifies, creates or deletes their data. +After a user logs in, the application will need the user Id in order to look up additional data for the user as well as ensure the user has the correct permissions to take actions. This user id will also be used when the user modifies, creates or deletes their data. @@ -1487,7 +1487,7 @@ Keep it on the server -Since the user id is such a powerful component of an application, it needs to be secured and validated. Applications can send the user id to the front-end but should do so in a secure and verifiable way. Leveraging JSON Web Tokens (JWTs) is a good way to send user data (including their id) to the front-end of an application. On the server side, the APIs that are open to the front-end should never take a user id as the way to identify a user. This would allow any hacker to send it arbitrary ids and exploit user accounts. Instead, a secure token should be sent to APIs from the front-end. If you are using JWTs, these should be signed using RSA key-pairs. The server can then verify that the JWT is valid (by checking the RSA signature) and extract the user id from the JWT. Other solutions to this include using session cookies as the token, OAuth access tokens or other types of tokens. +Since the user Id is such a powerful component of an application, it needs to be secured and validated. Applications can send the user id to the front-end but should do so in a secure and verifiable way. Leveraging JSON Web Tokens (JWTs) is a good way to send user data (including their id) to the front-end of an application. On the server side, the APIs that are open to the front-end should never take a user id as the way to identify a user. This would allow any hacker to send it arbitrary ids and exploit user accounts. Instead, a secure token should be sent to APIs from the front-end. If you are using JWTs, these should be signed using RSA key-pairs. The server can then verify that the JWT is valid (by checking the RSA signature) and extract the user id from the JWT. Other solutions to this include using session cookies as the token, OAuth access tokens or other types of tokens. Here's a code snippet from a Node.js application that is leveraging FusionAuth and HTTP cookies to store a session identifier: @@ -1518,7 +1518,7 @@ router.route("/login").post(function (req, res) { }); ``` -Each request then uses the user object that was stored in the session when performing actions on behalf the user. Here's a code snippet that illustrates loading the user's id from the session and looking up the user's Todos from the database: +Each request then uses the user object that was stored in the session when performing actions on behalf the user. Here's a code snippet that illustrates loading the user's Id from the session and looking up the user's Todos from the database: ```javascript router.route("/todos").get(function (req, res) { @@ -1631,7 +1631,7 @@ The key security constraint for this approach is that the browser must conform t This approach is similar to the previous example, except it writes out a cookie that contains the CSRF token and also writes it out to the form. The cookie that is written out for this should be an `httpOnly` cookie. This means that it is not readable by JavaScript. This approach also works because of the access controls enforced by the browser. Even though the user might have the CSRF token on the website where the hacker has injected the malicious code, the hackers code will not be able to access the CSRF cookie using JavaScript and therefore won't be able to craft a form that contains the same CSRF token. -Here's an example HTTP resposne that contains the CSRF tokens in the cookie and the form: +Here's an example HTTP response that contains the CSRF tokens in the cookie and the form: ```html HTTP/1.1 200 OK @@ -1690,7 +1690,7 @@ This guide covers a set of best practices that will help you secure your user da We also would like to note that this guide is applicable for both large and small companies. Even if you have 10,000 servers and large configuration, deployment and management processes, you can still use the concepts in this guide to ensure your processes are secure. -If you find any errors in this guide, please let us know. Also, if you find any vulnerabilities in this guide, send us an email at dev@fusionauth.io so that we can investigate them and update the guide. +If you find any errors in this guide, please let us know. Also, if you find any vulnerabilities in this guide, send us an email at [dev@fusionauth.io](mailto:dev@fusionauth.io) so that we can investigate them and update the guide. ## References diff --git a/astro/src/content/articles/security/math-of-password-hashing-algorithms-entropy.md b/astro/src/content/articles/security/math-of-password-hashing-algorithms-entropy.md index 443063e9ee..45f98eb831 100644 --- a/astro/src/content/articles/security/math-of-password-hashing-algorithms-entropy.md +++ b/astro/src/content/articles/security/math-of-password-hashing-algorithms-entropy.md @@ -185,7 +185,7 @@ numberOfDays = numberOfHours / 24 = 116,909,722 or 116.9 million numberOfYears = numberOfDays / 365 = 320,300 ``` -Not bad. By slowing down the hash computation, we have increased the time from 4 minutes using our Bitcoin rig to 320,300 years. In this comparision you can see the practical difference between using SHA2 and BCrypt. BCrypt is purpose built to be extremely slow in comparison to SHA2 and other more traditional hashing algorithms. +Not bad. By slowing down the hash computation, we have increased the time from 4 minutes using our Bitcoin rig to 320,300 years. In this comparison you can see the practical difference between using SHA2 and BCrypt. BCrypt is purpose built to be extremely slow in comparison to SHA2 and other more traditional hashing algorithms. And here lies the debate that the security industry has been having for years: @@ -203,4 +203,4 @@ At the time of this writing, there are still numerous simple algorithms that hav ## How FusionAuth does it -FusionAuth defaults to `PBKDF2` with `24,000` iterations as the default password hashing scheme. This algorithm is quite complex and with the high number of iterations, it is sufficiently slow such that long and short passwords are challenging to brute force attack. Fusionauth also allow you to change the default algorithm as well as upgrade the algorithm for a user when they log in. This allows you to upgrade your applications password security over time. +FusionAuth defaults to `PBKDF2` with `24,000` iterations as the default password hashing scheme. This algorithm is quite complex and with the high number of iterations, it is sufficiently slow such that long and short passwords are challenging to brute force attack. FusionAuth also allow you to change the default algorithm as well as upgrade the algorithm for a user when they log in. This allows you to upgrade your applications password security over time. diff --git a/astro/src/content/articles/tokens/building-a-secure-jwt.md b/astro/src/content/articles/tokens/building-a-secure-jwt.md index 66c8427c67..205e94d0d3 100644 --- a/astro/src/content/articles/tokens/building-a-secure-jwt.md +++ b/astro/src/content/articles/tokens/building-a-secure-jwt.md @@ -50,7 +50,7 @@ You can [decode it using any number of online tools](/dev-tools/jwt-decoder), be Keep any data that you wouldn't want in the hands of someone else outside of your JWT. When you sign and send a token, or when you decode and receive it, you're guaranteed the contents didn't change. You're not guaranteed the contents are unseen. -A corollary of that is that any information you do send should avoid unintentional data leakage. This would include information such as identifiers. If a JWT includes a value like `123` for an id, that means anyone viewing it has a pretty good idea that there is an entity with the id of `122`. Use a GUID or random string for identifiers instead. Likewise, because tokens are not encrypted, use TLS for transmitting them. +A corollary of that is that any information you do send should avoid unintentional data leakage. This would include information such as identifiers. If a JWT includes a value like `123` for an Id, that means anyone viewing it has a pretty good idea that there is an entity with the Id of `122`. Use a GUID or random string for identifiers instead. Likewise, because tokens are not encrypted, use TLS for transmitting them. Don't send JWTs using an HTTP method that may be cached or logged. So don't append the token to a `GET` request as a parameter. If you must send it in a GET request, use an HTTP header. You can also use other HTTP methods such as `POST`, which sends the JWT as a part of a request body. Sending the token value as part of a `GET` URL might result in the JWT being stored in a proxy's memory or filesystem, a browser cache, or even in web server access logs. @@ -103,7 +103,7 @@ Therefore no claims are required by the RFC. But to maximize security, the follo * `iss` identifies the issuer of the JWT. It doesn't matter exactly what this string is as long as it is unique, doesn't leak information about the internals of the issuer, and is known by the consumer. * `aud` identifies the audience of the token. This can be a scalar or an array value, but in either case it should also be known by the consumer. -* `nbf` and `exp` claims determine the timeframe that the token is valid. The `nbf` claim can be useful if you are issuing a token for future use. The `exp` claim, a time beyond which the JWT is no longer valid, should always be set. +* `nbf` and `exp` claims determine the time frame that the token is valid. The `nbf` claim can be useful if you are issuing a token for future use. The `exp` claim, a time beyond which the JWT is no longer valid, should always be set. ### Revocation @@ -140,7 +140,7 @@ Clients request and hold tokens. A client can be a browser, a mobile phone or so Clients should deliver the JWT to consumers over a secure connection, typically TLS version 1.2 or later. -The client must store the token securely as well. How to do that depends on what the client actually is. For a browser, you should avoid storing the JWT in localstorage or a JavaScript object. You should instead keep it in a cookie with the following flags: +The client must store the token securely as well. How to do that depends on what the client actually is. For a browser, you should avoid storing the JWT in `localStorage` or a JavaScript object. You should instead keep it in a cookie with the following flags: * `Secure` to ensure the cookie is only sent over TLS. * `HttpOnly` so that no rogue JavaScript can access the cookie. @@ -156,7 +156,7 @@ For other types of clients, use platform specific best practices for securing da Tokens must be examined as carefully as they are crafted. When you are consuming a JWT, verify the JWT to ensure it was signed correctly, and validate and sanitize the claims. Just like with token creation, don't roll your own implementation; use existing libraries. -Verify that the JWT signature matches the content. Any library should be able to do this, but ensure that the algorithm that the token was signed with, based on the header, is used to decode it. In addition, verify the `kid` value in the header; make sure the key id matches the key you are using the validate the signature. It's worth mentioning again here that any JWTs using the `none` algorithm should be rejected immediately. +Verify that the JWT signature matches the content. Any library should be able to do this, but ensure that the algorithm that the token was signed with, based on the header, is used to decode it. In addition, verify the `kid` value in the header; make sure the key Id matches the key you are using the validate the signature. It's worth mentioning again here that any JWTs using the `none` algorithm should be rejected immediately. Then you want to validate the claims are as expected. This includes any implementation specific registered claims set on creation, as well as the issuer (`iss`) and the audience (`aud`) claims. A consumer should know the issuer it expects, based on out of band information such as documentation. You should also ensure the JWT is meant for you. diff --git a/astro/src/content/articles/tokens/jwt-components-explained.md b/astro/src/content/articles/tokens/jwt-components-explained.md index 234211000e..f04310ef2d 100644 --- a/astro/src/content/articles/tokens/jwt-components-explained.md +++ b/astro/src/content/articles/tokens/jwt-components-explained.md @@ -149,7 +149,7 @@ Therefore, you shouldn't put anything that should remain secret into a JWT. This * private information such as government Ids * secrets like passwords -* anything that would leak information like an integer id +* anything that would leak information like an integer Id Another security concern is related to the verification of the `aud` claim. Since consuming code already possesses the token, isn't verifying the `aud` claim extra work? The `aud` claim indicates who should receive this JWT, but the code already has it. Nope, always verify this claim. diff --git a/astro/src/content/articles/tokens/pros-and-cons-of-jwts.md b/astro/src/content/articles/tokens/pros-and-cons-of-jwts.md index c1f86497cc..9c63f3baa2 100644 --- a/astro/src/content/articles/tokens/pros-and-cons-of-jwts.md +++ b/astro/src/content/articles/tokens/pros-and-cons-of-jwts.md @@ -72,9 +72,9 @@ Both of these exploits have simple fixes. Specifically, you should never allow J ## Sessions as an Alternative -Instead of using JWTs or opaque tokens, you always have the option of using sessions. Sessions have been around for over two decades and are proven technology. Sessions generally work through the use of cookies and state that is stored on the server. The cookie contains a string of characters that is the session id. The server contains a large Hash that keys off the session id and stores arbitrary data. +Instead of using JWTs or opaque tokens, you always have the option of using sessions. Sessions have been around for over two decades and are proven technology. Sessions generally work through the use of cookies and state that is stored on the server. The cookie contains a string of characters that is the session Id. The server contains a large Hash that keys off the session Id and stores arbitrary data. -When a user logs in, the user object is stored in the session and the server sends back a session cookie that contains the session id. Each subsequent request to the server includes the session cookie. The server uses the session cookie to load the user object out of the session Hash. The user object is then used to identify the user making the request. Here are two diagrams that illustrate this concept: +When a user logs in, the user object is stored in the session and the server sends back a session cookie that contains the session Id. Each subsequent request to the server includes the session cookie. The server uses the session cookie to load the user object out of the session Hash. The user object is then used to identify the user making the request. Here are two diagrams that illustrate this concept: ### Login diff --git a/astro/src/content/articles/tokens/revoking-jwts.md b/astro/src/content/articles/tokens/revoking-jwts.md index 98cb5145c0..4fc2ff96f5 100644 --- a/astro/src/content/articles/tokens/revoking-jwts.md +++ b/astro/src/content/articles/tokens/revoking-jwts.md @@ -23,7 +23,7 @@ Here's a diagram that illustrates this architecture: Revoking JWTs
-The Todo Backend in the diagram can use the JWT and the public key to verify the JWT and then pull the user's id (in this case the subject) out of the JWT. The Todo Backend can then use the user's id to perform operations on that user's data. However, because the Todo Backend isn't verifying the JWT with the IdP, it has no idea if an administrator has logged into the IdP and locked or deleted that user's account. +The ToDo Backend in the diagram can use the JWT and the public key to verify the JWT and then pull the user's Id (in this case the subject) out of the JWT. The ToDo Backend can then use the user's Id to perform operations on that user's data. However, because the ToDo Backend isn't verifying the JWT with the IdP, it has no idea if an administrator has logged into the IdP and locked or deleted that user's account. ## Reduce the duration of the JWT @@ -55,7 +55,7 @@ The FusionAuth **jwt.refresh-token.revoke** event looks like this: } ``` -Next, let's write a simple Webhook in our application that will receive this event and update the JWTManager. (NOTE: our example has a variable called `applicationId` that is a global variable that stores the id of the application itself - in this case it would be **cc0567da-68a1-45f3-b15b-5a6228bb7146**). Our code below is written in Node.js and uses the [FusionAuth Node client library](https://github.com/FusionAuth/fusionauth-node-client). +Next, let's write a simple Webhook in our application that will receive this event and update the JWTManager. (NOTE: our example has a variable called `applicationId` that is a global variable that stores the Id of the application itself - in this case it would be **cc0567da-68a1-45f3-b15b-5a6228bb7146**). Our code below is written in Node.js and uses the [FusionAuth Node client library](https://github.com/FusionAuth/fusionauth-node-client). ```js /* Handle FusionAuth event. */ @@ -65,7 +65,7 @@ router.post('/fusionauth-webhook', function(req, res, next) { }); ``` -Here is how the JWTManager maintains the list of user ids whose JWTs should be revoked. Our implementation also starts a thread to clean up after itself so we don't run out of memory. +Here is how the JWTManager maintains the list of user Ids whose JWTs should be revoked. Our implementation also starts a thread to clean up after itself so we don't run out of memory. ```js const JWTManager = { @@ -73,7 +73,7 @@ const JWTManager = { /** * Checks if a JWT is valid. This assumes that the JWT contains a property named exp that is a - * NumericDate value defined in the JWT specification and a property named sub that is the user id the + * NumericDate value defined in the JWT specification and a property named sub that is the user Id the * JWT belongs to. * * @param {object} jwt The JWT object. @@ -85,9 +85,9 @@ const JWTManager = { }, /** - * Revokes all JWTs for the user with the given id using the duration (in seconds). + * Revokes all JWTs for the user with the given Id using the duration (in seconds). * - * @param {string} userId The user id (usually a UUID as a string). + * @param {string} userId The user Id (usually a UUID as a string). * @param {Number} durationSeconds The duration of all JWTs in seconds. */ revoke: function(userId, durationSeconds) { @@ -134,6 +134,7 @@ And finally we configure our Webhook in FusionAuth: We can now revoke a user's refresh token and FusionAuth will broadcast the event to our Webhook. The Webhook then updates the JWTManager which will cause JWTs for that user to be revoked. -This solution works well even in large systems with numerous backends. It requires the use of refresh tokens and an API that allows refresh tokens to be revoked. The only caveat is to be sure that your JWTManager code cleans up after itself to avoid running out memory. +This solution works well even in large systems with numerous backends. It requires the use of refresh tokens and an API that allows refresh tokens to be revoked. The only caveat is to be sure that your JWTManager code cleans up after itself to avoid running out memory. + +If you are using FusionAuth, you can use the Webhook and Event system to build this feature into your application quickly. We are also writing JWTManager implementations into each of our client libraries so you don't have to write those yourself. At the time of this writing, the Java and Node clients both have a JWTManager you can use. The other languages might have a JWTManager implementation now but if they don't, just submit a support ticket or a GitHub issue and we will write one for you. -If you are using FusionAuth, you can use the Webhook and Event system to build this feature into your application quickly. We are also writing JWTManager implementations into each of our client libraries so you don't have to write those yourself. At the time of this writing, the Java and Node clients both have a JWTManager you can use. The other languages might have a JWTManager implementation now but if they don't, just submit a support ticket or a Github issue and we will write one for you. diff --git a/astro/src/content/articles/tokens/tokens-microservices-boundaries.md b/astro/src/content/articles/tokens/tokens-microservices-boundaries.md index df3d16cabb..2ddad6342a 100644 --- a/astro/src/content/articles/tokens/tokens-microservices-boundaries.md +++ b/astro/src/content/articles/tokens/tokens-microservices-boundaries.md @@ -15,7 +15,7 @@ Consider this simple microservices based system. ![Simple microservices system architecture diagram.](/img/articles/tokens-microservices-boundaries/system-diagram.png) -We have three different services, all protected by an API gateway. This API gateway could be running NGINX, Apache, or some other open source system. It could be a commercial package such as HAProxy or Kong. It could also be a cloud vendor managed API gateway, such as an AWS Application Load Balancer or a Google Cloud Load Balancer. +We have three different services, all protected by an API gateway. This API gateway could be running nginx, Apache, or some other open source system. It could be a commercial package such as HAProxy or Kong. It could also be a cloud vendor managed API gateway, such as an AWS Application Load Balancer or a Google Cloud Load Balancer. When a request comes in, it will contain an access token. Getting this access token is beyond the scope of this article, but is documented in the [Modern Guide to OAuth](/articles/oauth/modern-guide-to-oauth/). This access token is often a JSON Web Token (JWT), which has intrinsic structure and can be signed and validated. @@ -56,7 +56,7 @@ Here the token is provided to the microservices and they each validate the signa You'll typically handle this with, in increasing order of effort and customizability: * a service mesh such as [Linkerd](https://linkerd.io/) or [Istio](https://istio.io/) -* an ambassador container running NGINX plus an [token processing NGINX library](https://github.com/zmartzone/lua-resty-openidc) or a similar proxy like [airbag](https://github.com/Soluto/airbag) +* an ambassador container running nginx plus an [token processing nginx library](https://github.com/zmartzone/lua-resty-openidc) or a similar proxy like [airbag](https://github.com/Soluto/airbag) * the code embedded in a library in your microservice which can then validate the signature and claims For example, if using Istio, you'd apply this command to create a request authentication policy, which confirms information about who created the JWT and validates the signature of the JWT. diff --git a/astro/src/content/blog/advanced-registration-form.mdx b/astro/src/content/blog/advanced-registration-form.mdx index ed200c0591..443e8d4c7d 100644 --- a/astro/src/content/blog/advanced-registration-form.mdx +++ b/astro/src/content/blog/advanced-registration-form.mdx @@ -130,7 +130,7 @@ Now that you've created a form with custom fields, the next step is to specify w Navigate to the "Applications" tab and create a new FusionAuth application. As a reminder, an application is anything a user can sign into: a web application, native app, API, anything. In this case, you are building out the real estate application; pick something descriptive. How about "Real estate search"? -You must configure a redirect URL; this is where the user is sent when registration succeeds. Navigate to the "OAuth" tab of your application and enter "https://mycompany.com" or another public website. For a production application, of course, you'd instead specify where a user should be sent after registration, such as a profile page. Though the specifics depend on your application settings, such as whether you require email verification, typically a user will be authenticated at the end of this registration process, with all that that entails. +You must configure a redirect URL; this is where the user is sent when registration succeeds. Navigate to the "OAuth" tab of your application and enter "https://mycompany.com" or another public website. For a production application, of course, you'd instead specify where a user should be sent after registration, such as a profile page. Though the specifics depend on your application settings, such as whether you require email verification, typically a user will be authenticated at the end of this registration process, with all that entails. Each application may have multiple redirect URLs. You can configure where to send a user after registration by adding a `redirect_uri` parameter to the registration form URL. For this tutorial, only one `redirect_uri` will be configured, and it will be automatically added to the registration URL generated by FusionAuth when you are ready to test drive user registration. Though it is likely enabled, also make sure you check "Authorization Code" under the "Enabled grants" section on the "OAuth" tab. diff --git a/astro/src/content/blog/auth0-and-fusionauth-a-tale-of-two-solutions.mdx b/astro/src/content/blog/auth0-and-fusionauth-a-tale-of-two-solutions.mdx index 69b84471dc..b79feee541 100644 --- a/astro/src/content/blog/auth0-and-fusionauth-a-tale-of-two-solutions.mdx +++ b/astro/src/content/blog/auth0-and-fusionauth-a-tale-of-two-solutions.mdx @@ -44,7 +44,7 @@ Auth0 and FusionAuth share many essential elements of a customer identity manage ### Free for Unlimited Users One of the biggest differences between Auth0 and FusionAuth is cost. FusionAuth is free for unlimited users. No strings, gimmicks, or tricks. No cost increases when you hit a certain Monthly Active User threshold. Much like a database or a web server, secure authentication is so essential that developers should be able to implement it quickly and easily without cost concerns. And unlike the free options from other vendors, we don't user-limit FusionAuth. You get a full unrestricted platform. -FusionAuth does offer advanced features and support for a price, but we have many many users running their business self hosting the community edition. +FusionAuth does offer advanced features and support for a price, but we have many users running their business self hosting the community edition. ### Single-Tenant Security We mentioned above that Auth0 and FusionAuth both have on-premise and cloud options. Our difference is both our local and cloud options deliver true data isolation as *single-tenant solutions*. This eliminates the possibility of data leakage between unrelated companies, whether accidentally or through hacker activity. For additional security, customers can implement a firewall at any layer, further protecting their data from unauthorized access. With the substantial increase in the number and sophistication of hacking, phishing and spoofing attacks, we felt it was the best choice. diff --git a/astro/src/content/blog/fusionauth-g2-high-performer.mdx b/astro/src/content/blog/fusionauth-g2-high-performer.mdx index 5789de43f8..c83cde151a 100644 --- a/astro/src/content/blog/fusionauth-g2-high-performer.mdx +++ b/astro/src/content/blog/fusionauth-g2-high-performer.mdx @@ -19,7 +19,7 @@ FusionAuth was named a High Performer across three categories in the G2 Winter 2 * [Identity and Access Management (IAM)](https://www.g2.com/categories/identity-and-access-management-iam) * [Single-Sign-On (SSO)](https://www.g2.com/categories/single-sign-on-sso) -Additionally, we were awarded Highest User Adoption, Easiest To Do Business With, and Best Meets Requirements within those categories. Our users left us 23 reviews with an an average of 4.8 out of 5 stars. +Additionally, we were awarded Highest User Adoption, Easiest To Do Business With, and Best Meets Requirements within those categories. Our users left us 23 reviews with an average of 4.8 out of 5 stars. G2 is the one of the technology industry’s most trusted source for customer reviews. Based on customer reviews and aggregating data from multiple sources, G2 released their Winter 2023 reports, rating companies in a multitude of industry categories. These scores determine market presence and overall customer satisfaction. diff --git a/astro/src/content/blog/fusionauth-introduces-pass-wordle.mdx b/astro/src/content/blog/fusionauth-introduces-pass-wordle.mdx index 5f31bbb769..f794a7a47d 100644 --- a/astro/src/content/blog/fusionauth-introduces-pass-wordle.mdx +++ b/astro/src/content/blog/fusionauth-introduces-pass-wordle.mdx @@ -38,7 +38,7 @@ We call it Pass-wordle™. Passwords, gamified. With this new technology, when someone forgets their password, it’s no biggie. No support desk or password reset emails are required. Pass-wordle™ login allows your users to skip all of the traditional hoop jumping and offers a self-service option. -This new gamified experience lets a user guess their password and and optionally receive hints in the form of colored squares. These hints let the user know when they have guessed incorrectly, or when they are on the right track. To increase the stakes, the user is locked out for the day if they exceed 5 guesses without correctly entering their password. In our user testing, this feature really helped increase the anxiety during login, proving to be a huge leap forward in password technology. +This new gamified experience lets a user guess their password and optionally receive hints in the form of colored squares. These hints let the user know when they have guessed incorrectly, or when they are on the right track. To increase the stakes, the user is locked out for the day if they exceed 5 guesses without correctly entering their password. In our user testing, this feature really helped increase the anxiety during login, proving to be a huge leap forward in password technology. Similar to the familiar idea of FOMO, or fear of missing out. We have coined the term FOBLO, or fear of being locked out. We can’t take total credit for this idea, we found the inspiration for this feature after watching Squid Games. diff --git a/astro/src/content/blog/how-sso-works.mdx b/astro/src/content/blog/how-sso-works.mdx index 06a0affcfd..0aad71e02d 100644 --- a/astro/src/content/blog/how-sso-works.mdx +++ b/astro/src/content/blog/how-sso-works.mdx @@ -96,7 +96,7 @@ FusionAuth provides an [open source library for Java](https://github.com/FusionA ## Why SAML -Why would you pick SAML over the OIDC flow mentioned above? Widespread support. SAML has been around since 2005 and many many commercial off the shelf and open source applications support it. +Why would you pick SAML over the OIDC flow mentioned above? Widespread support. SAML has been around since 2005 and many commercial off the shelf and open source applications support it. When evaluating your identity provider solution, think about what kinds of applications you need to support. diff --git a/astro/src/content/blog/how-to-authenticate-your-react-app.mdx b/astro/src/content/blog/how-to-authenticate-your-react-app.mdx index 1c241dbbd7..ceec9cdfca 100644 --- a/astro/src/content/blog/how-to-authenticate-your-react-app.mdx +++ b/astro/src/content/blog/how-to-authenticate-your-react-app.mdx @@ -336,7 +336,7 @@ And in `client/src/components`, create a new `Greeting` component. touch client/src/components/Greeting.jsx ``` -Go into the Greeting component and and add the following: +Go into the Greeting component and add the following: ```js import React from 'react'; diff --git a/astro/src/content/blog/how-to-migrate-from-azure-ad-b2c.mdx b/astro/src/content/blog/how-to-migrate-from-azure-ad-b2c.mdx index 7a4067c0be..4769f84f2e 100644 --- a/astro/src/content/blog/how-to-migrate-from-azure-ad-b2c.mdx +++ b/astro/src/content/blog/how-to-migrate-from-azure-ad-b2c.mdx @@ -128,7 +128,7 @@ Let's discuss the other option, a slow migration. With a slow, or phased, migration, users are not required to reset their password. Instead, they log in to the new system, and provide their username and password, which is then forwarded to Azure AD B2C. You can use the Resource Owners Credentials grant, often called the Password grant. If credentials are correct, the user is logged in. The new system can rehash and store the password along with other user data. -The connection between Azure AD B2C must be secure and over HTTPS. Use IP restrictions, custom headers and/or client certificates; you don't want anyone to be able to pass credentials to Azure AD B2C or or to inspect traffic between the new system and Azure AD B2C. +The connection between Azure AD B2C must be secure and over HTTPS. Use IP restrictions, custom headers and/or client certificates; you don't want anyone to be able to pass credentials to Azure AD B2C or to inspect traffic between the new system and Azure AD B2C. The Azure AD B2C OAuth endpoint is monitored by rate limiting systems. If a dynamic threshold of failed authentications is exceeded, the rate limiting system may identify a repeated IP address (i.e. from the new system) as an attacker, so you'll want to plan for that possibility. diff --git a/astro/src/content/blog/password-history.mdx b/astro/src/content/blog/password-history.mdx index f48804993d..be00d2961c 100644 --- a/astro/src/content/blog/password-history.mdx +++ b/astro/src/content/blog/password-history.mdx @@ -13,7 +13,7 @@ Happy world password day! This is a great day to change your passwords on import {/* more */} -World password day day is the [first Thursday in May](https://nationaldaycalendar.com/world-password-day-first-thursday-in-may/) every year. Inspired by security researcher [Mark Burnett](https://xato.net/), this is a yearly reminder to change your important passwords. This will help protect your accounts if there is a data breach. Password data can remain in the world for a long long time, but changing a password for an important account immediately helps secure it. +World Password Day is the [first Thursday in May](https://nationaldaycalendar.com/world-password-day-first-thursday-in-may/) every year. Inspired by security researcher [Mark Burnett](https://xato.net/), this is a yearly reminder to change your important passwords. This will help protect your accounts if there is a data breach. Password data can remain in the world for a long long time, but changing a password for an important account immediately helps secure it. Choosing a good password as well as enabling [multi-factor authentication](/learn/expert-advice/authentication/multi-factor-authentication) will ensure that your data remains secure. diff --git a/astro/src/content/blog/scaling-auth-system-excerpt.mdx b/astro/src/content/blog/scaling-auth-system-excerpt.mdx index 589d1b682a..fcdafe182e 100644 --- a/astro/src/content/blog/scaling-auth-system-excerpt.mdx +++ b/astro/src/content/blog/scaling-auth-system-excerpt.mdx @@ -63,5 +63,5 @@ If your authentication functionality is unavailable for any given time, it inevi This makes authentication a difficult problem: not only must it be secure and scalable, _but highly available, too._ Again, this means more hardware, more servers, and more money. -To learn about how you can can effectively scale your auth system, read [Making Sure Your Auth System Can Scale](/learn/expert-advice/ciam/making-sure-your-auth-system-scales). +To learn about how you can effectively scale your auth system, read [Making Sure Your Auth System Can Scale](/learn/expert-advice/ciam/making-sure-your-auth-system-scales). diff --git a/astro/src/content/blog/setting-up-single-sign-on-for-nodebb.mdx b/astro/src/content/blog/setting-up-single-sign-on-for-nodebb.mdx index 06dace08fd..48c926e641 100644 --- a/astro/src/content/blog/setting-up-single-sign-on-for-nodebb.mdx +++ b/astro/src/content/blog/setting-up-single-sign-on-for-nodebb.mdx @@ -39,7 +39,7 @@ First, create an application in FusionAuth. I'm going to call mine, creatively, After you save the application, edit it again, as we'll need to record a couple of configuration variables. Start at the "OAuth" tab. -The client id and client secret are used by FusionAuth to identify the application asking for user information. These values look like `fe4b813b-e2ec-49c8-b27f-40af5e271792` and and `Qz6PKsagXv13ipiHb4TZ9ii5Q9n_YcFAD-R0D5RKkqo` respectively. Save them off to a text file, as you'll use them later. +The client Id and client secret are used by FusionAuth to identify the application asking for user information. These values look like `fe4b813b-e2ec-49c8-b27f-40af5e271792` and `Qz6PKsagXv13ipiHb4TZ9ii5Q9n_YcFAD-R0D5RKkqo` respectively. Save them off to a text file, as you'll use them later. We also need to set up an "authorized redirect URL". This will look like `https://HOSTNAME/auth/fusionauth-oidc/callback` where `HOSTNAME` is the location of your NodeBB server. Since I'm running NodeBB locally, this value is `http://localhost:4567/auth/fusionauth-oidc/callback`. diff --git a/astro/src/content/blog/what-is-webauthn-why-do-you-care.mdx b/astro/src/content/blog/what-is-webauthn-why-do-you-care.mdx index 9242f0ea18..5435080b1f 100644 --- a/astro/src/content/blog/what-is-webauthn-why-do-you-care.mdx +++ b/astro/src/content/blog/what-is-webauthn-why-do-you-care.mdx @@ -110,7 +110,7 @@ The operating systems often offer authentication methods which would be difficul If you implement WebAuthn, you gain access to all of these authentication methods with little effort. -There are other authenticators which serve different purposes. The hardware authenticators fit certain use cases such as workforce or employee login. But they aren't a fit for for the Cosmo's Clown Store consumer e-commerce use case; normal folks typically don't have hardware authenticators. +There are other authenticators which serve different purposes. The hardware authenticators fit certain use cases such as workforce or employee login. But they aren't a fit for the Cosmo's Clown Store consumer e-commerce use case; normal folks typically don't have hardware authenticators. ## What does a WebAuthn process look like? diff --git a/astro/src/content/blog/when-to-self-host.mdx b/astro/src/content/blog/when-to-self-host.mdx index 182c262cce..60765bb4d8 100644 --- a/astro/src/content/blog/when-to-self-host.mdx +++ b/astro/src/content/blog/when-to-self-host.mdx @@ -21,7 +21,7 @@ Although self-hosting may seem like a simple decision at first, especially in th ![A diagram comparing self-hosted to SaaS deployment models..](/img/blogs/when-to-self-host/diagram-comparing-saas-self-hosting.png) -Self-hosting is not a new concept; in fact, it was the default choice prior to the more recent proliferation of SaaS. As software companies discovered the benefits of reliable and recurring revenue from subscription services, and organizations discovered the benefits of consuming specialized software produced by focused teams, the industry shifted from large, release-driven, self-hosted software to continuous releases delivered as as a service (SaaS is an acronym for “software as a service”). +Self-hosting is not a new concept; in fact, it was the default choice prior to the more recent proliferation of SaaS. As software companies discovered the benefits of reliable and recurring revenue from subscription services, and organizations discovered the benefits of consuming specialized software produced by focused teams, the industry shifted from large, release-driven, self-hosted software to continuous releases delivered as a service (SaaS is an acronym for “software as a service”). This trend was especially profound in the consumer software business but quickly spread to business software as well. Today, many services are "SaaS first," with only a few offering a self-hosted option that is usually limited to certain customers and plans. [GitHub](https://github.com/enterprise) and [Bitbucket](https://www.atlassian.com/software/bitbucket/enterprise/data-center), for example, only offer self-hosted versions of their software as part of their Enterprise or “Datacenter” plans, which are significantly more expensive than their commercial SaaS offerings. diff --git a/astro/src/content/docs/_shared/_hosted-backend-warning.md b/astro/src/content/docs/_shared/_hosted-backend-warning.md index 9b986f788c..3d2f67cbbb 100644 --- a/astro/src/content/docs/_shared/_hosted-backend-warning.md +++ b/astro/src/content/docs/_shared/_hosted-backend-warning.md @@ -7,7 +7,7 @@ If possible, have FusionAuth and your application served by the same domain, usi If this configuration is not possible, use one of these alternative methods: * Develop using a local FusionAuth instance, so both your webapp and FusionAuth are running on `localhost`. -* Do not use the the FusionAuth hosted backend, and instead write your own backend with a cross origin cookie policy: [here's an example](https://github.com/FusionAuth/fusionauth-example-react-sdk/tree/main/server). +* Do not use the FusionAuth hosted backend, and instead write your own backend with a cross origin cookie policy: [here's an example](https://github.com/FusionAuth/fusionauth-example-react-sdk/tree/main/server). * Configure a [custom domain name for the FusionAuth Cloud instance](/docs/get-started/run-in-the-cloud/cloud#updating-with-existing-custom-domains) (limited to certain plans). Modifying FusionAuth CORS configuration options does not fix this issue because the cookies that FusionAuth writes will not be accessible cross domain. diff --git a/astro/src/content/docs/_shared/_setup-wizard.mdx b/astro/src/content/docs/_shared/_setup-wizard.mdx index 7316c12a71..29d744c032 100644 --- a/astro/src/content/docs/_shared/_setup-wizard.mdx +++ b/astro/src/content/docs/_shared/_setup-wizard.mdx @@ -22,7 +22,7 @@ users can be assigned the `admin` role at a later time. To complete the setup wizard you must toggle the Accept button after reading the FusionAuth license agreement. You won't find any surprise strings attached here, just the normal lawyer speak for CYA. #### Stay informed -Optionally stay informed by opting-in to receive FusionAuth technical announcements, tutorials and other technical focused emails. You may opt-out at any time in the future, or opt-in at a later date by visiting fusionauth.io and finding the "Subscribe for updates" form at the bottom of the page. +Optionally stay informed by opting-in to receive FusionAuth technical announcements, tutorials and other technical focused emails. You may opt-out at any time in the future, or opt-in at a later date by visiting [fusionauth.io](/) and finding the "Subscribe for updates" form at the bottom of the page. ## Complete Setup diff --git a/astro/src/content/docs/_shared/_user-search-limits.mdx b/astro/src/content/docs/_shared/_user-search-limits.mdx index d1fda14cda..e42b3b4af7 100644 --- a/astro/src/content/docs/_shared/_user-search-limits.mdx +++ b/astro/src/content/docs/_shared/_user-search-limits.mdx @@ -1,4 +1,4 @@ -You cannot filter search results in FusionAuth to only return certain fields. Instead you must do this through post-processing. So if you want to retrieve only the `firstName` and `birthDate` fields of a set of users, the results will give you each entire user object and you must select desired fields. You can use the JSON processing facilities in your chosen language to do so, or use a tool such as [jq](https://stedolan.github.io/jq/). +You cannot filter search results in FusionAuth to only return certain fields. Instead you must do this through post-processing. So if you want to retrieve only the `firstName` and `birthDate` fields of a set of users, the results will give you each entire user object and you must select desired fields. You can use the JSON processing facilities in your chosen language to do so, or use a tool such as [`jq`](https://stedolan.github.io/jq/). Prior to version 1.48.0, when using the Elasticsearch search engine, the maximum number of users returned for any search is 10,000 users. For versions 1.48.0 and later, there is no limit on the number of users which can be returned if you paginate through the results. diff --git a/astro/src/content/docs/apis/_application-request-body.mdx b/astro/src/content/docs/apis/_application-request-body.mdx index 8b2de11a68..908d440574 100644 --- a/astro/src/content/docs/apis/_application-request-body.mdx +++ b/astro/src/content/docs/apis/_application-request-body.mdx @@ -58,7 +58,7 @@ import AdvancedEditionBlurbApi from 'src/content/docs/_shared/_advanced-edition- - The unique Id of the form to to enable authenticated users to manage their profile on the account page. + The unique Id of the form to enable authenticated users to manage their profile on the account page. @@ -132,7 +132,7 @@ import AdvancedEditionBlurbApi from 'src/content/docs/_shared/_advanced-edition- The Id of the Lambda that will be invoked when an Id token is generated for this application during an OpenID Connect authentication request. - The Id of the Lambda that will be invoked when a a SAML response is generated during a SAML authentication request. + The Id of the Lambda that will be invoked when a SAML response is generated during a SAML authentication request. The unique Id of the lambda that will be used to perform additional validation on registration form steps. @@ -450,7 +450,7 @@ import AdvancedEditionBlurbApi from 'src/content/docs/_shared/_advanced-edition- One or more authorized URLS that may be specified by the SAML v2 Service Provider in the Authentication request `[AssertionConsumerServiceURL]` element. If a requested URL is not in this list the request will be rejected by FusionAuth. - This is the URL that FusionAuth will send the SAML response during a SAML login request, this URL is also referred to as the Assertion Consumer Service or ACS). If the the Authentication request does not contain the `[AssertionConsumerServiceURL]` element, the first URL found in this list will be used to send the SAML response back to the Service Provider. + This is the URL that FusionAuth will send the SAML response during a SAML login request, this URL is also referred to as the Assertion Consumer Service or ACS). If the Authentication request does not contain the `[AssertionConsumerServiceURL]` element, the first URL found in this list will be used to send the SAML response back to the Service Provider. If the application.samlv2Configuration.initiatedLogin.enabled is `true`, the particular URL where the user will end up after successful login can be configured by appending a parameter to the `Initiate login URL`. The parameter must be either `redirect_uri` or `RelayState`. The value should be a URL encoded URL present in this field. If both `RelayState` and `redirect_uri` are present `redirect_uri` will be ignored in favor of `RelayState`. diff --git a/astro/src/content/docs/apis/_application-response-body-base.mdx b/astro/src/content/docs/apis/_application-response-body-base.mdx index 7abc84af45..1e01a7a56d 100644 --- a/astro/src/content/docs/apis/_application-response-body-base.mdx +++ b/astro/src/content/docs/apis/_application-response-body-base.mdx @@ -55,7 +55,7 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature When enabled a user will be required to provide their current password when changing their password on a self-service account form. - The unique Id of the form to to enable authenticated users to manage their profile on the account page. + The unique Id of the form to enable authenticated users to manage their profile on the account page. The unique identifier for this Application. @@ -117,7 +117,7 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature The Id of the Lambda that will be invoked when an Id token is generated for this application during an OpenID Connect authentication request. - The Id of the Lambda that will be invoked when a a SAML response is generated during a SAML authentication request. + The Id of the Lambda that will be invoked when a SAML response is generated during a SAML authentication request. The unique Id of the lambda that will be used to perform additional validation on registration form steps. @@ -375,7 +375,7 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature One or more authorized URLS that may be specified by the SAML v2 Service Provider in the Authentication request `[AssertionConsumerServiceURL]` element. If a requested URL is not in this list the request will be rejected by FusionAuth. - This is the URL that FusionAuth will send the SAML response during a SAML login request, this URL is also referred to as the Assertion Consumer Service or ACS). If the the Authentication request does not contain the `[AssertionConsumerServiceURL]` element, the first URL found in this list will be used to send the SAML response back to the Service Provider. + This is the URL that FusionAuth will send the SAML response during a SAML login request, this URL is also referred to as the Assertion Consumer Service or ACS). If the Authentication request does not contain the `[AssertionConsumerServiceURL]` element, the first URL found in this list will be used to send the SAML response back to the Service Provider. The URL of the callback (sometimes called the Assertion Consumer Service or ACS). This is where FusionAuth sends the browser after the user logs in via SAML. diff --git a/astro/src/content/docs/apis/_refresh-token-response-body-base.mdx b/astro/src/content/docs/apis/_refresh-token-response-body-base.mdx index 0503a575f7..ae81dfe345 100644 --- a/astro/src/content/docs/apis/_refresh-token-response-body-base.mdx +++ b/astro/src/content/docs/apis/_refresh-token-response-body-base.mdx @@ -38,7 +38,7 @@ import JSON from 'src/components/JSON.astro'; In version `1.46.0` and beyond, this value can be any string value you'd like, have fun with it! - The scopes associated with this Refresh Token. These are set at authentication when when the Refresh Token is first created. + The scopes associated with this Refresh Token. These are set at authentication when the Refresh Token is first created. The [instant](/docs/reference/data-types#instants) of the start of this Refresh Token. This value will be used to calculate token expiration. diff --git a/astro/src/content/docs/apis/_system-configuration-request-body.mdx b/astro/src/content/docs/apis/_system-configuration-request-body.mdx index 9e39f66e31..9efeee813e 100644 --- a/astro/src/content/docs/apis/_system-configuration-request-body.mdx +++ b/astro/src/content/docs/apis/_system-configuration-request-body.mdx @@ -42,7 +42,7 @@ import JSON from 'src/components/JSON.astro'; An object that can hold any information about the System that should be persisted. - The number of events to retain. Once the the number of event logs exceeds this configured value they will be deleted starting with the oldest event logs. + The number of events to retain. Once the number of event logs exceeds this configured value they will be deleted starting with the oldest event logs. Whether or not FusionAuth should delete the login records based upon this configuration. When `true` the loginRecordConfiguration.delete.numberOfDaysToRetain will be used to identify login records that are eligible for deletion. When this value is set to `false` login records will be preserved forever. diff --git a/astro/src/content/docs/apis/_system-configuration-response-body.mdx b/astro/src/content/docs/apis/_system-configuration-response-body.mdx index 3acb0dc482..97f2f26616 100644 --- a/astro/src/content/docs/apis/_system-configuration-response-body.mdx +++ b/astro/src/content/docs/apis/_system-configuration-response-body.mdx @@ -47,7 +47,7 @@ import JSON from 'src/components/JSON.astro'; An object that can hold any information about the System that should be persisted. - The number of events to retain. Once the the number of event logs exceeds this configured value they will be deleted starting with the oldest event logs. + The number of events to retain. Once the number of event logs exceeds this configured value they will be deleted starting with the oldest event logs. Whether or not FusionAuth should delete the login records based upon this configuration. When `true` the loginRecordConfiguration.delete.numberOfDaysToRetain will be used to identify login records that are eligible for deletion. When this value is set to `false` login records will be preserved forever. diff --git a/astro/src/content/docs/apis/_user-data-email-field-response.mdx b/astro/src/content/docs/apis/_user-data-email-field-response.mdx index 49bde1062f..01ac49e3c5 100644 --- a/astro/src/content/docs/apis/_user-data-email-field-response.mdx +++ b/astro/src/content/docs/apis/_user-data-email-field-response.mdx @@ -4,5 +4,5 @@ import APIField from 'src/components/api/APIField.astro'; This field will be used as the email address if no user.email field is found. - This feature was removed in version 1.26.0 and added back in in 1.27.2. + This feature was removed in version 1.26.0 and added back in 1.27.2. diff --git a/astro/src/content/docs/apis/connectors/_generic-request-body.mdx b/astro/src/content/docs/apis/connectors/_generic-request-body.mdx index 5d69d68788..e69a99c9f6 100644 --- a/astro/src/content/docs/apis/connectors/_generic-request-body.mdx +++ b/astro/src/content/docs/apis/connectors/_generic-request-body.mdx @@ -33,7 +33,7 @@ import JSON from 'src/components/JSON.astro'; The read timeout for the HTTP connection, in milliseconds. Value must be greater than `0`. - The Id of an existing [Key](/docs/apis/keys). The The X.509 certificate is used for client certificate authentication in requests to the Connector. + The Id of an existing [Key](/docs/apis/keys). The X.509 certificate is used for client certificate authentication in requests to the Connector. This field must be set to `Generic`. diff --git a/astro/src/content/docs/apis/identity-providers/_README.md b/astro/src/content/docs/apis/identity-providers/_README.md index 2ab92ad8e8..206e550233 100644 --- a/astro/src/content/docs/apis/identity-providers/_README.md +++ b/astro/src/content/docs/apis/identity-providers/_README.md @@ -2,12 +2,12 @@ ### Structure -There are two groups of Identity Providers. The first group are all very similiar, conform fairly well to a Oauth Redirect login flow and require a `client_id` and `client_secret` (except Steam, the only one-off in this group). The second group are all very different from the first group and each other. +There are two groups of Identity Providers. The first group are all very similar, conform fairly well to a OAuth Redirect login flow and require a `client_id` and `client_secret` (except Steam, the only one-off in this group). The second group are all very different from the first group and each other. -- Oauth IdPs: Epic, Google, Sony, Steam, Twitch, Xbox -- Others: Apple, External JWT, Facebook, HYPR, LinkedIn, OpenId, Saml V2 +- OAuth IdPs: Epic, Google, Sony, Steam, Twitch, Xbox +- Others: Apple, External JWT, Facebook, HYPR, LinkedIn, OpenId, SAML V2 -For the Oauth group they each have an "Overview" and then include the following tree (only the first 2 levels are listed, there are other, but you will find them as you go) of `adoc` files: +For the OAuth group they each have an "Overview" and then include the following tree (only the first 2 levels are listed, there are other, but you will find them as you go) of `adoc` files: - _oauth-idp-operations.mdx - _oauth-idp-request-body.mdx diff --git a/astro/src/content/docs/apis/identity-providers/facebook.mdx b/astro/src/content/docs/apis/identity-providers/facebook.mdx index d3a443e832..f973366094 100644 --- a/astro/src/content/docs/apis/identity-providers/facebook.mdx +++ b/astro/src/content/docs/apis/identity-providers/facebook.mdx @@ -97,7 +97,7 @@ There is only one Facebook Identity Provider, so this Identity Provider may be r ### Response -The response for this API contains the the Facebook Identity Provider. +The response for this API contains the Facebook Identity Provider. diff --git a/astro/src/content/docs/apis/users.mdx b/astro/src/content/docs/apis/users.mdx index aa7c7403c6..0549b63912 100644 --- a/astro/src/content/docs/apis/users.mdx +++ b/astro/src/content/docs/apis/users.mdx @@ -420,7 +420,7 @@ The response does not contain a body, the HTTP status code will indicate the res This API is used to search for Users. This API may be called using the `GET` or `POST` HTTP methods, examples of each are provided below. The `POST` method is provided to allow for a richer request object without worrying about exceeding the maximum length of a URL. -Calling this API with either the `GET` or `POST` HTTP method will will provide the same search results given the same query parameters. +Calling this API with either the `GET` or `POST` HTTP method will provide the same search results given the same query parameters. ### Request diff --git a/astro/src/content/docs/archive/apis/_system-configuration-request-body.mdx b/astro/src/content/docs/archive/apis/_system-configuration-request-body.mdx index e7d108d697..aebcb7af59 100644 --- a/astro/src/content/docs/archive/apis/_system-configuration-request-body.mdx +++ b/astro/src/content/docs/archive/apis/_system-configuration-request-body.mdx @@ -147,7 +147,7 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; In version 1.8.0 and beyond, event configuration is managed per [Tenant](/docs/apis/tenants). - The number of events to retain. Once the the number of event logs exceeds this configured value they will be deleted starting with the oldest event logs. + The number of events to retain. Once the number of event logs exceeds this configured value they will be deleted starting with the oldest event logs. The time in seconds until a OAuth authorization code in no longer valid to be exchanged for an access token. This is essentially the time allowed between the start @@ -565,7 +565,7 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; A hexadecimal color to override the default menu font color in the user interface. - + > Example: `FFFFFF` would set the menu font color to white. diff --git a/astro/src/content/docs/archive/apis/_system-configuration-response-body.mdx b/astro/src/content/docs/archive/apis/_system-configuration-response-body.mdx index 5e6743006d..26e9736aa0 100644 --- a/astro/src/content/docs/archive/apis/_system-configuration-response-body.mdx +++ b/astro/src/content/docs/archive/apis/_system-configuration-response-body.mdx @@ -157,7 +157,7 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; In version 1.8.0 and beyond, event configuration is managed per [Tenant](/docs/apis/tenants). - The number of events to retain. Once the the number of event logs exceeds this configured value they will be deleted starting with the oldest event logs. + The number of events to retain. Once the number of event logs exceeds this configured value they will be deleted starting with the oldest event logs. The time in seconds until a OAuth authorization code in no longer valid to be exchanged for an access token. This is essentially the time allowed between the start diff --git a/astro/src/content/docs/archive/passport-to-fusionauth.mdx b/astro/src/content/docs/archive/passport-to-fusionauth.mdx index b7bba6ec01..37ce9b25e3 100644 --- a/astro/src/content/docs/archive/passport-to-fusionauth.mdx +++ b/astro/src/content/docs/archive/passport-to-fusionauth.mdx @@ -79,7 +79,7 @@ Review the following breaking changes when moving from Passport to FusionAuth. A The Forgot Email and Setup Password templates no longer support the `verificationId` replacement parameter. The `verificationId` replacement parameter was provided for backwards compatibility with older versions of Passport and has been removed in FusionAuth. -Review your Forgot Password and Setup Password email templates and if you are using the the replacement value `${verificationId}` in either the HTML or Text version of the template, replace it with `${changePasswordId}`. +Review your Forgot Password and Setup Password email templates and if you are using the replacement value `${verificationId}` in either the HTML or Text version of the template, replace it with `${changePasswordId}`. See [Email Templates](/docs/customize/email-and-messages/email-templates) for additional information. diff --git a/astro/src/content/docs/customize/cli.mdx b/astro/src/content/docs/customize/cli.mdx index d80fcb7ba1..4d32ceb26e 100644 --- a/astro/src/content/docs/customize/cli.mdx +++ b/astro/src/content/docs/customize/cli.mdx @@ -78,4 +78,4 @@ npm update -g @fusionauth/cli The FusionAuth CLI is open source and we welcome pull requests. -You can [view the source code](https://github.com/FusionAuth/fusionauth-node-cli) and the [the npm package](https://www.npmjs.com/package/@fusionauth/cli). +You can [view the source code](https://github.com/FusionAuth/fusionauth-node-cli) and [the npm package](https://www.npmjs.com/package/@fusionauth/cli). diff --git a/astro/src/content/docs/customize/email-and-messages/configuring-application-specific-email-templates.mdx b/astro/src/content/docs/customize/email-and-messages/configuring-application-specific-email-templates.mdx index a48f87fe7d..ea2d6fff17 100644 --- a/astro/src/content/docs/customize/email-and-messages/configuring-application-specific-email-templates.mdx +++ b/astro/src/content/docs/customize/email-and-messages/configuring-application-specific-email-templates.mdx @@ -44,7 +44,7 @@ When a user clicks the `Forgot your password?` link on the login page or calls t Now you need to send an email using the default email template. -Make sure you've created an Application in the [Application overview]. Then navigate to your application login page by clicking on Applications in the navigation sidebar, selecting the green magnifying glass icon, and copying and pasting the Login URL into an incognito browser. +Make sure you've created an Application in the [Application overview]. Then navigate to your application login page by clicking on Applications in the navigation sidebar, selecting the green magnifying glass icon, and copying and pasting the [Login URL](/docs/get-started/core-concepts/applications) into an incognito browser. Click the `Forgot your password?` link, enter your email in the form, and the `Forgot Password` email should be sent to the user's email inbox. diff --git a/astro/src/content/docs/customize/email-and-messages/generic-messenger.mdx b/astro/src/content/docs/customize/email-and-messages/generic-messenger.mdx index 99a32abec5..b1078bb595 100644 --- a/astro/src/content/docs/customize/email-and-messages/generic-messenger.mdx +++ b/astro/src/content/docs/customize/email-and-messages/generic-messenger.mdx @@ -69,7 +69,7 @@ Complete the following fields: Password used to authenticate with the generic messenger - The SSL certificate in PEM format to be used when connecting to the messenger API endpoint. When provided an in memory keystore will be generated in order to complete the https connection to the messenger API endpoint. + The SSL certificate in PEM format to be used when connecting to the messenger API endpoint. When provided an in memory keystore will be generated in order to complete the HTTPS connection to the messenger API endpoint. diff --git a/astro/src/content/docs/customize/email-and-messages/twilio-messenger.mdx b/astro/src/content/docs/customize/email-and-messages/twilio-messenger.mdx index 7b3ffda536..8d2060bc95 100644 --- a/astro/src/content/docs/customize/email-and-messages/twilio-messenger.mdx +++ b/astro/src/content/docs/customize/email-and-messages/twilio-messenger.mdx @@ -50,7 +50,7 @@ Complete the following fields: Provided by Twilio and is often used in conjunction with the Copilot service. - When enabled, each message sent using this messenger will generate a new Debug Event Log which can be viewed using the Event Log API or from the admin UI by navigating to Sytem -> Event Log. + When enabled, each message sent using this messenger will generate a new Debug Event Log which can be viewed using the Event Log API or from the admin UI by navigating to System -> Event Log. diff --git a/astro/src/content/docs/extend/code/lambdas/openid-connect-response-reconcile.mdx b/astro/src/content/docs/extend/code/lambdas/openid-connect-response-reconcile.mdx index 3efb6b6e1e..54de2baab5 100644 --- a/astro/src/content/docs/extend/code/lambdas/openid-connect-response-reconcile.mdx +++ b/astro/src/content/docs/extend/code/lambdas/openid-connect-response-reconcile.mdx @@ -14,7 +14,7 @@ import OpenidConnectExampleLambda from 'src/content/docs/_shared/_openid-connect When an OpenID Connect identity provider is used to complete a federated login request FusionAuth will use well known OpenID Connect claims to reconcile user. -It is common that the claims returned from the Userinfo endpoint during an OpenID Connect login request will contain custom claims defined by your identity provider. In order to utilize these custom claims you may wish to use a lambda assist FusionAuth during the login request to reconcile these claims to the FusionAuth user. +It is common that the claims returned from the UserInfo endpoint during an OpenID Connect login request will contain custom claims defined by your identity provider. In order to utilize these custom claims you may wish to use a lambda assist FusionAuth during the login request to reconcile these claims to the FusionAuth user. When you create a new lambda using the FusionAuth UI we will provide you an empty function for you to implement. If you are using the API to create the lambda you will need to ensure your function has the following signature: @@ -27,7 +27,7 @@ function reconcile(user, registration, jwt, id_token, tokens) { This lambda must contain a function named `reconcile` that takes at least three parameters, a fourth parameter is optional. The parameters that the lambda is passed are: -* `jwt` - the JSON payload returned from the OpenID Connect Userinfo endpoint. This is read-only. +* `jwt` - the JSON payload returned from the OpenID Connect UserInfo endpoint. This is read-only. * `id_token` - the JSON payload returned in the `id_token` when available. This parameter may not be provided and will be `undefined` in that case. This is read-only. Available since 1.31.0 * `tokens` - an object containing the encoded versions of the `access_token` and optionally the `id_token` when available. This is read-only. Available since 1.48.0 @@ -63,7 +63,7 @@ FusionAuth will require an email or username to create a user. However, if the r This capability is available beginning in version `1.31.0`. It was also available from `1.17.3` to `1.28.0`. -In this example, we will assume the the `jwt` or `id_token` objects contain unique user information such as the `sub` claim. This unique value can be used to fabricate an email address. +In this example, we will assume the `jwt` or `id_token` objects contain unique user information such as the `sub` claim. This unique value can be used to fabricate an email address. ```javascript function(user, registration, jwt, id_token, tokens) { diff --git a/astro/src/content/docs/extend/code/lambdas/testing.mdx b/astro/src/content/docs/extend/code/lambdas/testing.mdx index 2b809f58a5..fbd411338c 100644 --- a/astro/src/content/docs/extend/code/lambdas/testing.mdx +++ b/astro/src/content/docs/extend/code/lambdas/testing.mdx @@ -216,7 +216,7 @@ Each of these types of lambda tests is outlined below. ### Test Library -There are many JavaScript test libraries available, and everyone has their preference. This guide uses a simple library for demonstration so that you can generalize the tests to your favorite library. The tests below use [`tape`](https://github.com/ljharb/tape), which implements the [Test Anything Protocol (TAP)](https://en.wikipedia.org/wiki/Test_Anything_Protocol), a language-agnostic specification for running tests that's been in use since 1987. The tests also use [fetch-mock](https://www.wheresrhys.co.uk/fetch-mock/) to mock `fetch` calls from your lambda, [`faucet`](https://www.npmjs.com/package/faucet) to to give neat output from `tape`, [`jsonwebtoken`](https://www.npmjs.com/package/jsonwebtoken) to decode the JWT, and [`uuid`](https://www.npmjs.com/package/uuid) to make a random user Id. +There are many JavaScript test libraries available, and everyone has their preference. This guide uses a simple library for demonstration so that you can generalize the tests to your favorite library. The tests below use [`tape`](https://github.com/ljharb/tape), which implements the [Test Anything Protocol (TAP)](https://en.wikipedia.org/wiki/Test_Anything_Protocol), a language-agnostic specification for running tests that's been in use since 1987. The tests also use [fetch-mock](https://www.wheresrhys.co.uk/fetch-mock/) to mock `fetch` calls from your lambda, [`faucet`](https://www.npmjs.com/package/faucet) to give neat output from `tape`, [`jsonwebtoken`](https://www.npmjs.com/package/jsonwebtoken) to decode the JWT, and [`uuid`](https://www.npmjs.com/package/uuid) to make a random user Id. Install the following packages in your test app terminal. diff --git a/astro/src/content/docs/extend/code/password-hashes/writing-a-plugin.mdx b/astro/src/content/docs/extend/code/password-hashes/writing-a-plugin.mdx index 98a916083d..cd2789cbe4 100644 --- a/astro/src/content/docs/extend/code/password-hashes/writing-a-plugin.mdx +++ b/astro/src/content/docs/extend/code/password-hashes/writing-a-plugin.mdx @@ -30,7 +30,7 @@ mvn compile package If the above commands were successful you have now downloaded the example code and performed and initial build of the jar. If last command was not found, you do not yet have Maven build tool installed. You may utilize whatever Java build system you prefer, such as Maven, Ant, Gradle or Savant. This example wil use the Maven build system. -The following is is a representation of the plugin project layout. +The following is a representation of the plugin project layout. ```plaintext title="Plugin Project Layout" fusionauth-example-password-encryptor @@ -64,7 +64,7 @@ To modify the name of your plugin, edit your build file. Below is a small porti ## Code the Plugin -This is where you get to code! Ideally you would have one or two known passwords in the data you will be importing to Fusionauth so that you can test your plugin prior to installing it in FusionAuth. +This is where you get to code! Ideally you would have one or two known passwords in the data you will be importing to FusionAuth so that you can test your plugin prior to installing it in FusionAuth. Begin by modifying the `MyExamplePasswordEncryptor` class found in `src/main/java`. @@ -80,7 +80,7 @@ The only two required methods for you to implement are `defaultFactor()`, and `e If you do not implement these methods in your plugin, the default implementations below will be used: -*PasswordEncryptor interface with default generateSalt and validateSalt methods* +*`PasswordEncryptor` interface with default `generateSalt` and `validateSalt` methods* If your plugin requires a specific salt length differing from the default implementation, implement these methods in your plugin to generate a salt that meets your requirements. diff --git a/astro/src/content/docs/extend/events-and-webhooks/events/user-actions.mdx b/astro/src/content/docs/extend/events-and-webhooks/events/user-actions.mdx index 2f20faa30a..ae418d8082 100644 --- a/astro/src/content/docs/extend/events-and-webhooks/events/user-actions.mdx +++ b/astro/src/content/docs/extend/events-and-webhooks/events/user-actions.mdx @@ -21,7 +21,7 @@ export const eventType = 'user.action';

-A temporal action is one that has a start time and and a duration. When a phase transition occurs for a temporal action, an event will be sent to the webhook. See the event.phase in the message body. +A temporal action is one that has a start time and a duration. When a phase transition occurs for a temporal action, an event will be sent to the webhook. See the event.phase in the message body.

diff --git a/astro/src/content/docs/extend/events-and-webhooks/events/user-login-success.mdx b/astro/src/content/docs/extend/events-and-webhooks/events/user-login-success.mdx index d70e560e4a..a605866908 100644 --- a/astro/src/content/docs/extend/events-and-webhooks/events/user-login-success.mdx +++ b/astro/src/content/docs/extend/events-and-webhooks/events/user-login-success.mdx @@ -54,7 +54,7 @@ export const eventType = 'user.login.success'; - The ip address provided in the login request. + The IP address provided in the login request. Moved to event.info in 1.30.0 diff --git a/astro/src/content/docs/extend/events-and-webhooks/signing.mdx b/astro/src/content/docs/extend/events-and-webhooks/signing.mdx index c63f2b8a45..f9809ff473 100644 --- a/astro/src/content/docs/extend/events-and-webhooks/signing.mdx +++ b/astro/src/content/docs/extend/events-and-webhooks/signing.mdx @@ -69,7 +69,7 @@ The `kid` identifies the Id of the key used to sign the JWT. JWT libraries can l ### Example Webhook Listener Code -The following code ([available on Github](https://github.com/FusionAuth/fusionauth-example-javascript-webhooks/blob/main/signature-verify/app.js)) demonstrates webhook signature verification with a simple Node server. +The following code ([available on GitHub](https://github.com/FusionAuth/fusionauth-example-javascript-webhooks/blob/main/signature-verify/app.js)) demonstrates webhook signature verification with a simple Node server. diff --git a/astro/src/content/docs/extend/events-and-webhooks/writing-a-webhook.mdx b/astro/src/content/docs/extend/events-and-webhooks/writing-a-webhook.mdx index d80900efa3..b4922012bb 100644 --- a/astro/src/content/docs/extend/events-and-webhooks/writing-a-webhook.mdx +++ b/astro/src/content/docs/extend/events-and-webhooks/writing-a-webhook.mdx @@ -35,7 +35,7 @@ Here's a video displaying how to configure a webhook. If you have multiple Webhooks configured for a single Tenant, the transaction setting for the event will dictate if FusionAuth will commit the transaction or not. -As of version 1.37.0 if you have multiple webhooks assigned to different tenants but configured for the same event, such as `user.create`, only the events matching both tenant and type will be delivered. For example, imagine you have Pied Piper and Hooli tenants and both have different webhooks (piedpier.com/webhook and hooli.com/webhook) and each is configured to listen only to their tenant for the `user.create` webhook event. In this case, piedpiper.com/webhook would receive only Pied Piper user creation event information; likewise hooli.com/webhook will receive only webhooks for the `user.create` event from the Hooli tenant. +As of version 1.37.0 if you have multiple webhooks assigned to different tenants but configured for the same event, such as `user.create`, only the events matching both tenant and type will be delivered. For example, imagine you have Pied Piper and Hooli tenants and both have different webhooks (`piedpier.com/webhook` and `hooli.com/webhook`) and each is configured to listen only to their tenant for the `user.create` webhook event. In this case, piedpiper.com/webhook would receive only Pied Piper user creation event information; likewise hooli.com/webhook will receive only webhooks for the `user.create` event from the Hooli tenant. Prior to version 1.37.0 if you have multiple tenants listening for the same event, they will all receive that event and can filter on the provided tenantId to determine if they should handle the event. @@ -125,7 +125,7 @@ While this scenario is most obvious when a user or registration is being created ## Example Code -Here's an example of a Webhook written in Node using Express. In this example, if the event is a `user.delete` event, this code deletes all of the user's Todos. The example code is [available on Github](https://github.com/FusionAuth/fusionauth-example-javascript-webhooks/blob/main/simple/app.js). +Here's an example of a Webhook written in Node using Express. In this example, if the event is a `user.delete` event, this code deletes all of the user's ToDos. The example code is [available on GitHub](https://github.com/FusionAuth/fusionauth-example-javascript-webhooks/blob/main/simple/app.js). In this example we are also checking the HTTP Authorization header for an API key. Using an API key or some type of authentication helps secure your Webhook to prevent malicious requests. You can configure the API key via the FusionAuth Web Interface or the API using the Headers of the Webhook configuration. diff --git a/astro/src/content/docs/get-started/core-concepts/users.mdx b/astro/src/content/docs/get-started/core-concepts/users.mdx index 50d89393c8..ad4011a5d5 100644 --- a/astro/src/content/docs/get-started/core-concepts/users.mdx +++ b/astro/src/content/docs/get-started/core-concepts/users.mdx @@ -879,7 +879,7 @@ And if you added more applications or stores, you'd face a combinatorial explosi ### The user.data Field -You can add add arbitrary JSON to the `user.data` field, such as `org_type` and `org_id` fields. You can do this using the [User API](/docs/apis/users) on user creation. +You can add arbitrary JSON to the `user.data` field, such as `org_type` and `org_id` fields. You can do this using the [User API](/docs/apis/users) on user creation. The `user.data` fields can then be read in a [JWT Populate Lambda](/docs/extend/code/lambdas/jwt-populate) and pushed into the tokens generated during authentication. diff --git a/astro/src/content/docs/get-started/download-and-install/fusionauth-app.mdx b/astro/src/content/docs/get-started/download-and-install/fusionauth-app.mdx index fb5aa79e65..5780b2e175 100644 --- a/astro/src/content/docs/get-started/download-and-install/fusionauth-app.mdx +++ b/astro/src/content/docs/get-started/download-and-install/fusionauth-app.mdx @@ -275,7 +275,7 @@ psql -U fusionauth < postgresql.sql ### Configuration -Before starting FusionAuth for the first time, you'll need to add your database connection in the the configuration. The name of this +Before starting FusionAuth for the first time, you'll need to add your database connection in the configuration. The name of this file is `fusionauth.properties`. The configuration file may be found in the following directory, assuming you installed in the default locations. If you have installed in an diff --git a/astro/src/content/docs/get-started/download-and-install/kubernetes/fusionauth-deployment.mdx b/astro/src/content/docs/get-started/download-and-install/kubernetes/fusionauth-deployment.mdx index 1cb10455ac..9add1e2c59 100644 --- a/astro/src/content/docs/get-started/download-and-install/kubernetes/fusionauth-deployment.mdx +++ b/astro/src/content/docs/get-started/download-and-install/kubernetes/fusionauth-deployment.mdx @@ -258,7 +258,7 @@ Navigate to `http://localhost:9011` and you will land on the FusionAuth Setup Wi ## Create an Ingress -If you want to connect FusionAuth with an external network, the last thing you need to do is to configure the cluster to be able to receive external requests. You might do this if you were using FusionAuth to authenticate users connecting to applications from the internet. On the other hand, you might not do this if you were using FusionAuth solely within your kubernetes cluster. +If you want to connect FusionAuth with an external network, the last thing you need to do is to configure the cluster to be able to receive external requests. You might do this if you were using FusionAuth to authenticate users connecting to applications from the internet. On the other hand, you might not do this if you were using FusionAuth solely within your kubernetes cluster. To direct external traffic to your cluster, you will use an [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/), a component that defines how external traffic should be handled, and an [Ingress Controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) that implements those rules. @@ -299,7 +299,7 @@ kubectl apply -f ./ingress.yaml ### Install an Ingress Controller -For this guide, you will use the NGINX Ingress controller. To install the the Ingress controller, add the [nginx-ingress](https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx) repository and install the Helm chart by running the following commands: +For this guide, you will use the NGINX Ingress controller. To install the Ingress controller, add the [nginx-ingress](https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx) repository and install the Helm chart by running the following commands: ```shell title="Add ingress-nginx chart repository" helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx diff --git a/astro/src/content/docs/get-started/download-and-install/system-requirements.mdx b/astro/src/content/docs/get-started/download-and-install/system-requirements.mdx index 4a6c363e24..ba624ddcce 100644 --- a/astro/src/content/docs/get-started/download-and-install/system-requirements.mdx +++ b/astro/src/content/docs/get-started/download-and-install/system-requirements.mdx @@ -11,7 +11,7 @@ import ElasticsearchRam from 'src/content/docs/_shared/_elasticsearch-ram.mdx'; ## System Requirements FusionAuth will install and run on nearly any system. We have done our best to document the supported configurations here. If you -have any questions about platform support, please ask a question on the forum or open an issue on Github. If you have a licensed edition you may open a support request from your account. +have any questions about platform support, please ask a question on the forum or open an issue on GitHub. If you have a licensed edition you may open a support request from your account. Please read through this documentation and ensure you have met all of the requirements before continuing with the installation of FusionAuth. diff --git a/astro/src/content/docs/get-started/run-in-the-cloud/cloud.mdx b/astro/src/content/docs/get-started/run-in-the-cloud/cloud.mdx index d793d3abda..59e62e2c48 100644 --- a/astro/src/content/docs/get-started/run-in-the-cloud/cloud.mdx +++ b/astro/src/content/docs/get-started/run-in-the-cloud/cloud.mdx @@ -822,5 +822,5 @@ FusionAuth Cloud has the same [limitations](/docs/get-started/core-concepts/limi * If you are on FusionAuth Cloud and you find that some requests are failing, it is possible you are being rate limited. This isn't intentional, but an automated part of our infrastructure to ensure FusionAuth Cloud performance and security. If you are rate limited but need these requests to occur, please open a [support ticket](https://account.fusionauth.io/account/support/) with details. * If you want to run Advanced Threat Detection, an Enterprise feature, you'll need a cloud deployment with sufficient memory. Currently that means it must be a Large or X-Large size. * With HA and other multi-node deployments, requests are passed through a load balancer. When making requests to node specific metrics endpoints such as `/api/status` or `/api/prometheus/metrics` each request may return different results because the response is specific to the service node responding to the request. -* If you are using the Elasticsearch search engine, you may not modify the Elasticsearch settings or view the Elasticsearch index directly. Among other things, this means that you can't use use some of the [troubleshooting steps](/docs/operate/troubleshooting/troubleshooting) available to users self-hosting FusionAuth. +* If you are using the Elasticsearch search engine, you may not modify the Elasticsearch settings or view the Elasticsearch index directly. Among other things, this means that you can't use some of the [troubleshooting steps](/docs/operate/troubleshooting/troubleshooting) available to users self-hosting FusionAuth. * OpenTelemetry data is not available on FusionAuth Cloud deployments. diff --git a/astro/src/content/docs/lifecycle/authenticate-users/application-authentication-tokens.mdx b/astro/src/content/docs/lifecycle/authenticate-users/application-authentication-tokens.mdx index b4a54023d6..c4b64c7f0e 100644 --- a/astro/src/content/docs/lifecycle/authenticate-users/application-authentication-tokens.mdx +++ b/astro/src/content/docs/lifecycle/authenticate-users/application-authentication-tokens.mdx @@ -22,7 +22,7 @@ An Authentication Token is a sequence of characters and it can be used in place token for you which is highly recommended, the token is built using a secure random generator and the URL safe Base64 encoded to produce a string 43 characters in length. While 128 bites of entropy is generally considered to be sufficiently secure , the generated Authentication Token provides 256 bites of entropy. This value is calculated -by multiplying the the number of characters by the entropy per character, and because a Base64 encoded character provides a entropy of 5.954 bits, a 43 character string will have 256 bits of entropy. +by multiplying the number of characters by the entropy per character, and because a Base64 encoded character provides a entropy of 5.954 bits, a 43 character string will have 256 bits of entropy. ### Enabling Authentication Tokens diff --git a/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/enterprise/samlv2-idp-initiated.mdx b/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/enterprise/samlv2-idp-initiated.mdx index f8a0015af0..4d98b586a5 100644 --- a/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/enterprise/samlv2-idp-initiated.mdx +++ b/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/enterprise/samlv2-idp-initiated.mdx @@ -22,7 +22,7 @@ import Fields from '../_samlv2-integration-details-fields.mdx'; Available since 1.26.0 -{/* Note: this warning text was taken from the the SAML v2 IdP-initiated page in the FusionAuth admin app (/admin/identity-provider/add/SAMLv2IdPInitiated)*/} +{/* Note: this warning text was taken from the SAML v2 IdP-initiated page in the FusionAuth admin app (/admin/identity-provider/add/SAMLv2IdPInitiated)*/}