Skip to content

Commit

Permalink
strip extra quotations in authorization response url encoding, add op…
Browse files Browse the repository at this point in the history
…tional state property to response

Signed-off-by: Ryan Tate <[email protected]>
  • Loading branch information
Ryanmtate committed Jan 24, 2025
1 parent 8df92db commit 1cd2b46
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 6 deletions.
8 changes: 7 additions & 1 deletion src/core/authorization_request/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::ops::{Deref, DerefMut};

use anyhow::{anyhow, bail, Context, Error, Result};
use parameters::ClientMetadata;
use parameters::{ClientMetadata, State};
use serde::{Deserialize, Serialize};
use serde_json::Value as Json;
use url::Url;
Expand Down Expand Up @@ -280,6 +280,12 @@ impl AuthorizationRequestObject {
.get()
.ok_or(anyhow!("missing vp_formats"))?
}

/// Return the `state` of the authorization request,
/// if it was provided.
pub fn state(&self) -> Option<Result<State>> {
self.0.get()
}
}

impl From<AuthorizationRequestObject> for UntypedObject {
Expand Down
2 changes: 1 addition & 1 deletion src/core/authorization_request/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ impl From<ResponseType> for Json {
}
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct State(pub String);

impl TypedParameter for State {
Expand Down
1 change: 1 addition & 0 deletions src/core/presentation_submission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ pub struct DescriptorMap {
pub id: DescriptorMapId,
pub format: ClaimFormatDesignation,
pub path: JsonPath,
#[serde(skip_serializing_if = "Option::is_none")]
pub path_nested: Option<Box<DescriptorMap>>,
}

Expand Down
41 changes: 37 additions & 4 deletions src/core/response/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use super::{object::UntypedObject, presentation_submission::PresentationSubmission};

use anyhow::{Context, Error, Result};
use parameters::State;
use serde::{Deserialize, Serialize};
use url::Url;

use self::parameters::VpToken;

pub mod parameters;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum AuthorizationResponse {
Unencoded(UnencodedAuthorizationResponse),
Jwt(JwtAuthorizationResponse),
Expand All @@ -30,25 +32,37 @@ impl AuthorizationResponse {
serde_json::from_str(&unencoded.presentation_submission)
.context("failed to decode presentation submission")?;

let state: Option<State> = unencoded
.state
.map(|s| serde_json::from_str(&s))
.transpose()
.context("failed to decode state")?;

Ok(Self::Unencoded(UnencodedAuthorizationResponse {
vp_token,
presentation_submission,
state,
}))
}
}

#[derive(Debug, Deserialize, Serialize)]
struct JsonEncodedAuthorizationResponse {
/// `vp_token` is JSON string encoded.
pub(crate) vp_token: String,
/// `presentation_submission` is JSON string encoded.
pub(crate) presentation_submission: String,
/// `vp_token` is JSON string encoded.
pub(crate) vp_token: String,
/// `state` is a regular string.
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) state: Option<String>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct UnencodedAuthorizationResponse {
pub vp_token: VpToken,
pub presentation_submission: PresentationSubmission,
pub vp_token: VpToken,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<State>,
}

impl UnencodedAuthorizationResponse {
Expand All @@ -73,18 +87,37 @@ impl UnencodedAuthorizationResponse {
}
}

// Helper method for cleaning up quoted strings.
// urlencoding a JSON string adds quotes around the string,
// which causes issues when decoding.
fn clean_quoted_string(s: &str) -> String {
s.trim_matches(|c| c == '"' || c == '\'').to_string()
}

impl From<UnencodedAuthorizationResponse> for JsonEncodedAuthorizationResponse {
fn from(value: UnencodedAuthorizationResponse) -> Self {
let vp_token = serde_json::to_string(&value.vp_token)
.ok()
// Need to strip quotes from the string.
.map(|s| clean_quoted_string(&s))
// SAFTEY: VP Token will always be a valid JSON object.
.unwrap();

let presentation_submission = serde_json::to_string(&value.presentation_submission)
// SAFETY: presentation submission will always be a valid JSON object.
.unwrap();

let state = value
.state
.map(|s| serde_json::to_string(&s))
.transpose()
// SAFETY: State will always be a valid JSON object.
.unwrap();

Self {
vp_token,
presentation_submission,
state,
}
}
}
Expand Down

0 comments on commit 1cd2b46

Please sign in to comment.