Skip to content

Commit

Permalink
fix(introspection): parse roles from claims if attached (#482)
Browse files Browse the repository at this point in the history
  • Loading branch information
buehler committed Apr 14, 2023
1 parent 677d88a commit 45c375b
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 5 deletions.
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# ZITADEL .NET

[![.NET Release](https://github.com/zitadel/zitadel-net/actions/workflows/dotnet-release.yml/badge.svg)](https://github.com/zitadel/zitadel-net/actions/workflows/dotnet-release.yml)
[![Code Security Testing](https://github.com/zitadel/zitadel-net/actions/workflows/security-analysis.yml/badge.svg)](https://github.com/zitadel/zitadel-net/actions/workflows/security-analysis.yml)
[![.NET Release](https://github.com/smartive/zitadel-net/actions/workflows/dotnet-release.yml/badge.svg)](https://github.com/smartive/zitadel-net/actions/workflows/dotnet-release.yml)
[![Nuget](https://img.shields.io/nuget/v/Zitadel)](https://www.nuget.org/packages/Zitadel/)

Welcome to the repository of the ZITADEL dotnet libraries.
Expand Down Expand Up @@ -30,8 +29,6 @@ To set up the dev environment you merely only need to:
- use `git submodule update --init` to initialize the submodules
- install the [.NET SDK](https://dotnet.microsoft.com/download)

The build directory uses ["nuke"](https://nuke.build/) to build the libraries.

##### License

These libraries are licensed under the [Apache 2.0 License](LICENSE).
37 changes: 36 additions & 1 deletion src/Zitadel/Extensions/ApplicationBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using System.Security.Claims;
using System.Text.Json;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authentication.OpenIdConnect.Claims;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Zitadel.Authentication;
using Zitadel.Authentication.Handler;
using Zitadel.Authentication.Options;
Expand Down Expand Up @@ -176,6 +176,41 @@ public static AuthenticationBuilder AddZitadelIntrospection(
options.ForwardSignIn = zitadelOptions.ForwardSignIn;
options.ForwardSignOut = zitadelOptions.ForwardSignOut;

options.Events.OnTokenValidated += context =>
{
var roleClaims = context.Principal?.Claims.Where(c => c.Type == context.Options.RoleClaimType);
if (roleClaims is null)
{
return Task.CompletedTask;
}

var roleIdentity = new ClaimsIdentity(
roleClaims
.Select(
c => JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(
c.Value))
.OfType<Dictionary<string, Dictionary<string, string>>>()
.SelectMany(
dict => dict.SelectMany(
role => role.Value
.Select(
org => new Claim(
ZitadelClaimTypes.OrganizationRole(org.Key),
role.Key,
ClaimValueTypes.String,
context.Options.ClaimsIssuer))
.Append(
new(
ClaimTypes.Role,
role.Key,
ClaimValueTypes.String,
context.Options.ClaimsIssuer)))));

context.Principal?.AddIdentity(roleIdentity);

return Task.CompletedTask;
};

if (zitadelOptions.JwtProfile == null)
{
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Net;
using System.Net.Http.Json;
using System.Security.Claims;
using FluentAssertions;
using Xunit;
using Zitadel.Authentication;
using Zitadel.Test.WebFactories;

namespace Zitadel.Test.Authentication;
Expand Down Expand Up @@ -42,4 +44,17 @@ public async Task Should_Return_Data_With_Token()
var result = await client.GetAsync("/authed");
result.StatusCode.Should().Be(HttpStatusCode.OK);
}

[Fact]
public async Task Should_Attach_Roles_To_Claims()
{
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Authorization = new("Bearer", TestData.PersonalAccessToken);
var result = await client.GetAsync("/authed");
var parsed = await result.Content.ReadFromJsonAsync<AuthenticationHandlerWebFactory.Authed>();
parsed.Claims.Should().Contain(c => c.Key == ClaimTypes.Role);
parsed.Claims.Should().Contain(c => c.Key == ZitadelClaimTypes.OrganizationRole(TestData.OrgId));
parsed.Claims.Should().Contain(c => c.Value == "test-1");
parsed.Claims.Should().Contain(c => c.Value == "test-2");
}
}
1 change: 1 addition & 0 deletions tests/Zitadel.Test/TestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public static class TestData
{
public const string ApiUrl = "https://zitadel-libraries-l8boqa.zitadel.cloud";
public const string PersonalAccessToken = "ge85fvmgTX4XAhjpF0XGpelB2vn9LZanJaqmUQDuf7iTpKVowb44LFl-86pqY2mfJCEoIOk";
public const string OrgId = "170079925099823361";

public const string ApplicationJson = @"
{
Expand Down

0 comments on commit 45c375b

Please sign in to comment.