Has anyone had any success with using Auth0 for JW...
# help
n
Has anyone had any success with using Auth0 for JWT authorization on an SST API? My API is secured but I'm trying to use the Auth0 SDK to get my access token in a React app so I can add it to my headers when calling the API. The Auth0 examples require a lot more info than what the SST examples show. Any pointers from anyone who has successfully got the Auth0 access token within a React app?
a
I believe this is the example in question - https://auth0.com/docs/quickstart/spa/react/01-login The first example’s purpose is to fetch the user’s identity via auth0. This step returns an id token which is a JWT with user info. So, this token is just for knowing that your user is authenticated via auth0. You can use this to populate user info on profile pages, show avatar, etc. The next step in the flow is to register an API in auth0, here’s how - https://auth0.com/docs/get-started/auth0-overview/set-up-apis So, every API that you register will have a unique identifier called an audience and you can customise the scopes which basically help you achieve generic authorisation / access control. Here’s an article detailing this to a better extent possibly - https://auth0.com/blog/complete-guide-to-react-user-authentication/#Calling-an-API Hope this helps! Be vary auth0 become expensive very quickly. Maybe you could enrol for their startup program which is free.
The sst example is the server side alternative for the part-2 of the example. Use the audience and issuer to create a HttpJwtAuthorizer, pass the token in the request header and boom, everything will just work.
n
Thanks, those are indeed the examples that I'm working through. My confusion is around the fact that I need to use the Auth0 dashboard to set the scope for my API, whereas the SST example (or securing the API with a JWT) suggests that this is done within the API (or the stack at least). I would have thought (perhaps naively) that after successful login using the Auth0 login, it would issue a JWT that could be used on the SST API, this doesn't seem to be the case. Point taken re the price of Auth0, i'm just at proof of concept stage at the moment.
a
yep, I thought that might have been the confusion as well. The audience and issuer work together in pair. Your issuer is your tenant url and the audience is every individual API group. If you try to get an access_token for an API (read audience) that you don’t have configured in that tenant then auth0 will return a 401 saying you don’t have access to that audience, in case of an undefined scope for an audience you’ll get a 403 saying that scope isn’t accessible.
n
I'll play around with adding my API* in the Auth0 dashboard then and see how I get on. *the very basic SST example for /public and /private.
a
sure, good luck.
n
Nearly there. I'm getting a "the token does not have a valid audience" error. I have the API setup in the Auth0 dashboard and I get an access token back. I'm getting the error when I fetch from my API on the "private" endpoint secured with a JWT. The API security works fine when I run through the SST example with the curl commands. Any ideas?
a
you need to give your client application permission to use the api, it’s a toggle switch, check whether that connection has been done. Finally, the audience that you send from the frontend app needs to exactly match the identifier you defined for the api and the jwt authorizer in sst, you can go to jwt.io and check whether the token generated has the aud or not. Finally, don’t interchange the id and access tokens, while they’re both jwts they have different claims backing them.
n
I've checked all of that bar the giving the client app permission. Is this within Auth0 as I can't see where that would or should be? Everything else is as it should be.
f
@manitej can we update the Auth0 JWT example to include the frontend part like the Google Auth example?
m
yup @Frank will update those
a
@Neil Balcombe could you share your sst jwt config and an access token, I could check that out for you.
n
JWT here. This is how I configure the API
Copy code
// Create Api
   const api = new Api(stack, 'Api', {
      authorizers: {
         jwt: {
            type: 'jwt',
            cdk: {
               authorizer: new apigAuthorizers.HttpJwtAuthorizer('Authorizer', '<https://dev-8rchfy1d.us.auth0.com/>', {
                  jwtAudience: ['ExWTATqlrVZXReAEv7JMjUkQmZWAXDlB'],
               }),
            },
         },
      },
      defaults: {
         authorizer: 'jwt',
      },
      routes: {
         'GET /private': 'functions/private.handler',
         'GET /public': {
            function: 'functions/public.handler',
            authorizer: 'none',
         },
      },
   });
a
your
jwtAudience
should be
<https://aw6lgqy70i.execute-api.us-east-1.amazonaws.com>
and not
ExWTATqlrVZXReAEv7JMjUkQmZWAXDlB
. Change that it should work.
what was the unique identifier that you setup for the API that you created within auth0? Did you set
<https://aw6lgqy70i.execute-api.us-east-1.amazonaws.com>
as the unique identifier? If yes, keep in mind that this endpoint is ephemeral in nature, if you tear down the stack and recreate it this endpoint will be different.
n
Yep, that's worked! Thank you. I have a question though, I'm setting the JWT audience in the API constructor. I won't know until I have run it what that API end point is going to be. This seems like a flaw?!?
And yes, I do use the endpoint url for the Auth0 identifier.
a
no, the auth0 API identifier is just that, an identifier, it doesn’t have to have any relation to your API’s endpoints. you can keep the identifier as
<https://some-amazing-api-audience.somedomain.sometld>
and it will still work. It’s just that this identifier needs to be available to your authorizers as well, you should also consider separating the user and admin APIs into different audiences that way your admin APIs get protected automatically from hijack attempts from normal users. provide the issuer and audiences to your APIs via env variables. Also, if you’re separating your dev and prod environments as you should across multiple stages, separate them in auth0 at the tenant level, so have a tenant for your dev stage and another for your production stage. Hope that helps!
n
You've been a great help, thank you. To be honest, this was my first dabble with any kind of auth outside of Cognito (on AWS at least). I'm playing with SST to try and scaffold a basic project that I can use as a starting block for any new client projects. I'm going to look at a few other alternatives but might stick with Cognito unless there is a client need to use something else.
a
the docs around cognito are very limited and support from the community is non-existential and so be vary. It’s a pleasure. I just created my own auth implementation to sunset auth0's use and so I’m very up to speed with all things auth, glad to be helpful.
m
@Ashishkumar Pandey I’m getting 401 when trying to call the private endpoint
here’s the jwt
a
and the authorizer?
m
here’s the api in auth0
Copy code
api = new Api(stack, "Api", {
    authorizers: {
      auth0: {
        type: "jwt",
        cdk: {
          authorizer: new apigAuthorizers.HttpJwtAuthorizer(
            "Authorizer",
            "<https://dev-0abky2gm.us.auth0.com>",
            {
              jwtAudience: ["private"],
            }
          ),
        },
      },
    },
n
I do have further questions around general architecture of the SST Auth and API stacks, specifically around roles/privileges but I think I'll ask these in a general discussion on here once I've done some more research.
a
is there an issuer mismatch? the token lists iss as
<https://dev-0abky2gm.us.auth0.com/>
whereas the authorizer shows
<https://dev-0abky2gm.us.auth0.com>
.
n
@manitej, interesting that your Api constructor is explicitly saying auth0 as an authorizer. I didn't do that (see my stack above).
m
that’s the issue @Ashishkumar Pandey! thank you 🙂
a
nice! glad that worked.
m
@Neil Balcombe that’s just an identifier, you can keep anything you want there
@Neil Balcombe in V1, you can even simplify it as
Copy code
authorizers: {
      auth0: {
        type: "jwt",
        jwt: {
          issuer: "....",
          audience: ["...."],
        },
      },
    },
Detailed guide will be coming soon on website. thanks @Ashishkumar Pandey for the tip!
a
great! will definitely help a lot of people.