Complete idp login doesn't return refreshToken
-
Hi,
I completing a login after a google login from our own login page with this endpoint (https://fusionauth.io/docs/v1/tech/apis/identity-providers/google#complete-the-google-login). I don't understand why I don't receive a
refreshToken
.
The only condition mentionned in the doc is the presence of theapplicationId
which we did provided, it's event present in the returning payload:from the doc:
Because a refresh token is per user and per application, this value will only be returned when an applicationId was provided on the login request.
Return payload received from FA:
{ "user" : { "id" : "userId" "active" : true, "firstName" : "Stefan", "registrations" : [ { "lastLoginInstant" : 1595002474203, "applicationId" : "1e85ab7d-7e27-4729-b61f-fdb9f9ce6d6e", "tokens" : { "Google" : "googles token" }, "insertInstant" : 1595002474186, "id" : "82f88268-dffb-4a81-8323-ec28fde87754", "verified" : true, "usernameStatus" : "ACTIVE" } ], "tenantId" : "db507f75-2f84-2e46-5f8c-bc9913a3880b", "usernameStatus" : "ACTIVE", "verified" : true, "twoFactorDelivery" : "None", "imageUrl" : "https:\/\/lh5.googleusercontent.com\/-82xeGvvebOk\/AAAAAAAAAAI\/AAAAAAAAAAA\/AMZuucka1J5muJev4xFKfUtD84QfCWPM-w\/s96-c\/photo.jpg", "insertInstant" : 1595002474143, "twoFactorEnabled" : false, "passwordLastUpdateInstant" : 1595002474175, "fullName" : "Stefan and his lastname", "lastName" : "last name", "email" : "stefanemail@gmail.com", "lastLoginInstant" : 1595002474203, "passwordChangeRequired" : false }, "token" : "valid jwt token" }
Is there some other condition needed to get the refreshToken ?
Some information:
instance:
https://swift-tech.fusionauth.io/
running 1.17.4Here's the config of the application in case it helps:
Screen Shot 2020-07-17 at 19.48.45
-
@dan could you have a quick run at this? I'm always reluctant to file a bug until I've cleared the possible obvious reasons
-
Hi,
After nosing around a bit, it looks like if you use the google identity provider, we don't request the refresh token, only the access token.
You can try to use the OIDC identity provider against google instead: https://fusionauth.io/docs/v1/tech/identity-providers/openid-connect/ You can request the
offline_access
scope and if Google returns a refresh token based upon that scope you could store it using a lambda, in theregistration.data
field, for example, and then retrieve it later.Of course, you can also file an issue explaining what you'd prefer to happen with the google identity provider. There are some limits google places on refresh tokens which may impact implementation: https://developers.google.com/identity/protocols/oauth2/openid-connect#refresh-tokens
-
Hi @dan ,
Thanks for looking into it. I think there is a misunderstanding, I'm not looking to obtain a refresh token from google but one issued by FusionAuth.I don't need google's refresh token for this use case, I let FA retrieve the info it needs once and that's it, I don't need to have further access to google's resources.
then, as an application resource server, I just check the tokens provided by FA, without even knowing if the user registered with an idp or not.
I'm looking for the refresh token issued by FA, that I can later exchange for a new AccessToken (still issued by Fa, not Google)
this refreshtoken : https://fusionauth.io/docs/v1/tech/apis/identity-providers/google#response-body-4
-
Ah, thanks for the explanation.
Are you passing a scope parameter to FusionAuth?
From the applications docs:
When enabled, FusionAuth will return a refresh token when the offline_access scope has been requested. When this setting is disabled refresh tokens will not be generated even if the offline_access scope is requested.
I was able to do this locally by using this url: `http://localhost:9011/oauth2/authorize?client_id=9d995316-d175-4e74-b08b-4073de0eb44a&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Foauth-redirect&scope=offline_access
Then, when I complete signing in via google, I see a
refresh_token
in the response.If that doesn't work for you, please let me know as it may be a bug.
-
Thanks again for your answer @dan ,
Are you passing a scope parameter to FusionAuth?
Not I'm not passing any scope, because the endpoint I'm using doesn't accept one: https://fusionauth.io/docs/v1/tech/apis/identity-providers/google#complete-the-google-login
Are you saying that I must first have a flow through the
oauth2/authorize
endpoint?From what I understand from the doc of the complete-the-google-login it isn't necessary, I should be able to use that endpoint to create a user
For example, if you built your own login page, you could add a Login with Google button and complete the Google authentication. When you complete the Google authentication you will have been returned an id token from Google. Using this API you can pass that id token returned from Google to FusionAuth and we will complete the login workflow and reconcile the user to FusionAuth.
The user does not need to exist yet in FusionAuth to utilize this API.So If my user doesn't exist yet in fusionauth, I can't have provided a scope before hand.
I'm starting to think I may misunderstand what this complete login endpoint objective is.
I'm building my own login page, and letting users auth themselves through google and then I silently register them to my fusionauth instance. User never hears about fusionauth. Does that scenario fits what /api/identity-provider/login offers ? -
I'm starting to think I may misunderstand what this complete login endpoint objective is.
I think I'm the one who is misunderstanding things Yes, you should be able to build your own login pages to auth directly with google, and yes, you should get the
refresh_token
returned. I didn't follow what you were attempting to do, I thought you were using the google form provided by FusionAuth (which is what I tested and which returns arefresh_token
if you provide the scope).This sure looks like a bug because the
refresh_token
should be returned according to the docs. At the very least it is a doc bug, because thenoJWT
parameter doesn't state that the refreshToken will be returned ifnoJWT = false
:When this value is set to true a JWT will not be issued as part of this request. The response body will not contain the token field, and the access_token and refresh_token cookies will not be written to the HTTP response
But the response body states a
refreshToken
will be returned:The refresh token that can be used to obtain a new access token once the provide one has expired. Because a refresh token is per user and per application, this value will only be returned when an applicationId was provided on the login request.
Can you please file a bug? https://github.com/fusionauth/fusionauth-issues/issues