Pré-requisitos

Criando claims automaticamente

Para que o Kodigos ID saiba que existem claims como “Clientes”, “Projetos”, “Dashboard”, elas precisam estar cadastradas. É possível fazer isso manualmente pelo painel, mas em projetos com vários módulos, o mais prático é registrá-las todas de uma vez via código. Para isso, recomenda-se criar um service que é responsável por autenticar sua aplicação no Kodigos ID e enviar a lista de claims necessárias. O fluxo funciona em duas etapas: primeiro a aplicação obtém um token de acesso via client_credentials, e em seguida usa esse token para registrar as claims em lote.
ApiTokenResponseDto.cs
using Newtonsoft.Json;

namespace Kodigos.Dominio.Dtos.Profiles;

public class ApiTokenResponseDto
{
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }

    [JsonProperty("token_type")]
    public string TokenType { get; set; }
}
O ServiceProfile lê as configurações de URL, ApplicationId e ClientSecret do appsettings.json, obtém o token via GetToken(), e então envia a lista de claims para o endpoint /admin/api/Claims/many através do método CreateClaims().
ServiceProfile.cs
using System.Net.Http.Headers;
using System.Text;
using Kodigos.Dominio.Dtos.Profiles;
using Kodigos.Dominio.Interfaces.Services.Profiles;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;

namespace Kodigos.Services.Services.Profiles;

public class ServiceProfile : IServiceProfile
{
    private readonly string _apiUrl;
    private readonly string _apiApplicationId;
    private readonly string _apiClientSecret;

    public ServiceProfile(IConfiguration configuration)
    {
        // Lê as configurações do appsettings.json
        _apiUrl = configuration.GetSection("ApiAuth:Url").Value ?? string.Empty;
        _apiApplicationId = configuration.GetSection("ApiAuth:ApplicationId").Value ?? string.Empty;
        _apiClientSecret = configuration.GetSection("ApiAuth:ClientSecret").Value ?? string.Empty;
    }

	// Obtém o token do client_credentials
    private async Task<ApiTokenResponseDto?> GetToken()
    {
        var handler = new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback =
                (message, cert, chain, errors) => true
        };
        var client = new HttpClient(handler);

        // Parâmetros do fluxo client_credentials
        var values = new Dictionary<string, string>
        {
            { "grant_type", "client_credentials" }, // Tipo de autenticação
            { "client_id", _apiApplicationId }, // ID da aplicação
            { "client_secret", _apiClientSecret }, // Segredo da aplicação
            { "scope", "adminapi" } // Escopo de admin
        };

        var content = new FormUrlEncodedContent(values);
        var request = new HttpRequestMessage(
            HttpMethod.Post,
            _apiUrl + "/connect/token" // Endpoint de token do Identity
        );
        request.Headers.Add("Accept", "application/json");
        request.Content = content;

        var response = await client.SendAsync(request);
        var stringResponse = await response.Content.ReadAsStringAsync();

        // Retorna o access_token para usar nas próximas chamadas
        return JsonConvert.DeserializeObject<ApiTokenResponseDto>(stringResponse);
    }

	//Envia as claims para o Kodigos ID
    public async Task CreateClaims()
    {
        var handler = new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback =
                (message, cert, chain, errors) => true
        };
        var client = new HttpClient(handler);

        // Obtém token de acesso
        var token = await GetToken();

        // Cada string aqui vira um "Type" de claim no Kodigos ID.
        // Quando precisar de um novo módulo, adicione aqui.
        List<string> claims = [
            "Dashboard",
            "Clientes",
            "Impostos",
            "Família de Produtos",
            "Etapas",
            "Projetos"
        ];

        // Monta a URL base
        var url = _apiUrl.EndsWith("/identity", StringComparison.OrdinalIgnoreCase)
            ? _apiUrl[..^"/identity".Length]
            : _apiUrl;

        // Envia para o endpoint de criação em massa
        var data = JsonConvert.SerializeObject(new
        {
            claimNames = claims,
            applicationId = _apiApplicationId
        });

        var request = new HttpRequestMessage(
            HttpMethod.Post,
            url + "/admin/api/Claims/many"     // Endpoint de criação em massa
        );
        request.Headers.Add("Accept", "application/json");
        request.Content = new StringContent(
            data, Encoding.UTF8, "application/json"
        );
        request.Headers.Authorization = new AuthenticationHeaderValue(
            token.TokenType ?? "Bearer",
            token.AccessToken
        );

        var response = await client.SendAsync(request);
    }
}

Como executar

O método CreateClaims() deve ser chamado durante a inicialização da aplicação, no Program.cs. Dessa forma, toda vez que a aplicação for executada, as claims são garantidas no Kodigos ID.
Program.cs
var app = builder.Build();

// Registra claims no startup
using (var serviceScope = app.Services.GetService<IServiceScopeFactory>().CreateScope())
{
	var context = serviceScope.ServiceProvider.GetRequiredService<KodigosContext>();
	context.Database.Migrate();
            
	var serviceProfile = serviceScope.ServiceProvider.GetRequiredService<IServiceProfile>();
	serviceProfile.CreateClaims();
 }

app.UseCors();
app.UseAuthentication();
//...

Adicionando um novo módulo

Para adicionar um novo módulo à sua aplicação, siga os passos abaixo:
1

Adicione na lista de claims

ServiceProfile.cs
List<string> claims = [
    "Dashboard",
    "Clientes",
    "Impostos",
    "Família de Produtos",
    "Etapas",
    "Projetos",
    "Relatórios" // ← novo
];
2

Execute o CreateClaims novamente

Como o CreateClaims() é chamado no startup da aplicação, basta reiniciá-la. As claims já existentes no Identity são ignoradas automaticamente, ou seja, somente a nova será criada.
3

Configuração da nova claim

Acesse o painel do Identity para atribuir os valores padrões da claim “Relatórios” e para vincular aos perfis desejados. Consulte os artigos Definir valores padrões da claim e Vincular permissões a um perfil se precisar de orientação.
4

Crie o controller com o [ResourceName]

Por fim, basta adicionar o atributo [ResourceName] no controller com o mesmo nome usado na claim. Consulte o artigo Criar filtro de permissões para mais detalhes sobre como o filtro funciona.
ReportController.cs
[ResourceName("Relatórios")]
[Route("api/[controller]")]
[ApiController]
public class ReportController : ControllerBase { ... }