Skip to content

Commit

Permalink
Provide API key directly instead of providing username and password (#33
Browse files Browse the repository at this point in the history
)

The current login flow is:
- provide your username and password
- the process passes this to Pusher
- Pusher responds with that account's API key
- save the API key
- use the API key for all auth'd requests

This proposes a new login flow:
- provide your API key
- save the API key
- use the API key for all auth'd requests

This removes the requirement for a "swap your credentials for an API key" endpoint.
  • Loading branch information
jameshfisher authored and kn100 committed Apr 18, 2019
1 parent 9b529a1 commit 3c36c5c
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 126 deletions.
62 changes: 0 additions & 62 deletions api/account.go
@@ -1,74 +1,12 @@
package api

import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"

"github.com/pusher/cli/config"
"github.com/theherk/viper"
)

const getAPIKeyEndpoint = "/account/api_key"

type apiKeyResponse struct {
APIKey string `json:"apikey"`
}

func GetAPIKey(email, password string) (string, error) {
response, err := basicAuthRequest(getAPIKeyEndpoint, email, password)
if err != nil {
fmt.Println(err)
fmt.Println("The Pusher API didn't respond correctly. Please try again later!")
return "", err
}

var dat apiKeyResponse
err = json.Unmarshal(response, &dat)
if err != nil {
return "", errors.New("could not unmarshal JSON: " + err.Error() + " when parsing response: " + string(response))
}
if dat.APIKey == "" {
return "", errors.New("expected API key in response, but got: " + string(response))
}

return dat.APIKey, nil
}

func basicAuthRequest(path string, username string, password string) ([]byte, error) {
req, err := http.NewRequest("GET", viper.GetString("endpoint")+path, nil)
if err != nil {
return nil, err
}

req.Header.Set("Content-type", "application/json")
req.Header.Set("User-Agent", "PusherCLI/"+config.GetVersion())
req.SetBasicAuth(username, password)

resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode == 401 {
return nil, fmt.Errorf("invalid username or password")
} else if resp.StatusCode == 404 {
return nil, fmt.Errorf("no api key associated with the account, please visit https://dashboard.pusher.com/accounts/edit to add one")
} else if resp.StatusCode < 200 || 400 <= resp.StatusCode {
return nil, fmt.Errorf("unexpected status code %d", resp.StatusCode)
}

respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return respBody, nil
}

//isAPIKeyValid returns true if the stored API key is valid.
func isAPIKeyValid() bool {
if viper.GetString("token") != "" {
Expand Down
45 changes: 0 additions & 45 deletions api/account_test.go

This file was deleted.

30 changes: 11 additions & 19 deletions commands/auth/login.go
Expand Up @@ -3,9 +3,6 @@ package auth
import (
"fmt"
"os"
"syscall"

"golang.org/x/crypto/ssh/terminal"

"github.com/pusher/cli/api"
"github.com/spf13/cobra"
Expand All @@ -15,30 +12,25 @@ import (
// Login allows users to log in using an API token.
var Login = &cobra.Command{
Use: "login",
Short: "Enter and store Pusher account credentials",
Short: "Enter and store Pusher API key",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
if APIKeyValid() {
fmt.Println("Your API key is valid. If you'd like to use a different API key, use `logout` first.")
fmt.Println("Your current API key is valid. If you'd like to use a different API key, use `logout` first.")
os.Exit(1)
}
fmt.Println("What is your email address?")
var email string
fmt.Scanln(&email)

fmt.Println("What is your password?")
passwordBytes, _ := terminal.ReadPassword(int(syscall.Stdin))
password := string(passwordBytes)
fmt.Println("What is your API key? (Find this at https://dashboard.pusher.com/accounts/edit)")
var apikey string
fmt.Scanln(&apikey)
viper.Set("token", apikey)

// check if the user/pass can get an API key
apikey, err := api.GetAPIKey(email, password)
if err != nil {
fmt.Println("Couldn't get API key: " + err.Error())
return
if !APIKeyValid() {
fmt.Println("That API key is not valid!")
os.Exit(1)
}
fmt.Println("Got your API key!")
viper.Set("token", apikey)
err = viper.WriteConfig()

err := viper.WriteConfig()
if err != nil {
panic("Could not write config: " + err.Error())
}
Expand Down

0 comments on commit 3c36c5c

Please sign in to comment.