Skip to content

Commit

Permalink
Fix issuer claim check in VC (#1235)
Browse files Browse the repository at this point in the history
  • Loading branch information
abdulmth authored Sep 20, 2023
1 parent e8f33c7 commit 1644831
Showing 1 changed file with 261 additions and 0 deletions.
261 changes: 261 additions & 0 deletions identity_credential/src/credential/jwt_serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ where
credential_subject: InnerCredentialSubject::new(subject),
issuance_date: None,
expiration_date: None,
issuer: None,
credential_schema: Cow::Borrowed(credential_schema),
credential_status: credential_status.as_ref().map(Cow::Borrowed),
refresh_service: Cow::Borrowed(refresh_service),
Expand All @@ -118,6 +119,18 @@ where
/// Checks whether the fields that are set in the `vc` object are consistent with the corresponding values
/// set for the registered claims.
fn check_consistency(&self) -> Result<()> {
// Check consistency of issuer.
let issuer_from_claims: &Issuer = self.iss.as_ref();
if !self
.vc
.issuer
.as_ref()
.map(|value| value == issuer_from_claims)
.unwrap_or(true)
{
return Err(Error::InconsistentCredentialJwtClaims("inconsistent issuer"));
};

// Check consistency of issuanceDate
let issuance_date_from_claims = self.issuance_date.to_issuance_date()?;
if !self
Expand Down Expand Up @@ -197,6 +210,7 @@ where
properties,
proof,
issuance_date: _,
issuer: _,
expiration_date: _,
} = vc;

Expand Down Expand Up @@ -302,6 +316,9 @@ where
/// One or more URIs defining the type of the `Credential`.
#[serde(rename = "type")]
types: Cow<'credential, OneOrMany<String>>,
/// The issuer of the `Credential`.
#[serde(skip_serializing_if = "Option::is_none")]
issuer: Option<Issuer>,
/// One or more `Object`s representing the `Credential` subject(s).
#[serde(rename = "credentialSubject")]
credential_subject: InnerCredentialSubject<'credential>,
Expand Down Expand Up @@ -345,6 +362,7 @@ mod tests {
use identity_core::convert::ToJson;

use crate::credential::Credential;
use crate::Error;

use super::CredentialJwtClaims;

Expand Down Expand Up @@ -409,4 +427,247 @@ mod tests {

assert_eq!(credential, retrieved_credential);
}

#[test]
fn claims_duplication() {
let credential_json: &str = r#"
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "http://example.edu/credentials/3732",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "https://example.edu/issuers/14",
"issuanceDate": "2010-01-01T19:23:24Z",
"expirationDate": "2025-09-13T15:56:23Z",
"credentialSubject": {
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science in Mechanical Engineering"
}
}
}"#;

// `sub`, `exp`, `jti`, `iss`, `nbf` are duplicated in `vc`.
let claims_json: &str = r#"
{
"sub": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"jti": "http://example.edu/credentials/3732",
"iss": "https://example.edu/issuers/14",
"nbf": 1262373804,
"exp": 1757778983,
"vc": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "http://example.edu/credentials/3732",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "https://example.edu/issuers/14",
"issuanceDate": "2010-01-01T19:23:24Z",
"expirationDate": "2025-09-13T15:56:23Z",
"credentialSubject": {
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science in Mechanical Engineering"
}
}
}
}"#;

let credential: Credential = Credential::from_json(credential_json).unwrap();
let credential_from_claims: Credential = CredentialJwtClaims::<'_, Object>::from_json(&claims_json)
.unwrap()
.try_into_credential()
.unwrap();

assert_eq!(credential, credential_from_claims);
}

#[test]
fn inconsistent_issuer() {
// issuer is inconsistent (15 instead of 14).
let claims_json: &str = r#"
{
"sub": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"jti": "http://example.edu/credentials/3732",
"iss": "https://example.edu/issuers/14",
"nbf": 1262373804,
"vc": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "https://example.edu/issuers/15",
"credentialSubject": {
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science in Mechanical Engineering"
}
}
}
}"#;

let credential_from_claims_result: Result<Credential, _> =
CredentialJwtClaims::<'_, Object>::from_json(&claims_json)
.unwrap()
.try_into_credential();
assert!(matches!(
credential_from_claims_result.unwrap_err(),
Error::InconsistentCredentialJwtClaims("inconsistent issuer")
));
}

#[test]
fn inconsistent_id() {
let claims_json: &str = r#"
{
"sub": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"jti": "http://example.edu/credentials/3732",
"iss": "https://example.edu/issuers/14",
"nbf": 1262373804,
"vc": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"id": "http://example.edu/credentials/1111",
"credentialSubject": {
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science in Mechanical Engineering"
}
}
}
}"#;

let credential_from_claims_result: Result<Credential, _> =
CredentialJwtClaims::<'_, Object>::from_json(&claims_json)
.unwrap()
.try_into_credential();
assert!(matches!(
credential_from_claims_result.unwrap_err(),
Error::InconsistentCredentialJwtClaims("inconsistent credential id")
));
}

#[test]
fn inconsistent_subject() {
let claims_json: &str = r#"
{
"sub": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"jti": "http://example.edu/credentials/3732",
"iss": "https://example.edu/issuers/14",
"nbf": 1262373804,
"vc": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "http://example.edu/credentials/3732",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "https://example.edu/issuers/14",
"issuanceDate": "2010-01-01T19:23:24Z",
"credentialSubject": {
"id": "did:example:1111111111111111111111111",
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science in Mechanical Engineering"
}
}
}
}"#;

let credential_from_claims_result: Result<Credential, _> =
CredentialJwtClaims::<'_, Object>::from_json(&claims_json)
.unwrap()
.try_into_credential();
assert!(matches!(
credential_from_claims_result.unwrap_err(),
Error::InconsistentCredentialJwtClaims("inconsistent credentialSubject: identifiers do not match")
));
}

#[test]
fn inconsistent_issuance_date() {
// issuer is inconsistent (15 instead of 14).
let claims_json: &str = r#"
{
"sub": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"jti": "http://example.edu/credentials/3732",
"iss": "https://example.edu/issuers/14",
"nbf": 1262373804,
"vc": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "http://example.edu/credentials/3732",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "https://example.edu/issuers/14",
"issuanceDate": "2020-01-01T19:23:24Z",
"credentialSubject": {
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science in Mechanical Engineering"
}
}
}
}"#;

let credential_from_claims_result: Result<Credential, _> =
CredentialJwtClaims::<'_, Object>::from_json(&claims_json)
.unwrap()
.try_into_credential();
assert!(matches!(
credential_from_claims_result.unwrap_err(),
Error::InconsistentCredentialJwtClaims("inconsistent issuanceDate")
));
}

#[test]
fn inconsistent_expiration_date() {
// issuer is inconsistent (15 instead of 14).
let claims_json: &str = r#"
{
"sub": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"jti": "http://example.edu/credentials/3732",
"iss": "https://example.edu/issuers/14",
"nbf": 1262373804,
"exp": 1757778983,
"vc": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "http://example.edu/credentials/3732",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "https://example.edu/issuers/14",
"issuanceDate": "2010-01-01T19:23:24Z",
"expirationDate": "2026-09-13T15:56:23Z",
"credentialSubject": {
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science in Mechanical Engineering"
}
}
}
}"#;

let credential_from_claims_result: Result<Credential, _> =
CredentialJwtClaims::<'_, Object>::from_json(&claims_json)
.unwrap()
.try_into_credential();
assert!(matches!(
credential_from_claims_result.unwrap_err(),
Error::InconsistentCredentialJwtClaims("inconsistent credential expirationDate")
));
}
}

0 comments on commit 1644831

Please sign in to comment.