github.com/taubyte/tau-cli@v0.1.13-0.20240326000942-487f0d57edfc/prompts/login/token_web.go (about) 1 package loginPrompts 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "path" 9 "strings" 10 11 "github.com/pterm/pterm" 12 http "github.com/taubyte/http" 13 basicHttp "github.com/taubyte/http/basic" 14 "github.com/taubyte/http/options" 15 "github.com/urfave/cli/v2" 16 ) 17 18 type SessionData struct { 19 Expiry float64 `json:"exp"` 20 Provider string `json:"provider"` 21 Repositories []string `json:"repositories"` 22 Token string `json:"token"` 23 } 24 25 func extractTokenFromSession(session string) (data SessionData, err error) { 26 sessionSplit := strings.Split(session, ".") 27 if len(sessionSplit) < 1 { 28 err = fmt.Errorf("invalid session: `%s`", session) 29 return 30 } 31 32 base64Decoded, err := base64.RawStdEncoding.DecodeString(sessionSplit[1]) 33 if err != nil { 34 err = fmt.Errorf("decoding session `%s` failed with: %s", session, err) 35 return 36 } 37 38 err = json.Unmarshal(base64Decoded, &data) 39 if err != nil { 40 return 41 } 42 43 return 44 } 45 46 func getTokenConsoleURL(provider string, origin string) string { 47 consoleURL := "console.taubyte.com/" 48 consoleURL = "https://" + path.Join(consoleURL, fmt.Sprintf("oauth/%s/login", provider)) 49 return consoleURL + fmt.Sprintf("?origin=%s", origin) 50 } 51 52 // Token from web gives a link to github with a hook back to here 53 func TokenFromWeb(ctx *cli.Context, provider string) (token string, err error) { 54 tokenCh := make(chan string) 55 defer close(tokenCh) 56 57 errCh := make(chan error) 58 defer close(errCh) 59 60 // Open an http server to listen for the token 61 srv, err := basicHttp.New(ctx.Context, options.Listen(":"+githubLoginListenPort)) 62 if err != nil { 63 err = fmt.Errorf(StartingHttpFailedWith, githubLoginListenPort, err) 64 return 65 } 66 67 srv.GET(&http.RouteDefinition{ 68 Path: "/", 69 Handler: func(ctx http.Context) (iface interface{}, err error) { 70 session := ctx.Request().URL.Query().Get("session") 71 if len(session) == 0 { 72 errCh <- errors.New(NoSessionProvided) 73 return 74 } 75 76 sessionData, err := extractTokenFromSession(session) 77 if err != nil { 78 errCh <- err 79 return 80 } 81 82 // TODO track expiration of token 83 tokenCh <- sessionData.Token 84 85 return SuccessCheckBackAtYourTerminal, nil 86 }, 87 }) 88 89 // Start the http server listen 90 srv.Start() 91 92 origin := fmt.Sprintf("http://127.0.0.1:%s", githubLoginListenPort) 93 pterm.Info.Printfln(OpenURLToLogin, provider, getTokenConsoleURL(provider, origin)) 94 95 select { 96 case token = <-tokenCh: 97 break 98 case err = <-errCh: 99 break 100 } 101 102 // Stop the http server 103 srv.Stop() 104 if srv.Error() != nil { 105 // Only display error, as we got the token or an error 106 pterm.Warning.Printfln(ShuttingDownHttpFailedWith, githubLoginListenPort, srv.Error()) 107 } 108 109 return 110 }