oauth2 icon indicating copy to clipboard operation
oauth2 copied to clipboard

refresh access_token get userinfo raise token error

Open cangmean opened this issue 3 years ago • 1 comments

I use refresh_token refresh access_token, then use access_token get userinfo server side raise token error.

// token info
type TokenInfo struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	TokenType    string `json:"token_type"`
	ExpiresIn    int    `json:"expires_in"`
	Scope        string `json:"scope"`
	IdToken      string `json:"id_token"`
}

// client  AuthCallback
func authorizationCallback(ctx *gin.Context) {
	code, _ := ctx.GetQuery("code")

	fmt.Println("authorization code", code)

	tokenInfo := getAccessToken(code)

	refresh_token := tokenInfo.RefreshToken
	fmt.Println("access_token", tokenInfo.AccessToken)
	fmt.Println("refresh_token", tokenInfo.RefreshToken)

	ti := refreshAccessToken(refresh_token)

	access_token := ti.AccessToken
	fmt.Println("access_token",  ti.AccessToken)
	fmt.Println("refresh_token", ti.RefreshToken)

	fmt.Println("\n execute get_user_info")
	userinfo, err := getUserInfo(access_token)

	if err != nil {
		fmt.Println("user_info_error", err.Error())
		return
	}

	token, _ := utils.JWTEncode(userinfo.(UserInfo).Username, "shenmidaima")
	ctx.SetCookie("TOKEN", token, 0, "/", "http://sso.client.com:9001", false, true)

	ctx.Redirect(302, "/")
}

this is print info, returned access_token is same, but refresh_token changed.

// use getAccessToken
execute get_access_token
using_code:  YZU1YMJLYTQTNTI5MY0ZYMY3LTG2ZTUTYJK2NDUYZMU2ZMUW
access_token eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJjbGllbnRfMDEiLCJleHAiOjE2NDc5MjM4NDksInN1YiI6Im1pbmsifQ.G6SQgYHOkwLzVWt0dlTRom-iahBOIYUN_dLDMiBCZ10GEAoOmwNqaahZDZvYw6nvekiOJEshbAir2VyMpn2-Xw
refresh_token N2M3ZDZINJKTY2Q3MI01YMY0LWFKZMMTMDHKMJMWNMFJMGM5

// use refreshAccessToken
execute refresh token
using_refresh_token:  N2M3ZDZINJKTY2Q3MI01YMY0LWFKZMMTMDHKMJMWNMFJMGM5

access_token eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJjbGllbnRfMDEiLCJleHAiOjE2NDc5MjM4NDksInN1YiI6Im1pbmsifQ.G6SQgYHOkwLzVWt0dlTRom-iahBOIYUN_dLDMiBCZ10GEAoOmwNqaahZDZvYw6nvekiOJEshbAir2VyMpn2-Xw
refresh_token MZA5M2ZKMDUTYWI4OC01NWQ1LTHJMJKTMZM2YJE3NZAXNMNI

// use getUserInfo
execute get_user_info
user_info_err unexpected end of JSON input

this is server.go code

func getUserInfo(ctx *gin.Context) {
	r := ctx.Request
	token, err := srv.ValidationBearerToken(r)

	if err != nil {
		auth := r.Header.Get("Authorization")
		fmt.Println("auth: ", auth)
		fmt.Println("token error: ", err.Error())
		return
	}

	fmt.Println("token", token)

	ctx.JSON(200, gin.H{
		"username": username,
	})

}
//  print info
auth:  Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJjbGllbnRfMDEiLCJleHAiOjE2NDc5MjM4NDksInN1YiI6Im1pbmsifQ.G6SQgYHOkwLzVWt0dlTRom-iahBOIYUN_dLDMiBCZ10GEAoOmwNqaahZDZvYw6nvekiOJEshbAir2VyMpn2-Xw
token error:  invalid access token

I found srv.ValidationBearerToken use func (m *Manager) LoadAccessToken , so I add println like this

func (m *Manager) LoadAccessToken(ctx context.Context, access string) (oauth2.TokenInfo, error) {
	if access == "" {
		return nil, errors.ErrInvalidAccessToken
	}

	ct := time.Now()
	ti, err := m.tokenStore.GetByAccess(ctx, access)

        // add line
	fmt.Println("access", access)
	fmt.Println("ti", ti)

        if err != nil {
		return nil, err
	} else if ti == nil || ti.GetAccess() != access {

same as above

func (ts *TokenStore) GetByAccess(ctx context.Context, access string) (oauth2.TokenInfo, error) {
	basicID, err := ts.getBasicID(access)

	fmt.Println("basicID", basicID)
	if err != nil {
		return nil, err
	}
	return ts.getData(basicID)
}

// token storage use memoryTokenStore 

	manager.MustTokenStorage(store.NewMemoryTokenStore())
	manager.MapAccessGenerate(generates.NewJWTAccessGenerate("", []byte(cfg.OAuth2.JWTSignedKey), jwt.SigningMethodHS512))
	// 配置store
	clientStore := store.NewClientStore()

server print info

basicID 
access eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJjbGllbnRfMDEiLCJleHAiOjE2NDc5MjM4NDksInN1YiI6Im1pbmsifQ.G6SQgYHOkwLzVWt0dlTRom-iahBOIYUN_dLDMiBCZ10GEAoOmwNqaahZDZvYw6nvekiOJEshbAir2VyMpn2-Xw
ti <nil>
auth:  Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJjbGllbnRfMDEiLCJleHAiOjE2NDc5MjM4NDksInN1YiI6Im1pbmsifQ.G6SQgYHOkwLzVWt0dlTRom-iahBOIYUN_dLDMiBCZ10GEAoOmwNqaahZDZvYw6nvekiOJEshbAir2VyMpn2-Xw
token error:  invalid access token

I get userinfo if i don't use refreshAccessToken。can you help me find the problem?

go version: v1.17.8 darwin/amd64 go-auth2: v4.4.3

cangmean avatar Mar 22 '22 03:03 cangmean

Refer https://github.com/go-oauth2/oauth2/blob/master/manage/manager.go#L419 and https://github.com/go-oauth2/oauth2/blob/master/manage/config.go#L38

Whenever a refresh token is used, the current access token is removed from token store by default. You can change this behavior by doing manager.SetRefreshingConfig. https://github.com/go-oauth2/oauth2/blob/master/manage/manager.go#L87

realbucksavage avatar Apr 12 '22 10:04 realbucksavage