Authorization Code Grant

Hey All, I am trying to find some missing documentation and I’m hoping someone can help.

I’d like to do advanced server side authentication for my project but I can’t seem to find how to attain the signature in the following step in the documentation.

here’s the section of the doc page:

This is the general flow that a user will go through when authenticating with your app.

  • User connects their wallet to your website, and signs a message verifying that they own the wallet

  • This signature, along with their wallet address is sent to our auth server, which generates a one-time-use code that can be exchanged for an authorization token.


how do I get the signature after the user connects their wallet using the connect js widget?

Thanks for your help!
-Ryan

Looking at this, thanks for notifying us of the missing docs.

Actually, found it, it’s here:

I don’t see a link in your reply, would you mind posting it again? Thank you for your help!

Also is there an npm package available for this?
import ManifoldClient from '@manifoldxyz/manifold-data-client' mentioned in the docs?

Sorry, here’s the docs again:

Can you show me where in the docs you see that import comment? That is likely out of date?

Oh, I see, you’re looking for Authorization Code Grant. This isn’t supported yet. Sorry about that.

Actually, hold on, I’m adding more docs to see if we can support this.

The auth process should work as written, the data client isn’t publicly available just yet. We can publish this, but can you confirm everything beforehand worked as expected?

Ah ok, this is why I am confused.

I ended up following the “signature” work flow and use the /verify responseJson.address on my server back end to verify the user owns the wallet for the token that was sent to me in the manifold connect process on the client side…

client side:

let eth = window.ManifoldEthereumProvider;
      await eth.initialize(this.network);
      if (!eth.chainIsCorrect()) await eth.switchToCorrectChain();
      await eth.connect();

      let token = null;
      if (this.appName != null) {
        token = await eth.getOAuth({
          grantType: "signature",
          appName: this.appName,
          clientId: this.clientId
        });
        let abtoken = await this.api.post("/manifold/verify", { token });
        this.token = abtoken.data.token;
      }

      this.address = eth.selectedAddress();

server side:

 const token = req.body.token;
      const response = await axios.post("https://oauth2.manifoldxyz.dev/verify", { token });
      const responseJson = response.data;
      const address = responseJson.unwrappedJWT?.address;

      let valid = await DBAPI.isWhitelisted(address);
      if (valid) {
        let user = await DBAPI.getUserByAddress(address);
        let token = jwt.sign({ id: user.id }, process.env.TOKEN_SECRET, { expiresIn: 86400 });
        console.log("logged in address", user.id, "address", address, "token", token);
        req.session.manifoldToken = responseJson.access_token;
        req.session.user = user;
        res.json({ token });

I then store the responseJson.access_token in my user session and issue my own auth token to the user.

My assumption was that the access_token from the /verify response from manifold was sufficient to make data client requests on my server on behalf of the user.

But what I think I’m missing in the " Authorization Code Grant" flow is understanding the meaning of the “signature” query param that is referenced in the docs:

The Authorization Code Grant page references “access_token” as well, but I don’t know where the “signature” value comes from?

const response = await fetch('https://oauth2.manifoldxyz.dev/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    },
    body: JSON.stringify({
      clientId: clientId,
      code: authCode,
      clientSecret: clientSecret,
      signature: signature
    }),
  })

also do I need to also call /token after /verify to be able to invoke dataclient methods serverside? This is where I’m stuck, and I’m not sure how to get a reference to the dataclient without installing an npm package.

Thanks for your help!
-Ryan

Gotcha. If you could explain high level what you’re trying to accomplish, might be able to point you in the right direction.

Using signature type and grabbing the token and calling verify allows you to ensure that the user that’s calling your function is indeed the wallet that signed.

I’d like to use the data client on my server to ensure that a user owns a token before I allow them to gain write-access on the metadata associated with the token.

This appears to be available on client side only.

Ah, I see. In that case, the optimal thing to do is to use the session token to verify the user is actually the wallet being represented by doing an S2S validation.

Then, in the write request, simply validate the session token against our server, and make sure the wallet address returned matches the token owner via ethers and the smart contract directly. It’s the safest thing to do as there is no latency.

The server shouldn’t need the data client, and it’s best practice to validate against the smart contract directly anyways. The data client is a convenient tool to show the user which tokens they have to gain access to the UX though.

Does that mean I need to use a different provider like infuria or alchemy to query the network from the server? Or does manifold provide one? (or is that the service that is still in development?)

The former is recommended. You can probably get away with the free tier since you’re only fetching the owner information for write requests.