I can't seem to obtain refresh token from oauth2.Exchange() for an app under testing.
config.Exchange(ctx, code, oauth2.AccessTypeOffline, oauth2.ApprovalForce)
returns an access token with no refresh_token. What's even more annoying is that oauth2.ApprovalForce
does not prompt an OAuth consent screen for some reason. It only prompts for the very first time, and even after consenting for the first time, does not return a refresh token.
Checking the request through the debugger, the following is sent in the body of the request:
access_type=offline&client_id=...&client_secret=...&grant_type=authorization_code&prompt=consent&redirect_uri=...
So the library should be working fine. I've added a custom option
SetAuthURLParam("approval_prompt", "force")
and that also doesn't seem to work
func TestRegister(ctx context.Context, c *app.RequestContext) {
var err error
var req register.RegisterReq
// ...
var oauthState string
if oauthState, err = getOAuthState(c); err != nil {
c.JSON(400, map[string]any{"Error": err.Error()})
return
}
url := config.AuthCodeURL(oauthState)
c.Redirect(http.StatusTemporaryRedirect, []byte(url))
return
}
func getOAuthState(c *app.RequestContext) (string, error) {
expiration := 60 * 60 * 24
cookieName := "authstate"
b := make([]byte, 16)
var err error
if _, err = rand.Read(b); err != nil {
return "", err
}
state := base64.URLEncoding.EncodeToString(b)
c.SetCookie(cookieName, state, expiration, "/", "localhost", protocol.CookieSameSiteLaxMode, false, false)
return state, nil
}
func TestOauthCallback(ctx context.Context, c *app.RequestContext) {
var err error
var req register.OauthCallbackReq
// ...
queryArgs := ®ister.OauthCallbackReq{}
if err = c.BindQuery(queryArgs); err != nil {
c.JSON(500, map[string]any{"Error": err.Error()})
return
}
var token *oauth2.Token
if token, err = oauthAuthorize(ctx, queryArgs); err != nil {
c.JSON(500, map[string]any{"Error": err.Error()})
return
}
_ = token
// ...
}
func oauthAuthorize(ctx context.Context, queryArgs *register.OauthCallbackReq) (*oauth2.Token, error) {
var token *oauth2.Token
var err error
if token, err = config.Exchange(ctx, code, oauth2.AccessTypeOffline, oauth2.ApprovalForce); err != nil {
return nil, err
}
return token, err
}
It seems that you're supposed to provide the oauth2.AccessTypeOffline
and oauth2.ApprovalForce
args in AuthCodeURL(), not when requesting for the access token 🤡
It seems that you're supposed to provide the oauth2.AccessTypeOffline and oauth2.ApprovalForce args in AuthCodeURL() when initiating the OAuth process, not when requesting for the access token 🤡
url := googleproject.OauthConfig.AuthCodeURL(oauthState, oauth2.ApprovalForce, oauth2.AccessTypeOffline)
@LindaLawton-DaImTo Thanks for the example