aboutsummaryrefslogtreecommitdiffstats
path: root/client/go/auth/token.go
diff options
context:
space:
mode:
Diffstat (limited to 'client/go/auth/token.go')
-rw-r--r--client/go/auth/token.go68
1 files changed, 68 insertions, 0 deletions
diff --git a/client/go/auth/token.go b/client/go/auth/token.go
new file mode 100644
index 00000000000..e9b90b8994e
--- /dev/null
+++ b/client/go/auth/token.go
@@ -0,0 +1,68 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+package auth
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+)
+
+type TokenResponse struct {
+ AccessToken string `json:"access_token"`
+ IDToken string `json:"id_token"`
+ TokenType string `json:"token_type"`
+ ExpiresIn int `json:"expires_in"`
+}
+
+type TokenRetriever struct {
+ Authenticator *Authenticator
+ Secrets SecretStore
+ Client *http.Client
+}
+
+// Delete deletes the given tenant from the secrets' storage.
+func (t *TokenRetriever) Delete(tenant string) error {
+ return t.Secrets.Delete(SecretsNamespace, tenant)
+}
+
+// Refresh gets a new access token from the provided refresh token,
+// The request is used the default client_id and endpoint for device authentication.
+func (t *TokenRetriever) Refresh(ctx context.Context, tenant string) (TokenResponse, error) {
+ // get stored refresh token:
+ refreshToken, err := t.Secrets.Get(SecretsNamespace, tenant)
+ if err != nil {
+ return TokenResponse{}, fmt.Errorf("cannot get the stored refresh token: %w", err)
+ }
+ if refreshToken == "" {
+ return TokenResponse{}, errors.New("cannot use the stored refresh token: the token is empty")
+ }
+ // get access token:
+ r, err := t.Client.PostForm(t.Authenticator.OauthTokenEndpoint, url.Values{
+ "grant_type": {"refresh_token"},
+ "client_id": {t.Authenticator.ClientID},
+ "refresh_token": {refreshToken},
+ })
+ if err != nil {
+ return TokenResponse{}, fmt.Errorf("cannot get a new access token from the refresh token: %w", err)
+ }
+
+ defer r.Body.Close()
+ if r.StatusCode != http.StatusOK {
+ b, _ := ioutil.ReadAll(r.Body)
+ bodyStr := string(b)
+ return TokenResponse{}, fmt.Errorf("cannot get a new access token from the refresh token: %s", bodyStr)
+ }
+
+ var res TokenResponse
+ err = json.NewDecoder(r.Body).Decode(&res)
+ if err != nil {
+ return TokenResponse{}, fmt.Errorf("cannot decode response: %w", err)
+ }
+
+ return res, nil
+}