token.go raw
1 package logincreds
2
3 import (
4 "crypto/sha256"
5 "encoding/hex"
6 "errors"
7 "fmt"
8 "path/filepath"
9 "strings"
10 "time"
11
12 "github.com/aws/aws-sdk-go-v2/aws"
13 "github.com/aws/aws-sdk-go-v2/internal/sdk"
14 "github.com/aws/aws-sdk-go-v2/internal/shareddefaults"
15 "github.com/aws/aws-sdk-go-v2/service/signin"
16 )
17
18 var userHomeDir = shareddefaults.UserHomeDir
19
20 // StandardCachedTokenFilepath returns the filepath for the cached login token
21 // file. Key that will be used to compute a SHA256 value that is hex encoded.
22 //
23 // An overriden root dir can be provided, if not set the path defaults to
24 // ~/.aws/sso/cache.
25 func StandardCachedTokenFilepath(session, dir string) (string, error) {
26 session = strings.TrimSpace(session)
27
28 if len(dir) == 0 {
29 dir = userHomeDir()
30 if len(dir) == 0 {
31 return "", errors.New("user home dir is blank")
32 }
33 dir = filepath.Join(dir, ".aws", "login", "cache")
34 }
35
36 h := sha256.New()
37 h.Write([]byte(session))
38
39 filename := strings.ToLower(hex.EncodeToString(h.Sum(nil))) + ".json"
40 return filepath.Join(dir, filename), nil
41 }
42
43 // contents of the token as they appear on disk
44 type loginToken struct {
45 AccessToken *loginTokenAccessToken `json:"accessToken"`
46 TokenType string `json:"tokenType"`
47 RefreshToken string `json:"refreshToken"`
48 IdentityToken string `json:"identityToken"`
49 ClientID string `json:"clientId"`
50 DPOPKey string `json:"dpopKey"`
51 }
52
53 type loginTokenAccessToken struct {
54 AccessKeyID string `json:"accessKeyId"`
55 SecretAccessKey string `json:"secretAccessKey"`
56 SessionToken string `json:"sessionToken"`
57 AccountID string `json:"accountId"`
58 ExpiresAt time.Time `json:"expiresAt"`
59 }
60
61 func (t *loginToken) Validate() error {
62 if t.AccessToken == nil {
63 return fmt.Errorf("missing accessToken")
64 }
65 if t.AccessToken.AccessKeyID == "" {
66 return fmt.Errorf("missing accessToken.accessKeyId")
67 }
68 if t.AccessToken.SecretAccessKey == "" {
69 return fmt.Errorf("missing accessToken.secretAccessKey")
70 }
71 if t.AccessToken.SessionToken == "" {
72 return fmt.Errorf("missing accessToken.sessionToken")
73 }
74 if t.AccessToken.AccountID == "" {
75 return fmt.Errorf("missing accessToken.accountId")
76 }
77 if t.AccessToken.ExpiresAt.IsZero() {
78 return fmt.Errorf("missing accessToken.expiresAt")
79 }
80 if t.ClientID == "" {
81 return fmt.Errorf("missing clientId")
82 }
83 if t.RefreshToken == "" {
84 return fmt.Errorf("missing refreshToken")
85 }
86 if t.DPOPKey == "" {
87 return fmt.Errorf("missing dpopKey")
88 }
89 return nil
90 }
91
92 func (t *loginToken) Credentials() aws.Credentials {
93 return aws.Credentials{
94 AccessKeyID: t.AccessToken.AccessKeyID,
95 SecretAccessKey: t.AccessToken.SecretAccessKey,
96 SessionToken: t.AccessToken.SessionToken,
97 Source: ProviderName,
98 CanExpire: true,
99 Expires: t.AccessToken.ExpiresAt,
100 AccountID: t.AccessToken.AccountID,
101 }
102 }
103
104 func (t *loginToken) Update(out *signin.CreateOAuth2TokenOutput) {
105 t.AccessToken.AccessKeyID = *out.TokenOutput.AccessToken.AccessKeyId
106 t.AccessToken.SecretAccessKey = *out.TokenOutput.AccessToken.SecretAccessKey
107 t.AccessToken.SessionToken = *out.TokenOutput.AccessToken.SessionToken
108 t.AccessToken.ExpiresAt = sdk.NowTime().Add(time.Duration(*out.TokenOutput.ExpiresIn) * time.Second)
109 t.RefreshToken = *out.TokenOutput.RefreshToken
110 }
111