Authentication with Bearer access_token and refresh_token

Hey,

I have a REST API which takes cares of my Users ( basically i don’t use the Bubble.io user capability and I use Bubble.io as a front-end only ). My user when Signup (api/create-user) create a user in my Database and when they Login (api/authenticate) they receive a refresh and access_token.

Now what I want is that for every API call they do they have as Header :

Authorization : "Bearer access_token"

If 401 is returned I call another endpoint : api/refresh-token which gives me a new access_token and I retry the call.

It seems so weird that there is not an easy way to do it, in fact it seems that OAuth2 Custom Token or Password might be the right choice but apparently it is not if I don’t create users in Bubble which is something i don’t want to do because it would force me to mantain DB consistency.

Another problem for example is where can i store my refresh_token for a week (like i would do with cookies) without creating an user ?

Let me know if you know any workaround

1 Like

I don’t understand why you are looking for an “easy” way to do that when you don’t wan’t to use an easy way with Bubble DB :stuck_out_tongue:

If you wan’t to authenticate the user manually from an external DB without creating any user in Bubble DB, you have no choice to do each step manually. Normally, if you want to authenticate a user from External APP, you should use an oAuth2 authorization (user) flow. This will create a DB User in Bubble by default and Bubble will handle the auth process for you, including the refresh token.

Ok thanks a lot, I am searching an easy way because I already have a ( .net ) platform which has been running form more than 2 years and i have more than 1000 users and now I want to switch to Bubble.io only as front-end. In addition I have a UserEntity all across many micro-services dbs and I would not like to have a User on Bubble too ( but maybe you have got a solution for this as well).

By the way going back at OAuth2 : what would I need to do in the API Connector and on my back-end ?

In the API connector should I use a OAuth2 Custom Token, Password or User-Agent ?
And in my backend do I need to return a specific json message ?
Because my intuition would be that when the user login I do a OAuth2 Password call /authenticate where i return something like this :

{
"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"Bearer",
"expires_in":3600,
"refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"scope":"create"
}

Then my intuiton would be that bubble takes that refresh_token and access_token and save it in DB for future calls so if I now do another call as for example OAuth2 Custom Token it uses automatically that access_token and if it is expired try to refresh it using the refresh_token from before.

My intuition is probably wrong, so I would you do in order to make my api fit the requirement from the OAuth2 Custom Token, Password or User-Agent ?

If you follow oAuth2 authorization code, you will use the oAuth2 user-agent in Bubble.
In this case, you will provide your App ID and Secret and use Social network login. you also need an authorization screen, token url and a user endpoint to get ID and email.

Bubble will handle the rest for you. No need to store any data.

You cannot use other auth process for authenticating specific user. If you cannot do an authorization oAuth2 flow, you need to handle each part manually. You will set auth: none/self-handled and create API Call for token endpoint and for refresh token.

Thanks again, so I setup my backend authentication service as if it was a Social Network. While If I want to handle each part automatically I would need to do so for each call I do (so for example catch errors at every call ) which would be crazy.
Cause otherwise I was looking at this post : [Showcase] Manual OAuth2 Token Integration that uses Custom Token , would it work the same for my occasion ?

Yes. If you cannot use the oAuth user agent flow in Bubble, you can base your auth process like in this post. If you don’t have an authorization Screen, you will probably skip this step.

Thanks man i will talk with my team and maybe we decide that it is quicker if we create new users in the Bubble DB (and import the existing ones) and for any user details update we call each service individually and update their UserEnitity too.

Your advices were very helpful !!!

Hi Jici,
I am having trouble understanding how to implement on my side API the TOKEN Endpoints, because I would think that I have to create this three endpoints as described in the API Connector :

  • /api/authenticate
  • /api/token
  • /me

but I imaging I also need a /api/refresh-token otherwise how can Bubble refresh the token ?

No. Normally the refresh token is the same endpoint that you use for token. But the type is refresh_token instead of authorization_code
You need to check oAuth2 framework to know how to process each step. But you can also just check different app that use the oauth2 authorization code

1 Like

I am so sorry to bother you so much but I am getting crazy trying to understand the need of having a separated auth server (OAuth2) and a resource server.
I trust my API so I want it to be able to generate access_token (with encrypted the userId and role) and refresh_token and return these to bubble so that it can create requests with such tokens that once decoded allow my API to check that the user who is making the call has the right to access those resources (by checking its userId or role).
Should I for example use the JSON WebToken option ?

But then again why the RSA private key ? It is something I already have on my backend and that I use to encode and decode user information in the access token.

I cannot believe nobody ever had the same problem as me… I really need to solve this issue if someone can help me I can even pay ( but I would to have a call for example where I can show my problem more in detail ).

Why do you want to use a JWT?
I don’t understand what you are trying to do.
Like I told you, if you want to authenticate on behalf of user, you need to use oAuth2 authorization code (user agent) OR do a manual auth by Storing data like an API key or something. The goal is not about trusting your API, but securing the communication between your app and Bubble.

If you don’t need to authenticate on behalf of user, you don’t need a complex WF. The best is to use a oAuth2 client_credentials pattern. In most case, client_credentials will not need to use refresh_token.

You can also just use a simple API Key in header and this is fine. But if you want to authenticate on behalf of user, it will be better to store informations on Bubble about the access token/refresh token or API Key. Calling a public endpoint in your API to get them doesn’t make sense at all and is absolutely not secure!

I don’t know if I need to authenticate on behalf of user what I need is that if a user make a request like this to my API:
/api/details/{userId}
Then on my backend I decode the access_token and if the userId in the access token is the same of the one I am accessing the resources to (in the request) then I return the resources otherwise I return Unathorized.

All of this would be fairly easy to do because I could simply save the access_token in current user and then add it to each call I do the problem is that I cannot check if it expired and refresh it.

You need first to know if you want to authenticate on behalf of user or not.
If not, you don’t need to have a refresh token. Just use a client credentials in custom token and this is fine. Everytime get access token and that’s all.
But according to what you say here:

Then on my backend I decode the access_token and if the userId in the access token is the same of the one I am accessing the resources to (in the request) then I return the resources otherwise I return Unathorized.

You need to auth on behalf of the user to know if the access token belong to this user or not. Each user will have a different access token from what I understand. So you need to store information in Bubble about the access token, refresh token and expiration.

The other option you have is to have a client credentials to call your API to get the access token according to the user ID and use it. But you will need to call this endpoint everytime because you will not store the data into Bubble.
If this is your API, you can choose how you want to work so… I higly suggest to “fake” a kind of oauth process.
A) Call a “authorize” endpoint where you will provide api key and user ID. this endpoint will return a code. In your API, store this code with the user ID.
B) Call a “token” endpoint. Like oauth2, you will provide an api key and secret + the code from the step A). This will return an access_token related to the user.
Just repeat this for every call. Don’t fetch refresh_token and set an expiration on access_token to a very short time like 1 minutes.

You could also do just step b, and in this step, add a new parameters for the userid. You can use the Custom Token at this moment. This will work perfectly.

1 Like

I have read all this website, but still cannot get my head around this

for example when you say :

Call a “authorize” endpoint where you will provide api key and user ID. this endpoint will return a code. In your API, store this code with the user ID.

What is the api key ? cause I see a lot of client_id in https://www.oauth.com/ but not Api key.
Plus all the OAuth2 authorization happen with a third-party app like Google or Facebook but it is not my case.
I just wan to be able to Login, get an access token and refresh it on my own API. I cannot believe there is not a tutorial for this…

In most case I should say client id / secret sorry
oAut2 process is: A) Send user to authorization prompt page where user accept and authorize your app to access data on behalf of this account/user.
B) The authorization granted will send the user back to the redirect url. This normally contain a code in url
C) You use this code to call the token endpoint and exchange it to access token and refresh token .
D) you call API endpoint using the access token
E) you refresh access token using the same url as C, but instead of authorization_code, it will be refresh_token. Some parameters are differents.

OK nice I can manage to fake all this on my backend but on Bubble side how would you do it ? Because I cannot do “Login With Social Network” can I ?

Which Authentication (OAuth2 User-Agent Flow, Password, Custom Token) would you use for each of this calls :

  • /login
  • /authenticate
  • /token

Do you want your user to go to the authorization to authorize your Bubble app to access to your API Data on behalf of this specific user?
If yes, you can set everything using login with social network (that is the oAuth2 user-agent)

I want the access_token to contain information about the user so that I can return only its information from my API and not the one from other user.

But for example if I do a login page with email and password field what are the next step (Action and API call) I have to do in bubble in order to have an access_token which refresh automatically and how do i initialise new request ( oAuth2 user-agent, passord etc…) for calling for example /api/details/me ?

I don’t think you should go that way.
Implementing oAuth2 process on your API is more complex. There’s a lot to do.
Ithink you focus too much on “access token” and more… on “refresh token”. Is it very important for you?
What is the process you have in mind when the user go to your Bubble app? They will enter their email and password? In this case, why not authenticate them in Bubble, then call your API to get the access token and store it in Bubble User DB?

I think you are going into a complex process while it could be a lot more easier to create

Yes I know but my boss is very reluctant with having the user and authentication services and DBs in Bubble or in general any functionality which is usually handled backend.
So i would like to do be able to authenticate with access and refresh tokens which to be honest is the industry standard, it is not so complicated I cannot believe they force you to become a OAuth Provider in order to use your External API for authentication.