@polymorphism-tech/morph-spec 2.2.0 → 2.4.0
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.
- package/CLAUDE.md +314 -1673
- package/LICENSE +72 -72
- package/README.md +515 -516
- package/bin/detect-agents.js +225 -225
- package/bin/morph-spec.js +358 -173
- package/bin/render-template.js +302 -302
- package/bin/semantic-detect-agents.js +246 -246
- package/bin/task-manager.js +429 -0
- package/bin/validate-agents-skills.js +251 -251
- package/bin/validate-agents.js +69 -69
- package/bin/validate-phase.js +263 -263
- package/bin/validate.js +369 -0
- package/content/.azure/README.md +293 -293
- package/content/.azure/docs/azure-devops-setup.md +454 -454
- package/content/.azure/docs/branch-strategy.md +398 -398
- package/content/.azure/docs/local-development.md +515 -515
- package/content/.azure/pipelines/pipeline-variables.yml +34 -34
- package/content/.azure/pipelines/prod-pipeline.yml +319 -319
- package/content/.azure/pipelines/staging-pipeline.yml +234 -234
- package/content/.azure/pipelines/templates/build-dotnet.yml +75 -75
- package/content/.azure/pipelines/templates/deploy-app-service.yml +94 -94
- package/content/.azure/pipelines/templates/deploy-container-app.yml +120 -120
- package/content/.azure/pipelines/templates/infra-deploy.yml +90 -90
- package/content/.claude/commands/morph-apply.md +221 -158
- package/content/.claude/commands/morph-archive.md +79 -79
- package/content/.claude/commands/morph-infra.md +209 -209
- package/content/.claude/commands/morph-preflight.md +227 -0
- package/content/.claude/commands/morph-proposal.md +122 -101
- package/content/.claude/commands/morph-status.md +86 -86
- package/content/.claude/commands/morph-troubleshoot.md +122 -0
- package/content/.claude/settings.local.json +15 -15
- package/content/.claude/skills/checklists/code-review.md +226 -0
- package/content/.claude/skills/checklists/morph-checklist.md +117 -0
- package/content/.claude/skills/checklists/simulation-checklist.md +77 -0
- package/content/.claude/skills/infra/bicep-architect.md +126 -419
- package/content/.claude/skills/infra/container-specialist.md +131 -437
- package/content/.claude/skills/infra/devops-engineer.md +119 -405
- package/content/.claude/skills/integrations/asaas-financial.md +130 -333
- package/content/.claude/skills/integrations/azure-identity.md +142 -309
- package/content/.claude/skills/integrations/clerk-auth.md +108 -290
- package/content/.claude/skills/integrations/resend-email.md +119 -0
- package/content/.claude/skills/specialists/ai-system-architect.md +192 -604
- package/content/.claude/skills/specialists/azure-architect.md +142 -142
- package/content/.claude/skills/specialists/code-analyzer.md +235 -0
- package/content/.claude/skills/specialists/dotnet-senior.md +287 -0
- package/content/.claude/skills/specialists/ef-modeler.md +113 -200
- package/content/.claude/skills/specialists/hangfire-orchestrator.md +126 -245
- package/content/.claude/skills/specialists/ms-agent-expert.md +109 -263
- package/content/.claude/skills/specialists/po-pm-advisor.md +197 -197
- package/content/.claude/skills/specialists/standards-architect.md +156 -78
- package/content/.claude/skills/specialists/testing-specialist.md +126 -0
- package/content/.claude/skills/specialists/ui-ux-designer.md +191 -1060
- package/content/.claude/skills/stacks/dotnet-blazor.md +210 -588
- package/content/.claude/skills/stacks/dotnet-nextjs.md +154 -402
- package/content/.claude/skills/workflows/morph-replicate.md +213 -0
- package/content/.claude/{commands/morph-clarify.md → skills/workflows/phase-clarify.md} +5 -58
- package/content/.claude/{commands/morph-design.md → skills/workflows/phase-design.md} +16 -86
- package/content/.claude/{commands/morph-setup.md → skills/workflows/phase-setup.md} +9 -17
- package/content/.claude/skills/workflows/phase-tasks.md +164 -0
- package/content/.claude/{commands/morph-uiux.md → skills/workflows/phase-uiux.md} +15 -88
- package/content/.morph/.morphversion +5 -5
- package/content/.morph/archive/.gitkeep +25 -25
- package/content/.morph/config/agents.json +378 -242
- package/content/.morph/config/config.template.json +89 -108
- package/content/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -392
- package/content/.morph/docs/workflows/design-impl.md +37 -0
- package/content/.morph/docs/workflows/fast-track.md +29 -0
- package/content/.morph/docs/workflows/full-morph.md +76 -0
- package/content/.morph/docs/workflows/standard.md +44 -0
- package/content/.morph/docs/workflows/ui-refresh.md +39 -0
- package/content/.morph/examples/api-nextjs/README.md +241 -241
- package/content/.morph/examples/api-nextjs/contracts.ts +307 -307
- package/content/.morph/examples/api-nextjs/spec.md +399 -399
- package/content/.morph/examples/api-nextjs/tasks.md +168 -168
- package/content/.morph/examples/micro-saas/README.md +125 -125
- package/content/.morph/examples/micro-saas/contracts.cs +358 -358
- package/content/.morph/examples/micro-saas/decisions.md +246 -246
- package/content/.morph/examples/micro-saas/spec.md +236 -236
- package/content/.morph/examples/micro-saas/tasks.md +150 -150
- package/content/.morph/examples/multi-agent/README.md +309 -309
- package/content/.morph/examples/multi-agent/contracts.cs +433 -433
- package/content/.morph/examples/multi-agent/spec.md +479 -479
- package/content/.morph/examples/multi-agent/tasks.md +185 -185
- package/content/.morph/examples/scheduled-reports/decisions.md +158 -0
- package/content/.morph/examples/scheduled-reports/proposal.md +95 -0
- package/content/.morph/examples/scheduled-reports/spec.md +267 -0
- package/content/.morph/examples/state-v3.json +188 -0
- package/content/.morph/features/.gitkeep +25 -25
- package/content/.morph/hooks/README.md +190 -239
- package/content/.morph/hooks/pre-commit-agents.sh +24 -24
- package/content/.morph/hooks/pre-commit-all.sh +48 -48
- package/content/.morph/hooks/pre-commit-specs.sh +49 -49
- package/content/.morph/hooks/pre-commit-tests.sh +60 -60
- package/content/.morph/project.md +160 -160
- package/content/.morph/schemas/agent.schema.json +296 -296
- package/content/.morph/schemas/tasks.schema.json +220 -0
- package/content/.morph/specs/.gitkeep +20 -20
- package/content/.morph/standards/agent-framework-blazor-ui.md +359 -0
- package/content/.morph/standards/agent-framework-production.md +410 -0
- package/content/.morph/standards/agent-framework-setup.md +413 -453
- package/content/.morph/standards/agent-framework-workflows.md +349 -0
- package/content/.morph/standards/architecture.md +325 -325
- package/content/.morph/standards/azure.md +605 -379
- package/content/.morph/standards/coding.md +377 -377
- package/content/.morph/standards/dotnet10-migration.md +520 -494
- package/content/.morph/standards/fluent-ui-setup.md +590 -590
- package/content/.morph/standards/migration-guide.md +514 -514
- package/content/.morph/standards/passkeys-auth.md +423 -423
- package/content/.morph/standards/vector-search-rag.md +536 -536
- package/content/.morph/state.json +17 -17
- package/content/.morph/templates/FluentDesignTheme.cs +149 -149
- package/content/.morph/templates/MudTheme.cs +281 -281
- package/content/.morph/templates/agent.cs +163 -172
- package/content/.morph/templates/clarify-questions.md +159 -0
- package/content/.morph/templates/component.razor +239 -239
- package/content/.morph/templates/contracts/Commands.cs +74 -0
- package/content/.morph/templates/contracts/Entities.cs +25 -0
- package/content/.morph/templates/contracts/Queries.cs +74 -0
- package/content/.morph/templates/contracts/README.md +74 -0
- package/content/.morph/templates/contracts.cs +217 -217
- package/content/.morph/templates/decisions.md +123 -106
- package/content/.morph/templates/design-system.css +226 -226
- package/content/.morph/templates/infra/.dockerignore.example +89 -89
- package/content/.morph/templates/infra/Dockerfile.example +82 -82
- package/content/.morph/templates/infra/README.md +286 -286
- package/content/.morph/templates/infra/app-insights.bicep +63 -63
- package/content/.morph/templates/infra/app-service.bicep +164 -164
- package/content/.morph/templates/infra/container-app-env.bicep +49 -49
- package/content/.morph/templates/infra/container-app.bicep +156 -156
- package/content/.morph/templates/infra/deploy-checklist.md +426 -0
- package/content/.morph/templates/infra/deploy.ps1 +229 -229
- package/content/.morph/templates/infra/deploy.sh +208 -208
- package/content/.morph/templates/infra/key-vault.bicep +91 -91
- package/content/.morph/templates/infra/main.bicep +189 -189
- package/content/.morph/templates/infra/parameters.dev.json +29 -29
- package/content/.morph/templates/infra/parameters.prod.json +29 -29
- package/content/.morph/templates/infra/parameters.staging.json +29 -29
- package/content/.morph/templates/infra/sql-database.bicep +103 -103
- package/content/.morph/templates/infra/storage.bicep +106 -106
- package/content/.morph/templates/integrations/asaas-client.cs +387 -387
- package/content/.morph/templates/integrations/asaas-webhook.cs +351 -351
- package/content/.morph/templates/integrations/azure-identity-config.cs +288 -288
- package/content/.morph/templates/integrations/clerk-config.cs +258 -258
- package/content/.morph/templates/job.cs +171 -171
- package/content/.morph/templates/migration.cs +83 -83
- package/content/.morph/templates/proposal.md +141 -155
- package/content/.morph/templates/recap.md +94 -105
- package/content/.morph/templates/repository.cs +141 -141
- package/content/.morph/templates/saas/subscription.cs +347 -347
- package/content/.morph/templates/saas/tenant.cs +338 -338
- package/content/.morph/templates/service.cs +139 -139
- package/content/.morph/templates/simulation.md +353 -0
- package/content/.morph/templates/spec.md +149 -148
- package/content/.morph/templates/sprint-status.yaml +68 -68
- package/content/.morph/templates/state.template.json +222 -222
- package/content/.morph/templates/story.md +143 -143
- package/content/.morph/templates/tasks.md +257 -235
- package/content/.morph/templates/test.cs +239 -239
- package/content/.morph/templates/ui-components.md +362 -276
- package/content/.morph/templates/ui-design-system.md +286 -286
- package/content/.morph/templates/ui-flows.md +336 -336
- package/content/.morph/templates/ui-mockups.md +133 -133
- package/content/.morph/test-infra/example.bicep +59 -59
- package/content/CLAUDE.md +150 -442
- package/content/README.md +79 -79
- package/detectors/config-detector.js +223 -223
- package/detectors/conversation-analyzer.js +163 -163
- package/detectors/index.js +84 -84
- package/detectors/standards-generator.js +275 -275
- package/detectors/structure-detector.js +245 -250
- package/docs/README.md +144 -149
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +977 -977
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1048 -1048
- package/docs/api/scripts/collapse.js +38 -38
- package/docs/api/scripts/commonNav.js +28 -28
- package/docs/api/scripts/linenumber.js +25 -25
- package/docs/api/scripts/nav.js +12 -12
- package/docs/api/scripts/polyfill.js +3 -3
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -202
- package/docs/api/scripts/prettify/lang-css.js +2 -2
- package/docs/api/scripts/prettify/prettify.js +28 -28
- package/docs/api/scripts/search.js +98 -98
- package/docs/api/styles/jsdoc.css +776 -776
- package/docs/api/styles/prettify.css +80 -80
- package/docs/examples.md +328 -328
- package/docs/getting-started.md +301 -302
- package/docs/installation.md +361 -361
- package/docs/templates.md +418 -418
- package/docs/validation-checklist.md +265 -266
- package/package.json +80 -80
- package/scripts/postinstall.js +132 -132
- package/src/commands/advance-phase.js +183 -0
- package/src/commands/analyze-blazor-concurrency.js +193 -0
- package/src/commands/create-story.js +351 -351
- package/src/commands/detect-agents.js +139 -0
- package/src/commands/detect.js +104 -104
- package/src/commands/doctor.js +356 -280
- package/src/commands/generate.js +149 -149
- package/src/commands/init.js +258 -245
- package/src/commands/lint-fluent.js +352 -0
- package/src/commands/rollback-phase.js +185 -0
- package/src/commands/session-summary.js +291 -0
- package/src/commands/shard-spec.js +224 -224
- package/src/commands/sprint-status.js +250 -250
- package/src/commands/state.js +333 -333
- package/src/commands/sync.js +167 -167
- package/src/commands/task.js +78 -0
- package/src/commands/troubleshoot.js +222 -0
- package/src/commands/update.js +192 -159
- package/src/commands/validate-blazor-state.js +210 -0
- package/src/commands/validate-blazor.js +156 -0
- package/src/commands/validate-css.js +84 -0
- package/src/commands/validate-phase.js +221 -0
- package/src/lib/blazor-concurrency-analyzer.js +288 -0
- package/src/lib/blazor-state-validator.js +291 -0
- package/src/lib/blazor-validator.js +374 -0
- package/src/lib/complexity-analyzer.js +441 -292
- package/src/lib/continuous-validator.js +421 -0
- package/src/lib/css-validator.js +352 -0
- package/src/lib/decision-constraint-loader.js +109 -0
- package/src/lib/design-system-generator.js +298 -298
- package/src/lib/learning-system.js +520 -0
- package/src/lib/mockup-generator.js +366 -0
- package/src/lib/recap-generator.js +205 -0
- package/src/lib/state-manager.js +397 -340
- package/src/lib/troubleshoot-grep.js +194 -0
- package/src/lib/troubleshoot-index.js +144 -0
- package/src/lib/ui-detector.js +350 -0
- package/src/lib/validation-runner.js +231 -0
- package/src/lib/validators/architecture-validator.js +387 -0
- package/src/lib/validators/contract-compliance-validator.js +273 -0
- package/src/lib/validators/package-validator.js +360 -0
- package/src/lib/validators/ui-contrast-validator.js +422 -0
- package/src/utils/file-copier.js +179 -139
- package/src/utils/logger.js +32 -32
- package/src/utils/version-checker.js +175 -175
- package/content/.claude/commands/morph-costs.md +0 -206
- package/content/.claude/commands/morph-tasks.md +0 -319
- package/content/.claude/skills/specialists/cost-guardian.md +0 -110
- package/content/.claude/skills/stacks/shopify.md +0 -445
- package/content/.morph/config/azure-pricing.json +0 -70
- package/content/.morph/config/azure-pricing.schema.json +0 -50
- package/content/.morph/hooks/pre-commit-costs.sh +0 -91
- package/docs/api/cost-calculator.js.html +0 -513
- package/docs/api/design-system-generator.js.html +0 -382
- package/docs/api/global.html +0 -5263
- package/docs/api/index.html +0 -96
- package/docs/api/state-manager.js.html +0 -423
- package/src/commands/cost.js +0 -181
- package/src/commands/update-pricing.js +0 -206
- package/src/lib/cost-calculator.js +0 -429
|
@@ -1,288 +1,288 @@
|
|
|
1
|
-
// ==============================================================================
|
|
2
|
-
// MORPH-SPEC - Azure Identity (Microsoft Identity) Configuration Template
|
|
3
|
-
// Configuração de autenticação com Microsoft Identity Platform
|
|
4
|
-
// ==============================================================================
|
|
5
|
-
|
|
6
|
-
using Microsoft.AspNetCore.Authentication;
|
|
7
|
-
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
|
8
|
-
using Microsoft.AspNetCore.Components.Authorization;
|
|
9
|
-
using Microsoft.Identity.Web;
|
|
10
|
-
using Microsoft.Identity.Web.UI;
|
|
11
|
-
using System.Security.Claims;
|
|
12
|
-
|
|
13
|
-
namespace {{Namespace}}.Infrastructure.Auth;
|
|
14
|
-
|
|
15
|
-
// ==============================================================================
|
|
16
|
-
// SERVICE EXTENSIONS
|
|
17
|
-
// ==============================================================================
|
|
18
|
-
|
|
19
|
-
public static class AzureIdentityServiceExtensions
|
|
20
|
-
{
|
|
21
|
-
/// <summary>
|
|
22
|
-
/// Adiciona autenticação Microsoft Identity para Web Apps
|
|
23
|
-
/// Requer: Microsoft.Identity.Web, Microsoft.Identity.Web.UI
|
|
24
|
-
/// </summary>
|
|
25
|
-
public static IServiceCollection AddAzureIdentityAuthentication(
|
|
26
|
-
this IServiceCollection services,
|
|
27
|
-
IConfiguration configuration)
|
|
28
|
-
{
|
|
29
|
-
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
|
30
|
-
.AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd"));
|
|
31
|
-
|
|
32
|
-
services.AddControllersWithViews()
|
|
33
|
-
.AddMicrosoftIdentityUI();
|
|
34
|
-
|
|
35
|
-
services.AddAuthorization(options =>
|
|
36
|
-
{
|
|
37
|
-
// Default policy - requires authenticated user
|
|
38
|
-
options.FallbackPolicy = options.DefaultPolicy;
|
|
39
|
-
|
|
40
|
-
// Custom policies
|
|
41
|
-
options.AddPolicy("RequireAdmin", policy =>
|
|
42
|
-
policy.RequireRole("Admin"));
|
|
43
|
-
|
|
44
|
-
options.AddPolicy("RequireManager", policy =>
|
|
45
|
-
policy.RequireAssertion(context =>
|
|
46
|
-
context.User.IsInRole("Admin") ||
|
|
47
|
-
context.User.IsInRole("Manager")));
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
return services;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/// <summary>
|
|
54
|
-
/// Adiciona autenticação Microsoft Identity para Blazor Server
|
|
55
|
-
/// </summary>
|
|
56
|
-
public static IServiceCollection AddAzureIdentityBlazor(
|
|
57
|
-
this IServiceCollection services,
|
|
58
|
-
IConfiguration configuration)
|
|
59
|
-
{
|
|
60
|
-
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
|
61
|
-
.AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd"));
|
|
62
|
-
|
|
63
|
-
services.AddControllersWithViews()
|
|
64
|
-
.AddMicrosoftIdentityUI();
|
|
65
|
-
|
|
66
|
-
services.AddRazorPages();
|
|
67
|
-
services.AddServerSideBlazor()
|
|
68
|
-
.AddMicrosoftIdentityConsentHandler();
|
|
69
|
-
|
|
70
|
-
services.AddAuthorization();
|
|
71
|
-
|
|
72
|
-
return services;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/// <summary>
|
|
76
|
-
/// Adiciona autenticação Microsoft Identity para APIs (JWT Bearer)
|
|
77
|
-
/// </summary>
|
|
78
|
-
public static IServiceCollection AddAzureIdentityApi(
|
|
79
|
-
this IServiceCollection services,
|
|
80
|
-
IConfiguration configuration)
|
|
81
|
-
{
|
|
82
|
-
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
|
83
|
-
.AddMicrosoftIdentityWebApi(configuration.GetSection("AzureAd"));
|
|
84
|
-
|
|
85
|
-
services.AddAuthorization();
|
|
86
|
-
|
|
87
|
-
return services;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/// <summary>
|
|
91
|
-
/// Adiciona suporte para chamar APIs downstream (Graph, custom APIs)
|
|
92
|
-
/// </summary>
|
|
93
|
-
public static IServiceCollection AddAzureIdentityWithDownstreamApi(
|
|
94
|
-
this IServiceCollection services,
|
|
95
|
-
IConfiguration configuration)
|
|
96
|
-
{
|
|
97
|
-
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
|
98
|
-
.AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd"))
|
|
99
|
-
.EnableTokenAcquisitionToCallDownstreamApi()
|
|
100
|
-
.AddMicrosoftGraph(configuration.GetSection("Graph"))
|
|
101
|
-
.AddInMemoryTokenCaches();
|
|
102
|
-
|
|
103
|
-
return services;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// ==============================================================================
|
|
108
|
-
// USER SERVICE
|
|
109
|
-
// ==============================================================================
|
|
110
|
-
|
|
111
|
-
public interface IAzureIdentityUserService
|
|
112
|
-
{
|
|
113
|
-
string? GetUserId();
|
|
114
|
-
string? GetUserEmail();
|
|
115
|
-
string? GetUserName();
|
|
116
|
-
IEnumerable<string> GetUserRoles();
|
|
117
|
-
bool IsAuthenticated();
|
|
118
|
-
bool IsInRole(string role);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
public class AzureIdentityUserService : IAzureIdentityUserService
|
|
122
|
-
{
|
|
123
|
-
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
124
|
-
|
|
125
|
-
public AzureIdentityUserService(IHttpContextAccessor httpContextAccessor)
|
|
126
|
-
{
|
|
127
|
-
_httpContextAccessor = httpContextAccessor;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
private ClaimsPrincipal? User => _httpContextAccessor.HttpContext?.User;
|
|
131
|
-
|
|
132
|
-
public string? GetUserId() =>
|
|
133
|
-
User?.FindFirstValue(ClaimTypes.NameIdentifier) ??
|
|
134
|
-
User?.FindFirstValue("oid"); // Azure AD Object ID
|
|
135
|
-
|
|
136
|
-
public string? GetUserEmail() =>
|
|
137
|
-
User?.FindFirstValue(ClaimTypes.Email) ??
|
|
138
|
-
User?.FindFirstValue("preferred_username");
|
|
139
|
-
|
|
140
|
-
public string? GetUserName() =>
|
|
141
|
-
User?.FindFirstValue(ClaimTypes.Name) ??
|
|
142
|
-
User?.FindFirstValue("name");
|
|
143
|
-
|
|
144
|
-
public IEnumerable<string> GetUserRoles() =>
|
|
145
|
-
User?.FindAll(ClaimTypes.Role).Select(c => c.Value) ??
|
|
146
|
-
Enumerable.Empty<string>();
|
|
147
|
-
|
|
148
|
-
public bool IsAuthenticated() =>
|
|
149
|
-
User?.Identity?.IsAuthenticated ?? false;
|
|
150
|
-
|
|
151
|
-
public bool IsInRole(string role) =>
|
|
152
|
-
User?.IsInRole(role) ?? false;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// ==============================================================================
|
|
156
|
-
// MIDDLEWARE PIPELINE
|
|
157
|
-
// ==============================================================================
|
|
158
|
-
|
|
159
|
-
public static class AzureIdentityMiddlewareExtensions
|
|
160
|
-
{
|
|
161
|
-
public static IApplicationBuilder UseAzureIdentityAuthentication(this IApplicationBuilder app)
|
|
162
|
-
{
|
|
163
|
-
app.UseAuthentication();
|
|
164
|
-
app.UseAuthorization();
|
|
165
|
-
return app;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// ==============================================================================
|
|
170
|
-
// BLAZOR COMPONENTS HELPER
|
|
171
|
-
// ==============================================================================
|
|
172
|
-
|
|
173
|
-
/*
|
|
174
|
-
<!-- App.razor -->
|
|
175
|
-
<CascadingAuthenticationState>
|
|
176
|
-
<Router AppAssembly="@typeof(App).Assembly">
|
|
177
|
-
<Found Context="routeData">
|
|
178
|
-
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
|
|
179
|
-
<NotAuthorized>
|
|
180
|
-
@if (!context.User.Identity?.IsAuthenticated ?? true)
|
|
181
|
-
{
|
|
182
|
-
<RedirectToLogin />
|
|
183
|
-
}
|
|
184
|
-
else
|
|
185
|
-
{
|
|
186
|
-
<p>Você não tem permissão para acessar este recurso.</p>
|
|
187
|
-
}
|
|
188
|
-
</NotAuthorized>
|
|
189
|
-
</AuthorizeRouteView>
|
|
190
|
-
</Found>
|
|
191
|
-
</Router>
|
|
192
|
-
</CascadingAuthenticationState>
|
|
193
|
-
*/
|
|
194
|
-
|
|
195
|
-
// ==============================================================================
|
|
196
|
-
// REDIRECT TO LOGIN COMPONENT
|
|
197
|
-
// ==============================================================================
|
|
198
|
-
|
|
199
|
-
/*
|
|
200
|
-
<!-- Components/RedirectToLogin.razor -->
|
|
201
|
-
@inject NavigationManager Navigation
|
|
202
|
-
|
|
203
|
-
@code {
|
|
204
|
-
protected override void OnInitialized()
|
|
205
|
-
{
|
|
206
|
-
var returnUrl = Uri.EscapeDataString(Navigation.Uri);
|
|
207
|
-
Navigation.NavigateTo($"MicrosoftIdentity/Account/SignIn?redirectUri={returnUrl}", forceLoad: true);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
*/
|
|
211
|
-
|
|
212
|
-
// ==============================================================================
|
|
213
|
-
// APPSETTINGS EXAMPLE
|
|
214
|
-
// ==============================================================================
|
|
215
|
-
|
|
216
|
-
/*
|
|
217
|
-
{
|
|
218
|
-
"AzureAd": {
|
|
219
|
-
"Instance": "https://login.microsoftonline.com/",
|
|
220
|
-
"Domain": "yourdomain.onmicrosoft.com",
|
|
221
|
-
"TenantId": "your-tenant-id",
|
|
222
|
-
"ClientId": "your-client-id",
|
|
223
|
-
"ClientSecret": "your-client-secret",
|
|
224
|
-
"CallbackPath": "/signin-oidc"
|
|
225
|
-
},
|
|
226
|
-
"Graph": {
|
|
227
|
-
"BaseUrl": "https://graph.microsoft.com/v1.0",
|
|
228
|
-
"Scopes": "User.Read"
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
*/
|
|
232
|
-
|
|
233
|
-
// ==============================================================================
|
|
234
|
-
// PROGRAM.CS EXAMPLES
|
|
235
|
-
// ==============================================================================
|
|
236
|
-
|
|
237
|
-
/*
|
|
238
|
-
// Web App (MVC/Razor Pages)
|
|
239
|
-
var builder = WebApplication.CreateBuilder(args);
|
|
240
|
-
builder.Services.AddAzureIdentityAuthentication(builder.Configuration);
|
|
241
|
-
|
|
242
|
-
var app = builder.Build();
|
|
243
|
-
app.UseAzureIdentityAuthentication();
|
|
244
|
-
app.MapControllers();
|
|
245
|
-
app.Run();
|
|
246
|
-
|
|
247
|
-
// Blazor Server
|
|
248
|
-
var builder = WebApplication.CreateBuilder(args);
|
|
249
|
-
builder.Services.AddAzureIdentityBlazor(builder.Configuration);
|
|
250
|
-
|
|
251
|
-
var app = builder.Build();
|
|
252
|
-
app.UseAzureIdentityAuthentication();
|
|
253
|
-
app.MapBlazorHub();
|
|
254
|
-
app.MapFallbackToPage("/_Host");
|
|
255
|
-
app.Run();
|
|
256
|
-
|
|
257
|
-
// API (JWT Bearer)
|
|
258
|
-
var builder = WebApplication.CreateBuilder(args);
|
|
259
|
-
builder.Services.AddAzureIdentityApi(builder.Configuration);
|
|
260
|
-
|
|
261
|
-
var app = builder.Build();
|
|
262
|
-
app.UseAzureIdentityAuthentication();
|
|
263
|
-
app.MapControllers().RequireAuthorization();
|
|
264
|
-
app.Run();
|
|
265
|
-
*/
|
|
266
|
-
|
|
267
|
-
// ==============================================================================
|
|
268
|
-
// AZURE AD B2C CONFIGURATION
|
|
269
|
-
// ==============================================================================
|
|
270
|
-
|
|
271
|
-
/*
|
|
272
|
-
// For Azure AD B2C, use this configuration:
|
|
273
|
-
{
|
|
274
|
-
"AzureAdB2C": {
|
|
275
|
-
"Instance": "https://yourtenant.b2clogin.com",
|
|
276
|
-
"Domain": "yourtenant.onmicrosoft.com",
|
|
277
|
-
"TenantId": "your-tenant-id",
|
|
278
|
-
"ClientId": "your-client-id",
|
|
279
|
-
"SignUpSignInPolicyId": "B2C_1_signupsignin",
|
|
280
|
-
"ResetPasswordPolicyId": "B2C_1_passwordreset",
|
|
281
|
-
"EditProfilePolicyId": "B2C_1_editprofile"
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// And use:
|
|
286
|
-
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
|
287
|
-
.AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAdB2C"));
|
|
288
|
-
*/
|
|
1
|
+
// ==============================================================================
|
|
2
|
+
// MORPH-SPEC - Azure Identity (Microsoft Identity) Configuration Template
|
|
3
|
+
// Configuração de autenticação com Microsoft Identity Platform
|
|
4
|
+
// ==============================================================================
|
|
5
|
+
|
|
6
|
+
using Microsoft.AspNetCore.Authentication;
|
|
7
|
+
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
|
8
|
+
using Microsoft.AspNetCore.Components.Authorization;
|
|
9
|
+
using Microsoft.Identity.Web;
|
|
10
|
+
using Microsoft.Identity.Web.UI;
|
|
11
|
+
using System.Security.Claims;
|
|
12
|
+
|
|
13
|
+
namespace {{Namespace}}.Infrastructure.Auth;
|
|
14
|
+
|
|
15
|
+
// ==============================================================================
|
|
16
|
+
// SERVICE EXTENSIONS
|
|
17
|
+
// ==============================================================================
|
|
18
|
+
|
|
19
|
+
public static class AzureIdentityServiceExtensions
|
|
20
|
+
{
|
|
21
|
+
/// <summary>
|
|
22
|
+
/// Adiciona autenticação Microsoft Identity para Web Apps
|
|
23
|
+
/// Requer: Microsoft.Identity.Web, Microsoft.Identity.Web.UI
|
|
24
|
+
/// </summary>
|
|
25
|
+
public static IServiceCollection AddAzureIdentityAuthentication(
|
|
26
|
+
this IServiceCollection services,
|
|
27
|
+
IConfiguration configuration)
|
|
28
|
+
{
|
|
29
|
+
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
|
30
|
+
.AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd"));
|
|
31
|
+
|
|
32
|
+
services.AddControllersWithViews()
|
|
33
|
+
.AddMicrosoftIdentityUI();
|
|
34
|
+
|
|
35
|
+
services.AddAuthorization(options =>
|
|
36
|
+
{
|
|
37
|
+
// Default policy - requires authenticated user
|
|
38
|
+
options.FallbackPolicy = options.DefaultPolicy;
|
|
39
|
+
|
|
40
|
+
// Custom policies
|
|
41
|
+
options.AddPolicy("RequireAdmin", policy =>
|
|
42
|
+
policy.RequireRole("Admin"));
|
|
43
|
+
|
|
44
|
+
options.AddPolicy("RequireManager", policy =>
|
|
45
|
+
policy.RequireAssertion(context =>
|
|
46
|
+
context.User.IsInRole("Admin") ||
|
|
47
|
+
context.User.IsInRole("Manager")));
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return services;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// <summary>
|
|
54
|
+
/// Adiciona autenticação Microsoft Identity para Blazor Server
|
|
55
|
+
/// </summary>
|
|
56
|
+
public static IServiceCollection AddAzureIdentityBlazor(
|
|
57
|
+
this IServiceCollection services,
|
|
58
|
+
IConfiguration configuration)
|
|
59
|
+
{
|
|
60
|
+
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
|
61
|
+
.AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd"));
|
|
62
|
+
|
|
63
|
+
services.AddControllersWithViews()
|
|
64
|
+
.AddMicrosoftIdentityUI();
|
|
65
|
+
|
|
66
|
+
services.AddRazorPages();
|
|
67
|
+
services.AddServerSideBlazor()
|
|
68
|
+
.AddMicrosoftIdentityConsentHandler();
|
|
69
|
+
|
|
70
|
+
services.AddAuthorization();
|
|
71
|
+
|
|
72
|
+
return services;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// <summary>
|
|
76
|
+
/// Adiciona autenticação Microsoft Identity para APIs (JWT Bearer)
|
|
77
|
+
/// </summary>
|
|
78
|
+
public static IServiceCollection AddAzureIdentityApi(
|
|
79
|
+
this IServiceCollection services,
|
|
80
|
+
IConfiguration configuration)
|
|
81
|
+
{
|
|
82
|
+
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
|
83
|
+
.AddMicrosoftIdentityWebApi(configuration.GetSection("AzureAd"));
|
|
84
|
+
|
|
85
|
+
services.AddAuthorization();
|
|
86
|
+
|
|
87
|
+
return services;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// <summary>
|
|
91
|
+
/// Adiciona suporte para chamar APIs downstream (Graph, custom APIs)
|
|
92
|
+
/// </summary>
|
|
93
|
+
public static IServiceCollection AddAzureIdentityWithDownstreamApi(
|
|
94
|
+
this IServiceCollection services,
|
|
95
|
+
IConfiguration configuration)
|
|
96
|
+
{
|
|
97
|
+
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
|
98
|
+
.AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd"))
|
|
99
|
+
.EnableTokenAcquisitionToCallDownstreamApi()
|
|
100
|
+
.AddMicrosoftGraph(configuration.GetSection("Graph"))
|
|
101
|
+
.AddInMemoryTokenCaches();
|
|
102
|
+
|
|
103
|
+
return services;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ==============================================================================
|
|
108
|
+
// USER SERVICE
|
|
109
|
+
// ==============================================================================
|
|
110
|
+
|
|
111
|
+
public interface IAzureIdentityUserService
|
|
112
|
+
{
|
|
113
|
+
string? GetUserId();
|
|
114
|
+
string? GetUserEmail();
|
|
115
|
+
string? GetUserName();
|
|
116
|
+
IEnumerable<string> GetUserRoles();
|
|
117
|
+
bool IsAuthenticated();
|
|
118
|
+
bool IsInRole(string role);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public class AzureIdentityUserService : IAzureIdentityUserService
|
|
122
|
+
{
|
|
123
|
+
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
124
|
+
|
|
125
|
+
public AzureIdentityUserService(IHttpContextAccessor httpContextAccessor)
|
|
126
|
+
{
|
|
127
|
+
_httpContextAccessor = httpContextAccessor;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private ClaimsPrincipal? User => _httpContextAccessor.HttpContext?.User;
|
|
131
|
+
|
|
132
|
+
public string? GetUserId() =>
|
|
133
|
+
User?.FindFirstValue(ClaimTypes.NameIdentifier) ??
|
|
134
|
+
User?.FindFirstValue("oid"); // Azure AD Object ID
|
|
135
|
+
|
|
136
|
+
public string? GetUserEmail() =>
|
|
137
|
+
User?.FindFirstValue(ClaimTypes.Email) ??
|
|
138
|
+
User?.FindFirstValue("preferred_username");
|
|
139
|
+
|
|
140
|
+
public string? GetUserName() =>
|
|
141
|
+
User?.FindFirstValue(ClaimTypes.Name) ??
|
|
142
|
+
User?.FindFirstValue("name");
|
|
143
|
+
|
|
144
|
+
public IEnumerable<string> GetUserRoles() =>
|
|
145
|
+
User?.FindAll(ClaimTypes.Role).Select(c => c.Value) ??
|
|
146
|
+
Enumerable.Empty<string>();
|
|
147
|
+
|
|
148
|
+
public bool IsAuthenticated() =>
|
|
149
|
+
User?.Identity?.IsAuthenticated ?? false;
|
|
150
|
+
|
|
151
|
+
public bool IsInRole(string role) =>
|
|
152
|
+
User?.IsInRole(role) ?? false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ==============================================================================
|
|
156
|
+
// MIDDLEWARE PIPELINE
|
|
157
|
+
// ==============================================================================
|
|
158
|
+
|
|
159
|
+
public static class AzureIdentityMiddlewareExtensions
|
|
160
|
+
{
|
|
161
|
+
public static IApplicationBuilder UseAzureIdentityAuthentication(this IApplicationBuilder app)
|
|
162
|
+
{
|
|
163
|
+
app.UseAuthentication();
|
|
164
|
+
app.UseAuthorization();
|
|
165
|
+
return app;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ==============================================================================
|
|
170
|
+
// BLAZOR COMPONENTS HELPER
|
|
171
|
+
// ==============================================================================
|
|
172
|
+
|
|
173
|
+
/*
|
|
174
|
+
<!-- App.razor -->
|
|
175
|
+
<CascadingAuthenticationState>
|
|
176
|
+
<Router AppAssembly="@typeof(App).Assembly">
|
|
177
|
+
<Found Context="routeData">
|
|
178
|
+
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
|
|
179
|
+
<NotAuthorized>
|
|
180
|
+
@if (!context.User.Identity?.IsAuthenticated ?? true)
|
|
181
|
+
{
|
|
182
|
+
<RedirectToLogin />
|
|
183
|
+
}
|
|
184
|
+
else
|
|
185
|
+
{
|
|
186
|
+
<p>Você não tem permissão para acessar este recurso.</p>
|
|
187
|
+
}
|
|
188
|
+
</NotAuthorized>
|
|
189
|
+
</AuthorizeRouteView>
|
|
190
|
+
</Found>
|
|
191
|
+
</Router>
|
|
192
|
+
</CascadingAuthenticationState>
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
// ==============================================================================
|
|
196
|
+
// REDIRECT TO LOGIN COMPONENT
|
|
197
|
+
// ==============================================================================
|
|
198
|
+
|
|
199
|
+
/*
|
|
200
|
+
<!-- Components/RedirectToLogin.razor -->
|
|
201
|
+
@inject NavigationManager Navigation
|
|
202
|
+
|
|
203
|
+
@code {
|
|
204
|
+
protected override void OnInitialized()
|
|
205
|
+
{
|
|
206
|
+
var returnUrl = Uri.EscapeDataString(Navigation.Uri);
|
|
207
|
+
Navigation.NavigateTo($"MicrosoftIdentity/Account/SignIn?redirectUri={returnUrl}", forceLoad: true);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
*/
|
|
211
|
+
|
|
212
|
+
// ==============================================================================
|
|
213
|
+
// APPSETTINGS EXAMPLE
|
|
214
|
+
// ==============================================================================
|
|
215
|
+
|
|
216
|
+
/*
|
|
217
|
+
{
|
|
218
|
+
"AzureAd": {
|
|
219
|
+
"Instance": "https://login.microsoftonline.com/",
|
|
220
|
+
"Domain": "yourdomain.onmicrosoft.com",
|
|
221
|
+
"TenantId": "your-tenant-id",
|
|
222
|
+
"ClientId": "your-client-id",
|
|
223
|
+
"ClientSecret": "your-client-secret",
|
|
224
|
+
"CallbackPath": "/signin-oidc"
|
|
225
|
+
},
|
|
226
|
+
"Graph": {
|
|
227
|
+
"BaseUrl": "https://graph.microsoft.com/v1.0",
|
|
228
|
+
"Scopes": "User.Read"
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
*/
|
|
232
|
+
|
|
233
|
+
// ==============================================================================
|
|
234
|
+
// PROGRAM.CS EXAMPLES
|
|
235
|
+
// ==============================================================================
|
|
236
|
+
|
|
237
|
+
/*
|
|
238
|
+
// Web App (MVC/Razor Pages)
|
|
239
|
+
var builder = WebApplication.CreateBuilder(args);
|
|
240
|
+
builder.Services.AddAzureIdentityAuthentication(builder.Configuration);
|
|
241
|
+
|
|
242
|
+
var app = builder.Build();
|
|
243
|
+
app.UseAzureIdentityAuthentication();
|
|
244
|
+
app.MapControllers();
|
|
245
|
+
app.Run();
|
|
246
|
+
|
|
247
|
+
// Blazor Server
|
|
248
|
+
var builder = WebApplication.CreateBuilder(args);
|
|
249
|
+
builder.Services.AddAzureIdentityBlazor(builder.Configuration);
|
|
250
|
+
|
|
251
|
+
var app = builder.Build();
|
|
252
|
+
app.UseAzureIdentityAuthentication();
|
|
253
|
+
app.MapBlazorHub();
|
|
254
|
+
app.MapFallbackToPage("/_Host");
|
|
255
|
+
app.Run();
|
|
256
|
+
|
|
257
|
+
// API (JWT Bearer)
|
|
258
|
+
var builder = WebApplication.CreateBuilder(args);
|
|
259
|
+
builder.Services.AddAzureIdentityApi(builder.Configuration);
|
|
260
|
+
|
|
261
|
+
var app = builder.Build();
|
|
262
|
+
app.UseAzureIdentityAuthentication();
|
|
263
|
+
app.MapControllers().RequireAuthorization();
|
|
264
|
+
app.Run();
|
|
265
|
+
*/
|
|
266
|
+
|
|
267
|
+
// ==============================================================================
|
|
268
|
+
// AZURE AD B2C CONFIGURATION
|
|
269
|
+
// ==============================================================================
|
|
270
|
+
|
|
271
|
+
/*
|
|
272
|
+
// For Azure AD B2C, use this configuration:
|
|
273
|
+
{
|
|
274
|
+
"AzureAdB2C": {
|
|
275
|
+
"Instance": "https://yourtenant.b2clogin.com",
|
|
276
|
+
"Domain": "yourtenant.onmicrosoft.com",
|
|
277
|
+
"TenantId": "your-tenant-id",
|
|
278
|
+
"ClientId": "your-client-id",
|
|
279
|
+
"SignUpSignInPolicyId": "B2C_1_signupsignin",
|
|
280
|
+
"ResetPasswordPolicyId": "B2C_1_passwordreset",
|
|
281
|
+
"EditProfilePolicyId": "B2C_1_editprofile"
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// And use:
|
|
286
|
+
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
|
287
|
+
.AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAdB2C"));
|
|
288
|
+
*/
|