Verify JWT token

Is there a way to verify JWT without a function?

I have netlify-identity-widget setup for my site, and I can login to Netlify and my frontend has the access token.

However, without the secret key for the token, my backend cannot verify then token hasn’t been tampered with. Is there a way to do this? I do not wish to use functions as I have an existing backend.

I was assuming using a proxy would reject requests with an unverified token, but this is not the case. I have signed proxy redirects setup, but that allows me to verify that the requests are coming through the proxy, but does not verify the token.

1 Like

Hi there @turtlebits,

Right now there is no way to get your account’s JWT secret. What I generally do is use a Netlify function to authenticate the token. Another option is to use a signed proxy redirect so you can confirm that the request is coming via Netlify. More info on JWS can be found at Introducing Structured Redirects and Headers

Thanks, a signed proxy redirect just allows me to verify if a request to my backend is coming via the netlify proxy, but there is no way to verify the JWT payload. So someone can just post to my proxy URL with a tampered token. (I double checked - the proxy doesn’t try to verify the JWT by sending a tampered token through it).

Hi @turtlebits, I’m currently investigating a possible solution to your question. I’ll update here once I confirm the solution.

1 Like

Hi @Dennis! Were you successful in finding a solution?

Dennis will likely be able to give you a longer answer later, but you might want to look into this area of our docs: Rewrites and proxies | Netlify Docs

Right, so the signed proxy redirects can definitely help with making sure your external url has a way to identify requests from your netlify site.

But if you also want to validate your JWT against your site’s Identity instance, you will need to do as @futuregerald mentioned and use a Netlify Function in conjunction with GitHub - netlify/gotrue-js: JavaScript client library for GoTrue. If you invoked your Netlify Function with the appropriate Authorization header (Authorization: Bearer <JWT here>), our system will populate the context.clientContext object. You can then use this to information your function whether the request is valid or not. And example might look like: GitHub - netlify/gotrue-js: JavaScript client library for GoTrue.

Between the two options, that hopefully gets you what you need.

Sorry for the long delay in updating here.

Thank you for the suggestions, @marcus & @Dennis!

Hi @futuregerald

More info on JWS can be found at https://www.netlify.com/blog/2017/10/17/introducing-structured-redirects-and-headers/#signed-proxy-redirects

Will you please advice on how to verify x-nf-sign header?
I was able to sign the requests but now struggling to find the right way to verify the signature.

Thank you!

UPDATE: used jws GitHub - auth0/node-jws: JSON Web Signatures and it is working!

hey, @yuyokk
just wondering when using node-jws you still need to use s secret in order to verify a signature
may i know where did you get the secret on netlify ?

jws.verify(signature, algorithm, secretOrKey)

thanks!

Hi @romain1304,

As @futuregerald mentioned here:

You’d have to hardcode the secret in your Netlify Function. Considering your publish directory might be different from functions directory, the function’s code cannot be read by anyone else, it should not be a problem. If it’s in a public repo, you’d have to set the secret in an environment variable and then access it using process.env.VAR_NAME.

I’m disappointed to hear that there’s no way to get your account’s JWT secret. To me this makes using the identify service and deploying with netlify in general far less flexiable than it should be. Since netlify’s functions are not the right choice for every situation this limits being able to stand up external infrastructure but still being able to verify user requests.

Chris Biscardi has a solution to this, but it’s an async one based on making a call to the identity service for each request

Is there a reason why we can’t access the secret?

Alternatively, could we set our own with an env-var?

You can set a custom JWT secret in your site settings, but I believe that feature is not available for starter plans. So if you plan to use Netlify Identity with custom JWT on starter plan, it won’t work. And if you set the custom JWT secret, you could also set the same secret in an ENV Variable and access it elsewhere.

Oh I didn’t realise, thanks for the follow up.

So it’s not in the free plan because setting the JWT secret is under “access-control” not identity settings and access-control is a paid feature?

That’s my impression from this, (only docs I could find for setting JWT secret)

Yes, that is correct. The Role Based Redirects work on free plan, but custom JWT secret requires a higher plan.

I wanted to post a follow up here as it is one of the top google hits when people are looking for a way to use Netlify identity to restrict access to EXTERNAL services without having to opt into the $99/Mo role based access control plan etc…

I am sure people already know this but given there’s absolutely zero “how to” on this topic and much of the Netlify documentation does not spell this out nor do the answers in this thread do so I thought I’d provide a fairly strait forward “how to” with some of the details that are not well documented.

Goal: Use Netlify Identity authentication and roles to restrict access to external services on a free account or paid account that does not have “role based access control” nor the ability to set your own JWT secret.

Solution:

  1. On Netlify setup identity and specify roles for users (admin, editor, etc)
  2. Use signed proxies redirect in the netlify.toml config with conditions = {Role = [admin, etc, whatever]
  3. Setup environment for the secret used/referenced in the signed proxy configuration above.

On all levels of accounts this will work to only proxy the configured roles to your external service.

Important note for those using C/C++/Go/Rust/Etc on your services backed. The “secret/token” you setup in your netlify environment is very specifically a HS256 HMAC SHA256 signature (translation a very simple use the same string as a private key to verify, it is not a public key scheme)

Generally speaking on the external/backend services you are securing using whatever mechanism is convenient write a super simple middleware that verifies the HS256 signature from netlify and either rejects on fail or brokers to the target services based on role. This is trivial with standard patterns used in anything that’s remotely request/response type setups and have a provision for middleware. On 99% of backends I have from the last decade I typically have auth based middleware and just add a new middleware for this scheme.

I’ll post a typical Go based scheme that’s generic (IE not customized to my environments) if anyone needs something like that or would find it useful.

RB

To correct this part, RBAC is available on all plans, including Starter. But setting custom JWT secret is what requires a paid plan.

Yes,

I was clarifying how to use RBAC with signed proxy redirects as an alternative to JWT’s with a known secret which is what seems to be the goal of people on this thread.