Udap.Client 0.4.0

dotnet add package Udap.Client --version 0.4.0                
NuGet\Install-Package Udap.Client -Version 0.4.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Udap.Client" Version="0.4.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Udap.Client --version 0.4.0                
#r "nuget: Udap.Client, 0.4.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Udap.Client as a Cake Addin
#addin nuget:?package=Udap.Client&version=0.4.0

// Install Udap.Client as a Cake Tool
#tool nuget:?package=Udap.Client&version=0.4.0                

Udap.Client

UDAP logo

📦 Nuget Package: Udap.Client

Udap.Config simple dependency injection example configuration

If you chose to load a trust anchor yourself or non at all then registration can be a simple as the following.

builder.Services.AddScoped<TrustChainValidator>();
builder.Services.AddHttpClient<IUdapClient, UdapClient>();

The Udap.Client returns a UdapDiscoveryDocumentResponse . For convenience it contains a IsError property. If you need to understand why there is an error then you can investigate the Error, Exception, ErrorType, and HttpErrorReason depending on the reason for the error. There are also events you can subscribe to to get details about JWT and Certificate chaining errors. The Problem events come from the TrustChainValidator and are very useful. See example below.

var udapClient = serviceProvider.GetRequiredService<IUdapClient>();
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger(typeof(Program));

udapClient.Problem += element => logger.LogWarning(element.ChainElementStatus
    .Summarize(TrustChainValidator.DefaultProblemFlags));

udapClient.Untrusted += certificate2 => logger.LogWarning("Untrusted: " + certificate2.Subject);
udapClient.TokenError += message => logger.LogWarning("TokenError: " + message);

var response = await udapClient.ValidateResource(options.BaseUrl, trustAnchorStore, community);

if (response.IsError)
{
    logger.LogError(response.HttpErrorReason);
}
else
{
    logger.LogInformation(JsonSerializer.Serialize(
        response, 
        new JsonSerializerOptions{WriteIndented = true})); 
}

Experiment with this example code in the 1_UdapClientMetadata CLI Project

Example command line run: dotnet run --baseUrl https://fhirlabs.net/fhir/r4 --trustAnchor "C:\SureFhirLabs_CA.cer" --community udap://ECDSA/


NOTE The above example trust anchor (download) is used by most communities in the https://fhirlabs.net/fhir/r4 test server.


Udap.Client configuration with a ITrustAnchorStore implementation

Implement the ITrustAnchorStore to load trust anchors from a store. Below is dependency injection example of a file system store implementation. Note the CertStore folder in this project with anchors and intermediates folders. Also take note of the appsettings.json configuration. Notice each community has an Anchors and Intermediates collection of file references. In accompanying example project all communities issue certificates through a sub-certificate authority, yet the configuration only configured one Intermediate. Why is this? If the published certificate at the resource ./well-known/udap endpoint contains a AIA extension then the .NET X509Chain.Build method will follow the URL in the extension. This is true on Windows and Linux. Some Certificate Authorities may not follow this practice and you will have to configure for the intermediate certificate.


Note: An anchor must be chosen for each community. When you receive signed metadata the client will proceed to build a certificate chain from the first x5c header certificate and the anchor as the root certificate.


There is another way for intermediate certificates to be discovered. That is within the x5c header of the signed metadata. While the first certificate in the x5c header must be the signing certificate, the rest of the certificates may be the rest of the chain. But again you must have an anchor deliberately chosen and loaded into the client. The client will no load and trust an anchor from the x5c header.

<details><summary><a>View Metadata</></summary>

"UdapFileCertStoreManifest": {
  "Communities": [
    {
      "Name": "udap://stage.healthtogo.me/",
      "Anchors": [
        {
          "FilePath": "CertStore/anchors/EMRDirectTestCA.crt"
        }
      ]
    },
    {
      "Name": "udap://fhirlabs.net/",
      "Intermediates": [
        "CertStore/intermediates/SureFhirLabs_Intermediate.cer"
      ],
      "Anchors": [
        {
          "FilePath": "CertStore/anchors/SureFhirLabs_CA.cer"
        }
      ]
    },
    {
      "Name": "udap://expired.fhirlabs.net/",
      "Anchors": [
        {
          "FilePath": "CertStore/anchors/SureFhirLabs_CA.cer"
        }
      ]
    },
    {
      "Name": "udap://revoked.fhirlabs.net/",
      "Anchors": [
        {
          "FilePath": "CertStore/anchors/SureFhirLabs_CA.cer"
        }
      ]
    },
    {
      "Name": "udap://untrusted.fhirlabs.net/",
      "Anchors": [
        {
          "FilePath": "CertStore/anchors/SureFhirLabs_CA.cer"
        }
      ]
    },
    {
      "Name": "udap://Iss.Miss.Match.To.SubjAltName/",
      "Anchors": [
        {
          "FilePath": "CertStore/anchors/SureFhirLabs_CA.cer"
        }
      ]
    },
    {
      "Name": "udap://Iss.Miss.Match.To.BaseUrl//",
      "Anchors": [
        {
          "FilePath": "CertStore/anchors/SureFhirLabs_CA.cer"
        }
      ]
    },
    {
      "Name": "udap://ECDSA/",
      "Anchors": [
        {
          "FilePath": "CertStore/anchors/SureFhirLabs_CA.cer"
        }
      ]
    }
  ]
}

</details> <br/>

services.Configure<UdapFileCertStoreManifest>(context.Configuration.GetSection("UdapFileCertStoreManifest"));
services.AddSingleton<ITrustAnchorStore, TrustAnchorFileStore>();
services.AddScoped<TrustChainValidator>();
services.AddHttpClient<IUdapClient, UdapClient>();

Experiment with this example code in the 1_UdapClientMetadata CLI Project

Udap.Client advanced configuration

The TrustChainValidator a couple ways to control it's behavior when validating a chain. One is the control the Problem Flags identified in the .NET X509ChainStatusFlags settings. The defaults are recommended. Perhaps you are running some unit tests that do not publish a certificate revocation list. Then your code might look something like the following where we mask out OfflineRevocation and RevocationStatusUnknown flags.

services.Configure<UdapFileCertStoreManifest>(context.Configuration.GetSection("UdapFileCertStoreManifest"));
                    
var problemFlags = X509ChainStatusFlags.NotTimeValid |
                    X509ChainStatusFlags.Revoked |
                    X509ChainStatusFlags.NotSignatureValid |
                    X509ChainStatusFlags.InvalidBasicConstraints |
                    X509ChainStatusFlags.CtlNotTimeValid |
                    X509ChainStatusFlags.UntrustedRoot |
                    // X509ChainStatusFlags.OfflineRevocation |
                    X509ChainStatusFlags.CtlNotSignatureValid;
                    // X509ChainStatusFlags.RevocationStatusUnknown;

services.AddSingleton<ITrustAnchorStore, TrustAnchorFileStore>();
services.AddScoped<TrustChainValidator>(sp => new TrustChainValidator(new X509ChainPolicy(), problemFlags, sp.GetService<ILogger<TrustChainValidator>>()));
services.AddHttpClient<IUdapClient, UdapClient>();

TODO: Cover X509ChainPolicy

Udap.Client Dynamic Client Registration with a ICertificateStore implementation

Example projects

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Udap.Client:

Package Downloads
Udap.Server

Package is a part of the UDAP reference implementation for .NET.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.4.0 139 12/14/2024
0.3.96 276 11/6/2024
0.3.95 206 11/2/2024
0.3.94 128 10/31/2024
0.3.93 277 10/13/2024
0.3.92 109 10/13/2024
0.3.91 104 10/10/2024
0.3.89 139 10/10/2024
0.3.87 141 10/5/2024
0.3.86 157 10/5/2024
0.3.85 121 10/4/2024
0.3.84 113 10/3/2024
0.3.83 108 10/3/2024
0.3.82 166 9/20/2024
0.3.81 213 9/19/2024
0.3.80 159 9/19/2024
0.3.79 152 9/19/2024
0.3.78 145 9/19/2024
0.3.77 184 9/17/2024
0.3.76 117 9/17/2024
0.3.75 124 9/12/2024
0.3.74 118 9/12/2024
0.3.73 140 9/10/2024
0.3.72 289 9/7/2024
0.3.71 128 9/5/2024
0.3.70 124 9/5/2024
0.3.69 128 9/5/2024
0.3.68 146 9/4/2024
0.3.67 115 9/4/2024
0.3.66 108 9/4/2024
0.3.65 114 9/4/2024
0.3.64 114 9/2/2024
0.3.63 121 8/31/2024
0.3.62 135 8/29/2024
0.3.61 134 8/28/2024
0.3.60 195 8/2/2024
0.3.59 146 8/1/2024
0.3.58 106 8/1/2024
0.3.57 213 7/19/2024
0.3.56 121 7/19/2024
0.3.54 129 7/18/2024
0.3.53 136 7/15/2024
0.3.52 129 7/15/2024
0.3.51 128 7/12/2024
0.3.50 202 7/1/2024
0.3.49 140 7/1/2024
0.3.48 346 5/22/2024
0.3.47 239 5/15/2024
0.3.46 113 5/14/2024
0.3.45 176 5/12/2024
0.3.44 117 5/12/2024
0.3.43 102 5/12/2024
0.3.42 112 5/12/2024
0.3.41 189 5/6/2024
0.3.40 171 5/4/2024
0.3.39 133 5/1/2024
0.3.38 141 4/30/2024
0.3.37 214 4/11/2024
0.3.36 130 4/10/2024
0.3.35 257 4/9/2024
0.3.34 158 4/8/2024
0.3.33 154 4/7/2024
0.3.32 148 4/5/2024
0.3.31 145 4/4/2024
0.3.30 123 4/4/2024
0.3.29 179 4/3/2024
0.3.28 114 4/3/2024
0.3.27 131 4/2/2024
0.3.26 107 4/2/2024
0.3.25 158 4/2/2024
0.3.24 193 3/24/2024
0.3.22 242 3/6/2024
0.3.21 137 3/6/2024
0.3.20 141 3/5/2024
0.3.19 159 3/2/2024
0.3.18 148 3/2/2024
0.3.13 162 3/1/2024
0.3.12 131 2/24/2024
0.3.10 134 2/14/2024
0.3.8 214 2/11/2024
0.3.7 141 2/11/2024
0.3.6 139 2/10/2024
0.3.5 123 2/10/2024
0.3.4 130 2/10/2024
0.3.2 139 2/10/2024
0.3.0 289 1/31/2024
0.2.21 551 10/24/2023
0.2.20 147 10/23/2023
0.2.19 188 10/20/2023
0.2.18 198 10/11/2023
0.2.17 195 10/5/2023
0.2.16 264 9/21/2023
0.2.15 150 9/21/2023
0.2.14 211 9/20/2023
0.2.13 141 9/20/2023
0.2.12 162 9/20/2023
0.2.11 158 9/19/2023
0.2.10 229 9/13/2023
0.2.9 312 8/26/2023
0.2.8 185 8/18/2023
0.2.7 184 8/15/2023
0.2.6 173 8/12/2023
0.2.5 212 8/11/2023
0.2.4 190 8/10/2023
0.2.3 224 8/2/2023
0.2.2 191 8/1/2023
0.2.1 201 7/25/2023
0.2.0 248 7/16/2023
0.1.24 346 5/26/2023
0.1.23 167 5/22/2023
0.1.22 135 5/22/2023
0.1.21 163 5/21/2023
0.1.20 169 5/20/2023
0.1.17 171 5/9/2023
0.1.16 145 5/6/2023
0.1.15 162 5/4/2023
0.1.14 183 5/2/2023
0.1.12 153 5/1/2023
0.1.11 166 4/29/2023
0.1.9 162 4/29/2023
0.1.8 162 4/29/2023
0.1.7 194 4/28/2023
0.1.6 176 4/27/2023
0.1.5 185 4/27/2023
0.1.4 189 4/25/2023
0.1.3 206 4/23/2023
0.1.2 218 4/22/2023
0.1.1 237 4/22/2023
0.0.4-preview040 152 4/21/2023
0.0.4-preview039 127 4/13/2023
0.0.4-preview038 154 4/11/2023
0.0.4-preview037 140 4/7/2023
0.0.4-preview036 150 3/31/2023
0.0.4-preview035 131 3/31/2023
0.0.4-preview034 145 3/31/2023
0.0.4-preview033 153 3/30/2023
0.0.4-preview032 156 3/19/2023
0.0.4-preview029 151 3/18/2023
0.0.4-preview028 148 3/15/2023
0.0.4-preview027 139 3/13/2023
0.0.4-preview026 143 3/12/2023
0.0.4-preview025 149 3/10/2023
0.0.4-preview024 147 3/9/2023
0.0.4-preview022 171 3/9/2023
0.0.4-preview021 140 3/7/2023
0.0.4-preview020 168 3/7/2023
0.0.4-preview019 128 3/4/2023
0.0.4-preview018 167 3/4/2023
0.0.4-preview017 154 3/4/2023
0.0.4-preview016 133 3/1/2023
0.0.4-preview015 152 2/28/2023
0.0.4-preview014 158 2/23/2023
0.0.4-preview013 170 2/23/2023
0.0.4-preview012 180 2/21/2023
0.0.4-preview011 146 2/20/2023
0.0.4-preview010 142 2/20/2023
0.0.4-preview009 135 2/19/2023
0.0.4-preview008 174 2/14/2023
0.0.4-preview007 143 2/10/2023
0.0.4-preview006 153 2/8/2023
0.0.4-preview005 161 2/8/2023
0.0.4-preview004 128 2/7/2023
0.0.4-preview003 131 2/7/2023
0.0.4-preview002 146 2/7/2023
0.0.4-preview001 146 2/3/2023
0.0.4-preview000 145 2/2/2023
0.0.3-preview032 151 2/1/2023
0.0.3-preview031 144 2/1/2023
0.0.3-preview030 166 1/30/2023
0.0.3-preview029 157 1/21/2023
0.0.3-preview028 150 1/19/2023
0.0.3-preview027 167 1/18/2023
0.0.3-preview026 181 1/16/2023
0.0.3-preview025 134 1/15/2023
0.0.3-preview024 179 1/15/2023
0.0.3-preview020 159 1/15/2023
0.0.3-preview019 145 1/11/2023
0.0.3-preview018 169 1/11/2023
0.0.3-preview017 175 1/7/2023
0.0.3-preview016 156 1/7/2023
0.0.3-preview015 162 1/6/2023
0.0.3-preview014 154 1/6/2023
0.0.3-preview013 162 1/6/2023
0.0.3-preview012 169 1/6/2023
0.0.3-preview011 160 1/6/2023
0.0.3-preview010 182 1/3/2023
0.0.3-preview009 165 1/3/2023
0.0.3-preview008 171 1/2/2023
0.0.3-preview007 168 1/2/2023
0.0.3-preview006 154 1/2/2023
0.0.3-preview005 163 1/2/2023
0.0.3-preview004 170 1/1/2023
0.0.3-preview003 162 12/31/2022
0.0.3-preview002 210 12/28/2022
0.0.3-preview001 214 12/21/2022
0.0.3-preview000 163 11/29/2022
0.0.2-preview003 143 11/4/2022
0.0.2-preview002 157 11/4/2022
0.0.2-preview000 212 11/4/2022
0.0.1-preview002 188 11/4/2022
0.0.1-preview001 174 11/4/2022