From f64fea7acb75d404f96eed13f8fcbc644265ff00 Mon Sep 17 00:00:00 2001 From: Aerex Date: Mon, 1 Nov 2021 11:26:12 -0500 Subject: [PATCH 01/21] fix(core_config): Added HasExpired method to check if token expired --- .../configuration/core_config/bx_config.go | 9 ++--- .../configuration/core_config/iam_token.go | 15 ++++++++ .../core_config/iam_token_test.go | 31 ++++++++++++++++ .../configuration/core_config/uaa_token.go | 13 +++++++ .../core_config/uaa_token_test.go | 35 +++++++++++++++++++ 5 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 bluemix/configuration/core_config/uaa_token_test.go diff --git a/bluemix/configuration/core_config/bx_config.go b/bluemix/configuration/core_config/bx_config.go index 7a33964b..b517849c 100644 --- a/bluemix/configuration/core_config/bx_config.go +++ b/bluemix/configuration/core_config/bx_config.go @@ -297,10 +297,11 @@ func (c *bxConfig) IAMID() (guid string) { } func (c *bxConfig) IsLoggedIn() (loggedIn bool) { - c.read(func() { - loggedIn = c.data.IAMToken != "" - }) - return + if token := c.IAMToken(); token != "" { + iamTokenInfo := NewIAMTokenInfo(token) + return iamTokenInfo.HasExpired() + } + return false } func (c *bxConfig) CurrentAccount() (account models.Account) { diff --git a/bluemix/configuration/core_config/iam_token.go b/bluemix/configuration/core_config/iam_token.go index 72f98128..1f8058d5 100644 --- a/bluemix/configuration/core_config/iam_token.go +++ b/bluemix/configuration/core_config/iam_token.go @@ -14,6 +14,8 @@ const ( SubjectTypeTrustedProfile = "Profile" ) +const expiryDelta = 10 * time.Second + type IAMTokenInfo struct { IAMID string `json:"iam_id"` ID string `json:"id"` @@ -82,3 +84,16 @@ func decodeAccessToken(token string) (tokenJSON []byte, err error) { encodedTokenJSON := encodedParts[1] return base64.RawURLEncoding.DecodeString(encodedTokenJSON) } + +// HasExpired returns True if the token expiry has occured +// before today + delta time or a token is invalid +func (t IAMTokenInfo) HasExpired() bool { + // We can assume that a token without an ID is invalid and expired + if t.ID == "" { + return true + } + if t.Expiry.IsZero() { + return false + } + return t.Expiry.Before(time.Now().Add(expiryDelta)) +} diff --git a/bluemix/configuration/core_config/iam_token_test.go b/bluemix/configuration/core_config/iam_token_test.go index 971cf82c..adccb140 100644 --- a/bluemix/configuration/core_config/iam_token_test.go +++ b/bluemix/configuration/core_config/iam_token_test.go @@ -6,6 +6,12 @@ import ( "github.com/stretchr/testify/assert" ) + +type iamTokenTestCases struct { + token string + name string +} + var TestIAMTokenData = []string{ //token from password "eyJraWQiOiIyMDE3MTAzMC0wMDowMDowMCIsImFsZyI6IlJTMjU2In0.eyJpYW1faWQiOiJJQk1pZC0yNzAwMDZWOEhNIiwiaWQiOiJJQk1pZC0yNzAwMDZWOEhNIiwicmVhbG1pZCI6IklCTWlkIiwiaWRlbnRpZmllciI6IjI3MDAwNlY4SE0iLCJnaXZlbl9uYW1lIjoiT0UgUnVudGltZXMiLCJmYW1pbHlfbmFtZSI6IlN5c3RlbSBVc2VyIiwibmFtZSI6Ik9FIFJ1bnRpbWVzIFN5c3RlbSBVc2VyIiwiZW1haWwiOiJydHN5c3VzckBjbi5pYm0uY29tIiwic3ViIjoicnRzeXN1c3JAY24uaWJtLmNvbSIsImFjY291bnQiOnsiYnNzIjoiOGQ2M2ZiMWNjNWU5OWU4NmRkNzIyOWRkZGZmYzA1YTUifSwiaWF0IjoxNTE2MTc0NjAzLCJleHAiOjE1MTYxNzgyMDMsImlzcyI6Imh0dHBzOi8vaWFtLmJsdWVtaXgubmV0L2lkZW50aXR5IiwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwic2NvcGUiOiJvcGVuaWQiLCJjbGllbnRfaWQiOiJieCJ9.gx-HQ1CSEwz5d4O1HXx4pusaYeEsqkQZgoBZ6esMBZG6wK6wQFPvC4D0Yvdi6CvKrVU-zV9PM_o3n5c-DFKjjTyTnRbQgrG0EPCRPmFW3bpepSb7eSw01S2YOLy5UTbz0cdM9hq-jafOu1S8pe9xeSMIMiA3-EFzCap5Z5CuoK9oIYJIFWseb1KsOyoiNOellbw1MaOmMzb4fsFz5Dr1Y8c1pNhoqp8M62E3y1yHe2jc6YepDab7Dqn2benK_e-MI3BlyWuBu4yo5mY2oCinJthr2E1YgbzWvcMy5a-ximnQIb4K6kscuUW_Yj_1GhDGJs4MP9u7M3-XdY1CNBGYeQ", @@ -31,6 +37,22 @@ var TestUAATokenData = []string{ "Bearer eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJqdGkiOiJhZGFkNWYwYzQ0ZDI0ZDlkYmVhN2YyNGIzMDNmOWNhNyIsInN1YiI6IjY3ODdiMzM2LTAwNzUtNGYwYy1hZmZiLWUyOWZjMmVhZWI4OCIsInNjb3BlIjpbIm9wZW5pZCIsInVhYS51c2VyIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwicGFzc3dvcmQud3JpdGUiLCJjbG91ZF9jb250cm9sbGVyLndyaXRlIl0sImNsaWVudF9pZCI6ImNmIiwiY2lkIjoiY2YiLCJhenAiOiJjZiIsImdyYW50X3R5cGUiOiJwYXNzd29yZCIsInVzZXJfaWQiOiI2Nzg3YjMzNi0wMDc1LTRmMGMtYWZmYi1lMjlmYzJlYWViODgiLCJvcmlnaW4iOiJ1YWEiLCJ1c2VyX25hbWUiOiJ3YW5nanVubEBjbi5pYm0uY29tIiwiZW1haWwiOiJ3YW5nanVubEBjbi5pYm0uY29tIiwiYXV0aF90aW1lIjoxNTE2MTczMjgxLCJpYXQiOjE1MTYxNzMyODEsImV4cCI6MTUxNjE3Njg4MCwiaXNzIjoiaHR0cHM6Ly91YWEubmcuYmx1ZW1peC5uZXQvb2F1dGgvdG9rZW4iLCJ6aWQiOiJ1YWEiLCJhdWQiOlsiY2xvdWRfY29udHJvbGxlciIsInBhc3N3b3JkIiwiY2YiLCJ1YWEiLCJvcGVuaWQiXX0.K-9HdMCrNdln81ewX_TQLR63F4wChz035G5KtMq9wkk", } +var TestIAMTokenHasExpiredTestCases = []uaaTokenTestCases{ + { + token: "", + name: "empty token", + }, + { + token: "eyJraWQiOiIyMDIxMTAxODA4MTkiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw", + name: "expired token", + }, + { + token: "ABCD.DEFG.HIGK", + name: "invalid token", + }, +} + + func TestNewIAMTokenInfo(t *testing.T) { for _, token := range TestIAMTokenData { tokenInfo := NewIAMTokenInfo(token) @@ -72,3 +94,12 @@ func TestUAATokenInfo(t *testing.T) { assert.Equal(t, tokenInfo.UserGUID, "6787b336-0075-4f0c-affb-e29fc2eaeb88") } } + +func TestIAMTokenHasExpired(t *testing.T) { + for _, testCase := range TestIAMTokenHasExpiredTestCases { + t.Run(testCase.name, func(t *testing.T) { + tokenInfo := NewIAMTokenInfo(testCase.token) + assert.True(t, tokenInfo.HasExpired(), "%s should return true", testCase.name) + }) + } +} diff --git a/bluemix/configuration/core_config/uaa_token.go b/bluemix/configuration/core_config/uaa_token.go index 0c3e1e23..7ff6739c 100644 --- a/bluemix/configuration/core_config/uaa_token.go +++ b/bluemix/configuration/core_config/uaa_token.go @@ -36,3 +36,16 @@ func NewUAATokenInfo(token string) UAATokenInfo { ret.IssueAt = t.IssueAt.Time() return ret } + +// HasExpired returns True if the token expiry has occured +// before today + delta time or a token is invalid +func (t UAATokenInfo) HasExpired() bool { + // We can assume that a UAA token without an UserGUID is invalid and expired + if t.UserGUID == "" { + return true + } + if t.Expiry.IsZero() { + return false + } + return t.Expiry.Before(time.Now().Add(expiryDelta)) +} diff --git a/bluemix/configuration/core_config/uaa_token_test.go b/bluemix/configuration/core_config/uaa_token_test.go new file mode 100644 index 00000000..ee378cda --- /dev/null +++ b/bluemix/configuration/core_config/uaa_token_test.go @@ -0,0 +1,35 @@ +package core_config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +type uaaTokenTestCases struct { + token string + name string +} +var TestUAATokenHasExpiredTestCases = []uaaTokenTestCases{ + { + token: "", + name: "empty token", + }, + { + token: "eyJraWQiOiIyMDIxMTAxODA4MTkiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw", + name: "expired token", + }, + { + token: "ABCD.DEFG.HIGK", + name: "invalid token", + }, +} + +func TestUAATokenHasExpired(t *testing.T) { + for _, testCase := range TestUAATokenHasExpiredTestCases { + t.Run(testCase.name, func(t *testing.T) { + tokenInfo := NewUAATokenInfo(testCase.token) + assert.True(t, tokenInfo.HasExpired(), "%s should return true", testCase.name) + }) + } +} From ce2a50886a1b501eb5ca44e3c7e7fc07d749d1de Mon Sep 17 00:00:00 2001 From: Aerex Date: Tue, 2 Nov 2021 16:58:27 -0500 Subject: [PATCH 02/21] test: Added test to check HasExpired on long lasting token --- bluemix/configuration/core_config/bx_config.go | 2 +- bluemix/configuration/core_config/iam_token_test.go | 11 ++++++++++- bluemix/configuration/core_config/uaa_token_test.go | 11 ++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/bluemix/configuration/core_config/bx_config.go b/bluemix/configuration/core_config/bx_config.go index b517849c..7069ddcb 100644 --- a/bluemix/configuration/core_config/bx_config.go +++ b/bluemix/configuration/core_config/bx_config.go @@ -296,7 +296,7 @@ func (c *bxConfig) IAMID() (guid string) { return } -func (c *bxConfig) IsLoggedIn() (loggedIn bool) { +func (c *bxConfig) IsLoggedIn() (bool) { if token := c.IAMToken(); token != "" { iamTokenInfo := NewIAMTokenInfo(token) return iamTokenInfo.HasExpired() diff --git a/bluemix/configuration/core_config/iam_token_test.go b/bluemix/configuration/core_config/iam_token_test.go index adccb140..85e9e66f 100644 --- a/bluemix/configuration/core_config/iam_token_test.go +++ b/bluemix/configuration/core_config/iam_token_test.go @@ -10,6 +10,7 @@ import ( type iamTokenTestCases struct { token string name string + isExpired bool } var TestIAMTokenData = []string{ @@ -41,14 +42,22 @@ var TestIAMTokenHasExpiredTestCases = []uaaTokenTestCases{ { token: "", name: "empty token", + isExpired: true, }, { token: "eyJraWQiOiIyMDIxMTAxODA4MTkiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw", name: "expired token", + isExpired: true, }, { token: "ABCD.DEFG.HIGK", name: "invalid token", + isExpired: true, + }, + { + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNzM1NDQyMDI3LCJleHAiOjE3ODYxNzgyMDMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.3ZOgRfe6JcQv303O3DYdCI9OCDkxdlMEBHp8f7iy1fI", + name: "token expired in 2029", + isExpired: false, }, } @@ -99,7 +108,7 @@ func TestIAMTokenHasExpired(t *testing.T) { for _, testCase := range TestIAMTokenHasExpiredTestCases { t.Run(testCase.name, func(t *testing.T) { tokenInfo := NewIAMTokenInfo(testCase.token) - assert.True(t, tokenInfo.HasExpired(), "%s should return true", testCase.name) + assert.Equal(t, testCase.isExpired, tokenInfo.HasExpired()) }) } } diff --git a/bluemix/configuration/core_config/uaa_token_test.go b/bluemix/configuration/core_config/uaa_token_test.go index ee378cda..74ee7403 100644 --- a/bluemix/configuration/core_config/uaa_token_test.go +++ b/bluemix/configuration/core_config/uaa_token_test.go @@ -9,19 +9,28 @@ import ( type uaaTokenTestCases struct { token string name string + isExpired bool } var TestUAATokenHasExpiredTestCases = []uaaTokenTestCases{ { token: "", name: "empty token", + isExpired: true, }, { token: "eyJraWQiOiIyMDIxMTAxODA4MTkiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw", name: "expired token", + isExpired: true, }, { token: "ABCD.DEFG.HIGK", name: "invalid token", + isExpired: true, + }, + { + token:"eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJqdGkiOiJhZGFkNWYwYzQ0ZDI0ZDlkYmVhN2YyNGIzMDNmOWNhNyIsInN1YiI6IjY3ODdiMzM2LTAwNzUtNGYwYy1hZmZiLWUyOWZjMmVhZWI4OCIsInNjb3BlIjpbIm9wZW5pZCIsInVhYS51c2VyIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwicGFzc3dvcmQud3JpdGUiLCJjbG91ZF9jb250cm9sbGVyLndyaXRlIl0sImNsaWVudF9pZCI6ImNmIiwiY2lkIjoiY2YiLCJhenAiOiJjZiIsImdyYW50X3R5cGUiOiJwYXNzd29yZCIsInVzZXJfaWQiOiI2Nzg3YjMzNi0wMDc1LTRmMGMtYWZmYi1lMjlmYzJlYWViODgiLCJvcmlnaW4iOiJ1YWEiLCJ1c2VyX25hbWUiOiJ3YW5nanVubEBjbi5pYm0uY29tIiwiZW1haWwiOiJ3YW5nanVubEBjbi5pYm0uY29tIiwiYXV0aF90aW1lIjoxNTE2MTczMjgxLCJpYXQiOjE4MTYxNzMyODEsImV4cCI6MjkyNjE3Njg4MCwiaXNzIjoiaHR0cHM6Ly91YWEubmcuYmx1ZW1peC5uZXQvb2F1dGgvdG9rZW4iLCJ6aWQiOiJ1YWEiLCJhdWQiOlsiY2xvdWRfY29udHJvbGxlciIsInBhc3N3b3JkIiwiY2YiLCJ1YWEiLCJvcGVuaWQiXX0.CPUPLMtDpGScEbK9pyD5pzOCWXUir7TX-gZSmFFSRLM", + name: "token expired in 2062", + isExpired: false, }, } @@ -29,7 +38,7 @@ func TestUAATokenHasExpired(t *testing.T) { for _, testCase := range TestUAATokenHasExpiredTestCases { t.Run(testCase.name, func(t *testing.T) { tokenInfo := NewUAATokenInfo(testCase.token) - assert.True(t, tokenInfo.HasExpired(), "%s should return true", testCase.name) + assert.Equal(t, testCase.isExpired, tokenInfo.HasExpired()) }) } } From 10e380919b73ba467df4777c1c0a97800a6e5a07 Mon Sep 17 00:00:00 2001 From: Aerex Date: Tue, 2 Nov 2021 17:10:22 -0500 Subject: [PATCH 03/21] fix: Use !HasExpired when checking if logged in --- bluemix/configuration/core_config/bx_config.go | 2 +- bluemix/configuration/core_config/bx_config_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bluemix/configuration/core_config/bx_config.go b/bluemix/configuration/core_config/bx_config.go index 7069ddcb..61388509 100644 --- a/bluemix/configuration/core_config/bx_config.go +++ b/bluemix/configuration/core_config/bx_config.go @@ -299,7 +299,7 @@ func (c *bxConfig) IAMID() (guid string) { func (c *bxConfig) IsLoggedIn() (bool) { if token := c.IAMToken(); token != "" { iamTokenInfo := NewIAMTokenInfo(token) - return iamTokenInfo.HasExpired() + return !iamTokenInfo.HasExpired() } return false } diff --git a/bluemix/configuration/core_config/bx_config_test.go b/bluemix/configuration/core_config/bx_config_test.go index 866eca10..881ecee4 100644 --- a/bluemix/configuration/core_config/bx_config_test.go +++ b/bluemix/configuration/core_config/bx_config_test.go @@ -300,7 +300,7 @@ func TestVPCCRITokenURL(t *testing.T) { func TestIsLoggedInAsProfile(t *testing.T) { config := prepareConfigForCLI(`{"UsageStatsEnabledLastUpdate": "2020-03-29T12:23:43.519017+08:00","UsageStatsEnabled": true}`, t) - testIAMCRTokenData := "Bearer eyJraWQiOiIyMDE3MTAzMC0wMDowMDowMCIsImFsZyI6IlJTMjU2In0.ewoJImlhbV9pZCI6ICJpYW0tUHJvZmlsZS05NDQ5N2QwZC0yYWMzLTQxYmYtYTk5My1hNDlkMWIxNDYyN2MiLAoJImlkIjogIklCTWlkLXRlc3QiLAoJInJlYWxtaWQiOiAiaWFtIiwKCSJqdGkiOiAiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4IiwKCSJpZGVudGlmaWVyIjogIlByb2ZpbGUtOTQ0OTdkMGQtMmFjMy00MWJmLWE5OTMtYTQ5ZDFiMTQ2MjdjIiwKCSJuYW1lIjogIk15IFByb2ZpbGUiLAoJInN1YiI6ICJQcm9maWxlLTk0NDk3ZDBkLTJhYzMtNDFiZi1hOTkzLWE0OWQxYjE0NjI3YyIsCgkic3ViX3R5cGUiOiAiUHJvZmlsZSIsCgkiYXV0aG4iOiB7CgkgICJzdWIiOiAiY3JuOnYxOnN0YWdpbmc6cHVibGljOmlhbS1pZGVudGl0eTo6YS8xOGUzMDIwNzQ5Y2U0NzQ0YjBiNDcyNDY2ZDYxZmRiNDo6Y29tcHV0ZXJlc291cmNlOkZha2UtQ29tcHV0ZS1SZXNvdXJjZSIsCgkgICJpYW1faWQiOiAiY3JuLWNybjp2MTpzdGFnaW5nOnB1YmxpYzppYW0taWRlbnRpdHk6OmEvMThlMzAyMDc0OWNlNDc0NGIwYjQ3MjQ2NmQ2MWZkYjQ6OmNvbXB1dGVyZXNvdXJjZTpGYWtlLUNvbXB1dGUtUmVzb3VyY2UiLAoJICAibmFtZSI6ICJteV9jb21wdXRlX3Jlc291cmNlIgoJfSwKCSJhY2NvdW50IjogewoJICAiYm91bmRhcnkiOiAiZ2xvYmFsIiwKCSAgInZhbGlkIjogdHJ1ZSwKCSAgImJzcyI6ICJmYWtlX2JzcyIKCX0sCgkiaWF0IjogMTYyOTkyOTQ2MywKCSJleHAiOiAxNjI5OTMzMDYzLAoJImlzcyI6ICJodHRwczovL2lhbS5jbG91ZC5pYm0uY29tL2lkZW50aXR5IiwKCSJncmFudF90eXBlIjogInVybjppYm06cGFyYW1zOm9hdXRoOmdyYW50LXR5cGU6Y3ItdG9rZW4iLAoJInNjb3BlIjogImlibSBvcGVuaWQiLAoJImNsaWVudF9pZCI6ICJieCIKICB9.CuSOKifh4DvE__bjwDsn5BKmAHF2NaXznoiA1KG-2s2njbJs9nQdOJ3lkOnM77BqvLEpu2cwsmhi4Gsdy-MiJ6ACub0A5zyB-D95IXsGYa5tbFQBLbPpmFDAgAhLG5gXlVnU7nyIJN17Slm3pcWSNXEdWcsA1tgDkC9gQc_rpDhUfhnFeGA2LpvVMtRDolcOrbRuWN4NEbBOwdTbG5-6ijZ5Ag2z3lVmlQZ_6BLBCSVM8WlI8eIGICqCx0HYsmCiMlSqZ-4fkpg2DBYYYX_XsMQlamGynuPeoiBckJIyGEgsJD2egYN2bOUNLcn5htSCGxoJ4HJfXJ70_iCzmovb0w" + testIAMCRTokenData := "Bearer eyJraWQiOiIyMDE3MTAzMC0wMDowMDowMCIsImFsZyI6IkhTMjU2In0.eyJpYW1faWQiOiJpYW0tUHJvZmlsZS05NDQ5N2QwZC0yYWMzLTQxYmYtYTk5My1hNDlkMWIxNDYyN2MiLCJpZCI6IklCTWlkLXRlc3QiLCJyZWFsbWlkIjoiaWFtIiwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4IiwiaWRlbnRpZmllciI6IlByb2ZpbGUtOTQ0OTdkMGQtMmFjMy00MWJmLWE5OTMtYTQ5ZDFiMTQ2MjdjIiwibmFtZSI6Ik15IFByb2ZpbGUiLCJzdWIiOiJQcm9maWxlLTk0NDk3ZDBkLTJhYzMtNDFiZi1hOTkzLWE0OWQxYjE0NjI3YyIsInN1Yl90eXBlIjoiUHJvZmlsZSIsImF1dGhuIjp7InN1YiI6ImNybjp2MTpzdGFnaW5nOnB1YmxpYzppYW0taWRlbnRpdHk6OmEvMThlMzAyMDc0OWNlNDc0NGIwYjQ3MjQ2NmQ2MWZkYjQ6OmNvbXB1dGVyZXNvdXJjZTpGYWtlLUNvbXB1dGUtUmVzb3VyY2UiLCJpYW1faWQiOiJjcm4tY3JuOnYxOnN0YWdpbmc6cHVibGljOmlhbS1pZGVudGl0eTo6YS8xOGUzMDIwNzQ5Y2U0NzQ0YjBiNDcyNDY2ZDYxZmRiNDo6Y29tcHV0ZXJlc291cmNlOkZha2UtQ29tcHV0ZS1SZXNvdXJjZSIsIm5hbWUiOiJteV9jb21wdXRlX3Jlc291cmNlIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiZmFrZV9ic3MifSwiaWF0IjoxNjI5OTI5NDYzLCJleHAiOjgwMjk5MzMwNjMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpjci10b2tlbiIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4In0.ACeIK_8Wi0QmgQ19w4J2OA0OKgC4zb6M6PuGuPTEY_E" // check checkUsageStats(true, true, config, t) From 8c7b8da525bd8f1bd2b73cc241067eba31fd581e Mon Sep 17 00:00:00 2001 From: Aerex Date: Tue, 2 Nov 2021 17:19:55 -0500 Subject: [PATCH 04/21] test: Added test to LoggedInWithServiceID --- bluemix/configuration/core_config/bx_config_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bluemix/configuration/core_config/bx_config_test.go b/bluemix/configuration/core_config/bx_config_test.go index 881ecee4..bd1c1f05 100644 --- a/bluemix/configuration/core_config/bx_config_test.go +++ b/bluemix/configuration/core_config/bx_config_test.go @@ -313,6 +313,13 @@ func TestIsLoggedInAsProfile(t *testing.T) { t.Cleanup(cleanupConfigFiles) } +func TestIsLoggedInWithServiceID(t *testing.T) { + config := prepareConfigForCLI(`{"UsageStatsEnabledLastUpdate": "2020-03-29T12:23:43.519017+08:00","UsageStatsEnabled": true}`, t) + testIAMCRTokenData := "eyJraWQiOiIyMDE3MTAzMC0wMDowMDowMCIsImFsZyI6IkhTMjU2In0.eyJpYW1faWQiOiJpYW0tUHJvZmlsZS05NDQ5N2QwZC0yYWMzLTQxYmYtYTk5My1hNDlkMWIxNDYyN2MiLCJpZCI6IklCTWlkLXRlc3QiLCJyZWFsbWlkIjoiaWFtIiwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4IiwiaWRlbnRpZmllciI6IlByb2ZpbGUtOTQ0OTdkMGQtMmFjMy00MWJmLWE5OTMtYTQ5ZDFiMTQ2MjdjIiwibmFtZSI6Ik15IFNlcnZpY2UiLCJzdWIiOiJQcm9maWxlLTk0NDk3ZDBkLTJhYzMtNDFiZi1hOTkzLWE0OWQxYjE0NjI3YyIsInN1Yl90eXBlIjoiU2VydmljZUlkIiwiYXV0aG4iOnsic3ViIjoiY3JuOnYxOnN0YWdpbmc6cHVibGljOmlhbS1pZGVudGl0eTo6YS8xOGUzMDIwNzQ5Y2U0NzQ0YjBiNDcyNDY2ZDYxZmRiNDo6Y29tcHV0ZXJlc291cmNlOkZha2UtQ29tcHV0ZS1SZXNvdXJjZSIsImlhbV9pZCI6ImNybi1jcm46djE6c3RhZ2luZzpwdWJsaWM6aWFtLWlkZW50aXR5OjphLzE4ZTMwMjA3NDljZTQ3NDRiMGI0NzI0NjZkNjFmZGI0Ojpjb21wdXRlcmVzb3VyY2U6RmFrZS1Db21wdXRlLVJlc291cmNlIiwibmFtZSI6Im15X2NvbXB1dGVfcmVzb3VyY2UifSwiYWNjb3VudCI6eyJib3VuZGFyeSI6Imdsb2JhbCIsInZhbGlkIjp0cnVlLCJic3MiOiJmYWtlX2JzcyJ9LCJpYXQiOjE2Mjk5Mjk0NjMsImV4cCI6MjYyOTkzMzA2MywiaXNzIjoiaHR0cHM6Ly9pYW0uY2xvdWQuaWJtLmNvbS9pZGVudGl0eSIsImdyYW50X3R5cGUiOiJ1cm46aWJtOnBhcmFtczpvYXV0aDpncmFudC10eXBlOmNyLXRva2VuIiwic2NvcGUiOiJpYm0gb3BlbmlkIiwiY2xpZW50X2lkIjoiYngifQ.n3WF2O2KMmhW0nBDN2CooOwgcSDGI2qK858BzaHB6YI" + config.SetIAMToken(testIAMCRTokenData) + assert.True(t, config.IsLoggedInWithServiceID()) +} + func TestIsLoggedInAsCRI(t *testing.T) { config := prepareConfigForCLI(`{"UsageStatsEnabledLastUpdate": "2020-03-29T12:23:43.519017+08:00","UsageStatsEnabled": true}`, t) From bc85bb39306badb564a2c32b8351f1df39a3b3dd Mon Sep 17 00:00:00 2001 From: Aerex Date: Tue, 2 Nov 2021 17:21:17 -0500 Subject: [PATCH 05/21] chore: Added spacing between setup and assertion statements --- bluemix/configuration/core_config/bx_config_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bluemix/configuration/core_config/bx_config_test.go b/bluemix/configuration/core_config/bx_config_test.go index bd1c1f05..a0caed21 100644 --- a/bluemix/configuration/core_config/bx_config_test.go +++ b/bluemix/configuration/core_config/bx_config_test.go @@ -314,9 +314,12 @@ func TestIsLoggedInAsProfile(t *testing.T) { } func TestIsLoggedInWithServiceID(t *testing.T) { + // Setup config := prepareConfigForCLI(`{"UsageStatsEnabledLastUpdate": "2020-03-29T12:23:43.519017+08:00","UsageStatsEnabled": true}`, t) testIAMCRTokenData := "eyJraWQiOiIyMDE3MTAzMC0wMDowMDowMCIsImFsZyI6IkhTMjU2In0.eyJpYW1faWQiOiJpYW0tUHJvZmlsZS05NDQ5N2QwZC0yYWMzLTQxYmYtYTk5My1hNDlkMWIxNDYyN2MiLCJpZCI6IklCTWlkLXRlc3QiLCJyZWFsbWlkIjoiaWFtIiwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4IiwiaWRlbnRpZmllciI6IlByb2ZpbGUtOTQ0OTdkMGQtMmFjMy00MWJmLWE5OTMtYTQ5ZDFiMTQ2MjdjIiwibmFtZSI6Ik15IFNlcnZpY2UiLCJzdWIiOiJQcm9maWxlLTk0NDk3ZDBkLTJhYzMtNDFiZi1hOTkzLWE0OWQxYjE0NjI3YyIsInN1Yl90eXBlIjoiU2VydmljZUlkIiwiYXV0aG4iOnsic3ViIjoiY3JuOnYxOnN0YWdpbmc6cHVibGljOmlhbS1pZGVudGl0eTo6YS8xOGUzMDIwNzQ5Y2U0NzQ0YjBiNDcyNDY2ZDYxZmRiNDo6Y29tcHV0ZXJlc291cmNlOkZha2UtQ29tcHV0ZS1SZXNvdXJjZSIsImlhbV9pZCI6ImNybi1jcm46djE6c3RhZ2luZzpwdWJsaWM6aWFtLWlkZW50aXR5OjphLzE4ZTMwMjA3NDljZTQ3NDRiMGI0NzI0NjZkNjFmZGI0Ojpjb21wdXRlcmVzb3VyY2U6RmFrZS1Db21wdXRlLVJlc291cmNlIiwibmFtZSI6Im15X2NvbXB1dGVfcmVzb3VyY2UifSwiYWNjb3VudCI6eyJib3VuZGFyeSI6Imdsb2JhbCIsInZhbGlkIjp0cnVlLCJic3MiOiJmYWtlX2JzcyJ9LCJpYXQiOjE2Mjk5Mjk0NjMsImV4cCI6MjYyOTkzMzA2MywiaXNzIjoiaHR0cHM6Ly9pYW0uY2xvdWQuaWJtLmNvbS9pZGVudGl0eSIsImdyYW50X3R5cGUiOiJ1cm46aWJtOnBhcmFtczpvYXV0aDpncmFudC10eXBlOmNyLXRva2VuIiwic2NvcGUiOiJpYm0gb3BlbmlkIiwiY2xpZW50X2lkIjoiYngifQ.n3WF2O2KMmhW0nBDN2CooOwgcSDGI2qK858BzaHB6YI" config.SetIAMToken(testIAMCRTokenData) + + // Assertions assert.True(t, config.IsLoggedInWithServiceID()) } From f67ca92dfd96e1ee90607d2f6ee69e3895f55e09 Mon Sep 17 00:00:00 2001 From: Aerex Date: Mon, 29 Nov 2021 18:44:51 -0500 Subject: [PATCH 06/21] chore: Fixed build failures due to false positives in detect secrets --- .secrets.baseline | 58 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 60e62cf3..3870f234 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2021-12-02T17:22:21Z", + "generated_at": "2021-12-06T21:15:12Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -188,12 +188,20 @@ ], "bluemix/configuration/core_config/bx_config_test.go": [ { - "hashed_secret": "9507a758af9127f99a700b500657fd558b705dc9", + "hashed_secret": "90919f1360ad1f9525de7a64061c105d061df1c8", "is_secret": false, "is_verified": false, "line_number": 303, "type": "JSON Web Token", "verified_result": null + }, + { + "hashed_secret": "40e89785a3d6a88c5ef431f64ec054b1d39e186e", + "is_secret": false, + "is_verified": false, + "line_number": 319, + "type": "JSON Web Token", + "verified_result": null } ], "bluemix/configuration/core_config/cf_config.go": [ @@ -211,7 +219,7 @@ "hashed_secret": "8d8e2cec529a6f642c25b4473b2adc8cde563c36", "is_secret": false, "is_verified": false, - "line_number": 12, + "line_number": 19, "type": "JSON Web Token", "verified_result": null }, @@ -219,7 +227,7 @@ "hashed_secret": "de89e230a57dd89a612cc8439c00d0001ffa6389", "is_secret": false, "is_verified": false, - "line_number": 15, + "line_number": 22, "type": "JSON Web Token", "verified_result": null }, @@ -227,7 +235,7 @@ "hashed_secret": "6a4b65a72c0da02a03007867d9838f4a256a384b", "is_secret": false, "is_verified": false, - "line_number": 21, + "line_number": 28, "type": "JSON Web Token", "verified_result": null }, @@ -235,7 +243,7 @@ "hashed_secret": "42be9b0e85dc9f0fcb42c69058b133fd23dfde2b", "is_secret": false, "is_verified": false, - "line_number": 27, + "line_number": 34, "type": "JSON Web Token", "verified_result": null }, @@ -243,7 +251,23 @@ "hashed_secret": "73f596843cdc77ecc6a0a4cdc5b5d89071ad1b79", "is_secret": false, "is_verified": false, - "line_number": 31, + "line_number": 38, + "type": "JSON Web Token", + "verified_result": null + }, + { + "hashed_secret": "c017c618a0ef5209f2cbbb367a7c68eb0404e043", + "is_secret": false, + "is_verified": false, + "line_number": 48, + "type": "JSON Web Token", + "verified_result": null + }, + { + "hashed_secret": "6160045cbf6bfe6c1669311f5720fd73cbe56243", + "is_secret": false, + "is_verified": false, + "line_number": 58, "type": "JSON Web Token", "verified_result": null }, @@ -251,11 +275,29 @@ "hashed_secret": "63a47776714d85556701c61dd731a302ed132385", "is_secret": false, "is_verified": false, - "line_number": 47, + "line_number": 78, "type": "Hex High Entropy String", "verified_result": null } ], + "bluemix/configuration/core_config/uaa_token_test.go": [ + { + "hashed_secret": "c017c618a0ef5209f2cbbb367a7c68eb0404e043", + "is_secret": false, + "is_verified": false, + "line_number": 21, + "type": "JSON Web Token", + "verified_result": null + }, + { + "hashed_secret": "3c1dbf49c59ee96e6a9ac90bea40471c0cb8b4f1", + "is_secret": false, + "is_verified": false, + "line_number": 31, + "type": "JSON Web Token", + "verified_result": null + } + ], "bluemix/env.go": [ { "hashed_secret": "33e5e588d24c979db687c950cf004784e95ddb1b", From 5d56d43d34917febff23dd3eec162346202104d8 Mon Sep 17 00:00:00 2001 From: Aerex Date: Tue, 30 Nov 2021 19:02:31 -0500 Subject: [PATCH 07/21] docs: Used correct link to create pre-commit for detect secrets --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c7a1cb05..d23477ff 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,7 @@ We follow the offical [CodeReviewComments](https://github.com/golang/go/wiki/Cod Make sure you have good unit test. Run `go test -cover $(go list ./...)`, and ensure coverage is above 80% for major packages (aka packages other than i18n, fakes, docs...). #### Secret Detection -This project uses the IBM Detect Secrets Module. Install the module, by following these [instructions](https://github.com/ibm/detect-secrets#installupgrade-module). Once installed, enable the pre-commit secret detection hook by following these [instructions](https://github.com/ibm/detect-secrets#installupgrade-module) to ensure no secrets are committed to this repo. +This project uses the IBM Detect Secrets Module. Install the module, by following these [instructions](https://github.com/ibm/detect-secrets#installupgrade-module). Once installed, enable the pre-commit secret detection hook by following these [instructions](https://github.com/ibm/detect-secrets#prevention-pre-commit-hook) to ensure no secrets are committed to this repo. #### Commit Message From 4d6901c57a976d01dbff5d49ab9c394ea030b0a8 Mon Sep 17 00:00:00 2001 From: Aerex Date: Tue, 30 Nov 2021 19:04:06 -0500 Subject: [PATCH 08/21] fix: Allowed IsLoggedIn to check both token and refresh token if applicable --- .../configuration/core_config/bx_config.go | 8 ++--- .../core_config/bx_config_test.go | 34 +++++++++++++++++++ .../configuration/core_config/cf_config.go | 9 ++--- .../configuration/core_config/iam_token.go | 2 +- .../core_config/iam_token_test.go | 24 ++++++------- 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/bluemix/configuration/core_config/bx_config.go b/bluemix/configuration/core_config/bx_config.go index 61388509..db03c995 100644 --- a/bluemix/configuration/core_config/bx_config.go +++ b/bluemix/configuration/core_config/bx_config.go @@ -296,10 +296,10 @@ func (c *bxConfig) IAMID() (guid string) { return } -func (c *bxConfig) IsLoggedIn() (bool) { - if token := c.IAMToken(); token != "" { - iamTokenInfo := NewIAMTokenInfo(token) - return !iamTokenInfo.HasExpired() +func (c *bxConfig) IsLoggedIn() bool { + if token, refresh := c.IAMToken(), c.IAMRefreshToken(); token != "" || refresh != "" { + iamTokenInfo, refreshTokenInfo := NewIAMTokenInfo(token), NewIAMTokenInfo(refresh) + return !iamTokenInfo.HasExpired() || !refreshTokenInfo.HasExpired() } return false } diff --git a/bluemix/configuration/core_config/bx_config_test.go b/bluemix/configuration/core_config/bx_config_test.go index a0caed21..97381489 100644 --- a/bluemix/configuration/core_config/bx_config_test.go +++ b/bluemix/configuration/core_config/bx_config_test.go @@ -298,6 +298,40 @@ func TestVPCCRITokenURL(t *testing.T) { t.Cleanup(cleanupConfigFiles) } +func TestIsLoggedIn(t *testing.T) { + config := prepareConfigForCLI(`{"UsageStatsEnabledLastUpdate": "2021-11-29T12:23:43.519017+08:00","UsageStatsEnabled": true}`, t) + expiredToken := "Bearer eyJraWQiOiIyMDIxMTAxODA4MTkiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw" + token := "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNzM1NDQyMDI3LCJleHAiOjE3ODYxNzgyMDMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.3ZOgRfe6JcQv303O3DYdCI9OCDkxdlMEBHp8f7iy1fI" + tests := []struct { + name string + token string + refresh string + isLoggedIn bool + }{ + { + name: "token is valid", + token: token, + refresh: token, + isLoggedIn: true, + }, + { + name: "token is invalid but refresh is valid", + token: expiredToken, + refresh: token, + isLoggedIn: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + config.SetIAMToken(test.token) + config.SetIAMRefreshToken(test.refresh) + assert.Equal(t, test.isLoggedIn, config.IsLoggedIn()) + t.Cleanup(cleanupConfigFiles) + }) + } +} + func TestIsLoggedInAsProfile(t *testing.T) { config := prepareConfigForCLI(`{"UsageStatsEnabledLastUpdate": "2020-03-29T12:23:43.519017+08:00","UsageStatsEnabled": true}`, t) testIAMCRTokenData := "Bearer eyJraWQiOiIyMDE3MTAzMC0wMDowMDowMCIsImFsZyI6IkhTMjU2In0.eyJpYW1faWQiOiJpYW0tUHJvZmlsZS05NDQ5N2QwZC0yYWMzLTQxYmYtYTk5My1hNDlkMWIxNDYyN2MiLCJpZCI6IklCTWlkLXRlc3QiLCJyZWFsbWlkIjoiaWFtIiwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4IiwiaWRlbnRpZmllciI6IlByb2ZpbGUtOTQ0OTdkMGQtMmFjMy00MWJmLWE5OTMtYTQ5ZDFiMTQ2MjdjIiwibmFtZSI6Ik15IFByb2ZpbGUiLCJzdWIiOiJQcm9maWxlLTk0NDk3ZDBkLTJhYzMtNDFiZi1hOTkzLWE0OWQxYjE0NjI3YyIsInN1Yl90eXBlIjoiUHJvZmlsZSIsImF1dGhuIjp7InN1YiI6ImNybjp2MTpzdGFnaW5nOnB1YmxpYzppYW0taWRlbnRpdHk6OmEvMThlMzAyMDc0OWNlNDc0NGIwYjQ3MjQ2NmQ2MWZkYjQ6OmNvbXB1dGVyZXNvdXJjZTpGYWtlLUNvbXB1dGUtUmVzb3VyY2UiLCJpYW1faWQiOiJjcm4tY3JuOnYxOnN0YWdpbmc6cHVibGljOmlhbS1pZGVudGl0eTo6YS8xOGUzMDIwNzQ5Y2U0NzQ0YjBiNDcyNDY2ZDYxZmRiNDo6Y29tcHV0ZXJlc291cmNlOkZha2UtQ29tcHV0ZS1SZXNvdXJjZSIsIm5hbWUiOiJteV9jb21wdXRlX3Jlc291cmNlIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiZmFrZV9ic3MifSwiaWF0IjoxNjI5OTI5NDYzLCJleHAiOjgwMjk5MzMwNjMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpjci10b2tlbiIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4In0.ACeIK_8Wi0QmgQ19w4J2OA0OKgC4zb6M6PuGuPTEY_E" diff --git a/bluemix/configuration/core_config/cf_config.go b/bluemix/configuration/core_config/cf_config.go index f759d527..3a1f05b0 100644 --- a/bluemix/configuration/core_config/cf_config.go +++ b/bluemix/configuration/core_config/cf_config.go @@ -280,10 +280,11 @@ func (c *cfConfig) Username() (name string) { } func (c *cfConfig) IsLoggedIn() (loggedIn bool) { - c.read(func() { - loggedIn = c.data.AccessToken != "" - }) - return + if token, refresh := c.UAAToken(), c.UAARefreshToken(); token != "" || refresh != "" { + uaaTokenInfo, refreshTokenInfo := NewUAATokenInfo(token), NewUAATokenInfo(refresh) + return !uaaTokenInfo.HasExpired() || !refreshTokenInfo.HasExpired() + } + return false } func (c *cfConfig) CurrentOrganization() (org models.OrganizationFields) { diff --git a/bluemix/configuration/core_config/iam_token.go b/bluemix/configuration/core_config/iam_token.go index 1f8058d5..2b11b583 100644 --- a/bluemix/configuration/core_config/iam_token.go +++ b/bluemix/configuration/core_config/iam_token.go @@ -85,7 +85,7 @@ func decodeAccessToken(token string) (tokenJSON []byte, err error) { return base64.RawURLEncoding.DecodeString(encodedTokenJSON) } -// HasExpired returns True if the token expiry has occured +// HasExpired returns True if the token and refresh token expiry has occured // before today + delta time or a token is invalid func (t IAMTokenInfo) HasExpired() bool { // We can assume that a token without an ID is invalid and expired diff --git a/bluemix/configuration/core_config/iam_token_test.go b/bluemix/configuration/core_config/iam_token_test.go index 85e9e66f..5844fd6c 100644 --- a/bluemix/configuration/core_config/iam_token_test.go +++ b/bluemix/configuration/core_config/iam_token_test.go @@ -6,10 +6,9 @@ import ( "github.com/stretchr/testify/assert" ) - type iamTokenTestCases struct { - token string - name string + token string + name string isExpired bool } @@ -38,30 +37,29 @@ var TestUAATokenData = []string{ "Bearer eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJqdGkiOiJhZGFkNWYwYzQ0ZDI0ZDlkYmVhN2YyNGIzMDNmOWNhNyIsInN1YiI6IjY3ODdiMzM2LTAwNzUtNGYwYy1hZmZiLWUyOWZjMmVhZWI4OCIsInNjb3BlIjpbIm9wZW5pZCIsInVhYS51c2VyIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwicGFzc3dvcmQud3JpdGUiLCJjbG91ZF9jb250cm9sbGVyLndyaXRlIl0sImNsaWVudF9pZCI6ImNmIiwiY2lkIjoiY2YiLCJhenAiOiJjZiIsImdyYW50X3R5cGUiOiJwYXNzd29yZCIsInVzZXJfaWQiOiI2Nzg3YjMzNi0wMDc1LTRmMGMtYWZmYi1lMjlmYzJlYWViODgiLCJvcmlnaW4iOiJ1YWEiLCJ1c2VyX25hbWUiOiJ3YW5nanVubEBjbi5pYm0uY29tIiwiZW1haWwiOiJ3YW5nanVubEBjbi5pYm0uY29tIiwiYXV0aF90aW1lIjoxNTE2MTczMjgxLCJpYXQiOjE1MTYxNzMyODEsImV4cCI6MTUxNjE3Njg4MCwiaXNzIjoiaHR0cHM6Ly91YWEubmcuYmx1ZW1peC5uZXQvb2F1dGgvdG9rZW4iLCJ6aWQiOiJ1YWEiLCJhdWQiOlsiY2xvdWRfY29udHJvbGxlciIsInBhc3N3b3JkIiwiY2YiLCJ1YWEiLCJvcGVuaWQiXX0.K-9HdMCrNdln81ewX_TQLR63F4wChz035G5KtMq9wkk", } -var TestIAMTokenHasExpiredTestCases = []uaaTokenTestCases{ +var TestIAMTokenHasExpiredTestCases = []iamTokenTestCases{ { - token: "", - name: "empty token", + token: "", + name: "empty token", isExpired: true, }, { - token: "eyJraWQiOiIyMDIxMTAxODA4MTkiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw", - name: "expired token", + token: "eyJraWQiOiIyMDIxMTAxODA4MTkiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw", + name: "expired token", isExpired: true, }, { - token: "ABCD.DEFG.HIGK", - name: "invalid token", + token: "ABCD.DEFG.HIGK", + name: "invalid token", isExpired: true, }, { - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNzM1NDQyMDI3LCJleHAiOjE3ODYxNzgyMDMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.3ZOgRfe6JcQv303O3DYdCI9OCDkxdlMEBHp8f7iy1fI", - name: "token expired in 2029", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNzM1NDQyMDI3LCJleHAiOjE3ODYxNzgyMDMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.3ZOgRfe6JcQv303O3DYdCI9OCDkxdlMEBHp8f7iy1fI", + name: "token expired in 2029", isExpired: false, }, } - func TestNewIAMTokenInfo(t *testing.T) { for _, token := range TestIAMTokenData { tokenInfo := NewIAMTokenInfo(token) From 74a3db17795df1a1a5c288a5af209ae8d6662b62 Mon Sep 17 00:00:00 2001 From: Aerex Date: Tue, 30 Nov 2021 19:08:32 -0500 Subject: [PATCH 09/21] refactor(core_config): Made HasExpired into a private method --- bluemix/configuration/core_config/bx_config.go | 2 +- bluemix/configuration/core_config/iam_token.go | 4 ++-- bluemix/configuration/core_config/iam_token_test.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bluemix/configuration/core_config/bx_config.go b/bluemix/configuration/core_config/bx_config.go index db03c995..bbdc9eb1 100644 --- a/bluemix/configuration/core_config/bx_config.go +++ b/bluemix/configuration/core_config/bx_config.go @@ -299,7 +299,7 @@ func (c *bxConfig) IAMID() (guid string) { func (c *bxConfig) IsLoggedIn() bool { if token, refresh := c.IAMToken(), c.IAMRefreshToken(); token != "" || refresh != "" { iamTokenInfo, refreshTokenInfo := NewIAMTokenInfo(token), NewIAMTokenInfo(refresh) - return !iamTokenInfo.HasExpired() || !refreshTokenInfo.HasExpired() + return !iamTokenInfo.hasExpired() || !refreshTokenInfo.hasExpired() } return false } diff --git a/bluemix/configuration/core_config/iam_token.go b/bluemix/configuration/core_config/iam_token.go index 2b11b583..3d7f7147 100644 --- a/bluemix/configuration/core_config/iam_token.go +++ b/bluemix/configuration/core_config/iam_token.go @@ -85,9 +85,9 @@ func decodeAccessToken(token string) (tokenJSON []byte, err error) { return base64.RawURLEncoding.DecodeString(encodedTokenJSON) } -// HasExpired returns True if the token and refresh token expiry has occured +// hasExpired returns True if the token and refresh token expiry has occured // before today + delta time or a token is invalid -func (t IAMTokenInfo) HasExpired() bool { +func (t IAMTokenInfo) hasExpired() bool { // We can assume that a token without an ID is invalid and expired if t.ID == "" { return true diff --git a/bluemix/configuration/core_config/iam_token_test.go b/bluemix/configuration/core_config/iam_token_test.go index 5844fd6c..aa71aa0d 100644 --- a/bluemix/configuration/core_config/iam_token_test.go +++ b/bluemix/configuration/core_config/iam_token_test.go @@ -106,7 +106,7 @@ func TestIAMTokenHasExpired(t *testing.T) { for _, testCase := range TestIAMTokenHasExpiredTestCases { t.Run(testCase.name, func(t *testing.T) { tokenInfo := NewIAMTokenInfo(testCase.token) - assert.Equal(t, testCase.isExpired, tokenInfo.HasExpired()) + assert.Equal(t, testCase.isExpired, tokenInfo.hasExpired()) }) } } From ba4a84979351d7ffdf2c6eec240f623a1ec29b4e Mon Sep 17 00:00:00 2001 From: Aerex Date: Tue, 30 Nov 2021 19:16:55 -0500 Subject: [PATCH 10/21] chore: Updated secrets baselines for test tokens --- .secrets.baseline | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 3870f234..8b4dc45e 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2021-12-06T21:15:12Z", + "generated_at": "2021-12-01T00:16:38Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -188,18 +188,34 @@ ], "bluemix/configuration/core_config/bx_config_test.go": [ { - "hashed_secret": "90919f1360ad1f9525de7a64061c105d061df1c8", + "hashed_secret": "c017c618a0ef5209f2cbbb367a7c68eb0404e043", "is_secret": false, "is_verified": false, "line_number": 303, "type": "JSON Web Token", "verified_result": null }, + { + "hashed_secret": "6160045cbf6bfe6c1669311f5720fd73cbe56243", + "is_secret": false, + "is_verified": false, + "line_number": 304, + "type": "JSON Web Token", + "verified_result": null + }, + { + "hashed_secret": "90919f1360ad1f9525de7a64061c105d061df1c8", + "is_secret": false, + "is_verified": false, + "line_number": 337, + "type": "JSON Web Token", + "verified_result": null + }, { "hashed_secret": "40e89785a3d6a88c5ef431f64ec054b1d39e186e", "is_secret": false, "is_verified": false, - "line_number": 319, + "line_number": 353, "type": "JSON Web Token", "verified_result": null } From d1462e39072d9cb2e1f5322033479f55d71e5fb1 Mon Sep 17 00:00:00 2001 From: Aerex Date: Wed, 1 Dec 2021 11:48:14 -0500 Subject: [PATCH 11/21] feat: Exposed DecodeIAMToken as a public method --- bluemix/configuration/core_config/iam_token.go | 4 ++-- bluemix/configuration/core_config/uaa_token.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bluemix/configuration/core_config/iam_token.go b/bluemix/configuration/core_config/iam_token.go index 3d7f7147..c114e825 100644 --- a/bluemix/configuration/core_config/iam_token.go +++ b/bluemix/configuration/core_config/iam_token.go @@ -53,7 +53,7 @@ type Authn struct { } func NewIAMTokenInfo(token string) IAMTokenInfo { - tokenJSON, err := decodeAccessToken(token) + tokenJSON, err := DecodeAccessToken(token) if err != nil { return IAMTokenInfo{} } @@ -74,7 +74,7 @@ func NewIAMTokenInfo(token string) IAMTokenInfo { return ret } -func decodeAccessToken(token string) (tokenJSON []byte, err error) { +func DecodeAccessToken(token string) (tokenJSON []byte, err error) { encodedParts := strings.Split(token, ".") if len(encodedParts) < 3 { diff --git a/bluemix/configuration/core_config/uaa_token.go b/bluemix/configuration/core_config/uaa_token.go index 7ff6739c..faf11c08 100644 --- a/bluemix/configuration/core_config/uaa_token.go +++ b/bluemix/configuration/core_config/uaa_token.go @@ -16,7 +16,7 @@ type UAATokenInfo struct { } func NewUAATokenInfo(token string) UAATokenInfo { - tokenJSON, err := decodeAccessToken(token) + tokenJSON, err := DecodeAccessToken(token) if err != nil { return UAATokenInfo{} } From 3d1bd5787c084b65f96c71d280c3478ed1908403 Mon Sep 17 00:00:00 2001 From: Aerex Date: Wed, 1 Dec 2021 17:25:15 -0500 Subject: [PATCH 12/21] fix: Refreshed iam token accordingly when calling IsLoggedIn --- .secrets.baseline | 19 +++----- .../configuration/core_config/bx_config.go | 20 +++++++- .../core_config/bx_config_test.go | 46 ++++++++++++++++--- 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 8b4dc45e..8c001bbf 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2021-12-01T00:16:38Z", + "generated_at": "2021-12-01T22:24:59Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -31,6 +31,9 @@ "ghe_instance": "github.ibm.com", "name": "GheDetector" }, + { + "name": "GitHubTokenDetector" + }, { "hex_limit": 3, "name": "HexHighEntropyString" @@ -187,19 +190,11 @@ } ], "bluemix/configuration/core_config/bx_config_test.go": [ - { - "hashed_secret": "c017c618a0ef5209f2cbbb367a7c68eb0404e043", - "is_secret": false, - "is_verified": false, - "line_number": 303, - "type": "JSON Web Token", - "verified_result": null - }, { "hashed_secret": "6160045cbf6bfe6c1669311f5720fd73cbe56243", "is_secret": false, "is_verified": false, - "line_number": 304, + "line_number": 307, "type": "JSON Web Token", "verified_result": null }, @@ -207,7 +202,7 @@ "hashed_secret": "90919f1360ad1f9525de7a64061c105d061df1c8", "is_secret": false, "is_verified": false, - "line_number": 337, + "line_number": 369, "type": "JSON Web Token", "verified_result": null }, @@ -215,7 +210,7 @@ "hashed_secret": "40e89785a3d6a88c5ef431f64ec054b1d39e186e", "is_secret": false, "is_verified": false, - "line_number": 353, + "line_number": 385, "type": "JSON Web Token", "verified_result": null } diff --git a/bluemix/configuration/core_config/bx_config.go b/bluemix/configuration/core_config/bx_config.go index bbdc9eb1..6b6b663a 100644 --- a/bluemix/configuration/core_config/bx_config.go +++ b/bluemix/configuration/core_config/bx_config.go @@ -296,11 +296,29 @@ func (c *bxConfig) IAMID() (guid string) { return } +// IsLoggedIn will check if the user is logged in. To determine if the user is logged both the access +// +// If token is near expiration or expired, and a refresh token is present attempt to refresh the token. +// If token refresh was successful, check if the new iam token is valid. If valid, user is logged in, +// otherwise user can be considered logged out. If refresh failed, then user is considered logged out. +// If no refresh token is present, and token is expired, then user is considered logged out. func (c *bxConfig) IsLoggedIn() bool { if token, refresh := c.IAMToken(), c.IAMRefreshToken(); token != "" || refresh != "" { iamTokenInfo, refreshTokenInfo := NewIAMTokenInfo(token), NewIAMTokenInfo(refresh) - return !iamTokenInfo.hasExpired() || !refreshTokenInfo.hasExpired() + if iamTokenInfo.hasExpired() && refreshTokenInfo.isValid() { + repo := newRepository(c, nil) + if _, err := repo.RefreshIAMToken(); err != nil { + return false + } + + return true + } else if iamTokenInfo.hasExpired() && !refreshTokenInfo.isValid() { + return false + } else { + return true + } } + return false } diff --git a/bluemix/configuration/core_config/bx_config_test.go b/bluemix/configuration/core_config/bx_config_test.go index 97381489..8de434cc 100644 --- a/bluemix/configuration/core_config/bx_config_test.go +++ b/bluemix/configuration/core_config/bx_config_test.go @@ -1,7 +1,10 @@ package core_config_test import ( + "fmt" "io/ioutil" + "net/http" + "net/http/httptest" "os" "testing" @@ -300,33 +303,62 @@ func TestVPCCRITokenURL(t *testing.T) { func TestIsLoggedIn(t *testing.T) { config := prepareConfigForCLI(`{"UsageStatsEnabledLastUpdate": "2021-11-29T12:23:43.519017+08:00","UsageStatsEnabled": true}`, t) - expiredToken := "Bearer eyJraWQiOiIyMDIxMTAxODA4MTkiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw" - token := "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNzM1NDQyMDI3LCJleHAiOjE3ODYxNzgyMDMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.3ZOgRfe6JcQv303O3DYdCI9OCDkxdlMEBHp8f7iy1fI" + expiredToken := "eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw" + oldToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNzM1NDQyMDI3LCJleHAiOjE3ODYxNzgyMDMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.3ZOgRfe6JcQv303O3DYdCI9OCDkxdlMEBHp8f7iy1fI" + newToken := "eyJraWQiOiIyMDE3MTAzMC0wMDowMDowMCIsImFsZyI6IkhTMjU2In0.eyJpYW1faWQiOiJpYW0tUHJvZmlsZS05NDQ5N2QwZC0yYWMzLTQxYmYtYTk5My1hNDlkMWIxNDYyN2MiLCJpZCI6IklCTWlkLXRlc3QiLCJyZWFsbWlkIjoiaWFtIiwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4IiwiaWRlbnRpZmllciI6IlByb2ZpbGUtOTQ0OTdkMGQtMmFjMy00MWJmLWE5OTMtYTQ5ZDFiMTQ2MjdjIiwibmFtZSI6Ik15IFByb2ZpbGUiLCJzdWIiOiJQcm9maWxlLTk0NDk3ZDBkLTJhYzMtNDFiZi1hOTkzLWE0OWQxYjE0NjI3YyIsInN1Yl90eXBlIjoiUHJvZmlsZSIsImF1dGhuIjp7InN1YiI6ImNybjp2MTpzdGFnaW5nOnB1YmxpYzppYW0taWRlbnRpdHk6OmEvMThlMzAyMDc0OWNlNDc0NGIwYjQ3MjQ2NmQ2MWZkYjQ6OmNvbXB1dGVyZXNvdXJjZTpGYWtlLUNvbXB1dGUtUmVzb3VyY2UiLCJpYW1faWQiOiJjcm4tY3JuOnYxOnN0YWdpbmc6cHVibGljOmlhbS1pZGVudGl0eTo6YS8xOGUzMDIwNzQ5Y2U0NzQ0YjBiNDcyNDY2ZDYxZmRiNDo6Y29tcHV0ZXJlc291cmNlOkZha2UtQ29tcHV0ZS1SZXNvdXJjZSIsIm5hbWUiOiJteV9jb21wdXRlX3Jlc291cmNlIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiZmFrZV9ic3MifSwiaWF0IjoxNjI5OTI5NDYzLCJleHAiOjgwMjk5MzMwNjMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpjci10b2tlbiIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4In0.ACeIK_8Wi0QmgQ19w4J2OA0OKgC4zb6M6PuGuPTEY_E" tests := []struct { name string token string + newToken string refresh string + newRefresh string isLoggedIn bool }{ { - name: "token is valid", - token: token, - refresh: token, + name: "token is expired and refresh token is present", + token: expiredToken, + newToken: "bearer " + newToken, // on refresh the bearer header is append to the token + refresh: oldToken, + newRefresh: newToken, isLoggedIn: true, }, { - name: "token is invalid but refresh is valid", + name: "token is expired and refresh token is NOT present", token: expiredToken, - refresh: token, + newToken: expiredToken, + refresh: "", + newRefresh: "", + isLoggedIn: false, + }, + { + name: "token is not expired", + token: newToken, + newToken: newToken, + refresh: newToken, + newRefresh: newToken, isLoggedIn: true, }, } + IAMEndpoints := models.Endpoints{} for _, test := range tests { t.Run(test.name, func(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + fmt.Fprintf(w, "{\"access_token\": \"%s\", \"refresh_token\": \"%s\", \"token_type\": \"bearer\"}", newToken, newToken) + })) + defer ts.Close() + + IAMEndpoints.PublicEndpoint = ts.URL + IAMEndpoints.PrivateEndpoint = ts.URL + IAMEndpoints.PrivateVPCEndpoint = ts.URL + config.SetIAMToken(test.token) config.SetIAMRefreshToken(test.refresh) + config.SetIAMEndpoints(IAMEndpoints) assert.Equal(t, test.isLoggedIn, config.IsLoggedIn()) + assert.Equal(t, test.newToken, config.IAMToken()) + assert.Equal(t, test.newRefresh, config.IAMRefreshToken()) t.Cleanup(cleanupConfigFiles) }) } From 7c08f7e3952d0bb3c899243c4f7703d614485d46 Mon Sep 17 00:00:00 2001 From: Aerex Date: Wed, 1 Dec 2021 17:26:14 -0500 Subject: [PATCH 13/21] style: Added function docs to DecodeAccessToken and added isValid method --- bluemix/configuration/core_config/iam_token.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bluemix/configuration/core_config/iam_token.go b/bluemix/configuration/core_config/iam_token.go index c114e825..22f8e6b2 100644 --- a/bluemix/configuration/core_config/iam_token.go +++ b/bluemix/configuration/core_config/iam_token.go @@ -74,6 +74,9 @@ func NewIAMTokenInfo(token string) IAMTokenInfo { return ret } +// DecodeAccessToken will decode an access token string into a raw JSON. +// The encoded string is expected to be in three parts separated by a period. +// This method does not validate the contents of the parts func DecodeAccessToken(token string) (tokenJSON []byte, err error) { encodedParts := strings.Split(token, ".") @@ -85,8 +88,10 @@ func DecodeAccessToken(token string) (tokenJSON []byte, err error) { return base64.RawURLEncoding.DecodeString(encodedTokenJSON) } -// hasExpired returns True if the token and refresh token expiry has occured -// before today + delta time or a token is invalid +func (t IAMTokenInfo) isValid() bool { + return t.ID != "" +} + func (t IAMTokenInfo) hasExpired() bool { // We can assume that a token without an ID is invalid and expired if t.ID == "" { From d5fa03f8461b36554c9e8d91fd23ced60b0b5765 Mon Sep 17 00:00:00 2001 From: Aerex Date: Thu, 2 Dec 2021 10:09:27 -0500 Subject: [PATCH 14/21] fix: Refreshed uaa token accordinly when calling IsLoggedIn --- .secrets.baseline | 8 ++-- .../configuration/core_config/cf_config.go | 44 ++++++++++++++++++- .../configuration/core_config/uaa_token.go | 10 +++-- .../core_config/uaa_token_test.go | 23 +++++----- 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 8c001bbf..e2002752 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2021-12-01T22:24:59Z", + "generated_at": "2021-12-02T15:09:15Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -220,7 +220,7 @@ "hashed_secret": "e85f6eac7402c010fcea6b6d024a1875ac213f99", "is_secret": false, "is_verified": false, - "line_number": 221, + "line_number": 241, "type": "Secret Keyword", "verified_result": null } @@ -296,7 +296,7 @@ "hashed_secret": "c017c618a0ef5209f2cbbb367a7c68eb0404e043", "is_secret": false, "is_verified": false, - "line_number": 21, + "line_number": 22, "type": "JSON Web Token", "verified_result": null }, @@ -304,7 +304,7 @@ "hashed_secret": "3c1dbf49c59ee96e6a9ac90bea40471c0cb8b4f1", "is_secret": false, "is_verified": false, - "line_number": 31, + "line_number": 32, "type": "JSON Web Token", "verified_result": null } diff --git a/bluemix/configuration/core_config/cf_config.go b/bluemix/configuration/core_config/cf_config.go index 3a1f05b0..5666aea6 100644 --- a/bluemix/configuration/core_config/cf_config.go +++ b/bluemix/configuration/core_config/cf_config.go @@ -2,11 +2,15 @@ package core_config import ( "encoding/json" + "errors" + "fmt" "sync" "time" + "github.com/IBM-Cloud/ibm-cloud-cli-sdk/bluemix/authentication/uaa" "github.com/IBM-Cloud/ibm-cloud-cli-sdk/bluemix/configuration" "github.com/IBM-Cloud/ibm-cloud-cli-sdk/bluemix/models" + "github.com/IBM-Cloud/ibm-cloud-cli-sdk/common/rest" "github.com/fatih/structs" ) @@ -153,6 +157,22 @@ func (c *cfConfig) writeRaw(cb func()) { } } +func (c *cfConfig) refreshToken(refreshToken string) (uaa.Token, error) { + auth := uaa.NewClient(uaa.DefaultConfig(c.data.AuthorizationEndpoint), rest.NewClient()) + refreshedToken, err := auth.GetToken(uaa.RefreshTokenRequest(refreshToken)) + if err != nil { + return uaa.Token{}, err + } + + // return an error if refreshed token is invalid + refreshedTokenInfo := NewUAATokenInfo(refreshedToken.AccessToken) + if !refreshedTokenInfo.isValid() { + return uaa.Token{}, errors.New("could not refresh token") + } + + return *refreshedToken, nil +} + func (c *cfConfig) APIVersion() (version string) { c.read(func() { version = c.data.APIVersion @@ -279,11 +299,33 @@ func (c *cfConfig) Username() (name string) { return } +// IsLoggedIn will check if the user is logged in. To determine if the user is logged both the access +// +// If token is near expiration or expired, and a refresh token is present attempt to refresh the token. +// If token refresh was successful, check if the new iam token is valid. If valid, user is logged in, +// otherwise user can be considered logged out. If refresh failed, then user is considered logged out. +// If no refresh token is present, and token is expired, then user is considered logged out. func (c *cfConfig) IsLoggedIn() (loggedIn bool) { if token, refresh := c.UAAToken(), c.UAARefreshToken(); token != "" || refresh != "" { uaaTokenInfo, refreshTokenInfo := NewUAATokenInfo(token), NewUAATokenInfo(refresh) - return !uaaTokenInfo.HasExpired() || !refreshTokenInfo.HasExpired() + if uaaTokenInfo.hasExpired() && refreshTokenInfo.isValid() { + refreshedToken, err := c.refreshToken(token) + if err != nil { + return false + } + + uaaToken := fmt.Sprintf("%s %s", refreshedToken.TokenType, refreshedToken.AccessToken) + c.SetUAAToken(uaaToken) + c.SetUAARefreshToken(refreshedToken.RefreshToken) + + return true + } else if uaaTokenInfo.hasExpired() && !refreshTokenInfo.isValid() { + return false + } else { + return true + } } + return false } diff --git a/bluemix/configuration/core_config/uaa_token.go b/bluemix/configuration/core_config/uaa_token.go index faf11c08..f0c9c393 100644 --- a/bluemix/configuration/core_config/uaa_token.go +++ b/bluemix/configuration/core_config/uaa_token.go @@ -37,10 +37,12 @@ func NewUAATokenInfo(token string) UAATokenInfo { return ret } -// HasExpired returns True if the token expiry has occured -// before today + delta time or a token is invalid -func (t UAATokenInfo) HasExpired() bool { - // We can assume that a UAA token without an UserGUID is invalid and expired +func (t UAATokenInfo) isValid() bool { + // UAA token without an UserGUID is invalid + return t.UserGUID != "" +} + +func (t UAATokenInfo) hasExpired() bool { if t.UserGUID == "" { return true } diff --git a/bluemix/configuration/core_config/uaa_token_test.go b/bluemix/configuration/core_config/uaa_token_test.go index 74ee7403..547a1372 100644 --- a/bluemix/configuration/core_config/uaa_token_test.go +++ b/bluemix/configuration/core_config/uaa_token_test.go @@ -7,29 +7,30 @@ import ( ) type uaaTokenTestCases struct { - token string - name string + token string + name string isExpired bool } + var TestUAATokenHasExpiredTestCases = []uaaTokenTestCases{ { - token: "", - name: "empty token", + token: "", + name: "empty token", isExpired: true, }, { - token: "eyJraWQiOiIyMDIxMTAxODA4MTkiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw", - name: "expired token", + token: "eyJraWQiOiIyMDIxMTAxODA4MTkiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw", + name: "expired token", isExpired: true, }, { - token: "ABCD.DEFG.HIGK", - name: "invalid token", + token: "ABCD.DEFG.HIGK", + name: "invalid token", isExpired: true, }, { - token:"eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJqdGkiOiJhZGFkNWYwYzQ0ZDI0ZDlkYmVhN2YyNGIzMDNmOWNhNyIsInN1YiI6IjY3ODdiMzM2LTAwNzUtNGYwYy1hZmZiLWUyOWZjMmVhZWI4OCIsInNjb3BlIjpbIm9wZW5pZCIsInVhYS51c2VyIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwicGFzc3dvcmQud3JpdGUiLCJjbG91ZF9jb250cm9sbGVyLndyaXRlIl0sImNsaWVudF9pZCI6ImNmIiwiY2lkIjoiY2YiLCJhenAiOiJjZiIsImdyYW50X3R5cGUiOiJwYXNzd29yZCIsInVzZXJfaWQiOiI2Nzg3YjMzNi0wMDc1LTRmMGMtYWZmYi1lMjlmYzJlYWViODgiLCJvcmlnaW4iOiJ1YWEiLCJ1c2VyX25hbWUiOiJ3YW5nanVubEBjbi5pYm0uY29tIiwiZW1haWwiOiJ3YW5nanVubEBjbi5pYm0uY29tIiwiYXV0aF90aW1lIjoxNTE2MTczMjgxLCJpYXQiOjE4MTYxNzMyODEsImV4cCI6MjkyNjE3Njg4MCwiaXNzIjoiaHR0cHM6Ly91YWEubmcuYmx1ZW1peC5uZXQvb2F1dGgvdG9rZW4iLCJ6aWQiOiJ1YWEiLCJhdWQiOlsiY2xvdWRfY29udHJvbGxlciIsInBhc3N3b3JkIiwiY2YiLCJ1YWEiLCJvcGVuaWQiXX0.CPUPLMtDpGScEbK9pyD5pzOCWXUir7TX-gZSmFFSRLM", - name: "token expired in 2062", + token: "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJqdGkiOiJhZGFkNWYwYzQ0ZDI0ZDlkYmVhN2YyNGIzMDNmOWNhNyIsInN1YiI6IjY3ODdiMzM2LTAwNzUtNGYwYy1hZmZiLWUyOWZjMmVhZWI4OCIsInNjb3BlIjpbIm9wZW5pZCIsInVhYS51c2VyIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwicGFzc3dvcmQud3JpdGUiLCJjbG91ZF9jb250cm9sbGVyLndyaXRlIl0sImNsaWVudF9pZCI6ImNmIiwiY2lkIjoiY2YiLCJhenAiOiJjZiIsImdyYW50X3R5cGUiOiJwYXNzd29yZCIsInVzZXJfaWQiOiI2Nzg3YjMzNi0wMDc1LTRmMGMtYWZmYi1lMjlmYzJlYWViODgiLCJvcmlnaW4iOiJ1YWEiLCJ1c2VyX25hbWUiOiJ3YW5nanVubEBjbi5pYm0uY29tIiwiZW1haWwiOiJ3YW5nanVubEBjbi5pYm0uY29tIiwiYXV0aF90aW1lIjoxNTE2MTczMjgxLCJpYXQiOjE4MTYxNzMyODEsImV4cCI6MjkyNjE3Njg4MCwiaXNzIjoiaHR0cHM6Ly91YWEubmcuYmx1ZW1peC5uZXQvb2F1dGgvdG9rZW4iLCJ6aWQiOiJ1YWEiLCJhdWQiOlsiY2xvdWRfY29udHJvbGxlciIsInBhc3N3b3JkIiwiY2YiLCJ1YWEiLCJvcGVuaWQiXX0.CPUPLMtDpGScEbK9pyD5pzOCWXUir7TX-gZSmFFSRLM", + name: "token expired in 2062", isExpired: false, }, } @@ -38,7 +39,7 @@ func TestUAATokenHasExpired(t *testing.T) { for _, testCase := range TestUAATokenHasExpiredTestCases { t.Run(testCase.name, func(t *testing.T) { tokenInfo := NewUAATokenInfo(testCase.token) - assert.Equal(t, testCase.isExpired, tokenInfo.HasExpired()) + assert.Equal(t, testCase.isExpired, tokenInfo.hasExpired()) }) } } From d6ae342bfdbebac4725a012e69ed4ef4b51d2a78 Mon Sep 17 00:00:00 2001 From: Aerex Date: Thu, 2 Dec 2021 10:21:05 -0500 Subject: [PATCH 15/21] chore: Cleaned up code --- bluemix/configuration/core_config/iam_token.go | 4 ++-- bluemix/configuration/core_config/uaa_token.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bluemix/configuration/core_config/iam_token.go b/bluemix/configuration/core_config/iam_token.go index 22f8e6b2..c682962a 100644 --- a/bluemix/configuration/core_config/iam_token.go +++ b/bluemix/configuration/core_config/iam_token.go @@ -89,12 +89,12 @@ func DecodeAccessToken(token string) (tokenJSON []byte, err error) { } func (t IAMTokenInfo) isValid() bool { + // token without an ID is invalid return t.ID != "" } func (t IAMTokenInfo) hasExpired() bool { - // We can assume that a token without an ID is invalid and expired - if t.ID == "" { + if !t.isValid() { return true } if t.Expiry.IsZero() { diff --git a/bluemix/configuration/core_config/uaa_token.go b/bluemix/configuration/core_config/uaa_token.go index f0c9c393..e547ecbf 100644 --- a/bluemix/configuration/core_config/uaa_token.go +++ b/bluemix/configuration/core_config/uaa_token.go @@ -43,7 +43,7 @@ func (t UAATokenInfo) isValid() bool { } func (t UAATokenInfo) hasExpired() bool { - if t.UserGUID == "" { + if !t.isValid() { return true } if t.Expiry.IsZero() { From d0dbc622815a80dabb6862f7043175143abae2a2 Mon Sep 17 00:00:00 2001 From: Aerex Date: Thu, 2 Dec 2021 11:29:48 -0500 Subject: [PATCH 16/21] refactor: Renamed isValid to exists --- bluemix/configuration/core_config/bx_config.go | 4 ++-- bluemix/configuration/core_config/cf_config.go | 6 +++--- bluemix/configuration/core_config/iam_token.go | 4 ++-- bluemix/configuration/core_config/uaa_token.go | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bluemix/configuration/core_config/bx_config.go b/bluemix/configuration/core_config/bx_config.go index 6b6b663a..25309f36 100644 --- a/bluemix/configuration/core_config/bx_config.go +++ b/bluemix/configuration/core_config/bx_config.go @@ -305,14 +305,14 @@ func (c *bxConfig) IAMID() (guid string) { func (c *bxConfig) IsLoggedIn() bool { if token, refresh := c.IAMToken(), c.IAMRefreshToken(); token != "" || refresh != "" { iamTokenInfo, refreshTokenInfo := NewIAMTokenInfo(token), NewIAMTokenInfo(refresh) - if iamTokenInfo.hasExpired() && refreshTokenInfo.isValid() { + if iamTokenInfo.hasExpired() && refreshTokenInfo.exists() { repo := newRepository(c, nil) if _, err := repo.RefreshIAMToken(); err != nil { return false } return true - } else if iamTokenInfo.hasExpired() && !refreshTokenInfo.isValid() { + } else if iamTokenInfo.hasExpired() && !refreshTokenInfo.exists() { return false } else { return true diff --git a/bluemix/configuration/core_config/cf_config.go b/bluemix/configuration/core_config/cf_config.go index 5666aea6..b3f1956e 100644 --- a/bluemix/configuration/core_config/cf_config.go +++ b/bluemix/configuration/core_config/cf_config.go @@ -166,7 +166,7 @@ func (c *cfConfig) refreshToken(refreshToken string) (uaa.Token, error) { // return an error if refreshed token is invalid refreshedTokenInfo := NewUAATokenInfo(refreshedToken.AccessToken) - if !refreshedTokenInfo.isValid() { + if !refreshedTokenInfo.exists() { return uaa.Token{}, errors.New("could not refresh token") } @@ -308,7 +308,7 @@ func (c *cfConfig) Username() (name string) { func (c *cfConfig) IsLoggedIn() (loggedIn bool) { if token, refresh := c.UAAToken(), c.UAARefreshToken(); token != "" || refresh != "" { uaaTokenInfo, refreshTokenInfo := NewUAATokenInfo(token), NewUAATokenInfo(refresh) - if uaaTokenInfo.hasExpired() && refreshTokenInfo.isValid() { + if uaaTokenInfo.hasExpired() && refreshTokenInfo.exists() { refreshedToken, err := c.refreshToken(token) if err != nil { return false @@ -319,7 +319,7 @@ func (c *cfConfig) IsLoggedIn() (loggedIn bool) { c.SetUAARefreshToken(refreshedToken.RefreshToken) return true - } else if uaaTokenInfo.hasExpired() && !refreshTokenInfo.isValid() { + } else if uaaTokenInfo.hasExpired() && !refreshTokenInfo.exists() { return false } else { return true diff --git a/bluemix/configuration/core_config/iam_token.go b/bluemix/configuration/core_config/iam_token.go index c682962a..b458debf 100644 --- a/bluemix/configuration/core_config/iam_token.go +++ b/bluemix/configuration/core_config/iam_token.go @@ -88,13 +88,13 @@ func DecodeAccessToken(token string) (tokenJSON []byte, err error) { return base64.RawURLEncoding.DecodeString(encodedTokenJSON) } -func (t IAMTokenInfo) isValid() bool { +func (t IAMTokenInfo) exists() bool { // token without an ID is invalid return t.ID != "" } func (t IAMTokenInfo) hasExpired() bool { - if !t.isValid() { + if !t.exists() { return true } if t.Expiry.IsZero() { diff --git a/bluemix/configuration/core_config/uaa_token.go b/bluemix/configuration/core_config/uaa_token.go index e547ecbf..46dba9e8 100644 --- a/bluemix/configuration/core_config/uaa_token.go +++ b/bluemix/configuration/core_config/uaa_token.go @@ -37,13 +37,13 @@ func NewUAATokenInfo(token string) UAATokenInfo { return ret } -func (t UAATokenInfo) isValid() bool { +func (t UAATokenInfo) exists() bool { // UAA token without an UserGUID is invalid return t.UserGUID != "" } func (t UAATokenInfo) hasExpired() bool { - if !t.isValid() { + if !t.exists() { return true } if t.Expiry.IsZero() { From a7855929e22fa9a096be8644f4124b8f325ab847 Mon Sep 17 00:00:00 2001 From: Aerex Date: Thu, 2 Dec 2021 15:59:04 -0500 Subject: [PATCH 17/21] tests: Added unit test to verify token not expired and refresh not present --- .secrets.baseline | 14 +++---------- .../configuration/core_config/bx_config.go | 12 +++++------ .../core_config/bx_config_test.go | 20 +++++++++++++------ .../configuration/core_config/cf_config.go | 12 +++++------ 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index e2002752..f96bd57b 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2021-12-02T15:09:15Z", + "generated_at": "2021-12-02T20:58:58Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -190,19 +190,11 @@ } ], "bluemix/configuration/core_config/bx_config_test.go": [ - { - "hashed_secret": "6160045cbf6bfe6c1669311f5720fd73cbe56243", - "is_secret": false, - "is_verified": false, - "line_number": 307, - "type": "JSON Web Token", - "verified_result": null - }, { "hashed_secret": "90919f1360ad1f9525de7a64061c105d061df1c8", "is_secret": false, "is_verified": false, - "line_number": 369, + "line_number": 377, "type": "JSON Web Token", "verified_result": null }, @@ -210,7 +202,7 @@ "hashed_secret": "40e89785a3d6a88c5ef431f64ec054b1d39e186e", "is_secret": false, "is_verified": false, - "line_number": 385, + "line_number": 393, "type": "JSON Web Token", "verified_result": null } diff --git a/bluemix/configuration/core_config/bx_config.go b/bluemix/configuration/core_config/bx_config.go index 25309f36..62bc3ca9 100644 --- a/bluemix/configuration/core_config/bx_config.go +++ b/bluemix/configuration/core_config/bx_config.go @@ -296,23 +296,23 @@ func (c *bxConfig) IAMID() (guid string) { return } -// IsLoggedIn will check if the user is logged in. To determine if the user is logged both the access -// +// IsLoggedIn will check if the user is logged in. To determine if the user is logged in both the +// token and the refresh token will be checked // If token is near expiration or expired, and a refresh token is present attempt to refresh the token. -// If token refresh was successful, check if the new iam token is valid. If valid, user is logged in, +// If token refresh was successful, check if the new IAM token is valid. If valid, user is logged in, // otherwise user can be considered logged out. If refresh failed, then user is considered logged out. // If no refresh token is present, and token is expired, then user is considered logged out. func (c *bxConfig) IsLoggedIn() bool { if token, refresh := c.IAMToken(), c.IAMRefreshToken(); token != "" || refresh != "" { - iamTokenInfo, refreshTokenInfo := NewIAMTokenInfo(token), NewIAMTokenInfo(refresh) - if iamTokenInfo.hasExpired() && refreshTokenInfo.exists() { + iamTokenInfo := NewIAMTokenInfo(token) + if iamTokenInfo.hasExpired() && refresh != "" { repo := newRepository(c, nil) if _, err := repo.RefreshIAMToken(); err != nil { return false } return true - } else if iamTokenInfo.hasExpired() && !refreshTokenInfo.exists() { + } else if iamTokenInfo.hasExpired() && refresh == "" { return false } else { return true diff --git a/bluemix/configuration/core_config/bx_config_test.go b/bluemix/configuration/core_config/bx_config_test.go index 8de434cc..f9619181 100644 --- a/bluemix/configuration/core_config/bx_config_test.go +++ b/bluemix/configuration/core_config/bx_config_test.go @@ -303,8 +303,8 @@ func TestVPCCRITokenURL(t *testing.T) { func TestIsLoggedIn(t *testing.T) { config := prepareConfigForCLI(`{"UsageStatsEnabledLastUpdate": "2021-11-29T12:23:43.519017+08:00","UsageStatsEnabled": true}`, t) + refresh := "eyJhbGciOiJydCJ9.eyJzZXNzaW9uX2lkIjoiQy02YzUzN2U3My0wMjAxLTQ0YmUtODZlZC0zMDY0YTUwMTMwNGYiLCJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiYWNjb3VudF9pZCI6IjYwOWMxNGI4NjhmNTQ1OWM5YmZkOGJhOGI4OTZiYmE5In0._WLlp2iYEpA9PTStswtoXPj5GhiXwrEB0EhEVIF-SKu34qL3-gmfjIeN7RJGT--nwvmuuDfcVIdhA2j7MCmjPqk8YUMVmvR38YY7pA81sk7ynBOeJSg_D2_QCDeH-p1waMZlmedvzhVhSJAqhsorQYOR5GMDmz-kiwOwbQ0ewBiX7Bkc5S_49spJG7T5qsBwLjd8EXjCFGGWg4MS-QXn1SnVKBJZ82VyRL8lSTrMCC2DGseA29ptLOhJJldKVjDrfgLAMDILge08Rbz5NZplwkBRLYT7bvMEaO1cj_we6Ya1DPEO70rYkkIJQ-UtYyOUMEVw4th1LKHkKFNYK4oR_it5DpX-w4jTi49yNbV8ragDtmfUQy1dQ7Vxv5Xc7IsF8htFboxtqYwqRi32M0821ftoGYbxZRX2W6BsijmaBUpE_iaBV39ulFJrvW4Uf9fp-GvjIkZo3iJZN8syrr6LQ_RicB73s3rhZ1tIA7i4w7lapSMAgGH2xqufh6Ca31YBN7Karj0Cy6CxX_2P4aLPlAgZL4qJK3gOz56h4hWqmLhurjf5bn0uPXznPAMAoWpim2MwvSSH3EPRbxUyqGusUe-AXhcY_bTjfWibQJ59wL0q3s6gNwkn1y0RKEdlGoc1ofkJU9XfJWc_HCrZ0Lkq5PjQDqk3WkhkxxVGuD92Ha8LNlff-u_hqpBT86nV7D9r9das0vl4etJA6QK8FJMJ5prRNUpKmrVWpMJrSCQr5o8FxvB94yC0H6FcvDTdIl2slVtOO5wtOkaqtcHLm2trpQO6T3nyJQMWd9rUalJjWP32Gpv5yBSEHKC_toJk050oVemk8fis2B5_Qlb86b5vJsnAMqhBC4SttBztlPf0vIDlReMle_HHRnNXUl58Eaady9jgaGqD2b-dU20wjX8p6SLtfMuYbN0hWhYl2_hP2jfzY4zCtQtO3nGNYKeHy_H678NK_WTjvvqvLighORbbi0KINDEVWqepxLxBnzXywWrSMki6CF6016nUh49DMpEpSeziriuxYllg_j2Uwcl396ecuGxkuN9iziHt9qKhnjS4oyjRo8pE3lGw6oc5DMBgxZcpgPJ8QHGlti1rs8vxdCxl2XxFu-Rsckj9jKjTeULKRV4voQKmiFoFELbgodp91fanimBVCLdBygLhm0v04o5tw6J6NkLnu4GPlFvASTLTG9PydIdSnWvP8sXR0T8PS_4l4ot96N2jqd-UKcaQgk5A-fo3NVfTELMz9CvdFYH1r33GtQvO2BtWmlJxU24wge5KtHVwmXe1BFZOxwE_nfV2AMxY-SplWh8lkjM34vJ7YUw8kmvjdSB7nFjCAyxmhPA" // pragma: allowlist secret expiredToken := "eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNjM1NDQyMDI3LCJleHAiOjE2MzU0NDI5MjcsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.RsBd371ACEKOlhkTJngqBVDCY90Z-MT-iYb1OiLA5OpLYPZunR0saHUzBLh2LxnV-Jo0oeitPBmIK38jDk8MCb-rZa3qYNB2qe0WgO50bCMLKgwhKqJwVM6jMMpg4vg6up8kH8Ftc61kivaa1GrJKmQkonnHrjgrLo5IB2yfkMEAbUAMPb_jcRfjEsSP44I-Vx3dYIVSZs8bIufkgmDbJjlMmdhRenh57iwtQ7uImFgK2d-qQ-7sWLvhfzj2VdBLRHPa-dWYlrVgOAMpk6SCMz8wh6LcDUx9LdNKHpxMGCXpGT_UUWvwYqBuLTI3nmkIWIb_Cqa6al7-gQKPTC00Fw" - oldToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYW1faWQiOiJJQk1pZC02NjYwMDE1UktKIiwiaWQiOiJJQk1pZC02NjYwMDE1UktKIiwicmVhbG1pZCI6IklCTWlkIiwic2Vzc2lvbl9pZCI6IkMtMDBkNDIyYjAtYzcyZC00MzNmLWE0YmUtMzc2ZjkyZDEyNDliIiwianRpIjoiNzNmMzVmNGQtZmI2Ny00NTc3LThlNGMtNDE3YzA5MDYwNDU3IiwiaWRlbnRpZmllciI6IjY2NjAwMTVSS0oiLCJnaXZlbl9uYW1lIjoiTkFOQSIsImZhbWlseV9uYW1lIjoiQU1GTyIsIm5hbWUiOiJOQU5BIEFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIiwic3ViIjoibm9hbWZvQGlibS5jb20iLCJhdXRobiI6eyJzdWIiOiJub2FtZm9AaWJtLmNvbSIsImlhbV9pZCI6IklCTWlkLTY2NjAwMTVSS0oiLCJuYW1lIjoiTkFOQSBBTUZPIiwiZ2l2ZW5fbmFtZSI6Ik5BTkEiLCJmYW1pbHlfbmFtZSI6IkFNRk8iLCJlbWFpbCI6Im5vYW1mb0BpYm0uY29tIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiMDY3OGUzOWY3ZWYxNDkyODk1OWM0YzFhOGY2YTdiYmYifSwiaWF0IjoxNzM1NDQyMDI3LCJleHAiOjE3ODYxNzgyMDMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwYXNzY29kZSIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4IiwiYWNyIjozLCJhbXIiOlsidG90cCIsIm1mYSIsIm90cCIsInB3ZCJdfQ.3ZOgRfe6JcQv303O3DYdCI9OCDkxdlMEBHp8f7iy1fI" newToken := "eyJraWQiOiIyMDE3MTAzMC0wMDowMDowMCIsImFsZyI6IkhTMjU2In0.eyJpYW1faWQiOiJpYW0tUHJvZmlsZS05NDQ5N2QwZC0yYWMzLTQxYmYtYTk5My1hNDlkMWIxNDYyN2MiLCJpZCI6IklCTWlkLXRlc3QiLCJyZWFsbWlkIjoiaWFtIiwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4IiwiaWRlbnRpZmllciI6IlByb2ZpbGUtOTQ0OTdkMGQtMmFjMy00MWJmLWE5OTMtYTQ5ZDFiMTQ2MjdjIiwibmFtZSI6Ik15IFByb2ZpbGUiLCJzdWIiOiJQcm9maWxlLTk0NDk3ZDBkLTJhYzMtNDFiZi1hOTkzLWE0OWQxYjE0NjI3YyIsInN1Yl90eXBlIjoiUHJvZmlsZSIsImF1dGhuIjp7InN1YiI6ImNybjp2MTpzdGFnaW5nOnB1YmxpYzppYW0taWRlbnRpdHk6OmEvMThlMzAyMDc0OWNlNDc0NGIwYjQ3MjQ2NmQ2MWZkYjQ6OmNvbXB1dGVyZXNvdXJjZTpGYWtlLUNvbXB1dGUtUmVzb3VyY2UiLCJpYW1faWQiOiJjcm4tY3JuOnYxOnN0YWdpbmc6cHVibGljOmlhbS1pZGVudGl0eTo6YS8xOGUzMDIwNzQ5Y2U0NzQ0YjBiNDcyNDY2ZDYxZmRiNDo6Y29tcHV0ZXJlc291cmNlOkZha2UtQ29tcHV0ZS1SZXNvdXJjZSIsIm5hbWUiOiJteV9jb21wdXRlX3Jlc291cmNlIn0sImFjY291bnQiOnsiYm91bmRhcnkiOiJnbG9iYWwiLCJ2YWxpZCI6dHJ1ZSwiYnNzIjoiZmFrZV9ic3MifSwiaWF0IjoxNjI5OTI5NDYzLCJleHAiOjgwMjk5MzMwNjMsImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoidXJuOmlibTpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpjci10b2tlbiIsInNjb3BlIjoiaWJtIG9wZW5pZCIsImNsaWVudF9pZCI6ImJ4In0.ACeIK_8Wi0QmgQ19w4J2OA0OKgC4zb6M6PuGuPTEY_E" tests := []struct { name string @@ -318,8 +318,8 @@ func TestIsLoggedIn(t *testing.T) { name: "token is expired and refresh token is present", token: expiredToken, newToken: "bearer " + newToken, // on refresh the bearer header is append to the token - refresh: oldToken, - newRefresh: newToken, + refresh: refresh, + newRefresh: refresh, isLoggedIn: true, }, { @@ -334,8 +334,16 @@ func TestIsLoggedIn(t *testing.T) { name: "token is not expired", token: newToken, newToken: newToken, - refresh: newToken, - newRefresh: newToken, + refresh: refresh, + newRefresh: refresh, + isLoggedIn: true, + }, + { + name: "token is not expired and refresh it not present", + token: newToken, + newToken: newToken, + refresh: "", + newRefresh: "", isLoggedIn: true, }, } @@ -345,7 +353,7 @@ func TestIsLoggedIn(t *testing.T) { t.Run(test.name, func(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) - fmt.Fprintf(w, "{\"access_token\": \"%s\", \"refresh_token\": \"%s\", \"token_type\": \"bearer\"}", newToken, newToken) + fmt.Fprintf(w, "{\"access_token\": \"%s\", \"refresh_token\": \"%s\", \"token_type\": \"bearer\"}", newToken, refresh) })) defer ts.Close() diff --git a/bluemix/configuration/core_config/cf_config.go b/bluemix/configuration/core_config/cf_config.go index b3f1956e..77a84e18 100644 --- a/bluemix/configuration/core_config/cf_config.go +++ b/bluemix/configuration/core_config/cf_config.go @@ -299,16 +299,16 @@ func (c *cfConfig) Username() (name string) { return } -// IsLoggedIn will check if the user is logged in. To determine if the user is logged both the access -// +// IsLoggedIn will check if the user is logged in. To determine if the user is logged in both the +// token and the refresh token will be checked // If token is near expiration or expired, and a refresh token is present attempt to refresh the token. -// If token refresh was successful, check if the new iam token is valid. If valid, user is logged in, +// If token refresh was successful, check if the new UAA token is valid. If valid, user is logged in, // otherwise user can be considered logged out. If refresh failed, then user is considered logged out. // If no refresh token is present, and token is expired, then user is considered logged out. func (c *cfConfig) IsLoggedIn() (loggedIn bool) { if token, refresh := c.UAAToken(), c.UAARefreshToken(); token != "" || refresh != "" { - uaaTokenInfo, refreshTokenInfo := NewUAATokenInfo(token), NewUAATokenInfo(refresh) - if uaaTokenInfo.hasExpired() && refreshTokenInfo.exists() { + uaaTokenInfo := NewUAATokenInfo(token) + if uaaTokenInfo.hasExpired() && refresh != "" { refreshedToken, err := c.refreshToken(token) if err != nil { return false @@ -319,7 +319,7 @@ func (c *cfConfig) IsLoggedIn() (loggedIn bool) { c.SetUAARefreshToken(refreshedToken.RefreshToken) return true - } else if uaaTokenInfo.hasExpired() && !refreshTokenInfo.exists() { + } else if uaaTokenInfo.hasExpired() && refresh == "" { return false } else { return true From e7e04d4629cdb7b16895c60e8ff71ab881d5569e Mon Sep 17 00:00:00 2001 From: Aerex Date: Thu, 2 Dec 2021 16:02:07 -0500 Subject: [PATCH 18/21] chore: Fixed typo in comment --- bluemix/configuration/core_config/bx_config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bluemix/configuration/core_config/bx_config_test.go b/bluemix/configuration/core_config/bx_config_test.go index f9619181..99ec1760 100644 --- a/bluemix/configuration/core_config/bx_config_test.go +++ b/bluemix/configuration/core_config/bx_config_test.go @@ -339,7 +339,7 @@ func TestIsLoggedIn(t *testing.T) { isLoggedIn: true, }, { - name: "token is not expired and refresh it not present", + name: "token is not expired and refresh is not present", token: newToken, newToken: newToken, refresh: "", From 00889857730a87d701969c96e635fc42164f55ab Mon Sep 17 00:00:00 2001 From: Aerex Date: Thu, 2 Dec 2021 16:04:45 -0500 Subject: [PATCH 19/21] chore: Clean up comments --- bluemix/configuration/core_config/bx_config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bluemix/configuration/core_config/bx_config_test.go b/bluemix/configuration/core_config/bx_config_test.go index 99ec1760..ed360da8 100644 --- a/bluemix/configuration/core_config/bx_config_test.go +++ b/bluemix/configuration/core_config/bx_config_test.go @@ -339,7 +339,7 @@ func TestIsLoggedIn(t *testing.T) { isLoggedIn: true, }, { - name: "token is not expired and refresh is not present", + name: "token is not expired and refresh is NOT present", token: newToken, newToken: newToken, refresh: "", From 5fa2563f35590e57df266929079204e4416927d2 Mon Sep 17 00:00:00 2001 From: Aerex Date: Fri, 3 Dec 2021 10:31:29 -0500 Subject: [PATCH 20/21] fix: Check refreshed tokens are not expired in IsLoggedIn --- bluemix/configuration/core_config/bx_config.go | 4 ++++ bluemix/configuration/core_config/cf_config.go | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/bluemix/configuration/core_config/bx_config.go b/bluemix/configuration/core_config/bx_config.go index 62bc3ca9..a9774304 100644 --- a/bluemix/configuration/core_config/bx_config.go +++ b/bluemix/configuration/core_config/bx_config.go @@ -310,6 +310,10 @@ func (c *bxConfig) IsLoggedIn() bool { if _, err := repo.RefreshIAMToken(); err != nil { return false } + // Check again to make sure that the new token has not expired + if iamTokenInfo = NewIAMTokenInfo(c.IAMToken()); iamTokenInfo.hasExpired() { + return false + } return true } else if iamTokenInfo.hasExpired() && refresh == "" { diff --git a/bluemix/configuration/core_config/cf_config.go b/bluemix/configuration/core_config/cf_config.go index 77a84e18..93e88185 100644 --- a/bluemix/configuration/core_config/cf_config.go +++ b/bluemix/configuration/core_config/cf_config.go @@ -314,6 +314,11 @@ func (c *cfConfig) IsLoggedIn() (loggedIn bool) { return false } + // Check again to make sure that the new token has not expired + if uaaTokenInfo = NewUAATokenInfo(c.UAAToken()); uaaTokenInfo.hasExpired() { + return false + } + uaaToken := fmt.Sprintf("%s %s", refreshedToken.TokenType, refreshedToken.AccessToken) c.SetUAAToken(uaaToken) c.SetUAARefreshToken(refreshedToken.RefreshToken) From a0af8111a4b0ef0dd45cb009960fa39555e43cb0 Mon Sep 17 00:00:00 2001 From: Jorge Rangel Date: Mon, 6 Dec 2021 15:02:56 -0600 Subject: [PATCH 21/21] chore: bump version to v0.8.1 --- .secrets.baseline | 21 +++++++++------------ bluemix/version.go | 2 +- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index f96bd57b..cfc57f20 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2021-12-02T20:58:58Z", + "generated_at": "2021-12-06T21:18:44Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -31,9 +31,6 @@ "ghe_instance": "github.ibm.com", "name": "GheDetector" }, - { - "name": "GitHubTokenDetector" - }, { "hex_limit": 3, "name": "HexHighEntropyString" @@ -222,7 +219,7 @@ "hashed_secret": "8d8e2cec529a6f642c25b4473b2adc8cde563c36", "is_secret": false, "is_verified": false, - "line_number": 19, + "line_number": 18, "type": "JSON Web Token", "verified_result": null }, @@ -230,7 +227,7 @@ "hashed_secret": "de89e230a57dd89a612cc8439c00d0001ffa6389", "is_secret": false, "is_verified": false, - "line_number": 22, + "line_number": 21, "type": "JSON Web Token", "verified_result": null }, @@ -238,7 +235,7 @@ "hashed_secret": "6a4b65a72c0da02a03007867d9838f4a256a384b", "is_secret": false, "is_verified": false, - "line_number": 28, + "line_number": 27, "type": "JSON Web Token", "verified_result": null }, @@ -246,7 +243,7 @@ "hashed_secret": "42be9b0e85dc9f0fcb42c69058b133fd23dfde2b", "is_secret": false, "is_verified": false, - "line_number": 34, + "line_number": 33, "type": "JSON Web Token", "verified_result": null }, @@ -254,7 +251,7 @@ "hashed_secret": "73f596843cdc77ecc6a0a4cdc5b5d89071ad1b79", "is_secret": false, "is_verified": false, - "line_number": 38, + "line_number": 37, "type": "JSON Web Token", "verified_result": null }, @@ -262,7 +259,7 @@ "hashed_secret": "c017c618a0ef5209f2cbbb367a7c68eb0404e043", "is_secret": false, "is_verified": false, - "line_number": 48, + "line_number": 47, "type": "JSON Web Token", "verified_result": null }, @@ -270,7 +267,7 @@ "hashed_secret": "6160045cbf6bfe6c1669311f5720fd73cbe56243", "is_secret": false, "is_verified": false, - "line_number": 58, + "line_number": 57, "type": "JSON Web Token", "verified_result": null }, @@ -278,7 +275,7 @@ "hashed_secret": "63a47776714d85556701c61dd731a302ed132385", "is_secret": false, "is_verified": false, - "line_number": 78, + "line_number": 76, "type": "Hex High Entropy String", "verified_result": null } diff --git a/bluemix/version.go b/bluemix/version.go index d867f581..8c9bebd3 100644 --- a/bluemix/version.go +++ b/bluemix/version.go @@ -3,7 +3,7 @@ package bluemix import "fmt" // Version is the SDK version -var Version = VersionType{Major: 0, Minor: 8, Build: 0} +var Version = VersionType{Major: 0, Minor: 8, Build: 1} // VersionType describe version info type VersionType struct {