Skip to content

Commit cd6387b

Browse files
committed
fix space
1 parent d5a867c commit cd6387b

File tree

1 file changed

+188
-44
lines changed

1 file changed

+188
-44
lines changed

attendabot/frontend/src/simulations/flowData.ts

Lines changed: 188 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ export const flows: AuthFlow[] = [
88
subtitle: "No identity verification at all",
99
entities: [
1010
{ id: "client", label: "Client", icon: "\uD83D\uDCBB", color: "#6c8cff" },
11-
{ id: "server", label: "Server", icon: "\uD83D\uDDA5\uFE0F", color: "#4ade80" },
11+
{
12+
id: "server",
13+
label: "Server",
14+
icon: "\uD83D\uDDA5\uFE0F",
15+
color: "#4ade80",
16+
},
1217
],
1318
steps: [
1419
{
@@ -45,11 +50,27 @@ export const flows: AuthFlow[] = [
4550
{
4651
id: "password-hashing",
4752
title: "Password Storage",
48-
subtitle: "How servers store and verify passwords without ever keeping the plaintext",
53+
subtitle:
54+
"How servers store and verify passwords without ever keeping the plaintext",
4955
entities: [
50-
{ id: "client", label: "Browser", icon: "\uD83C\uDF10", color: "#6c8cff" },
51-
{ id: "server", label: "Server", icon: "\uD83D\uDDA5\uFE0F", color: "#4ade80" },
52-
{ id: "db", label: "User Database", icon: "\uD83D\uDDC4\uFE0F", color: "#fb923c" },
56+
{
57+
id: "client",
58+
label: "Browser",
59+
icon: "\uD83C\uDF10",
60+
color: "#6c8cff",
61+
},
62+
{
63+
id: "server",
64+
label: "Server",
65+
icon: "\uD83D\uDDA5\uFE0F",
66+
color: "#4ade80",
67+
},
68+
{
69+
id: "db",
70+
label: "User Database",
71+
icon: "\uD83D\uDDC4\uFE0F",
72+
color: "#fb923c",
73+
},
5374
],
5475
steps: [
5576
{
@@ -66,7 +87,7 @@ export const flows: AuthFlow[] = [
6687
to: "server",
6788
label: "Generate salt",
6889
description:
69-
"Server generates a random string called a \"salt\" \u2014 unique to this user. The salt prevents two users with the same password from having the same stored hash, and defeats precomputed \"rainbow table\" attacks.",
90+
'Server generates a random string called a "salt" \u2014 unique to this user. The salt prevents two users with the same password from having the same stored hash, and defeats precomputed "rainbow table" attacks.',
7091
payload: `salt = randomBytes(16)\n\u2192 "a1b2c3d4e5f6..."\n\nWhy salt?\n Without it, every user with\n password "123456" would have the\n same hash \u2014 cracking one cracks\n them all.`,
7192
color: "#a78bfa",
7293
},
@@ -75,7 +96,7 @@ export const flows: AuthFlow[] = [
7596
to: "server",
7697
label: "Hash password + salt",
7798
description:
78-
"Server concatenates the password with the salt and runs it through a slow hash function (like bcrypt, scrypt, or argon2). The \"cost\" parameter controls how slow it is \u2014 slow enough to make brute-force impractical, fast enough to not annoy users.",
99+
'Server concatenates the password with the salt and runs it through a slow hash function (like bcrypt, scrypt, or argon2). The "cost" parameter controls how slow it is \u2014 slow enough to make brute-force impractical, fast enough to not annoy users.',
79100
payload: `hash = bcrypt(\n "correct-horse-battery" + "a1b2c3d4e5f6...",\n cost: 12\n)\n\n\u2192 "$2b$12$LJ3m4ks9Hx8Gk1e..."\n\nThis is a ONE-WAY function:\n hash \u2192 password is infeasible\n password \u2192 hash is easy`,
80101
color: "#a78bfa",
81102
},
@@ -138,8 +159,8 @@ export const flows: AuthFlow[] = [
138159
to: "client",
139160
label: "Login successful",
140161
description:
141-
"The hashes match! The server now knows the user provided the correct password, without ever having stored it. From here, the server creates a session (see the Server Sessions+Browser Cookies flow).",
142-
payload: `HTTP/1.1 200 OK\nSet-Cookie: session_id=s_abc123;\n HttpOnly; Secure\n\n{ "message": "Welcome back, Alice!" }\n\n\u2192 See "Server Sessions+Browser Cookies" for\n what happens next`,
162+
"The hashes match! The server now knows the user provided the correct password, without ever having stored it. From here, the server creates a session (see the Server Sessions + Browser Cookies flow).",
163+
payload: `HTTP/1.1 200 OK\nSet-Cookie: session_id=s_abc123;\n HttpOnly; Secure\n\n{ "message": "Welcome back, Alice!" }\n\n\u2192 See "Server Sessions + Browser Cookies" for\n what happens next`,
143164
color: "#4ade80",
144165
},
145166
],
@@ -164,7 +185,12 @@ export const flows: AuthFlow[] = [
164185
subtitle: "Asymmetric keys: what one key locks, only the other can unlock",
165186
entities: [
166187
{ id: "alice", label: "Alice", icon: "\uD83D\uDC69", color: "#6c8cff" },
167-
{ id: "math", label: "Crypto Engine", icon: "\uD83D\uDD10", color: "#a78bfa" },
188+
{
189+
id: "math",
190+
label: "Crypto Engine",
191+
icon: "\uD83D\uDD10",
192+
color: "#a78bfa",
193+
},
168194
{ id: "bob", label: "Bob", icon: "\uD83D\uDC68", color: "#4ade80" },
169195
],
170196
steps: [
@@ -258,21 +284,36 @@ export const flows: AuthFlow[] = [
258284
],
259285
cons: [
260286
"More complex to understand than passwords or shared secrets",
261-
"Private key loss = permanent lockout (no \"forgot password\" reset)",
287+
'Private key loss = permanent lockout (no "forgot password" reset)',
262288
"Key management is the hard part \u2014 securely storing, rotating, and backing up keys",
263289
"Computationally more expensive than symmetric encryption (often used as a hybrid: public-key to exchange a symmetric key, then symmetric for bulk data)",
264290
],
265291
},
266292

267-
// ── Server Sessions+Browser Cookies ──
293+
// ── Server Sessions + Browser Cookies ──
268294
{
269295
id: "sessions",
270-
title: "Server Sessions+Browser Cookies",
296+
title: "Server Sessions + Browser Cookies",
271297
subtitle: "Stateful: server stores session records",
272298
entities: [
273-
{ id: "client", label: "Browser", icon: "\uD83C\uDF10", color: "#6c8cff" },
274-
{ id: "server", label: "Server", icon: "\uD83D\uDDA5\uFE0F", color: "#4ade80" },
275-
{ id: "db", label: "Session Store", icon: "\uD83D\uDDC4\uFE0F", color: "#fb923c" },
299+
{
300+
id: "client",
301+
label: "Browser",
302+
icon: "\uD83C\uDF10",
303+
color: "#6c8cff",
304+
},
305+
{
306+
id: "server",
307+
label: "Server",
308+
icon: "\uD83D\uDDA5\uFE0F",
309+
color: "#4ade80",
310+
},
311+
{
312+
id: "db",
313+
label: "Session Store",
314+
icon: "\uD83D\uDDC4\uFE0F",
315+
color: "#fb923c",
316+
},
276317
],
277318
steps: [
278319
{
@@ -357,11 +398,27 @@ export const flows: AuthFlow[] = [
357398
{
358399
id: "opaque-tokens",
359400
title: "Opaque Tokens",
360-
subtitle: "Like sessions, but token in Authorization header instead of cookie",
401+
subtitle:
402+
"Like sessions, but token in Authorization header instead of cookie",
361403
entities: [
362-
{ id: "client", label: "Client App", icon: "\uD83D\uDCF1", color: "#6c8cff" },
363-
{ id: "server", label: "Server", icon: "\uD83D\uDDA5\uFE0F", color: "#4ade80" },
364-
{ id: "db", label: "Token Store", icon: "\uD83D\uDDC4\uFE0F", color: "#fb923c" },
404+
{
405+
id: "client",
406+
label: "Client App",
407+
icon: "\uD83D\uDCF1",
408+
color: "#6c8cff",
409+
},
410+
{
411+
id: "server",
412+
label: "Server",
413+
icon: "\uD83D\uDDA5\uFE0F",
414+
color: "#4ade80",
415+
},
416+
{
417+
id: "db",
418+
label: "Token Store",
419+
icon: "\uD83D\uDDC4\uFE0F",
420+
color: "#fb923c",
421+
},
365422
],
366423
steps: [
367424
{
@@ -445,11 +502,27 @@ export const flows: AuthFlow[] = [
445502
{
446503
id: "api-keys",
447504
title: "API Key Authentication",
448-
subtitle: "Long-lived keys that identify an application or developer, not a user session",
505+
subtitle:
506+
"Long-lived keys that identify an application or developer, not a user session",
449507
entities: [
450-
{ id: "developer", label: "Developer", icon: "\uD83D\uDC69\u200D\uD83D\uDCBB", color: "#6c8cff" },
451-
{ id: "service", label: "API Service", icon: "\uD83D\uDD10", color: "#a78bfa" },
452-
{ id: "db", label: "Key Store", icon: "\uD83D\uDDC4\uFE0F", color: "#fb923c" },
508+
{
509+
id: "developer",
510+
label: "Developer",
511+
icon: "\uD83D\uDC69\u200D\uD83D\uDCBB",
512+
color: "#6c8cff",
513+
},
514+
{
515+
id: "service",
516+
label: "API Service",
517+
icon: "\uD83D\uDD10",
518+
color: "#a78bfa",
519+
},
520+
{
521+
id: "db",
522+
label: "Key Store",
523+
icon: "\uD83D\uDDC4\uFE0F",
524+
color: "#fb923c",
525+
},
453526
],
454527
steps: [
455528
{
@@ -538,7 +611,12 @@ export const flows: AuthFlow[] = [
538611
subtitle: "Stateless: the token IS the session",
539612
entities: [
540613
{ id: "client", label: "Client", icon: "\uD83D\uDCBB", color: "#6c8cff" },
541-
{ id: "server", label: "Server", icon: "\uD83D\uDDA5\uFE0F", color: "#4ade80" },
614+
{
615+
id: "server",
616+
label: "Server",
617+
icon: "\uD83D\uDDA5\uFE0F",
618+
color: "#4ade80",
619+
},
542620
],
543621
steps: [
544622
{
@@ -554,7 +632,7 @@ export const flows: AuthFlow[] = [
554632
to: "server",
555633
label: "Create & sign JWT",
556634
description:
557-
"Server constructs a payload (\"claims\") and cryptographically signs it. The result is three base64-encoded parts: header.payload.signature. This is NOT encryption \u2014 anyone can read the payload. The signature just proves it hasn\u2019t been tampered with.",
635+
'Server constructs a payload ("claims") and cryptographically signs it. The result is three base64-encoded parts: header.payload.signature. This is NOT encryption \u2014 anyone can read the payload. The signature just proves it hasn\u2019t been tampered with.',
558636
payload: `HEADER: { "alg": "HS256", "typ": "JWT" }\n\nPAYLOAD: { "sub": 42, "name": "alice",\n "role": "user", "iat": 1705312000,\n "exp": 1705398400 }\n\nSIGNATURE: HMAC-SHA256(\n base64(header) + "." + base64(payload),\n SECRET_KEY\n)`,
559637
color: "#a78bfa",
560638
},
@@ -571,7 +649,8 @@ export const flows: AuthFlow[] = [
571649
from: "client",
572650
to: "server",
573651
label: "Authorization: Bearer eyJ...",
574-
description: "Client sends the JWT in the Authorization header on subsequent requests.",
652+
description:
653+
"Client sends the JWT in the Authorization header on subsequent requests.",
575654
payload: `GET /api/profile HTTP/1.1\nAuthorization: Bearer eyJhbGciOiJIUz...`,
576655
color: "#6c8cff",
577656
},
@@ -580,7 +659,7 @@ export const flows: AuthFlow[] = [
580659
to: "server",
581660
label: "Verify signature",
582661
description:
583-
"Server recomputes the signature from the header+payload using its secret key and checks if it matches. NO database lookup needed! This is what makes JWT \"stateless.\"",
662+
'Server recomputes the signature from the header+payload using its secret key and checks if it matches. NO database lookup needed! This is what makes JWT "stateless."',
584663
payload: `expected = HMAC-SHA256(\n receivedHeader + "." + receivedPayload,\n SECRET_KEY\n)\n\nreceived === expected \u2192 \u2705 VALID\n\nAlso check: exp > now() \u2192 \u2705 NOT EXPIRED`,
585664
color: "#a78bfa",
586665
},
@@ -614,9 +693,24 @@ export const flows: AuthFlow[] = [
614693
title: "OAuth 2.0 + OIDC",
615694
subtitle: "Delegated auth via a third-party identity provider",
616695
entities: [
617-
{ id: "client", label: "Browser", icon: "\uD83C\uDF10", color: "#6c8cff" },
618-
{ id: "app", label: "Your Server", icon: "\uD83D\uDDA5\uFE0F", color: "#4ade80" },
619-
{ id: "provider", label: "Auth Provider\n(e.g. Google)", icon: "\uD83D\uDD10", color: "#a78bfa" },
696+
{
697+
id: "client",
698+
label: "Browser",
699+
icon: "\uD83C\uDF10",
700+
color: "#6c8cff",
701+
},
702+
{
703+
id: "app",
704+
label: "Your Server",
705+
icon: "\uD83D\uDDA5\uFE0F",
706+
color: "#4ade80",
707+
},
708+
{
709+
id: "provider",
710+
label: "Auth Provider\n(e.g. Google)",
711+
icon: "\uD83D\uDD10",
712+
color: "#a78bfa",
713+
},
620714
],
621715
steps: [
622716
{
@@ -721,18 +815,38 @@ export const flows: AuthFlow[] = [
721815
title: "Magic Links",
722816
subtitle: "Passwordless login via a one-time link sent to your email",
723817
entities: [
724-
{ id: "client", label: "Browser", icon: "\uD83C\uDF10", color: "#6c8cff" },
725-
{ id: "server", label: "Server", icon: "\uD83D\uDDA5\uFE0F", color: "#4ade80" },
726-
{ id: "db", label: "Token Store", icon: "\uD83D\uDDC4\uFE0F", color: "#fb923c" },
727-
{ id: "email", label: "Email Inbox", icon: "\uD83D\uDCE7", color: "#f472b6" },
818+
{
819+
id: "client",
820+
label: "Browser",
821+
icon: "\uD83C\uDF10",
822+
color: "#6c8cff",
823+
},
824+
{
825+
id: "server",
826+
label: "Server",
827+
icon: "\uD83D\uDDA5\uFE0F",
828+
color: "#4ade80",
829+
},
830+
{
831+
id: "db",
832+
label: "Token Store",
833+
icon: "\uD83D\uDDC4\uFE0F",
834+
color: "#fb923c",
835+
},
836+
{
837+
id: "email",
838+
label: "Email Inbox",
839+
icon: "\uD83D\uDCE7",
840+
color: "#f472b6",
841+
},
728842
],
729843
steps: [
730844
{
731845
from: "client",
732846
to: "server",
733847
label: "Enter email address",
734848
description:
735-
"User enters only their email address \u2014 no password field at all. This is the entire \"login form.\"",
849+
'User enters only their email address \u2014 no password field at all. This is the entire "login form."',
736850
payload: `POST /auth/magic-link\n\n{ "email": "alice@gmail.com" }`,
737851
color: "#6c8cff",
738852
},
@@ -757,7 +871,7 @@ export const flows: AuthFlow[] = [
757871
{
758872
from: "server",
759873
to: "client",
760-
label: "\"Check your email\"",
874+
label: '"Check your email"',
761875
description:
762876
"Server tells the user to go check their email. The user must now leave your app and open their email client \u2014 this is the main friction point.",
763877
payload: `HTTP/1.1 200 OK\n\n{ "message": "Check your email!\n We sent a login link to\n alice@gmail.com" }`,
@@ -821,9 +935,24 @@ export const flows: AuthFlow[] = [
821935
title: "One-Time Passwords (OTP)",
822936
subtitle: "Short-lived codes via SMS, email, or authenticator app",
823937
entities: [
824-
{ id: "client", label: "Browser", icon: "\uD83C\uDF10", color: "#6c8cff" },
825-
{ id: "server", label: "Server", icon: "\uD83D\uDDA5\uFE0F", color: "#4ade80" },
826-
{ id: "device", label: "Phone / Auth App", icon: "\uD83D\uDCF1", color: "#f472b6" },
938+
{
939+
id: "client",
940+
label: "Browser",
941+
icon: "\uD83C\uDF10",
942+
color: "#6c8cff",
943+
},
944+
{
945+
id: "server",
946+
label: "Server",
947+
icon: "\uD83D\uDDA5\uFE0F",
948+
color: "#4ade80",
949+
},
950+
{
951+
id: "device",
952+
label: "Phone / Auth App",
953+
icon: "\uD83D\uDCF1",
954+
color: "#f472b6",
955+
},
827956
],
828957
steps: [
829958
{
@@ -910,9 +1039,24 @@ export const flows: AuthFlow[] = [
9101039
title: "Passkeys / WebAuthn",
9111040
subtitle: "Public-key cryptography \u2014 phishing-resistant, passwordless",
9121041
entities: [
913-
{ id: "client", label: "Browser", icon: "\uD83C\uDF10", color: "#6c8cff" },
914-
{ id: "device", label: "Device\n(Biometrics)", icon: "\uD83D\uDD11", color: "#f472b6" },
915-
{ id: "server", label: "Server", icon: "\uD83D\uDDA5\uFE0F", color: "#4ade80" },
1042+
{
1043+
id: "client",
1044+
label: "Browser",
1045+
icon: "\uD83C\uDF10",
1046+
color: "#6c8cff",
1047+
},
1048+
{
1049+
id: "device",
1050+
label: "Device\n(Biometrics)",
1051+
icon: "\uD83D\uDD11",
1052+
color: "#f472b6",
1053+
},
1054+
{
1055+
id: "server",
1056+
label: "Server",
1057+
icon: "\uD83D\uDDA5\uFE0F",
1058+
color: "#4ade80",
1059+
},
9161060
],
9171061
steps: [
9181062
{
@@ -1031,7 +1175,7 @@ export const flows: AuthFlow[] = [
10311175
"Backed by FIDO Alliance + Apple, Google, Microsoft \u2014 credentials sync across devices",
10321176
],
10331177
cons: [
1034-
"Relatively new \u2014 user education is still a hurdle (\"where did my password go?\")",
1178+
'Relatively new \u2014 user education is still a hurdle ("where did my password go?")',
10351179
"Account recovery is harder if you lose all devices without sync set up",
10361180
"Cross-platform sync is improving but still inconsistent across ecosystems",
10371181
"Requires browser and OS support (widespread now, but not universal)",

0 commit comments

Comments
 (0)