Best way to store Bearer token from API?

Hello all. I’m looking for a bit of advice in regards to storing a bearer token for OAuth on my Ionic app.

Users will be able to log in using a backend system I have built. On successful login, the bearer token is sent in the response which the user will need to use to validate their API requests.

Where would you recommend storing the bearer token? I’ve explored using the capacitor Storage facility and simply having a kay/value pairing but I don’t feel as though I know enough about data security to make an informed decision? Should I go full sqlite and encrypt the bearer token? Does it really matter if the token changes every login?

Thank you for any guidance you can offer.

1 Like

I recently had this same question and read several articles and posts about this. By no means I am an expert, but from what I found, there are varying opinions (Similar to where to store JWT tokens in an SPA. Google it, there is no straight answer…lol).

I think it really depends on what kind of app you are developing and what kind of data your API is serving.

For me, I chose to use capacitor/storage. With this option, a user could get access to the API key if they really wanted to or if their phone is compromised, it could be accessed. If a phone is compromised, there are bigger problems to worry about though :slight_smile: For my app, these possible risks don’t warrant an encrypted option as we aren’t storing or serving confidential/personal information.

The ultimate most secure option is using an encrypted option like Ionic’s Identity Vault or Secure Storage. If I was developing a banking app or something like that, hands down I would use this. But, with my current app, I cannot justify the cost.

Some additional information, I am using Vue and Ionic 5 for my app. For caching my Vuex store, I am using Ionic Storage which stores the cache in several different options depending upon what is available (for me IndexedDB). I decided to store the API key using Capacitor Storage in order to save it outside of the browser storage which is a little more secure from my understanding.

The general flow is upon login or account creation, the API key gets put into my Vuex store in memory and saved to persistent storage using Capacitor Storage. All API calls use the key from the Vuex store (in memory). When the app is freshly loaded, the API key pulled from persistent storage using Capacitor Storage and re-populated into Vuex in memory.

6 Likes

Hi @twestrick and thanks for your comprehensive reply.

That is exactly my problem… I’ve tried Googling what the best practice is with results varying from “it needs to be as secure as possible” to “it doesn’t really matter as long as you manage the token distribution/expiration on your backend” with everything in between.

I think based on what I’ve read and from your own experiences, I’m going to implement a similar structure. I’ll get the token and store it using Capacitor Storage and call it when I need to make an API request. It does need to be reasonably secure, but it’s the kind of app which someone will only be visiting once every 24 hours or so for probably no more than 15 seconds. I will then implement some logic so when the app logs out, it clears the token from the storage and sends a request off to the API to logout and expire the assigned token.

Thanks again for your help!

You’re welcome! I am actually doing that exact thing as well upon log out. I am clearing the local storage of the API key along with sending a request to the API to also clear it in the backend.

If you are going to be doing a lot of API calls, you will want to store the API key/bearer token in memory so you don’t have to keep grabbing it with Capacitor Storage as that will be slower.

4 Likes

Good points. Honest question, what is the advantage of encrypting the bearer token other than hiding the format of it on the client side which in turn I guess would make it really hard to brute force auth? A bad actor can still use the encrypted token to authenticate with the backend API. It seems somewhat like a false sense of security to me :thinking:

In regards to changing the token every login, we do this; however, our app keeps you logged in so it really never rotates. I guess the optimal solution would be to have some logic in the app to rotate the token every so often behind the scenes.

EDIT
Just to clarify, I am talking about encrypting the token on the backend before it gets sent to the client. If you meant encrypting it on the client with the keychain or keystore, then I totally understand that. We aren’t currently do that for the reasons mentioned in my original comment. But, with the open source package by aparajita, it is much more obtainable/reasonable!

EDIT #2
Apparently the post I replied to talking about encrypting the bearer token is gone/been deleted :thinking:

And I’ve gone for something similar.

I use capacitor-secure-storage to encrypt the bearer token on the device to help prevent users from accessing it directly and then just attach it on the interceptor each time where an authenticated call is required.

With regards to token rotation, we have some logic in place to revoke and clear old tokens on logout with a token having a lifespan of 1 year (unless revoked). Primarily for the same reason as @twestrick in that we keep our users logged in and the presence of a valid bearer token both stored and valid forms part of the auto login process.

1 Like

Do you have a repo with a working example? I’d love to see how you implemented this. Also, are you saying that you use both capacitor-secure-storage along with ionic storage? If so, you’re populating ionic storage with whatever capacitor-secure-storage has in it? I’m using a java backend that creates a bearer token, and I want to store it on the client side in order to stay logged in / make requests. I am using signal store currently to keep track of the bearer token, but if I refresh my browser that goes away

I think this sums it up whether you are using the capacitor-secure-storage or @capacitor/preferences plugin (formerly @capacitor/storage. I did switch from Vuex to Pinia :slight_smile: You would want to store the key in memory while the app is being used since reading from either storage solution for every API call is going to be slower. You also wouldn’t use Ionic Storage to store it as well.

1 Like

Thanks for responding! Newbie at mobile dev here lol

Hey, we were all a newbie at some point! I was in the same boat 3 years ago. Let us know if you have any other questions. My code is super specific so not sure how useful it would be sharing.