@@ -2,6 +2,7 @@ package auth
22
33import (
44 "fmt"
5+ "net/http"
56 "os"
67 "strconv"
78 "time"
@@ -132,3 +133,71 @@ func getEmailFromToken(token string) (string, error) {
132133
133134 return claims .Email , nil
134135}
136+
137+ // RefreshAccessToken refreshes the access token if it's expired for the user token flow.
138+ // It returns the new access token or an error if the refresh fails.
139+ func RefreshAccessToken (p * print.Printer ) (string , error ) {
140+ flow , err := GetAuthFlow ()
141+ if err != nil {
142+ return "" , fmt .Errorf ("get authentication flow: %w" , err )
143+ }
144+ if flow != AUTH_FLOW_USER_TOKEN {
145+ return "" , fmt .Errorf ("token refresh is only supported for user token flow, current flow: %s" , flow )
146+ }
147+
148+ // Load tokens from storage
149+ authFields := map [authFieldKey ]string {
150+ ACCESS_TOKEN : "" ,
151+ REFRESH_TOKEN : "" ,
152+ IDP_TOKEN_ENDPOINT : "" ,
153+ }
154+ err = GetAuthFieldMap (authFields )
155+ if err != nil {
156+ return "" , fmt .Errorf ("get tokens from auth storage: %w" , err )
157+ }
158+
159+ accessToken := authFields [ACCESS_TOKEN ]
160+ refreshToken := authFields [REFRESH_TOKEN ]
161+ tokenEndpoint := authFields [IDP_TOKEN_ENDPOINT ]
162+
163+ if accessToken == "" {
164+ return "" , fmt .Errorf ("access token not set" )
165+ }
166+ if refreshToken == "" {
167+ return "" , fmt .Errorf ("refresh token not set" )
168+ }
169+ if tokenEndpoint == "" {
170+ return "" , fmt .Errorf ("token endpoint not set" )
171+ }
172+
173+ // Check if access token is expired
174+ accessTokenExpired , err := TokenExpired (accessToken )
175+ if err != nil {
176+ return "" , fmt .Errorf ("check if access token has expired: %w" , err )
177+ }
178+ if ! accessTokenExpired {
179+ // Token is still valid, return it
180+ return accessToken , nil
181+ }
182+
183+ p .Debug (print .DebugLevel , "access token expired, refreshing..." )
184+
185+ // Create a temporary userTokenFlow to reuse the refresh logic
186+ utf := & userTokenFlow {
187+ printer : p ,
188+ client : & http.Client {},
189+ authFlow : flow ,
190+ accessToken : accessToken ,
191+ refreshToken : refreshToken ,
192+ tokenEndpoint : tokenEndpoint ,
193+ }
194+
195+ // Refresh the tokens
196+ err = refreshTokens (utf )
197+ if err != nil {
198+ return "" , fmt .Errorf ("refresh access token: %w" , err )
199+ }
200+
201+ // Return the new access token
202+ return utf .accessToken , nil
203+ }
0 commit comments