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

Adds "Wallet" custom element and signOut functionality within the app #29

Merged
merged 10 commits into from
Jul 11, 2024

Conversation

elliotBraem
Copy link
Contributor

@elliotBraem elliotBraem commented Jul 1, 2024

Opening this to start a conversation on how we handle authentication (signIn and signOut) within our existing BOS apps.

Context

Several apps, such as Potlock or the Build DAO gateway are entirely made up of widgets, and so handle signIn and signOut within the VM itself. This is done by passing these functions as props from the gateway app, into the root widget. For example, nearbuilders.org has a specified page for login (/join): JoinPage.js in the gateway passes requestSignIn via passProps into the page's root widget, to then be trigged inside the login widget. Logout is done similarly.

image

This is handled differently when working with the web component. Since the web component is meant to be embedded in any web app, it is assumed that the web app will configure the wallet modal and handle sign in (in our case, triggering it via a click to a button with id "open-walletselector-button")-- and we pass this promise down into the web component, to be picked up in the VM's initNear.

Possible Solution

In the current PR, I've made two main changes:

  1. For signIn, in the outer "web app", I've modified the wallet selector modal to be triggered from ANY button that has the "open-walletselector-button" id -- meaning if a widget dev decides to create a button with this matching id, they can open the modal and prompt a sign in. It proves a way for Potlock + Build DAO gateway to trigger login within widgets, while the web app dev still has full control -- a web app dev doesn't NEED to make this modification -- and they can even change the id to whatever they want. This is NOT a change to the web component itself or how it works.

  2. For signOut, in the web component, I've added a custom element named "Wallet", which provides a signOut method to whatever content it is provided.

For example, some widget code might look like this:

return <Wallet
      provides={({ signOut }) => {
        return context.accountId ? (
          <button onClick={signOut}>Log out</button>
        ) : (
          <button id="open-walletselector-button" type="button">
            Open wallet selector
          </button>
        );
      }}
    />

This allows the widget dev to customize their logout button, and enables us to sign out from inside the web component without prop drilling.

However, this introduces a new custom element like <Link /> -- meaning that rendering a widget with <Wallet /> through a webcomponent or gateway that does not support this custom element will throw a "'Wallet' is not defined" error.

But it also enables opportunities for different Wallet implementations, as long as they implement a common interface. For example, consider https://trysui.near.page/ which exposes Sui's ConnectButton as a custom element. This could be standardized to a Wallet custom element, exposing typical "signIn" and "signOut" functions:

Viewing the widget with <Wallet /> through trysui.near.page will connect to Sui wallet, while viewing THE SAME widget through a hypothetical "tryaptos.near.page" could connect to an Aptos wallet, with no further configuration necessary for the widget dev. Although does this mean that viewing this widget through a "tryevil.near.page" could execute a custom "signIn" function that signs a malevolent EVM transaction...?

Questions & Concerns

  1. Do we want to enable this type of functionality (signIn or signOut), or should we maintain that all authentication is handled OUTSIDE the web component, within the web app that embeds it? This may mean that navbars should typically not be implemented as widgets, or maybe enforces a dedicated login/logout page per deploy. Also, I'm not confident -- can we handle logout from the web app with our current setup?
  2. How can this agree with web4? Which provides /web4/login and /web4/logout, should we be utilizing these instead? (I think this would need some VM changes)
  3. How else can we support logout?

Note: There is a failing test for validating a successful logout

@Megha-Dev-19
Copy link
Contributor

hey @elliotBraem, it's really great that you added this.
I would really like to have this functionality inside the web component so we can have our own navbar design with login/logout functionality, but instead of having to provide a specific id to the component I would prefer to have it as a simple function prop signIn and signOut, is that possible?
Because I don't want to pass same id to multiple buttons, but I want to have multiple login buttons across website.
I don't have much idea about the web4 login/logout, so can't speak there.

@elliotBraem
Copy link
Contributor Author

@Megha-Dev-19 I have that same desire for a simple "signIn" function... but atm, near-wallet-selector is imported and defined by the web app itself, and passes the selectorPromise down into the embedded web component -- and currently, signIn means opening the wallet selector modal.

In other words, the custom element does not have access to openModal(), and so cannot provide a signIn function.

Maybe we could introduce a janky signIn function that creates a hidden element with id="open-walletselector-button" and clicks it, but I don't really feel comfortable including this here... I think this would be up to whoever forks this repository to implement themselves.

@petersalomonsen
Copy link
Collaborator

@elliotBraem I think that we should support both ways. The existing, where the signin is handled on the outside, and also signin within the VM as you mention with other apps. I think then the dev experience as @Megha-Dev-19 suggest with being able to call signIn or signOut from anywhere within a VM widget, so that it is possible to customise the login experience. Some security considerations though has to be made though, since this will enable any widget to call signIn/signOut, and we need some threat modeling around that approach.

Since we are already passing the selectorPromise. Shouldn't we make it possible to use that for triggering the login modal? ( isn't it already possible)? In fact it already happens if you try to send a transaction and tick for "Don't ask again". The VM will then use the selectorPromise and trigger a sign in for the target contract. Let's make sure that we build upon what we already have in the VM here.

@elliotBraem
Copy link
Contributor Author

elliotBraem commented Jul 9, 2024

Since we are already passing the selectorPromise. Shouldn't we make it possible to use that for triggering the login modal? ( isn't it already possible)?

@petersalomonsen You know, I think I just had a misconception of how the selector + modal work together, and I kinda looked past this, thinking there was some blocker here. I introduced @near-wallet-selector/modal-ui-js" and signIn is working from custom element, while web app dev is still in full control of what wallets are available.

This means @Megha-Dev-19, Wallet now exposes signIn and signOut functions :)

And now we have test coverage verifying successful login and logout for near-wallet-selector!! 🥳
It seems this repository is becoming an end-to-end encapsulation of the whole near js stack! 😮

@elliotBraem elliotBraem marked this pull request as ready for review July 9, 2024 21:41
@elliotBraem
Copy link
Contributor Author

@race-of-sloths

@race-of-sloths
Copy link

🙁 This repository is not a part of the Race of Sloths

Please ask the maintainer to contact us to join the race!

What is the Race of Sloths

Race of Sloths is a friendly competition where you can participate in challenges and compete with other open-source contributors within your normal workflow

For contributors:

  • Tag us inside your pull requests
  • Wait for the maintainer to review and score your pull request
  • Check out your position in the Leaderboard
  • Keep weekly and monthly streaks to reach higher positions
  • Boast your contributions with a dynamic picture of your Profile

For maintainers:

  • Score pull requests that participate in the Race of Sloths
  • Engage contributors with fair scoring and fast responses so they keep their streaks
  • Promote the Race to the point where the Race starts promoting you
  • Grow the community of your contributors

Feel free to check our website for additional details!

@elliotBraem elliotBraem merged commit 0ea6431 into main Jul 11, 2024
1 check passed
@elliotBraem elliotBraem deleted the feat/wallet branch July 11, 2024 00:00
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.

4 participants