@@ -3,12 +3,14 @@ package cmd
33import (
44 "context"
55 _ "embed"
6+ "encoding/json"
67 "errors"
78 "fmt"
89 "net/http"
910 "net/url"
1011 "os"
1112 "path"
13+ "path/filepath"
1214 "strings"
1315 "time"
1416
@@ -81,6 +83,35 @@ func ensureToken(ctx context.Context, requiredScopes []string, signals chan os.S
8183 return context .WithValue (ctx , sdp.UserTokenContextKey {}, apiKey ), nil
8284 }
8385
86+ // Check for a locally saved token in ~/.overmind
87+ if home , err := os .UserHomeDir (); err == nil {
88+ // Read in the token JSON file
89+ path := filepath .Join (home , ".overmind" , "token.json" )
90+
91+ token := new (oauth2.Token )
92+
93+ if _ , err := os .Stat (path ); ! os .IsNotExist (err ) {
94+ // Read the file
95+ file , err := os .Open (path )
96+ if err != nil {
97+ log .WithContext (ctx ).WithError (err ).Errorf ("Failed to open token file at %v" , path )
98+ return ctx , fmt .Errorf ("error opening token file at %v: %w" , path , err )
99+ }
100+
101+ // Decode the file
102+ err = json .NewDecoder (file ).Decode (token )
103+ if err != nil {
104+ log .WithContext (ctx ).WithError (err ).Errorf ("Failed to decode token file at %v" , path )
105+ return ctx , fmt .Errorf ("error decoding token file at %v: %w" , path , err )
106+ }
107+ }
108+
109+ // Check to see if the token is still valid
110+ if token .Valid () {
111+ return context .WithValue (ctx , sdp.UserTokenContextKey {}, token .AccessToken ), nil
112+ }
113+ }
114+
84115 // Check to see if the URL is secure
85116 gatewayUrl := viper .GetString ("gateway-url" )
86117 if gatewayUrl == "" {
@@ -180,6 +211,28 @@ func ensureToken(ctx context.Context, requiredScopes []string, signals chan os.S
180211
181212 log .WithContext (ctx ).Info ("Authenticated successfully ✅" )
182213
214+ // Save the token locally
215+ if home , err := os .UserHomeDir (); err == nil {
216+ // Create the directory if it doesn't exist
217+ err = os .MkdirAll (filepath .Join (home , ".overmind" ), 0700 )
218+ if err != nil {
219+ log .WithContext (ctx ).WithError (err ).Error ("Failed to create ~/.overmind directory" )
220+ }
221+
222+ // Write the token to a file
223+ path := filepath .Join (home , ".overmind" , "token.json" )
224+ file , err := os .Create (path )
225+ if err != nil {
226+ log .WithContext (ctx ).WithError (err ).Errorf ("Failed to create token file at %v" , path )
227+ }
228+
229+ // Encode the token
230+ err = json .NewEncoder (file ).Encode (token )
231+ if err != nil {
232+ log .WithContext (ctx ).WithError (err ).Errorf ("Failed to encode token file at %v" , path )
233+ }
234+ }
235+
183236 // Set the token
184237 return context .WithValue (ctx , sdp.UserTokenContextKey {}, token .AccessToken ), nil
185238 }
0 commit comments