I’m near certain a hundred different versions of this question must have been asked by now, but I want to explain my scenario specifically because security is easy to mess up.
In my case, my site’s server is providing an endpoint from which a client can request an access token, which is really a JWT. The client provides their username and password and the server looks to see if their account is valid and if so provides a JWT that is signed using the server’s private key. The JWT also contains a claim for what “tier” of access they have (i.e., standard, premium, or admin).
What I want to do is be able to validate that the provided JWT is the one provided by the server. Specifically, I want to do this because I intend to save the JWT in local storage in the browser to avoid the authentication process again, and when I read the JWT from local storage, I want to validate that it’s not been tampered with as it contains claims that will change the site behavior client-side.
To allow for this validation, I was going to provide an endpoint on the server that returns the PEM-encoded public certificate of the site. The client could then request this and load the public key to validate the JWT.
So my question is: Is this a proper way to do this? Is it leaving the possibility for a malicious user to circumvent the JWT validation in some way?
I apologize for the delayed response, but just wanted to circle back on this one - Did you end up implementing something like this?
I’m not entirely clear on your case - Is the access token eventually consumed by an API? Access tokens are typically validated/verified by an API and most often using a 3rd party libraries (which use the jwks endpoint). ID tokens are the only tokens that should be consumed client-side.
One concern is with storing tokens in local storage as this opens them up to XSS, some more on that here. Here’s a helpful blog post on browser storage.
I like to link to our Architecture Scenario documentation any chance I get - There’s some really useful information on what common architectures look like: