Skip to content

Commit

Permalink
Update library to implementor's draft 1 (draft 13) (#14)
Browse files Browse the repository at this point in the history
Signed-off-by: Tiago Nascimento <tiago.nascimento@spruceid.com>
  • Loading branch information
theosirian authored Aug 14, 2024
1 parent 5ccb842 commit bee9a3d
Show file tree
Hide file tree
Showing 22 changed files with 960 additions and 203 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ async-signature = "0.3.0"
rand = "0.8.5"
time = { version = "0.3.29", features = ["serde"] }
thiserror = "1.0.49"
tracing = "0.1"
base64 = "0.21.4"
serde_urlencoded = "0.7.1"

Expand Down
52 changes: 41 additions & 11 deletions src/authorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ use openidconnect::{CsrfToken, IssuerUrl};
use serde::{Deserialize, Serialize};
use url::Url;

use crate::profiles::AuthorizationDetaislProfile;
use crate::profiles::AuthorizationDetailsProfile;

pub struct AuthorizationRequest<'a, AD>
where
AD: AuthorizationDetaislProfile,
AD: AuthorizationDetailsProfile,
{
inner: oauth2::AuthorizationRequest<'a>, // TODO
authorization_details: Vec<AuthorizationDetail<AD>>,
Expand All @@ -20,7 +20,7 @@ where

impl<'a, AD> AuthorizationRequest<'a, AD>
where
AD: AuthorizationDetaislProfile,
AD: AuthorizationDetailsProfile,
{
pub(crate) fn new(
inner: oauth2::AuthorizationRequest<'a>,
Expand Down Expand Up @@ -74,10 +74,10 @@ where
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct AuthorizationDetail<AD>
where
AD: AuthorizationDetaislProfile,
AD: AuthorizationDetailsProfile,
{
r#type: AuthorizationDetailType,
#[serde(flatten, bound = "AD: AuthorizationDetaislProfile")]
#[serde(flatten, bound = "AD: AuthorizationDetailsProfile")]
addition_profile_fields: AD,
#[serde(skip_serializing_if = "Option::is_none")]
locations: Option<Vec<IssuerUrl>>,
Expand All @@ -97,7 +97,7 @@ mod test {
use serde_json::json;

use crate::{
core::profiles::{w3c, CoreProfilesAuthorizationDetails},
core::profiles::{w3c, CoreProfilesAuthorizationDetails, ValueAuthorizationDetails},
metadata::CredentialUrl,
};

Expand All @@ -121,6 +121,34 @@ mod test {
.unwrap();
}

#[test]
fn example_authorization_details_credential_configuration_id() {
let _: Vec<AuthorizationDetail<CoreProfilesAuthorizationDetails>> =
serde_json::from_value(json!([
{
"type": "openid_credential",
"credential_configuration_id": "UniversityDegreeCredential"
}
]))
.unwrap();
}

#[test]
fn example_authorization_details_credential_configuration_id_deny() {
assert!(
serde_json::from_value::<Vec<AuthorizationDetail<CoreProfilesAuthorizationDetails>>>(
json!([
{
"type": "openid_credential",
"format": "jwt_vc_json",
"credential_configuration_id": "UniversityDegreeCredential"
}
])
)
.is_err()
);
}

#[test]
fn example_authorization_details_locations() {
let _: Vec<AuthorizationDetail<CoreProfilesAuthorizationDetails>> =
Expand Down Expand Up @@ -190,11 +218,13 @@ mod test {
let state = CsrfToken::new("state".into());
let authorization_details = vec![AuthorizationDetail {
r#type: AuthorizationDetailType::OpenidCredential,
addition_profile_fields: CoreProfilesAuthorizationDetails::JWTVC(
w3c::jwt::AuthorizationDetails::new(w3c::CredentialDefinition::new(vec![
"VerifiableCredential".into(),
"UniversityDegreeCredential".into(),
])),
addition_profile_fields: CoreProfilesAuthorizationDetails::Value(
ValueAuthorizationDetails::JWTVC(w3c::jwt::AuthorizationDetails::new(
w3c::CredentialDefinition::new(vec![
"VerifiableCredential".into(),
"UniversityDegreeCredential".into(),
]),
)),
),
locations: None,
}];
Expand Down
69 changes: 34 additions & 35 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ use serde::{Deserialize, Serialize};
use crate::{
authorization::AuthorizationRequest,
credential,
credential_response_encryption::CredentialResponseEncryptionMetadata,
metadata::{
AuthorizationMetadata, CredentialMetadata, CredentialUrl, IssuerMetadata,
IssuerMetadataDisplay,
AuthorizationMetadata, CredentialIssuerMetadata, CredentialIssuerMetadataDisplay,
CredentialMetadata, CredentialUrl,
},
profiles::{AuthorizationDetaislProfile, Profile},
profiles::{AuthorizationDetailsProfile, Profile},
pushed_authorization::PushedAuthorizationRequest,
token,
types::{BatchCredentialUrl, DeferredCredentialUrl, ParUrl},
Expand All @@ -41,7 +42,7 @@ where
C: Profile,
JT: JsonWebKeyType,
JE: JweContentEncryptionAlgorithm<JT>,
JA: JweKeyManagementAlgorithm,
JA: JweKeyManagementAlgorithm + Clone,
{
inner: oauth2::Client<
BasicErrorResponse,
Expand All @@ -56,11 +57,9 @@ where
par_auth_url: Option<ParUrl>,
batch_credential_endpoint: Option<BatchCredentialUrl>,
deferred_credential_endpoint: Option<DeferredCredentialUrl>,
credential_response_encryption_alg_values_supported: Option<Vec<JA>>,
credential_response_encryption_enc_values_supported: Option<Vec<JE>>,
require_credential_response_encryption: Option<bool>,
credentials_supported: Vec<CredentialMetadata<C::Metadata>>,
display: Option<IssuerMetadataDisplay>,
credential_response_encryption: Option<CredentialResponseEncryptionMetadata<JT, JE, JA>>,
credential_configurations_supported: Vec<CredentialMetadata<C::Metadata>>,
display: Option<Vec<CredentialIssuerMetadataDisplay>>,
_phantom_jt: PhantomData<JT>,
}

Expand Down Expand Up @@ -89,10 +88,8 @@ where
par_auth_url,
batch_credential_endpoint: None,
deferred_credential_endpoint: None,
credential_response_encryption_alg_values_supported: None,
credential_response_encryption_enc_values_supported: None,
require_credential_response_encryption: None,
credentials_supported: vec![],
credential_response_encryption: None,
credential_configurations_supported: vec![],
display: None,
_phantom_jt: PhantomData,
}
Expand All @@ -104,48 +101,50 @@ where
set_credential_endpoint -> credential_endpoint[CredentialUrl],
set_batch_credential_endpoint -> batch_credential_endpoint[Option<BatchCredentialUrl>],
set_deferred_credential_endpoint -> deferred_credential_endpoint[Option<DeferredCredentialUrl>],
set_credential_response_encryption_alg_values_supported -> credential_response_encryption_alg_values_supported[Option<Vec<JA>>],
set_credential_response_encryption_enc_values_supported -> credential_response_encryption_enc_values_supported[Option<Vec<JE>>],
set_require_credential_response_encryption -> require_credential_response_encryption[Option<bool>],
set_credentials_supported -> credentials_supported[Vec<CredentialMetadata<C::Metadata>>],
set_display -> display[Option<IssuerMetadataDisplay>],
set_credential_response_encryption -> credential_response_encryption[Option<CredentialResponseEncryptionMetadata<JT, JE, JA>>],
set_credential_configurations_supported -> credential_configurations_supported[Vec<CredentialMetadata<C::Metadata>>],
set_display -> display[Option<Vec<CredentialIssuerMetadataDisplay>>],
}
];

pub fn from_issuer_metadata(
issuer_metadata: IssuerMetadata<C::Metadata, JT, JE, JA>,
credential_issuer_metadata: CredentialIssuerMetadata<C::Metadata, JT, JE, JA>,
authorization_metadata: AuthorizationMetadata,
client_id: ClientId,
redirect_uri: RedirectUrl,
) -> Self {
Self::new(
client_id,
issuer_metadata.credential_issuer().clone(),
issuer_metadata.credential_endpoint().clone(),
credential_issuer_metadata.credential_issuer().clone(),
credential_issuer_metadata.credential_endpoint().clone(),
authorization_metadata.authorization_endpoint().clone(),
authorization_metadata
.pushed_authorization_endpoint()
.clone(),
authorization_metadata.token_endpoint().clone(),
redirect_uri,
)
.set_batch_credential_endpoint(issuer_metadata.batch_credential_endpoint().cloned())
.set_deferred_credential_endpoint(issuer_metadata.deferred_credential_endpoint().cloned())
.set_credential_response_encryption_alg_values_supported(
issuer_metadata
.credential_response_encryption_alg_values_supported()
.set_batch_credential_endpoint(
credential_issuer_metadata
.batch_credential_endpoint()
.cloned(),
)
.set_deferred_credential_endpoint(
credential_issuer_metadata
.deferred_credential_endpoint()
.cloned(),
)
.set_credential_response_encryption_enc_values_supported(
issuer_metadata
.credential_response_encryption_enc_values_supported()
.set_credential_response_encryption(
credential_issuer_metadata
.credential_response_encryption()
.cloned(),
)
.set_require_credential_response_encryption(
issuer_metadata.require_credential_response_encryption(),
.set_display(credential_issuer_metadata.display().cloned())
.set_credential_configurations_supported(
credential_issuer_metadata
.credential_configurations_supported()
.clone(),
)
.set_credentials_supported(issuer_metadata.credentials_supported().clone())
.set_display(issuer_metadata.display().cloned())
}

pub fn pushed_authorization_request<S, AD>(
Expand All @@ -154,7 +153,7 @@ where
) -> Result<PushedAuthorizationRequest<AD>, Error>
where
S: FnOnce() -> CsrfToken,
AD: AuthorizationDetaislProfile,
AD: AuthorizationDetailsProfile,
{
if self.par_auth_url.is_none() {
return Err(Error::ParUnsupported());
Expand All @@ -174,7 +173,7 @@ where
pub fn authorize_url<S, AD>(&self, state_fn: S) -> AuthorizationRequest<AD>
where
S: FnOnce() -> CsrfToken,
AD: AuthorizationDetaislProfile,
AD: AuthorizationDetailsProfile,
{
let inner = self.inner.authorize_url(state_fn);
AuthorizationRequest::new(inner, vec![], None, None, None)
Expand Down
2 changes: 1 addition & 1 deletion src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub mod metadata {

use super::profiles::CoreProfilesMetadata;

pub type IssuerMetadata = metadata::IssuerMetadata<
pub type CredentialIssuerMetadata = metadata::CredentialIssuerMetadata<
CoreProfilesMetadata,
CoreJsonWebKeyType,
CoreJweContentEncryptionAlgorithm,
Expand Down
29 changes: 25 additions & 4 deletions src/core/profiles/isomdl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use isomdl::definitions::device_request::DocType;
use serde::{Deserialize, Serialize};

use super::{
w3c::CredentialSubjectClaims, AuthorizationDetaislProfile, CredentialMetadataProfile,
w3c::CredentialSubjectClaims, AuthorizationDetailsProfile, CredentialMetadataProfile,
CredentialOfferProfile, CredentialRequestProfile, CredentialResponseProfile,
};

pub type Namespace = String;

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct Metadata {
// cryptographic_suites_supported: Option<Vec<cose::Algorithm>>, // TODO cose
// credential_signing_alg_values_supported: Option<Vec<cose::Algorithm>>, // TODO cose
doctype: DocType,
claims: Option<HashMap<Namespace, CredentialSubjectClaims>>,
order: Option<Vec<String>>,
Expand Down Expand Up @@ -63,14 +63,26 @@ impl CredentialOfferProfile for Offer {}
pub struct AuthorizationDetails {
doctype: DocType,
claims: Option<HashMap<Namespace, CredentialSubjectClaims>>,

#[serde(
default,
skip_serializing,
deserialize_with = "crate::deny_field::deny_field",
rename = "credential_configuration_id"
)]
_credential_configuration_id: (),
}

impl AuthorizationDetails {
pub fn new(
doctype: DocType,
claims: Option<HashMap<Namespace, CredentialSubjectClaims>>,
) -> Self {
Self { doctype, claims }
Self {
doctype,
claims,
_credential_configuration_id: (),
}
}
field_getters_setters![
pub self [self] ["ISO mDL authorization details value"] {
Expand All @@ -79,19 +91,28 @@ impl AuthorizationDetails {
}
];
}
impl AuthorizationDetaislProfile for AuthorizationDetails {}
impl AuthorizationDetailsProfile for AuthorizationDetails {}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct Request {
doctype: DocType,
claims: Option<HashMap<Namespace, CredentialSubjectClaims>>,

#[serde(
default,
skip_serializing,
deserialize_with = "crate::deny_field::deny_field",
rename = "credential_identifier"
)]
_credential_identifier: (),
}

impl Request {
pub fn new(doctype: DocType) -> Self {
Self {
doctype,
claims: None,
_credential_identifier: (),
}
}
field_getters_setters![
Expand Down
Loading

0 comments on commit bee9a3d

Please sign in to comment.