DK privilege - claim transforms

FoxIDs support claim transforms of DK privilege used in Danish NemLog-in and Context Handler IdPs.

Supported privilege standard:

  • OIO Basic Privilege Profile, Version 1.2
  • FoxIDs support PrivilegeGroup elements defined in model 2 (scoping and delegation) and model 3 (scoping, delegation and constraint).
  • FoxIDs support both to read the base64-encoded privilege string from the standard claim https://data.gov.dk/model/core/eid/privilegesIntermediate and a custom defined claim.

Configuring DK privilege - claim transforms

The DK privilege can both be configured in a SAML 2.0 authentication method and application registration and likewise in a OpenID Connect authentication method and application registration.

  • In SAML 2.0 the DK privilege claim transformer default read the standard claim https://data.gov.dk/model/core/eid/privilegesIntermediate and issue the transformed claim http://schemas.foxids.com/identity/claims/privilege.
  • In OpenID Connect the DK privilege claim transformer default read the standard claim privileges_intermediate and issue the transformed claim privilege.

Configure the DK privilege claim transformer on SAML 2.0 authentication method in FoxIDs Control Client:

  1. Select the Claim transform tab
  2. Click Add claim transform and click DK XML privilege to JSON.
  3. Then again, click Add claim transform and click Match claim.
  4. Select to remove the original privilege claim https://data.gov.dk/model/core/eid/privilegesIntermediate from the claims pipeline.
  5. Click update

Context Handler SAML 2.0 authentication method privilege claim transformation

Remember to add a claim mapping from SAML http://schemas.foxids.com/identity/claims/privilege to JWT privilege in the settings section. If you e.g. use a SAML 2.0 authentication method and a OpenID Connect application registration.

Model 2

The DK privilege claim is transformed into a list of claims, one claim for each group. The XML PrivilegeGroup element is transformed into a JSON object and serialized as a string.

The 4 possible scopes are translated into a properties with a short name:

  • Scope="urn:dk:gov:saml:cvrNumberIdentifier:<cvr_number>" become "cvr": "<cvr_number>"
  • Scope="urn:dk:gov:saml:productionUnitIdentifier:<p_number>" become "p": "<p_number>"
  • Scope="urn:dk:gov:saml:seNumberIdentifier:<se_number>" become "se": "<se_number>"
  • Scope="urn:dk:gov:saml:cprNumberIdentifier:<cpr_number>" become "cpr": "<cpr_number>"

The Privilege element(s) are translated into the property p with the privilege values(s) as a list.

DK privilege base64-decoded sample:
(with extra spaces and line breaks for display purposes only)

<?xml version="1.0" encoding="UTF-8"?>
<bpp:PrivilegeList xmlns:bpp="http://digst.dk/oiosaml/basic_privilege_profile" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
    <PrivilegeGroup Scope="urn:dk:gov:saml:cvrNumberIdentifier:12345678">
        <Privilege>urn:dk:some_domain:myPrivilege1A</Privilege>
        <Privilege>urn:dk:some_domain:myPrivilege1B</Privilege>
    </PrivilegeGroup>
    <PrivilegeGroup Scope="urn:dk:gov:saml:seNumberIdentifier:27384223">
        <Privilege>urn:dk:some_domain:myPrivilege1C</Privilege>
        <Privilege>urn:dk:some_domain:myPrivilege1D</Privilege>
    </PrivilegeGroup>
</bpp:PrivilegeList>

Is translated into two claims with JSON values:
(with extra spaces and line breaks for display purposes only)

{
    "cvr": "12345678",
    "p": [ "urn:dk:some_domain:myPrivilege1A", "urn:dk:some_domain:myPrivilege1B" ]
}

and

{
    "se": "27384223",
    "p": [ "urn:dk:some_domain:myPrivilege1C", "urn:dk:some_domain:myPrivilege1D" ]
}

Model 3

Model 3 is an extension to Model 2.

The Constraint element(s) are translated into the property c with the constraint(s) as a list of key value pairs.

DK privilege base64-decoded sample:
(with extra spaces and line breaks for display purposes only)

<?xml version="1.0" encoding="UTF-8"?>
<bpp:PrivilegeList xmlns:bpp="http://digst.dk/oiosaml/basic_privilege_profile" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
    <PrivilegeGroup Scope="urn:dk:gov:saml:cvrNumberIdentifier:12345678">
        <Constraint Name="urn:dk:kombit:KLE">25.*</Constraint>
        <Constraint Name="urn:dk:kombit:sensitivity">3</Constraint>
        <Privilege>urn:dk:kombit:system_xyz:view_case</Privilege>
    </PrivilegeGroup>
</bpp:PrivilegeList>

Is translated into one claims with JSON values:
(with extra spaces and line breaks for display purposes only)

{
    "cvr": "12345678",
    "c": [ { "urn:dk:kombit:KLE": "25.*" }, { "urn:dk:kombit:sensitivity": "3" } ]
    "p": [ "urn:dk:kombit:system_xyz:view_case" ]
}

Using JSON privilege claim in an application

The application registration application receives the privilege claim with the privilege serialized as a JSON string.
The following C# code example show how to deserialize the JSON claim to an object in ASP.NET Core application using Newtonsoft.Json.

Create privilege group class

public class DkPrivilegeGroup
{
    [JsonProperty(PropertyName = "cvr")]
    public string CvrNumber { get; set; }

    [JsonProperty(PropertyName = "pu")]
    public string ProductionUnit { get; set; }

    [JsonProperty(PropertyName = "se")]
    public string SeNumber { get; set; }

    [JsonProperty(PropertyName = "cpr")]
    public string CprNumber { get; set; }

    [JsonProperty(PropertyName = "c")]
    public Dictionary<string, string> Constraint { get; set; }

    [JsonProperty(PropertyName = "p")]
    public List<string> Privilege { get; set; }
}

and deserialize the claim in e.g., a controller

var privileges = User.Claims.Where(c => c.Type == "privilege")
    .Select(c => JsonConvert.DeserializeObject<DkPrivilegeGroup>(c.Value)).ToList();
foreach(var privilege in privileges)
{
    // TODO handle access based on the privilege
}