@chill-sharp/ui-core 1.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/.agents/skills/chillsharp-current-user-preferences/SKILL.md +70 -0
  2. package/.agents/skills/chillsharp-ui-template/SKILL.md +18 -0
  3. package/README.md +103 -0
  4. package/chill-sharp-ui-core.d.ts.map +1 -0
  5. package/doc/AIAssistedDevelopment/README.md +185 -0
  6. package/doc/AttachmentModel/README.md +173 -0
  7. package/doc/AuthenticationModel/README.md +213 -0
  8. package/doc/AuthenticationModel/how-to-integreate-auth-minimal-api.md +293 -0
  9. package/doc/ChillSharpClient.md +464 -0
  10. package/doc/ClientGeneration/README.md +172 -0
  11. package/doc/ComplianceGuide/README.md +178 -0
  12. package/doc/Configuration/README.md +94 -0
  13. package/doc/CurrentUserPreferences.md +114 -0
  14. package/doc/DateTimePolicy/README.md +154 -0
  15. package/doc/DateTimeSerialization.md +423 -0
  16. package/doc/Endpoints.md +260 -0
  17. package/doc/HowTo/01-simple-blog-sqlite.md +153 -0
  18. package/doc/HowTo/02-blog-schema-labels.md +140 -0
  19. package/doc/HowTo/03-authentication.md +218 -0
  20. package/doc/HowTo/04-blog-posts-one-to-many.md +194 -0
  21. package/doc/HowTo/05-docker-env-variables.md +274 -0
  22. package/doc/HowTo/06-chunk-transactions-autocomplete.md +196 -0
  23. package/doc/Mcp/ChatGPT.md +291 -0
  24. package/doc/Mcp/README.md +799 -0
  25. package/doc/MenuGuide/README.md +49 -0
  26. package/doc/ModelPreparation.md +255 -0
  27. package/doc/PermissionModel/README.md +277 -0
  28. package/doc/README.md +228 -0
  29. package/doc/ReferenceExistence.md +130 -0
  30. package/doc/RegisterContext.md +217 -0
  31. package/doc/UiCore/CRUD.md +170 -0
  32. package/doc/UiCore/README.md +13 -0
  33. package/doc/ValidationModel/README.md +117 -0
  34. package/doc/it/AIAssistedDevelopment/README.md +185 -0
  35. package/doc/it/AttachmentModel/README.md +173 -0
  36. package/doc/it/AuthenticationModel/README.md +171 -0
  37. package/doc/it/AuthenticationModel/how-to-integreate-auth-minimal-api.md +292 -0
  38. package/doc/it/ChillSharpClient.md +464 -0
  39. package/doc/it/ClientGeneration/README.md +152 -0
  40. package/doc/it/ComplianceGuide/README.md +178 -0
  41. package/doc/it/Configuration/README.md +94 -0
  42. package/doc/it/CurrentUserPreferences.md +114 -0
  43. package/doc/it/DateTimePolicy/README.md +154 -0
  44. package/doc/it/DateTimeSerialization.md +423 -0
  45. package/doc/it/Endpoints.md +260 -0
  46. package/doc/it/HowTo/01-simple-blog-sqlite.md +152 -0
  47. package/doc/it/HowTo/02-blog-schema-labels.md +139 -0
  48. package/doc/it/HowTo/03-authentication.md +221 -0
  49. package/doc/it/HowTo/04-blog-posts-one-to-many.md +193 -0
  50. package/doc/it/HowTo/05-docker-env-variables.md +268 -0
  51. package/doc/it/HowTo/06-chunk-transactions-autocomplete.md +196 -0
  52. package/doc/it/Mcp/ChatGPT.md +291 -0
  53. package/doc/it/Mcp/README.md +799 -0
  54. package/doc/it/MenuGuide/README.md +49 -0
  55. package/doc/it/ModelPreparation.md +254 -0
  56. package/doc/it/PermissionModel/README.md +190 -0
  57. package/doc/it/README.md +172 -0
  58. package/doc/it/ReferenceExistence.md +130 -0
  59. package/doc/it/RegisterContext.md +218 -0
  60. package/doc/it/UiCore/CRUD.md +170 -0
  61. package/doc/it/UiCore/README.md +13 -0
  62. package/doc/it/ValidationModel/README.md +117 -0
  63. package/fesm2022/chill-sharp-ui-core.mjs +16725 -0
  64. package/fesm2022/chill-sharp-ui-core.mjs.map +1 -0
  65. package/index.d.ts +6 -0
  66. package/lib/chill-sharp-ui-root.component.d.ts +6 -0
  67. package/lib/chill-sharp-ui-root.component.d.ts.map +1 -0
  68. package/lib/chill-sharp-ui.routes.d.ts +3 -0
  69. package/lib/chill-sharp-ui.routes.d.ts.map +1 -0
  70. package/lib/chill.config.d.ts +5 -0
  71. package/lib/chill.config.d.ts.map +1 -0
  72. package/lib/layouts/auth-shell.component.d.ts +8 -0
  73. package/lib/layouts/auth-shell.component.d.ts.map +1 -0
  74. package/lib/layouts/workspace-page.component.d.ts +49 -0
  75. package/lib/layouts/workspace-page.component.d.ts.map +1 -0
  76. package/lib/lib/chill-form.component.d.ts +151 -0
  77. package/lib/lib/chill-form.component.d.ts.map +1 -0
  78. package/lib/lib/chill-i18n-button-label.component.d.ts +27 -0
  79. package/lib/lib/chill-i18n-button-label.component.d.ts.map +1 -0
  80. package/lib/lib/chill-i18n-label.component.d.ts +30 -0
  81. package/lib/lib/chill-i18n-label.component.d.ts.map +1 -0
  82. package/lib/lib/chill-json-input.component.d.ts +31 -0
  83. package/lib/lib/chill-json-input.component.d.ts.map +1 -0
  84. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts +12 -0
  85. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts.map +1 -0
  86. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts +17 -0
  87. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts.map +1 -0
  88. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts +45 -0
  89. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts.map +1 -0
  90. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts +19 -0
  91. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts.map +1 -0
  92. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts +12 -0
  93. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts.map +1 -0
  94. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts +13 -0
  95. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts.map +1 -0
  96. package/lib/lib/chill-polymorphic-input.component.d.ts +452 -0
  97. package/lib/lib/chill-polymorphic-input.component.d.ts.map +1 -0
  98. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts +7 -0
  99. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts.map +1 -0
  100. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts +7 -0
  101. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts.map +1 -0
  102. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts +7 -0
  103. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts.map +1 -0
  104. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts +8 -0
  105. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts.map +1 -0
  106. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts +7 -0
  107. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts.map +1 -0
  108. package/lib/lib/chill-polymorphic-output.component.d.ts +75 -0
  109. package/lib/lib/chill-polymorphic-output.component.d.ts.map +1 -0
  110. package/lib/lib/chill-table.component.d.ts +434 -0
  111. package/lib/lib/chill-table.component.d.ts.map +1 -0
  112. package/lib/lib/chill-text-editor-dialog.component.d.ts +14 -0
  113. package/lib/lib/chill-text-editor-dialog.component.d.ts.map +1 -0
  114. package/lib/lib/crud-configuration.utils.d.ts +4 -0
  115. package/lib/lib/crud-configuration.utils.d.ts.map +1 -0
  116. package/lib/lib/culture-name-options.d.ts +3 -0
  117. package/lib/lib/culture-name-options.d.ts.map +1 -0
  118. package/lib/lib/date-format-options.d.ts +3 -0
  119. package/lib/lib/date-format-options.d.ts.map +1 -0
  120. package/lib/lib/iana-time-zone-options.d.ts +3 -0
  121. package/lib/lib/iana-time-zone-options.d.ts.map +1 -0
  122. package/lib/lib/notice-transition.directive.d.ts +17 -0
  123. package/lib/lib/notice-transition.directive.d.ts.map +1 -0
  124. package/lib/lib/schema-property-dialog.component.d.ts +74 -0
  125. package/lib/lib/schema-property-dialog.component.d.ts.map +1 -0
  126. package/lib/models/chill-auth.models.d.ts +176 -0
  127. package/lib/models/chill-auth.models.d.ts.map +1 -0
  128. package/lib/models/chill-menu.models.d.ts +12 -0
  129. package/lib/models/chill-menu.models.d.ts.map +1 -0
  130. package/lib/models/chill-schema.models.d.ts +141 -0
  131. package/lib/models/chill-schema.models.d.ts.map +1 -0
  132. package/lib/models/workspace-dialog.models.d.ts +16 -0
  133. package/lib/models/workspace-dialog.models.d.ts.map +1 -0
  134. package/lib/models/workspace-task.models.d.ts +36 -0
  135. package/lib/models/workspace-task.models.d.ts.map +1 -0
  136. package/lib/pages/confirm-reset-page.component.d.ts +21 -0
  137. package/lib/pages/confirm-reset-page.component.d.ts.map +1 -0
  138. package/lib/pages/crud/attachment-upload-dialog.component.d.ts +24 -0
  139. package/lib/pages/crud/attachment-upload-dialog.component.d.ts.map +1 -0
  140. package/lib/pages/crud/crud-page.component.d.ts +244 -0
  141. package/lib/pages/crud/crud-page.component.d.ts.map +1 -0
  142. package/lib/pages/login-page.component.d.ts +21 -0
  143. package/lib/pages/login-page.component.d.ts.map +1 -0
  144. package/lib/pages/permissions/auth-role-dialog.component.d.ts +29 -0
  145. package/lib/pages/permissions/auth-role-dialog.component.d.ts.map +1 -0
  146. package/lib/pages/permissions/auth-search-select.component.d.ts +28 -0
  147. package/lib/pages/permissions/auth-search-select.component.d.ts.map +1 -0
  148. package/lib/pages/permissions/auth-user-dialog.component.d.ts +35 -0
  149. package/lib/pages/permissions/auth-user-dialog.component.d.ts.map +1 -0
  150. package/lib/pages/permissions/permission-editor.component.d.ts +55 -0
  151. package/lib/pages/permissions/permission-editor.component.d.ts.map +1 -0
  152. package/lib/pages/permissions/permissions-page.component.d.ts +38 -0
  153. package/lib/pages/permissions/permissions-page.component.d.ts.map +1 -0
  154. package/lib/pages/permissions/role-permission.component.d.ts +43 -0
  155. package/lib/pages/permissions/role-permission.component.d.ts.map +1 -0
  156. package/lib/pages/permissions/user-permission.component.d.ts +43 -0
  157. package/lib/pages/permissions/user-permission.component.d.ts.map +1 -0
  158. package/lib/pages/register-page.component.d.ts +24 -0
  159. package/lib/pages/register-page.component.d.ts.map +1 -0
  160. package/lib/pages/reset-password-page.component.d.ts +18 -0
  161. package/lib/pages/reset-password-page.component.d.ts.map +1 -0
  162. package/lib/provide-chill-sharp-ui-core.d.ts +8 -0
  163. package/lib/provide-chill-sharp-ui-core.d.ts.map +1 -0
  164. package/lib/services/chill.service.d.ts +249 -0
  165. package/lib/services/chill.service.d.ts.map +1 -0
  166. package/lib/services/workspace-dialog.service.d.ts +22 -0
  167. package/lib/services/workspace-dialog.service.d.ts.map +1 -0
  168. package/lib/services/workspace-layout.service.d.ts +13 -0
  169. package/lib/services/workspace-layout.service.d.ts.map +1 -0
  170. package/lib/services/workspace-task-registry.service.d.ts +35 -0
  171. package/lib/services/workspace-task-registry.service.d.ts.map +1 -0
  172. package/lib/services/workspace-toolbar.service.d.ts +23 -0
  173. package/lib/services/workspace-toolbar.service.d.ts.map +1 -0
  174. package/lib/services/workspace.service.d.ts +114 -0
  175. package/lib/services/workspace.service.d.ts.map +1 -0
  176. package/lib/storage-keys.d.ts +5 -0
  177. package/lib/storage-keys.d.ts.map +1 -0
  178. package/lib/tasks/crud-task/crud-task.component.d.ts +33 -0
  179. package/lib/tasks/crud-task/crud-task.component.d.ts.map +1 -0
  180. package/lib/tasks/goto-url-task/goto-url-task.component.d.ts +31 -0
  181. package/lib/tasks/goto-url-task/goto-url-task.component.d.ts.map +1 -0
  182. package/lib/workspace/confirm-message-dialog.component.d.ts +16 -0
  183. package/lib/workspace/confirm-message-dialog.component.d.ts.map +1 -0
  184. package/lib/workspace/entity-options-dialog.component.d.ts +29 -0
  185. package/lib/workspace/entity-options-dialog.component.d.ts.map +1 -0
  186. package/lib/workspace/external-task-api.d.ts +2 -0
  187. package/lib/workspace/external-task-api.d.ts.map +1 -0
  188. package/lib/workspace/user-profile-dialog.component.d.ts +30 -0
  189. package/lib/workspace/user-profile-dialog.component.d.ts.map +1 -0
  190. package/lib/workspace/workspace-dialog-host.component.d.ts +26 -0
  191. package/lib/workspace/workspace-dialog-host.component.d.ts.map +1 -0
  192. package/lib/workspace/workspace-menu-item-dialog.component.d.ts +61 -0
  193. package/lib/workspace/workspace-menu-item-dialog.component.d.ts.map +1 -0
  194. package/lib/workspace/workspace-menu.component.d.ts +104 -0
  195. package/lib/workspace/workspace-menu.component.d.ts.map +1 -0
  196. package/lib/workspace/workspace-taskbar.component.d.ts +14 -0
  197. package/lib/workspace/workspace-taskbar.component.d.ts.map +1 -0
  198. package/package.json +54 -0
  199. package/public-api.d.ts +56 -0
  200. package/public-api.d.ts.map +1 -0
  201. package/service-worker/chill-sharp-service-worker.js +166 -0
  202. package/styles/core-theme.scss +1268 -0
  203. package/template-customization/upgrade.ps1.template +342 -0
  204. package/template-customization/upgrade.sh.template +271 -0
@@ -0,0 +1,213 @@
1
+ # ChillSharp Authentication And Authorization
2
+
3
+ Versione italiana: [Italiano](../it/AuthenticationModel/README.md)
4
+
5
+ This document covers the auth module at a reference level. For a guided setup, keep using [doc/HowTo/03-authentication.md](../HowTo/03-authentication.md).
6
+
7
+ ## Module Split
8
+
9
+ `ChillSharp.Auth` exposes two related but distinct concerns:
10
+
11
+ - account authentication
12
+ ASP.NET Core Identity-backed register, login, refresh, password-change, and password-reset flows
13
+
14
+ - authorization management
15
+ auth users, roles, role assignments, permission rules, and permission evaluation
16
+
17
+ ## Account Endpoints
18
+
19
+ Registered through:
20
+
21
+ ```csharp
22
+ builder.Services.AddChillAuthIdentityApi<AppDbContext, IdentityUser>();
23
+ ```
24
+
25
+ Typical routes:
26
+
27
+ - `/api/chill-auth/account/register`
28
+ - `/api/chill-auth/account/login`
29
+ - `/api/chill-auth/account/refresh`
30
+ - `/api/chill-auth/account/change-password`
31
+ - `/api/chill-auth/account/request-password-reset`
32
+ - `/api/chill-auth/account/reset-password`
33
+
34
+ These are the routes used internally by `ChillSharpClient`.
35
+
36
+ `RegisterAuthIdentityRequest` also supports:
37
+
38
+ - `DisplayName`
39
+ - `DisplayCultureName`
40
+ - `CreateChillAuthUser`
41
+
42
+ When `CreateChillAuthUser` is enabled and `DisplayCultureName` is provided, the linked `AuthUser` is automatically preset with:
43
+
44
+ - `DisplayCultureName`
45
+ - `DisplayTimeZone`
46
+ - `DisplayDateFormat`
47
+ - `DisplayNumberFormat`
48
+
49
+ The server resolves those defaults from the selected culture by using a best-effort time-zone mapping plus the culture date and number separators.
50
+
51
+ ## Authorization Management Endpoints
52
+
53
+ Registered through:
54
+
55
+ ```csharp
56
+ builder.Services.AddChillAuthApi<AppDbContext>();
57
+ ```
58
+
59
+ Typical route groups:
60
+
61
+ - `/api/chill-auth/users`
62
+ - `/api/chill-auth/roles`
63
+ - `/api/chill-auth/permissions`
64
+
65
+ These endpoints manage:
66
+
67
+ - `AuthUser`
68
+ - `AuthRole`
69
+ - `AuthUserRole`
70
+ - `AuthPermissionRule`
71
+ - permission evaluation results
72
+
73
+ `AuthUser` now also carries optional UI display preferences:
74
+
75
+ - `DisplayCultureName`
76
+ - `DisplayTimeZone`
77
+ - `DisplayDateFormat`
78
+ - `DisplayNumberFormat`
79
+
80
+ `AuthUser` and `AuthRole` also carry:
81
+
82
+ - `MenuHierarchy`
83
+
84
+ `MenuHierarchy` is used by the schema menu endpoints to filter which menu nodes are visible to the current user.
85
+
86
+ - values can be single codes or comma-separated lists
87
+ - user and active role values are merged before filtering
88
+ - `*` means full menu access
89
+ - any other value works as a prefix match, for example `SECTION-A` allows nodes whose menu hierarchy starts with `SECTION-A`
90
+ - an empty merged menu hierarchy set means no menu access
91
+
92
+ For the full menu-tree model and endpoint behavior, see [MenuGuide/README.md](../MenuGuide/README.md).
93
+
94
+ ## Token Lifetimes
95
+
96
+ ChillSharp auth account endpoints issue protected bearer access tokens and refresh tokens. These access tokens are not JWTs, but they are used in the same `Authorization: Bearer ...` header shape.
97
+
98
+ Default lifetimes:
99
+
100
+ - access token: 20 minutes
101
+ - refresh token: 14 days
102
+
103
+ Built-in environment variables:
104
+
105
+ - `CHILLSHARP_AUTH_ACCESS_TOKEN_MINUTES`
106
+ Positive integer number of minutes before an access token expires.
107
+ - `CHILLSHARP_AUTH_REFRESH_TOKEN_DAYS`
108
+ Positive integer number of days before a refresh token expires.
109
+
110
+ These variables are read by `ChillAuthIdentityApiOptions` and `ChillIdentityApiOptions` when the options object is created. Explicit code configuration still wins:
111
+
112
+ ```csharp
113
+ builder.Services.AddChillAuthIdentityApi<AppDbContext, IdentityUser>(options =>
114
+ {
115
+ options.AccessTokenLifetime = TimeSpan.FromMinutes(30);
116
+ options.RefreshTokenLifetime = TimeSpan.FromDays(7);
117
+ });
118
+ ```
119
+
120
+ ## Context Requirements
121
+
122
+ The host context must:
123
+
124
+ - implement `IChillAuthDbContext`
125
+ - include `modelBuilder.AddChillAuthModel()`
126
+
127
+ For Identity-backed accounts, the context must also be a valid EF store for ASP.NET Core Identity, typically:
128
+
129
+ ```csharp
130
+ public class AppDbContext : IdentityDbContext<IdentityUser>, IChillContext, IChillAuthDbContext
131
+ {
132
+ }
133
+ ```
134
+
135
+ ## Root User Bootstrap
136
+
137
+ `AddChillAuthIdentityApi(...)` can bootstrap a root account on startup.
138
+
139
+ Supported configuration:
140
+
141
+ - direct options in code
142
+ - environment variables
143
+
144
+ Default environment variables:
145
+
146
+ - `CHILLSHARP_AUTH_ROOT_USERNAME`
147
+ - `CHILLSHARP_AUTH_ROOT_PASSWORD`
148
+ - `CHILLSHARP_AUTH_ROOT_EMAIL`
149
+ - `CHILLSHARP_AUTH_ROOT_DISPLAY_NAME`
150
+
151
+ When enabled, the bootstrap flow can also create the linked ChillSharp `AuthUser` with permission-management access.
152
+
153
+ ## Permission Management Access
154
+
155
+ Being authenticated is not enough to manage the auth module.
156
+
157
+ Auth-management endpoints require a ChillSharp auth user with permission-management rights, typically:
158
+
159
+ - `CanManagePermissions = true`
160
+
161
+ This is the critical bootstrap problem for a clean database:
162
+
163
+ - the first registered Identity user may exist
164
+ - the linked `AuthUser` may exist
165
+ - but no one may yet have rights to manage roles and permissions
166
+
167
+ That is why root-user bootstrap or another trusted setup path matters.
168
+
169
+ ## Client Usage
170
+
171
+ Use the normal Chill base URL:
172
+
173
+ ```csharp
174
+ var client = new ChillSharpClient("http://localhost:5000/api/chill");
175
+ ```
176
+
177
+ `ChillSharpClient` automatically switches to `/api/chill-auth/...` for auth methods.
178
+
179
+ Examples:
180
+
181
+ - `RegisterAuthAccount`
182
+ - `LoginAuthAccount`
183
+ - `RefreshAuthAccount`
184
+ - `ChangeAuthPassword`
185
+ - `CreateAuthRole`
186
+ - `CreateAuthPermissionRule`
187
+ - `EvaluateAuthEntityPermission`
188
+
189
+ User list and user detail payloads also expose:
190
+
191
+ - `DisplayCultureName`
192
+ - `DisplayTimeZone`
193
+ - `DisplayDateFormat`
194
+ - `DisplayNumberFormat`
195
+
196
+ ## Token Handling
197
+
198
+ `ChillSharpClient` stores:
199
+
200
+ - access token
201
+ - refresh token
202
+
203
+ If a refresh token is present, the client can renew the access token automatically during later authenticated calls.
204
+
205
+ ## Relationship With The Permission Model
206
+
207
+ The exact permission-resolution rules are documented separately in:
208
+
209
+ - [PermissionModel/README.md](../PermissionModel/README.md)
210
+
211
+ Use that document for the precedence and scope model. Use this one for registration and runtime auth flow.
212
+
213
+
@@ -0,0 +1,293 @@
1
+ Versione italiana: [Italiano](../it/AuthenticationModel/how-to-integreate-auth-minimal-api.md)
2
+
3
+ Sure. Here’s the updated, correct, modern version of the setup using **Microsoft.IdentityModel.JsonWebTokens**, because Microsoft decided the old JWT library needed to be “legacy” for fun.
4
+
5
+ This is the clean way to do:
6
+
7
+ ✅ Identity user store
8
+ ✅ Minimal API login/register
9
+ ✅ JWT Bearer tokens
10
+ ✅ No cookies
11
+ ✅ No UI
12
+ ✅ No outdated JwtSecurityTokenHandler
13
+
14
+ ---
15
+
16
+ # ✅ ASP.NET Core Minimal Identity API + JWT (Modern JsonWebTokenHandler)
17
+
18
+ ---
19
+
20
+ # ✅ 1. Install Packages
21
+
22
+ Run:
23
+
24
+ ```bash
25
+ dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
26
+ dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
27
+ dotnet add package Microsoft.EntityFrameworkCore.SqlServer
28
+ dotnet add package Microsoft.IdentityModel.JsonWebTokens
29
+ ```
30
+
31
+ No `System.IdentityModel.Tokens.Jwt`. We are enlightened now.
32
+
33
+ ---
34
+
35
+ # ✅ 2. Create Identity DbContext
36
+
37
+ ```csharp
38
+ using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
39
+ using Microsoft.EntityFrameworkCore;
40
+
41
+ public class AppDbContext : IdentityDbContext
42
+ {
43
+ public AppDbContext(DbContextOptions<AppDbContext> options)
44
+ : base(options) { }
45
+ }
46
+ ```
47
+
48
+ ---
49
+
50
+ # ✅ 3. Configure Database + IdentityCore
51
+
52
+ In `Program.cs`:
53
+
54
+ ```csharp
55
+ builder.Services.AddDbContext<AppDbContext>(options =>
56
+ options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));
57
+ ```
58
+
59
+ Now add Identity:
60
+
61
+ ```csharp
62
+ builder.Services.AddIdentityCore<IdentityUser>()
63
+ .AddEntityFrameworkStores<AppDbContext>()
64
+ .AddDefaultTokenProviders();
65
+ ```
66
+
67
+ ✅ No UI
68
+ ✅ No Razor
69
+ ✅ No cookie circus
70
+
71
+ ---
72
+
73
+ # ✅ 4. Configure JWT Authentication (Bearer)
74
+
75
+ Add imports:
76
+
77
+ ```csharp
78
+ using Microsoft.AspNetCore.Authentication.JwtBearer;
79
+ using Microsoft.IdentityModel.Tokens;
80
+ using System.Text;
81
+ ```
82
+
83
+ Then:
84
+
85
+ ```csharp
86
+ var jwtKey = builder.Configuration["Jwt:Key"]!;
87
+ var jwtIssuer = builder.Configuration["Jwt:Issuer"]!;
88
+ ```
89
+
90
+ Now configure:
91
+
92
+ ```csharp
93
+ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
94
+ .AddJwtBearer(options =>
95
+ {
96
+ options.TokenValidationParameters = new TokenValidationParameters
97
+ {
98
+ ValidateIssuer = true,
99
+ ValidIssuer = jwtIssuer,
100
+
101
+ ValidateAudience = false,
102
+
103
+ ValidateIssuerSigningKey = true,
104
+ IssuerSigningKey = new SymmetricSecurityKey(
105
+ Encoding.UTF8.GetBytes(jwtKey)),
106
+
107
+ ValidateLifetime = true
108
+ };
109
+ });
110
+ ```
111
+
112
+ ---
113
+
114
+ # ✅ 5. Enable Authorization
115
+
116
+ ```csharp
117
+ builder.Services.AddAuthorization();
118
+ ```
119
+
120
+ ---
121
+
122
+ # ✅ 6. Add Middleware
123
+
124
+ After `var app = builder.Build();`
125
+
126
+ ```csharp
127
+ app.UseAuthentication();
128
+ app.UseAuthorization();
129
+ ```
130
+
131
+ If you skip this, nothing works and you’ll blame yourself, incorrectly.
132
+
133
+ ---
134
+
135
+ # ✅ 7. Generate JWT Token (Modern JsonWebTokenHandler)
136
+
137
+ Add imports:
138
+
139
+ ```csharp
140
+ using Microsoft.IdentityModel.JsonWebTokens;
141
+ using System.Security.Claims;
142
+ ```
143
+
144
+ Now define:
145
+
146
+ ```csharp
147
+ string GenerateJwtToken(IdentityUser user)
148
+ {
149
+ var claims = new List<Claim>
150
+ {
151
+ new Claim(JwtRegisteredClaimNames.Sub, user.Id),
152
+ new Claim(JwtRegisteredClaimNames.Email, user.Email!)
153
+ };
154
+
155
+ var key = new SymmetricSecurityKey(
156
+ Encoding.UTF8.GetBytes(jwtKey));
157
+
158
+ var creds = new SigningCredentials(
159
+ key,
160
+ SecurityAlgorithms.HmacSha256);
161
+
162
+ var tokenDescriptor = new SecurityTokenDescriptor
163
+ {
164
+ Subject = new ClaimsIdentity(claims),
165
+ Expires = DateTime.UtcNow.AddHours(2),
166
+ Issuer = jwtIssuer,
167
+ SigningCredentials = creds
168
+ };
169
+
170
+ var handler = new JsonWebTokenHandler();
171
+
172
+ return handler.CreateToken(tokenDescriptor);
173
+ }
174
+ ```
175
+
176
+ ✅ This is the replacement for the old JwtSecurityTokenHandler.
177
+
178
+ ---
179
+
180
+ # ✅ 8. Register Endpoint (Minimal API)
181
+
182
+ ```csharp
183
+ app.MapPost("/register", async (
184
+ UserManager<IdentityUser> userManager,
185
+ RegisterRequest request) =>
186
+ {
187
+ var user = new IdentityUser
188
+ {
189
+ UserName = request.Email,
190
+ Email = request.Email
191
+ };
192
+
193
+ var result = await userManager.CreateAsync(user, request.Password);
194
+
195
+ if (!result.Succeeded)
196
+ return Results.BadRequest(result.Errors);
197
+
198
+ return Results.Ok("User registered");
199
+ });
200
+ ```
201
+
202
+ ---
203
+
204
+ # ✅ 9. Login Endpoint (Returns JWT)
205
+
206
+ ```csharp
207
+ app.MapPost("/login", async (
208
+ UserManager<IdentityUser> userManager,
209
+ LoginRequest request) =>
210
+ {
211
+ var user = await userManager.FindByEmailAsync(request.Email);
212
+
213
+ if (user == null)
214
+ return Results.Unauthorized();
215
+
216
+ var valid = await userManager.CheckPasswordAsync(user, request.Password);
217
+
218
+ if (!valid)
219
+ return Results.Unauthorized();
220
+
221
+ var token = GenerateJwtToken(user);
222
+
223
+ return Results.Ok(new { token });
224
+ });
225
+ ```
226
+
227
+ ---
228
+
229
+ # ✅ 10. Protect an Endpoint
230
+
231
+ ```csharp
232
+ app.MapGet("/me", (ClaimsPrincipal user) =>
233
+ {
234
+ var email = user.FindFirst(ClaimTypes.Email)?.Value;
235
+
236
+ return Results.Ok(new { email });
237
+ })
238
+ .RequireAuthorization();
239
+ ```
240
+
241
+ ---
242
+
243
+ # ✅ 11. Add Request Models
244
+
245
+ ```csharp
246
+ public record RegisterRequest(string Email, string Password);
247
+
248
+ public record LoginRequest(string Email, string Password);
249
+ ```
250
+
251
+ ---
252
+
253
+ # ✅ 12. Configure appsettings.json
254
+
255
+ ```json
256
+ "Jwt": {
257
+ "Key": "REPLACE_WITH_A_REAL_SECRET_32+_CHARS",
258
+ "Issuer": "MyApiAuthServer"
259
+ }
260
+ ```
261
+
262
+ Make the key long and random, unless you want attackers logging in as you for sport.
263
+
264
+ ---
265
+
266
+ # ✅ Result
267
+
268
+ Now you have:
269
+
270
+ ✅ `/register`
271
+ ✅ `/login` → returns JWT
272
+ ✅ Protected endpoints with Bearer token
273
+ ✅ Identity user store in SQL
274
+ ✅ No cookies
275
+ ✅ No UI
276
+ ✅ No legacy JWT handler
277
+
278
+ ---
279
+
280
+ # If You Want Next Steps
281
+
282
+ The moment you want:
283
+
284
+ * Refresh tokens
285
+ * Roles + claims
286
+ * Password reset endpoints
287
+ * Email confirmation
288
+ * `/logout` with JWT invalidation (annoying)
289
+
290
+ Then authentication becomes a *real* system, not a demo.
291
+
292
+ Still, this setup is the clean foundation Microsoft should’ve shipped by default.
293
+