Skip to content

Commit

Permalink
refresh token automatically
Browse files Browse the repository at this point in the history
  • Loading branch information
cyrildiagne committed Jan 12, 2020
1 parent 35a46a2 commit 36a2170
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 1 deletion.
39 changes: 39 additions & 0 deletions cli/cmd/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import (
"encoding/json"
"errors"
"net/http"
"net/url"
"os"
"os/exec"
"strconv"
"time"

"github.com/cyrildiagne/kuda/pkg/auth"
Expand Down Expand Up @@ -78,3 +80,40 @@ func startLoginFlow(authURL string) (*auth.User, error) {
}
return user, nil
}

// RefreshToken stores refreshtoken results
type RefreshToken struct {
RefreshToken string `json:"refresh_token"`
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
}

// This is a simple util for the CLI to refresh expired tokens
func refreshAuthToken(refreshURL string, refreshToken string) (*RefreshToken, error) {
formData := url.Values{
"refresh_token": {refreshToken},
}
resp, err := http.PostForm(refreshURL, formData)
if err != nil {
return nil, err
}

decoder := json.NewDecoder(resp.Body)
user := map[string]string{}
if err := decoder.Decode(&user); err != nil {
return nil, err
}

expiresIn, err := strconv.Atoi(user["expires_in"])
if err != nil {
return nil, err
}

res := &RefreshToken{
RefreshToken: user["refresh_token"],
AccessToken: user["access_token"],
ExpiresIn: expiresIn,
}

return res, nil
}
24 changes: 24 additions & 0 deletions cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"io/ioutil"
"os"
"strconv"
"time"

"github.com/cyrildiagne/kuda/pkg/config"
homedir "github.com/mitchellh/go-homedir"
Expand Down Expand Up @@ -62,5 +64,27 @@ func loadConfig() {
panic(err)
} else {
fmt.Println("Loaded config from", cfgFile)

// Check access token
i, err := strconv.ParseInt(strconv.Itoa(cfg.Provider.User.Token.ExpirationTime/1000), 10, 64)
if err != nil {
panic(err)
}
tm := time.Unix(i, 0)

if tm.Before(time.Now()) {
fmt.Println("Refreshing token...")
refreshURL := cfg.Provider.AuthURL + "/refresh"
refreshToken := cfg.Provider.User.Token.RefreshToken
res, err := refreshAuthToken(refreshURL, refreshToken)
if err != nil {
panic(err)
}

cfg.Provider.User.Token.RefreshToken = res.RefreshToken
cfg.Provider.User.Token.AccessToken = res.AccessToken
cfg.Provider.User.Token.ExpirationTime = (int(time.Now().Unix()) + res.ExpiresIn) * 1000
writeConfig(cfg)
}
}
}
49 changes: 48 additions & 1 deletion images/auth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import (
"bytes"
"fmt"
"html/template"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"strings"
)

var authPage string
var config AuthConfig

// AuthConfig represents the AuthConfig Document.
type AuthConfig struct {
Expand All @@ -23,12 +27,52 @@ func home(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, authPage)
}

func refreshToken(w http.ResponseWriter, r *http.Request) {
fmt.Println("refreshing...")
fmt.Println(config.APIKey)
endpoint := "https://securetoken.googleapis.com/v1/token?key=" + config.APIKey

refreshToken := r.FormValue("refresh_token")
if refreshToken == "" {
http.Error(w, "refresh_token missing", 400)
}

data := url.Values{}
data.Set("grant_type", "refresh_token")
data.Set("refresh_token", refreshToken)

req, err := http.NewRequest("POST", endpoint, strings.NewReader(data.Encode())) // URL-encoded payload
if err != nil {
http.Error(w, err.Error(), 500)
}

req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
http.Error(w, err.Error(), 500)
}

if resp.StatusCode != http.StatusOK {
http.Error(w, "unknown error", resp.StatusCode)
}

bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
bodyString := string(bodyBytes)

fmt.Fprint(w, bodyString)
}

func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", home)

// Retrieve the auth env variables.
config := AuthConfig{
config = AuthConfig{
APIKey: os.Getenv("KUDA_AUTH_API_KEY"),
AuthDomain: os.Getenv("KUDA_AUTH_DOMAIN"),
TermsOfServiceURL: template.URL(os.Getenv("KUDA_AUTH_TOS_URL")),
Expand All @@ -48,6 +92,9 @@ func main() {
fileServer := http.FileServer(http.Dir("./public"))
mux.Handle("/public/", http.StripPrefix("/public", fileServer))

// Setup refresh token endpoint
mux.HandleFunc("/refresh", refreshToken)

// Start server
port := os.Getenv("PORT")
if port == "" {
Expand Down

0 comments on commit 36a2170

Please sign in to comment.