Trying to setup Auth0 to create custom JWT, experiencing "CORS: invalid origin 'https://xxxxx.projectdabl.com'"

What I’m trying to achieve:

  • On a deployed instance on Daml hub, include “Reader” in the “readAs: ” key in the JWT.

Steps taken:

  • Trying to setup custom Auth0, using Auth0 react component, and following the steps here:
    Easy authentication for your distributed app with Daml and Auth0
    However, the steps above don’t seem to work for a deployed version, and only locally as well.
  • I’ve followed all the steps above, and was also able to figure out how to include part and token params in the redirect Url.

I didn’t change the LoginScreen.tsx code, from the create-daml-app template, and I’m able to get back my custom JWT,

Using the Auth0 hook loginWithRedirect, I’m able to authenticate, and create a callbackUrl which gets passed to the below, (I believe this is similar to how when deploying on dabl is)

however the code errors out at the line where

      const ledger = new Ledger({ token: credentials.token, httpBaseUrl });

I get the error CORS: invalid origin ‘https://vqe14zmbblsl30te.projectdabl.com
The request url is Request URL: https://api.projectdabl.com/data/vqe14zmbblsl30te/v1/fetch

The code in LoginScreen.tsx

const login = useCallback(async (credentials: Credentials) => {
    try {
      
      const ledger = new Ledger({ token: credentials.token, httpBaseUrl });
      let userContract = await ledger.fetchByKey(User.User, credentials.party);
      if (userContract === null) {
        const user = { username: credentials.party, following: [], followers: [], influence: '0.0', reader: "Write" };
        userContract = await ledger.create(User.User, user);
      }
      onLogin(credentials);
    } catch (error) {
      alert(`Unknown error:\n${error}`);
    }
  }, [onLogin]);

Is it actually possible to create my own Auth0 settings, use a custom JWT and query a ledger deployed on daml hub?

In fact I was looking at this post as well

but again, not sure if this was done locally or not.

3 Likes

Caveat: I am not very familiar with Daml Hub, so take this with a grain of salt.

At first glance it looks like a bug in Daml Hub, as the server explicitly returns a CORS header:

access-control-allow-origin: https://vqe14zmbblsl30te.projectdabl.com

while simultaneously setting the body to:

CORS: invalid origin 'https://vqe14zmbblsl30te.projectdabl.com'

Those two things do not look like they should happen at the same time.

That said, I do not think custom authentication is supported on Daml Hub; I would assume they need to be in control of creating the tokens, as the party in the token needs to match the party on the ledger. You can’t just make them up yourself in Auth0. The create-daml-app template already has support for authentication on Daml Hub out-of-the box, and I believe the Daml Hub UI gives you some control over the parties in the generated tokens. I would look in that direction rather than try to plug in a custom Auth0 configuration. So my guess would be that there is a minor bug in the error message, but that this not working is by design.

The Daml Hub team is in the US so you may have to wait a few hours to get an answer from them.

4 Likes

Hi Gary,
Thanks for the swift response. From Daml Hub, it doesn’t look like we can do much regarding the parties. There are public and admin parties, but they won’t work in my usecase.

What I’m trying to do is

  1. User creates a token (visible only to user)
  2. User creates an offer for that token (should be visible to everyone, it has observer: [‘reader’])
  3. Since all users have “readAs: [reader]”, other users will be able to see this contract, and exercise a choice on it.

Regarding the party in the ledger, at least on Daml hub, the party and token are returned as params in the URL. It looks like we are just creating a Party based on the string.

2 Likes

@Max I believe that feature is in the pipeline for Daml Hub, but not available yet.

3 Likes

Actually per current documentation you should get the token from the cookie, not from the URL params. The token is still in the URL params for backwards compatibility for the time being, because that is how it used to be returned, but please don’t build any new system based on (now-)undocumented behaviour.

I’m aware that this is how Daml Hub works, when you use Daml Hub authentication. I thought you were trying to replace that with Auth0, though.

1 Like

Thanks for sharing, and yeah I was trying to replace the daml hub authentication. Because I wanted to add some custom roles into the returned JWT that damlHub doesn’t allow yet. But I might have to find another route for the time being.

1 Like

Hello.

Interesting post.

It is an interesting idea, but this is not currently possible, nor has it ever been.

Daml Hub in its entirety is singular Auth0 OAuth2 application. The experiment that you ran effectively attempted to replace the Daml Hub internal Auth0 application with a third party one for login to a specific customer ledger. This is different from the way the system is currently designed and configured: we only currently allow logins from a single centrally managed OAuth2 application.

The subject of the blog post you mentioned - Easy authentication for your distributed app with Daml and Auth0 - by @Robert_Autenrieth, is about creating your own distributed Daml app using Auth0 as an Identity Provider (or identity provider federator). It is possible to do so, as the blog post describes, and indeed the blog post was inspired by the way Daml Hub is architected, but the blog post, as far as I understand it, is intended towards groups that wish to have more control over their identity management systems end to end, without opting in to a more hosted solution that provides more user friendly alternatives, like Daml Hub.

So, in short, even though what the post describes is similar to how Daml Hub works, the experiment that you set up is attempting to replace the role of Daml Hub while also making use of it - you need to pick one or the other. Either you can use Daml Hub and therefore not have to worry about configuring these identity related things, or you can manage your identity and use Auth0 directly as an identity provider, but in the latter case you will need to fill in the blanks.

It is interesting that the error message is about CORS, though. I suspect that that is due to the CORS OPTIONS request failing its authentication checks on account of the public keys mismatching, which is then causing an auth error to be misreported as a CORS error.

Hope that helps!

3 Likes

I have some follow up questions here.

Are you referring to a JWT Bearer token, or a Daml contract representing a tokenized asset? I think it is the latter, but it is ambiguous.

If your intent is to disclose a Daml contract to all users-as-parties on the ledger, then the public party will work for that purpose, as documented here https://hub.daml.com/docs/api/iam/#public. Essentially in that setup each connected user has access to retrieve their own bearer JWT in order to query the ledger with, (as the singular per ledger public party), which can then be used to list out and then also exercise choices on publicly disclosed data.

Where this doesn’t work as well is if you want to record the ledger identity of the person interacting with your publicly disclosed contract. In that setup, issuing bearer JWTs to end users that include a readAs: with the unique per ledger public party identity would enable you to get both public disclosure as well as retaining the ability to exercise choices as yourself. This is something we have considered implementing on Daml Hub, but haven’t yet done.

There may be a way to still address the use case of public disclosure while retaining the ability for individual users to interact in an authenticated manner by enumerating the users and their parties involved, for instance using triggers, in the meantime. I’ll check if we have any good examples of this pattern in open source applications.

1 Like

apologies, yes I meant a Daml contract representing tokenized asset.

I was attempting to replicated what I was doing locally, which was including a “reader” party in the ReadAs field. But I realized that if I’m using the public party to read contracts, the contract doesn’t actually exist for my logged in user, hence I can never exercise any choices on it.

I believe the solution to what I am trying to do requires me adding another propose-accept pattern, but thank you for confirming what I was suspecting that it wasn’t possible with using the Auth0 method, I wasn’t entirely sure, but now I am!

2 Likes

to be very clear, what you’re suggesting - bearer token issuance that includes a party for the end user in addition to a per ledger public party - is possible using the Auth0 method, as you can configure the Auth0 tenant to create tokens of arbitrary shape, including with a list of parties, including the public party.

what is not possible as of the time of this writing is instructing Daml Hub (which uses Auth0 internally) on how to construct bearer tokens, so if you are deploying on Daml Hub we don’t (as of now) issue access tokens which also include a per ledger public party read-as designation, though we may in the future.

1 Like