Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authz/token validator #11

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft

Authz/token validator #11

wants to merge 4 commits into from

Conversation

MrWoo034
Copy link
Collaborator

@MrWoo034 MrWoo034 commented Dec 3, 2024

No description provided.

@MrWoo034 MrWoo034 requested review from ncpenke and jeffgrunewald and removed request for jeffgrunewald December 3, 2024 20:49
/// invalid without any further verification.
/// **Note**: this limit is part of the [IC specification](https://internetcomputer.org/docs/current/references/ic-interface-spec#authentication)
/// and so changing this value might be breaking or result in a deviation from the specification.
const MAXIMUM_NUMBER_OF_TARGETS_PER_DELEGATION: usize = 1_000;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we're worried about this deviating is there any function or constant exported in any of the IC crates we import that we can draw this value from so we can just implicitly continue to follow the spec even if it changes?

Comment on lines +110 to +121
pub enum RequestValidationError {
InvalidIngressExpiry(String),
InvalidDelegationExpiry(String),
UserIdDoesNotMatchPublicKey(UserId, Vec<u8>),
InvalidSignature(AuthenticationError),
InvalidDelegation(AuthenticationError),
MissingSignature(UserId),
AnonymousSignatureNotAllowed,
CanisterNotInDelegationTargets(CanisterId),
TooManyPathsError { length: usize, maximum: usize },
PathTooLongError { length: usize, maximum: usize },
NonceTooBigError { num_bytes: usize, maximum: usize },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use the thiserror #[error()] macro to define the display impls for these?

Suggested change
pub enum RequestValidationError {
InvalidIngressExpiry(String),
InvalidDelegationExpiry(String),
UserIdDoesNotMatchPublicKey(UserId, Vec<u8>),
InvalidSignature(AuthenticationError),
InvalidDelegation(AuthenticationError),
MissingSignature(UserId),
AnonymousSignatureNotAllowed,
CanisterNotInDelegationTargets(CanisterId),
TooManyPathsError { length: usize, maximum: usize },
PathTooLongError { length: usize, maximum: usize },
NonceTooBigError { num_bytes: usize, maximum: usize },
pub enum RequestValidationError {
#[error("invalid ingress expiry {0}")]
InvalidIngressExpiry(String),
#[error("invalid delegation expiry {0}")]
InvalidDelegationExpiry(String),
...


/// Error in verifying the signature or authentication part of a request.
#[derive(Debug, PartialEq, thiserror::Error)]
pub enum AuthenticationError {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question here

Comment on lines +227 to +230
"Specified ingress_expiry not within expected range: \
Minimum allowed expiry: {}, \
Maximum allowed expiry: {}, \
Provided expiry: {}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the variability in these different error messages feels like maybe the InvalidIngressExpiry needs to be split into a couple more specific errors? like IngressExpiryTooEarly, IngressExpiryTooLate etc which would allow for moving a lot of the message of the error into the macro-based display string for the error and allow for more targeted handling of the different errors through matching in the caller?

} else {
Err(UserIdDoesNotMatchPublicKey(
UserId::new(id),
sender_pubkey.to_vec(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if the error display impl allows for the hex encoding of these bytes but unless you want to be able to match on this error and make use of the raw bytes of the pubkey in the error handling code, why not just do the display-encoding here and then interpolate that value into the error message without encoding it there?

DelegationContainsCyclesError { public_key } => write!(
f,
"Chain of delegations contains at least one cycle: first repeating public key encountered {}",
hex::encode(public_key)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

especially if these are ultimately ed25519 public keys it might be more conventional to base58 code this when displaying

Comment on lines +258 to +275
pubkey: Vec<u8>,
root_of_trust_provider: &R,
) -> Result<(), RequestValidationError>
where
R::Error: std::error::Error,
{
ensure_delegations_does_not_contain_cycles(&pubkey, signed_delegations)?;
ensure_delegations_does_not_contain_too_many_targets(signed_delegations)?;

for sd in signed_delegations {
let delegation = sd.delegation();
let signature = sd.signature();

validate_delegation(
validator,
signature,
delegation,
&pubkey,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pubkey: Vec<u8>,
root_of_trust_provider: &R,
) -> Result<(), RequestValidationError>
where
R::Error: std::error::Error,
{
ensure_delegations_does_not_contain_cycles(&pubkey, signed_delegations)?;
ensure_delegations_does_not_contain_too_many_targets(signed_delegations)?;
for sd in signed_delegations {
let delegation = sd.delegation();
let signature = sd.signature();
validate_delegation(
validator,
signature,
delegation,
&pubkey,
pubkey: &[u8],
root_of_trust_provider: &R,
) -> Result<(), RequestValidationError>
where
R::Error: std::error::Error,
{
ensure_delegations_does_not_contain_cycles(pubkey, signed_delegations)?;
ensure_delegations_does_not_contain_too_many_targets(signed_delegations)?;
for sd in signed_delegations {
let delegation = sd.delegation();
let signature = sd.signature();
validate_delegation(
validator,
signature,
delegation,
pubkey,

}

fn validate_token_user_id_and_signature(token: &Token) -> Result<(), RequestValidationError> {
let _signature = &token.signature;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants