Skip to content

Commit

Permalink
implemented OID4VC (#13)
Browse files Browse the repository at this point in the history
Signed-off-by: Kevin <kevin.dinh@lissi.id>
  • Loading branch information
Dindexx authored Dec 4, 2023
1 parent 06efdfb commit f9d7b05
Show file tree
Hide file tree
Showing 66 changed files with 4,097 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<PackageReference Include="FluentValidation" Version="$(FluentValidationVersion)" />
<PackageReference Include="MediatR" Version="$(MediatrVersion)" />
<PackageReference Include="MicroElements.Swashbuckle.FluentValidation" Version="$(MicroElementsSwashbuckleFluentValidationVersion)" />
<PackageReference Include="System.Text.Json" Version="$(SystemTextJsonVersion)" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="$(SwashbuckleAspNetCoreAnnotationsVersion)" />
</ItemGroup>

Expand Down
74 changes: 66 additions & 8 deletions src/Hyperledger.Aries/Configuration/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,23 @@
using Hyperledger.Aries.Features.Handshakes.Connection;
using Hyperledger.Aries.Features.Handshakes.DidExchange;
using Hyperledger.Aries.Features.IssueCredential;
using Hyperledger.Aries.Features.OpenId4Vc.Vci.Services.Oid4VciClientService;
using Hyperledger.Aries.Features.OpenId4Vc.Vp.Services;
using Hyperledger.Aries.Features.OpenID4VC.Vp.Services;
using Hyperledger.Aries.Features.OutOfBand;
using Hyperledger.Aries.Features.Pex.Services;
using Hyperledger.Aries.Features.PresentProof;
using Hyperledger.Aries.Features.RevocationNotification;
using Hyperledger.Aries.Features.SdJwt.Services.SdJwtVcHolderService;
using Hyperledger.Aries.Ledger;
using Hyperledger.Aries.Ledger.V2;
using Hyperledger.Aries.Payments;
using Hyperledger.Aries.Runtime;
using Hyperledger.Aries.Signatures;
using Hyperledger.Aries.Storage;
using Microsoft.Extensions.DependencyInjection.Extensions;
using SD_JWT;
using SD_JWT.Abstractions;

// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection
Expand Down Expand Up @@ -70,27 +77,27 @@ public static AriesFrameworkBuilder AddAriesFrameworkV2(this IServiceCollection

internal static IServiceCollection AddDefaultServices(this IServiceCollection builder)
{
builder.TryAddSingleton<IEventAggregator, EventAggregator>();
builder.TryAddSingleton<IBasicMessageService, DefaultBasicMessageService>();
builder.TryAddSingleton<IOutOfBandService, DefaultOutOfBandService>();
builder.TryAddSingleton<IConnectionService, DefaultConnectionService>();
builder.TryAddSingleton<ICredentialService, DefaultCredentialService>();
builder.TryAddSingleton<IDidExchangeService, DefaultDidExchangeService>();
builder.TryAddSingleton<IDiscoveryService, DefaultDiscoveryService>();
builder.TryAddSingleton<IEventAggregator, EventAggregator>();
builder.TryAddSingleton<ILedgerService, DefaultLedgerService>();
builder.TryAddSingleton<ILedgerSigningService, DefaultLedgerSigningService>();
builder.TryAddSingleton<IMessageDispatcher, HttpMessageDispatcher>();
builder.TryAddSingleton<IMessageService, DefaultMessageService>();
builder.TryAddSingleton<IOutOfBandService, DefaultOutOfBandService>();
builder.TryAddSingleton<IPaymentService, DefaultPaymentService>();
builder.TryAddSingleton<IPoolService, DefaultPoolService>();
builder.TryAddSingleton<IProofService, DefaultProofService>();
builder.TryAddSingleton<IDiscoveryService, DefaultDiscoveryService>();
builder.TryAddSingleton<IProvisioningService, DefaultProvisioningService>();
builder.TryAddSingleton<IMessageService, DefaultMessageService>();
builder.TryAddSingleton<IMessageDispatcher, HttpMessageDispatcher>();
builder.TryAddSingleton<IRevocationNotificationService, DefaultRevocationNotificationService>();
builder.TryAddSingleton<ISchemaService, DefaultSchemaService>();
builder.TryAddSingleton<ITailsService, DefaultTailsService>();
builder.TryAddSingleton<IWalletRecordService, DefaultWalletRecordService>();
builder.TryAddSingleton<IWalletService, DefaultWalletService>();
builder.TryAddSingleton<IPaymentService, DefaultPaymentService>();
builder.TryAddSingleton<IRevocationNotificationService, DefaultRevocationNotificationService>();


return builder;
}

Expand All @@ -103,6 +110,23 @@ internal static IServiceCollection AddDefaultServicesV2(this IServiceCollection
return builder;
}

/// <summary>
/// Adds the default OpenID services.
/// </summary>
/// <param name="builder"> The builder. </param>
public static IServiceCollection AddOpenIdDefaultServices(this IServiceCollection builder)
{
builder.AddSingleton<IHolder, Holder>();
builder.AddSingleton<ISdJwtVcHolderService, DefaultSdJwtVcHolderService>();
builder.AddSingleton<IPexService, PexService>();
builder.AddSingleton<IOid4VciClientService, DefaultOid4VciClientService>();
builder.AddSingleton<IOid4VpClientService, Oid4VpClientService>();
builder.AddSingleton<IOid4VpHaipClient, Oid4VpHaipClient>();
builder.AddSingleton<IOid4VpRecordService, Oid4VpRecordService>();

return builder;
}

/// <summary>
/// Adds the extended protocol discovery service.
/// </summary>
Expand Down Expand Up @@ -449,5 +473,39 @@ public static IServiceCollection AddExtendedWalletService<TImplementation>(this
builder.AddSingleton<IWalletService, TImplementation>();
return builder;
}

/// <summary>
/// Adds the extended Sd-JWT credential service.
/// </summary>
/// <returns>The extended SD-JWT credential service.</returns>
/// <param name="builder">Builder.</param>
/// <typeparam name="TService">The 1st type parameter.</typeparam>
/// <typeparam name="TImplementation">The 2nd type parameter.</typeparam>
public static IServiceCollection AddExtendedSdJwtCredentialService<TService, TImplementation>(this IServiceCollection builder)
where TService : class, ISdJwtVcHolderService
where TImplementation : class, TService, ISdJwtVcHolderService
{
builder.AddSingleton<TImplementation>();
builder.AddSingleton<ISdJwtVcHolderService>(x => x.GetService<TImplementation>());
builder.AddSingleton<TService>(x => x.GetService<TImplementation>());
return builder;
}

/// <summary>
/// Adds the extended OpenID4Vci Client service.
/// </summary>
/// <returns>The extended OpenID4Vci Client service.</returns>
/// <param name="builder">Builder.</param>
/// <typeparam name="TService">The 1st type parameter.</typeparam>
/// <typeparam name="TImplementation">The 2nd type parameter.</typeparam>
public static IServiceCollection AddExtendedOid4VciClientService<TService, TImplementation>(this IServiceCollection builder)
where TService : class, IOid4VciClientService
where TImplementation : class, TService, IOid4VciClientService
{
builder.AddSingleton<TImplementation>();
builder.AddSingleton<IOid4VciClientService>(x => x.GetService<TImplementation>());
builder.AddSingleton<TService>(x => x.GetService<TImplementation>());
return builder;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Threading.Tasks;

namespace Hyperledger.Aries.Features.OpenId4Vc.KeyStore.Services
{
/// <summary>
/// Represents a store for managing keys.
/// This interface is intended to be implemented outside of the framework on the device side,
/// allowing flexibility in key generation or retrieval mechanisms.
/// </summary>
public interface IKeyStore
{
/// <summary>
/// Asynchronously generates a key for the specified algorithm and returns the key identifier.
/// </summary>
/// <param name="alg">The algorithm for key generation (default is "ES256").</param>
/// <returns>A <see cref="Task{TResult}" /> representing the generated key's identifier as a string.</returns>
Task<string> GenerateKey(string alg = "ES256");

/// <summary>
/// Asynchronously creates a proof of possession for a specific key, based on the provided audience and nonce.
/// </summary>
/// <param name="keyId">The identifier of the key to be used in creating the proof of possession.</param>
/// <param name="audience">The intended recipient of the proof. Typically represents the entity that will verify it.</param>
/// <param name="nonce">
/// A unique token, typically used to prevent replay attacks by ensuring that the proof is only used once.
/// </param>
/// <param name="type">The type of the proof. (For example "openid4vci-proof+jwt")</param>
/// <returns>
/// A <see cref="Task{TResult}" /> representing the asynchronous operation. When evaluated, the task's result contains
/// the proof.
/// </returns>
Task<string> GenerateProofOfPossessionAsync(string keyId, string audience, string nonce, string type);

/// <summary>
/// Asynchronously loads a key by its identifier and returns it as a JSON Web Key (JWK) containing the public key
/// information.
/// </summary>
/// <param name="keyId">The identifier of the key to load.</param>
/// <returns>A <see cref="Task{TResult}" /> representing the loaded key as a JWK string.</returns>
Task<string> LoadKey(string keyId);

/// <summary>
/// Asynchronously signs the given payload using the key identified by the provided key ID.
/// </summary>
/// <param name="keyId">The identifier of the key to use for signing.</param>
/// <param name="payload">The payload to sign.</param>
/// <returns>A <see cref="Task{TResult}" /> representing the signed payload as a byte array.</returns>
Task<byte[]> Sign(string keyId, byte[] payload);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Newtonsoft.Json;

namespace Hyperledger.Aries.Features.OpenId4Vc.Vci.Models.Authorization
{
/// <summary>
/// Represents the metadata associated with an OAuth 2.0 Authorization Server.
/// </summary>
public class AuthorizationServerMetadata
{
/// <summary>
/// Gets or sets the issuer location for the OAuth 2.0 Authorization Server.
/// </summary>
[JsonProperty("issuer")]
public string Issuer { get; set; }

/// <summary>
/// Gets or sets the URL of the OAuth 2.0 token endpoint.
/// Clients use this endpoint to obtain an access token by presenting its authorization grant or refresh token.
/// </summary>
[JsonProperty("token_endpoint")]
public string TokenEndpoint { get; set; }

/// <summary>
/// Gets or sets the response types that the OAuth 2.0 Authorization Server supports.
/// These types determine how the Authorization Server responds to client requests.
/// </summary>
[JsonProperty("response_types_supported")]
public string[] ResponseTypesSupported { get; set; }

/// <summary>
/// Gets or sets the supported authentication methods the OAuth 2.0 Authorization Server supports
/// when calling the token endpoint.
/// </summary>
[JsonProperty("token_endpoint_auth_methods_supported")]
public string[] TokenEndpointAuthMethodsSupported { get; set; }

/// <summary>
/// Gets or sets the supported token endpoint authentication signing algorithms.
/// This indicates which algorithms the Authorization Server supports when receiving requests
/// at the token endpoint.
/// </summary>
[JsonProperty("token_endpoint_auth_signing_alg_values_supported")]
public string[] TokenEndpointAuthSigningAlgValuesSupported { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#nullable enable

using System.Collections.Generic;
using System.Net.Http;
using Newtonsoft.Json;

namespace Hyperledger.Aries.Features.OpenId4Vc.Vci.Models.Authorization
{
/// <summary>
/// Represents a request for an access token from an OAuth 2.0 Authorization Server.
/// </summary>
public class TokenRequest
{
/// <summary>
/// Gets or sets the grant type of the request. Determines the type of token request being made.
/// </summary>
[JsonProperty("grant_type")]
public string GrantType { get; set; } = null!;

/// <summary>
/// Gets or sets the pre-authorized code. Represents the authorization to obtain specific credentials.
/// This is required if the grant type is urn:ietf:params:oauth:grant-type:pre-authorized_code.
/// </summary>
[JsonProperty("pre-authorized_code")]
public string PreAuthorizedCode { get; set; } = null!;

/// <summary>
/// Gets or sets the scope of the access request. Defines the permissions the client is asking for.
/// </summary>
[JsonProperty("scope")]
public string? Scope { get; set; }

/// <summary>
/// Gets or sets the user PIN. This value must be present if a PIN was required in a previous step.
/// </summary>
[JsonProperty("user_pin")]
public string? UserPin { get; set; }

/// <summary>
/// Converts the properties of the TokenRequest instance into an FormUrlEncodedContent type suitable for HTTP POST
/// operations.
/// </summary>
/// <returns>Returns an instance of FormUrlEncodedContent containing the URL-encoded properties of the TokenRequest.</returns>
public FormUrlEncodedContent ToFormUrlEncoded()
{
var keyValuePairs = new List<KeyValuePair<string, string>>();

if (!string.IsNullOrEmpty(GrantType))
keyValuePairs.Add(new KeyValuePair<string, string>("grant_type", GrantType));

if (!string.IsNullOrEmpty(PreAuthorizedCode))
keyValuePairs.Add(new KeyValuePair<string, string>("pre-authorized_code", PreAuthorizedCode));

if (!string.IsNullOrEmpty(Scope))
keyValuePairs.Add(new KeyValuePair<string, string>("scope", Scope));

if (!string.IsNullOrEmpty(UserPin))
keyValuePairs.Add(new KeyValuePair<string, string>("user_pin", UserPin));

return new FormUrlEncodedContent(keyValuePairs);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using Newtonsoft.Json;

namespace Hyperledger.Aries.Features.OpenId4Vc.Vci.Models.Authorization
{
/// <summary>
/// Represents a successful response from the OAuth 2.0 Authorization Server containing
/// the issued access token and related information.
/// </summary>
public class TokenResponse
{
/// <summary>
/// Indicates if the Token Request is still pending as the Credential Issuer
/// is waiting for the End-User interaction to complete.
/// </summary>
[JsonProperty("authorization_pending")]
public bool? AuthorizationPending { get; set; }

/// <summary>
/// Gets or sets the lifetime in seconds of the c_nonce.
/// </summary>
[JsonProperty("c_nonce_expires_in")]
public int? CNonceExpiresIn { get; set; }

/// <summary>
/// Gets or sets the lifetime in seconds of the access token.
/// </summary>
[JsonProperty("expires_in")]
public int? ExpiresIn { get; set; }

/// <summary>
/// Gets or sets the minimum amount of time in seconds that the client should wait
/// between polling requests to the Token Endpoint.
/// </summary>
[JsonProperty("interval")]
public int? Interval { get; set; }

/// <summary>
/// Gets or sets the access token issued by the authorization server.
/// </summary>
[JsonProperty("access_token")]
public string AccessToken { get; set; }

/// <summary>
/// Gets or sets the nonce to be used to create a proof of possession of key material
/// when requesting a Credential.
/// </summary>
[JsonProperty("c_nonce")]
public string CNonce { get; set; }

/// <summary>
/// Gets or sets the refresh token, which can be used to obtain new access tokens.
/// </summary>
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }

/// <summary>
/// Gets or sets the scope of the access token.
/// </summary>
[JsonProperty("scope")]
public string Scope { get; set; }

/// <summary>
/// Gets or sets the type of the token issued.
/// </summary>
[JsonProperty("token_type")]
public string TokenType { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#nullable enable

using Newtonsoft.Json;

namespace Hyperledger.Aries.Features.OpenId4Vc.Vci.Models.CredentialOffer.GrantTypes
{
/// <summary>
/// Represents the parameters for the 'authorization_code' grant type.
/// </summary>
public class AuthorizationCode
{
/// <summary>
/// Gets or sets an optional string value created by the Credential Issuer, opaque to the Wallet, that is used to bind
/// the subsequent Authorization Request with the Credential Issuer to a context set up during previous steps.
/// </summary>
[JsonProperty("issuer-state")]
public string? IssuerState { get; set; }
}
}
Loading

0 comments on commit f9d7b05

Please sign in to comment.