How to use token based authentication with graphql api?

So I’d like to build an API using graphql (Absinthe) and I’m trying to figure out how to proceed with the authentication. Seems like quite a hot topic as there so many threads about it but none which actually seems to solve the problem in a an easy way.

The flow in my drawing book looks like this:
Client (eg. React application in my case) sends a mutation with username/email and a password. User schema has a field for hashed password with which I’ll compare the given password and if ok I’ll return a token. With this bearer token the client can then request data using queries and mutations. Simple enough but there are some open questions.

I hear everyone saying JWT is no good for security or whatever reasons but I have yet to see an example of using anything else as a token. So what would be an alternative and how to use it?

How would one go about the refresh tokens? My understanding is this bearer token should expire rather fast, after which another token is used to get a new token, is this the case and again how is this done (how to check the expiry of the token in case it’s not a JWT token)?

As a user logs out it seems like the token should be invalidated. I gather this means using a db to list the used token to check against on every request (would assume this gets rather long with a time…)?

Not really Elixir related, but once the client (for example a React app) receives the bearer token, where should it be saved in order to avoid logging in every time page is refreshed? Again, I keep hearing local storage is bad etc. but haven’t really seen anyone giving a good alternative.

Are there any pitfalls to avoid using this type of an authentication with graphql?

Last but not least, are there any libraries/ready solutions to use or do I need to build this myself? Most of the libraries I’ve seen seem to fall short in one or another ways, Pow doesn’t seem to be made for api only use (at least not with Absinthe), Guardian seems to be using jwt etc.

As this is probably the singe most important part of the protected api I wouldn’t like to rely on some random google searches or sketchy home-made solutions in this.

It’s bad for sessions, but it’s great for server to server communication. Very much depends on the scope.

Pow in API is decribed here, and should give you some ideas how to work this in: How to use Pow in an API — Pow v1.0.20

Also there has been a few issues on GH about getting Pow to work with absinthe since the conn is not exposed, here’s one way to solve it: Use Pow.PasswordReset.Plug.create_reset_token without a conn · Issue #61 · pow-auth/pow · GitHub