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

Allow reusing SIWE messages in EIP4361-based condition authentication #529

Merged
merged 5 commits into from
Jul 1, 2024

Conversation

piotr-roslaniec
Copy link
Contributor

@piotr-roslaniec piotr-roslaniec commented Jun 12, 2024

Type of PR:

  • Feature

Required reviews:

  • 2

What this does:

  • Allows reusing of existing SIWE messages by providing them as a context parameter at decryption time
  • Internally, it reuses the :userAddressEIP4361 context parameter - Hence, no changes on the server side required.

Issues fixed/closed:

Notes for reviewers:

@piotr-roslaniec piotr-roslaniec force-pushed the reuse-siwe branch 2 times, most recently from a472dec to bb84d70 Compare June 12, 2024 10:46
@piotr-roslaniec
Copy link
Contributor Author

Sending review requests for an early review of this draft

Copy link
Member

@manumonti manumonti left a comment

Choose a reason for hiding this comment

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

This looks good to me, not sure how much more work is needed, but it seems pretty complete.

packages/taco/test/conditions/context.test.ts Outdated Show resolved Hide resolved
@piotr-roslaniec piotr-roslaniec marked this pull request as ready for review June 21, 2024 12:08
@piotr-roslaniec
Copy link
Contributor Author

Asking for review despite some rough edges to confirm the design

Copy link
Member

@derekpierre derekpierre left a comment

Choose a reason for hiding this comment

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

Based on the changes in #531 , feels like this PR would look a lot different post-#531. And if merged pre-#531 it would create quite a bit of merge conflicts for #531. Would basing over #531 make that simpler?

We also don't address how to help the user "easily" generates the AuthSignature .
It would be nice to have to a function/API (seemingly an AuthProvider) that helps with generating the AuthSignature format we want for external SIWE? Or is that planned for a follow-up? wdyt?

packages/taco/src/conditions/context/context.ts Outdated Show resolved Hide resolved
@piotr-roslaniec
Copy link
Contributor Author

@derekpierre I think we can rebase this over #531.

I added a public method to the EIP4361 auth provider to expose message-creating logic to end-users.

@piotr-roslaniec
Copy link
Contributor Author

Rebased over #531

Copy link
Member

@derekpierre derekpierre left a comment

Choose a reason for hiding this comment

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

One thought for this PR, was that the AuthSignature is the thing that is TACo-specific as opposed to the SIWE message. It could be helpful to have something (utility function or class or otherwise) that generates the AuthSignature type so that users don't need to know the specifics of it eg. generateSIWEAuthSignature(address: string, siweMessage: string, signature: Uint8Array). With something like that, the user can use whatever they want for generating the siweMessage and taco-auth can take those as parameters and simply produce an AuthSignature type for them.

It's not something overly flashy, but is helpful in abstracting away the creation of the AuthSignature a bit.

If they are using single sign-on then presumably they already have a SIWE library that they are using and we would be helping them convert that into a format that we can use i.e. the AuthSignature.

Thoughts?

packages/taco/src/conditions/context/context.ts Outdated Show resolved Hide resolved
return { signature, address, scheme, typedData: message };
}

public static prepareSiweMessage(address: string, chainId: number, domain: string, uri: string) {
Copy link
Member

Choose a reason for hiding this comment

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

Is this static method related to the TODO on L61?

I might be missing the use case for this method? Just a helper for the user to create a SIWE message to then use for the context variable? If so, it seems pretty restrictive since there are more values that SIWE allows apps to customize.

In terms of our default EIP4361 auth provider behaviour, there is a question about what values to use for domain and uri, and whether the user can customize that, so wondering if this is related?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just a helper for the user to create a SIWE message to then use for the context variable?

Yes, it's just a helper function to expose a SIWE-message-creating logic to end-users. I think I will also refactor-out the types related to SIWE so that it's more configurable and gives users more freedom (as you've noted).

so wondering if this is related?

Yes, it's related, but I planned on fixing the defaults later. I will attempt to squeeze it into this PR, but if it doesn't make sense I will follow up in the next one.

Copy link
Member

@derekpierre derekpierre Jun 24, 2024

Choose a reason for hiding this comment

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

Yes, it's just a helper function to expose a SIWE-message-creating logic to end-users. I think I will also refactor-out the types related to SIWE so that it's more configurable and gives users more freedom (as you've noted).

In that case, I'm a bit apprehensive about the benefits of us trying to provide extensive SIWE-message-creating logic. Then we just end up either making something more restrictive with limited use (less parameters than the SIWE API) or writing a layer on top of the SIWE library that uses the same API parameterization of the library anyway. Users should just use the siwe library or some other one for generating the SIWE message if they want such a high level of customization of messages.

At the moment, we have two worlds:

  1. Apps that expect TACo to do the SIWE info for them because they don't use SIWE at all (:userAddress)
  2. Apps that currently use SIWE and expect to provide TACo with their existing SIWE info so that it can be reused (:userAddressExternalEIP4361)

In world 1) apps don't currently use SIWE at all, so TACo will create/generate the AuthSignature on their behalf. At most, the app may need to specify the domain / uri if taco-auth can't detect those values from the window object / use some default value to get the right value based on the SIWE spec (i.e. prevent the signing from being flagged as "unsafe"). But these apps probably don't need more customization than that, or else they would probably be in world 2) anyway.

In world 2) the app uses their own tooling for the SIWE message/signature and all they want to do is give that information to TACo (Ceramic example). No customization of SIWE message parameters needed here because the message and signature are already generated by the app separately.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see your point. I had a slightly different idea of how to go about this, but I see merit in this solution.

I dropped the commit with previous changes and added an ability to set defaults for the EIP4361 provider. I will expose it as a part of #533

Copy link
Member

@derekpierre derekpierre Jun 25, 2024

Choose a reason for hiding this comment

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

I had a slightly different idea of how to go about this, but I see merit in this solution.

Happy to listen to and work through your ideas.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So far I'm happy with this PR as it is, I think we may revisit this once we deprecate EIP712 and start ironing-out the user-facing API

Comment on lines +37 to +38
// USER_ADDRESS_PARAM_EXTERNAL_EIP4361 is not reserved and can be used as a custom context parameter
// USER_ADDRESS_PARAM_EXTERNAL_EIP4361
Copy link
Member

Choose a reason for hiding this comment

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

Why not delete these lines instead of commenting them out?

Copy link
Contributor Author

@piotr-roslaniec piotr-roslaniec Jun 24, 2024

Choose a reason for hiding this comment

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

I thought it was more explicit (explicitly disabled), is it confusing? Maybe an assertion is better.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe an assertion is better.

Interesting. Where would you put the assertion?

Alternatively, maybe keep the comment on L37 and remove L38?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

An assertion could be a statement in this file that gets executed when the file is imported. That's a bit ham-fisted, I need to think about this. In the meantime, I will remove L38.

Copy link
Member

Choose a reason for hiding this comment

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

Agreed - the assertion seems too heavy.

@piotr-roslaniec
Copy link
Contributor Author

Thoughts?

I think AuthSignature will become a class rather than an interface, and we will add more utilities and conversion functions as we go. Adding more factory methods, especially for SIWE, makes sense. I will look into it.

Comment on lines +37 to +38
// USER_ADDRESS_PARAM_EXTERNAL_EIP4361 is not reserved and can be used as a custom context parameter
// USER_ADDRESS_PARAM_EXTERNAL_EIP4361
Copy link
Member

Choose a reason for hiding this comment

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

Maybe an assertion is better.

Interesting. Where would you put the assertion?

Alternatively, maybe keep the comment on L37 and remove L38?

Comment on lines +144 to 146
} else {
// Not a context parameter, we can skip
}
Copy link
Member

Choose a reason for hiding this comment

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

Is the empty block for a comment something common in typescript? Perhaps just the comment?

Suggested change
} else {
// Not a context parameter, we can skip
}
}
// else not a context parameter, we can skip

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's no TS-related, just something I sometimes do to be more explicit.


// If it's a user address parameter, we need to check if we have an auth provider
const authMethod = AUTH_METHOD_FOR_PARAM[param];
if (!authMethod && !this.customParameters[param]) {
Copy link
Member

Choose a reason for hiding this comment

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

For this case, should we also check that the customParameters[param] value is an AuthSignature? So not just that it is present in the custom parameters, but its type is correct. Or is that already done somewhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think we validate it against the structure of AuthSignature. We may want to use zod for that. Let's see.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Documented in #535, will address in a follow-up PR

@piotr-roslaniec
Copy link
Contributor Author

I'm going to go ahead and merge this, but we can continue discussing here or in #537 if anything

@piotr-roslaniec piotr-roslaniec merged commit 4eea8e7 into nucypher:epic-auth Jul 1, 2024
2 checks passed
@piotr-roslaniec piotr-roslaniec deleted the reuse-siwe branch July 1, 2024 09:41
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.

3 participants