From 5bbe0291871fafcd0752a0327ba43241af471ac5 Mon Sep 17 00:00:00 2001 From: maddieclayton Date: Thu, 9 Aug 2018 15:04:10 -0700 Subject: [PATCH] Add IRenewableToken class --- .../Authentication.Abstractions.csproj | 1 + .../Interfaces/IRenewableToken.cs | 26 +++++++++++++++++++ .../AuthenticationFactoryTests.cs | 12 ++++++--- .../ManagedServiceAccessToken.cs | 10 ++++++- .../Authentication/RawAccessToken.cs | 4 ++- .../ServicePrincipalTokenProvider.cs | 4 ++- .../UserTokenProvider.Netcore.cs | 6 +++-- .../Authentication/UserTokenProvider.cs | 6 +++-- .../Mocks/MockAccessToken.cs | 4 ++- src/ScenarioTest/Mocks/MockAccessToken.cs | 4 ++- 10 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 src/Authentication.Abstractions/Interfaces/IRenewableToken.cs diff --git a/src/Authentication.Abstractions/Authentication.Abstractions.csproj b/src/Authentication.Abstractions/Authentication.Abstractions.csproj index 981ec763eb..340c082292 100644 --- a/src/Authentication.Abstractions/Authentication.Abstractions.csproj +++ b/src/Authentication.Abstractions/Authentication.Abstractions.csproj @@ -134,6 +134,7 @@ + diff --git a/src/Authentication.Abstractions/Interfaces/IRenewableToken.cs b/src/Authentication.Abstractions/Interfaces/IRenewableToken.cs new file mode 100644 index 0000000000..fa944128c8 --- /dev/null +++ b/src/Authentication.Abstractions/Interfaces/IRenewableToken.cs @@ -0,0 +1,26 @@ +// ---------------------------------------------------------------------------------- +// +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------------- + +using System; + +namespace Microsoft.Azure.Commands.Common.Authentication +{ + /// + /// Canonical representation of a renewable access token + /// + public interface IRenewableToken : IAccessToken + { + DateTimeOffset ExpiresOn { get; } + } +} \ No newline at end of file diff --git a/src/Authentication.Test/AuthenticationFactoryTests.cs b/src/Authentication.Test/AuthenticationFactoryTests.cs index 08941d29f3..c829cf77b7 100644 --- a/src/Authentication.Test/AuthenticationFactoryTests.cs +++ b/src/Authentication.Test/AuthenticationFactoryTests.cs @@ -174,9 +174,10 @@ public void CanAuthenticateUsingMSIDefault() }; AzureSession.Instance.RegisterComponent(HttpClientOperationsFactory.Name, () => TestHttpOperationsFactory.Create(responses, _output), true); var authFactory = new AuthenticationFactory(); - var token = authFactory.Authenticate(account, environment, tenant, null, null, null); + IRenewableToken token = (IRenewableToken) authFactory.Authenticate(account, environment, tenant, null, null, null); _output.WriteLine($"Received access token for default Uri ${token.AccessToken}"); Assert.Equal(expectedAccessToken, token.AccessToken); + Assert.Equal(3600, Math.Round(token.ExpiresOn.DateTime.Subtract(DateTime.UtcNow).TotalSeconds)); var account2 = new AzureAccount { Id = userId, @@ -223,9 +224,10 @@ public void CanAuthenticateUsingMSIResourceId() }; AzureSession.Instance.RegisterComponent(HttpClientOperationsFactory.Name, () => TestHttpOperationsFactory.Create(responses, _output), true); var authFactory = new AuthenticationFactory(); - var token = authFactory.Authenticate(account, environment, tenant, null, null, null); + IRenewableToken token = (IRenewableToken) authFactory.Authenticate(account, environment, tenant, null, null, null); _output.WriteLine($"Received access token for default Uri ${token.AccessToken}"); Assert.Equal(expectedAccessToken, token.AccessToken); + Assert.Equal(3600, Math.Round(token.ExpiresOn.DateTime.Subtract(DateTime.UtcNow).TotalSeconds)); var account2 = new AzureAccount { Id = userId, @@ -271,9 +273,10 @@ public void CanAuthenticateUsingMSIClientId() }; AzureSession.Instance.RegisterComponent(HttpClientOperationsFactory.Name, () => TestHttpOperationsFactory.Create(responses, _output), true); var authFactory = new AuthenticationFactory(); - var token = authFactory.Authenticate(account, environment, tenant, null, null, null); + IRenewableToken token = (IRenewableToken) authFactory.Authenticate(account, environment, tenant, null, null, null); _output.WriteLine($"Received access token for default Uri ${token.AccessToken}"); Assert.Equal(expectedAccessToken, token.AccessToken); + Assert.Equal(3600, Math.Round(token.ExpiresOn.DateTime.Subtract(DateTime.UtcNow).TotalSeconds)); var account2 = new AzureAccount { Id = userId, @@ -319,9 +322,10 @@ public void CanAuthenticateUsingMSIObjectId() }; AzureSession.Instance.RegisterComponent(HttpClientOperationsFactory.Name, () => TestHttpOperationsFactory.Create(responses, _output), true); var authFactory = new AuthenticationFactory(); - var token = authFactory.Authenticate(account, environment, tenant, null, null, null); + IRenewableToken token = (IRenewableToken) authFactory.Authenticate(account, environment, tenant, null, null, null); _output.WriteLine($"Received access token for default Uri ${token.AccessToken}"); Assert.Equal(expectedAccessToken, token.AccessToken); + Assert.Equal(3600, Math.Round(token.ExpiresOn.DateTime.Subtract(DateTime.UtcNow).TotalSeconds)); var account2 = new AzureAccount { Id = userId, diff --git a/src/Authentication/Authentication/ManagedServiceAccessToken.cs b/src/Authentication/Authentication/ManagedServiceAccessToken.cs index 1cffd8e815..d0fd4ca4e2 100644 --- a/src/Authentication/Authentication/ManagedServiceAccessToken.cs +++ b/src/Authentication/Authentication/ManagedServiceAccessToken.cs @@ -23,7 +23,7 @@ namespace Microsoft.Azure.Commands.Common.Authentication { - public class ManagedServiceAccessToken : IAccessToken + public class ManagedServiceAccessToken : IRenewableToken { IAzureAccount _account; string _tenant; @@ -104,6 +104,14 @@ public string AccessToken public string UserId => _account.Id; + public DateTimeOffset ExpiresOn + { + get + { + return _expiration; + } + } + public void AuthorizeRequest(Action authTokenSetter) { authTokenSetter("Bearer", AccessToken); diff --git a/src/Authentication/Authentication/RawAccessToken.cs b/src/Authentication/Authentication/RawAccessToken.cs index 9ac1270669..c0a1dda882 100644 --- a/src/Authentication/Authentication/RawAccessToken.cs +++ b/src/Authentication/Authentication/RawAccessToken.cs @@ -16,7 +16,7 @@ namespace Microsoft.Azure.Commands.Common.Authentication { - public class RawAccessToken : IAccessToken + public class RawAccessToken : IRenewableToken { public string AccessToken { @@ -42,5 +42,7 @@ public void AuthorizeRequest(Action authTokenSetter) { authTokenSetter("Bearer", AccessToken); } + + public DateTimeOffset ExpiresOn { get; set; } } } diff --git a/src/Authentication/Authentication/ServicePrincipalTokenProvider.cs b/src/Authentication/Authentication/ServicePrincipalTokenProvider.cs index ca3ec6f534..0a7e1522c4 100644 --- a/src/Authentication/Authentication/ServicePrincipalTokenProvider.cs +++ b/src/Authentication/Authentication/ServicePrincipalTokenProvider.cs @@ -151,7 +151,7 @@ private void StoreAppKey(string appId, string tenantId, SecureString appKey) ServicePrincipalKeyStore.SaveKey(appId, tenantId, appKey); } - private class ServicePrincipalAccessToken : IAccessToken + private class ServicePrincipalAccessToken : IRenewableToken { internal readonly AdalConfiguration Configuration; internal AuthenticationResult AuthResult; @@ -211,6 +211,8 @@ private bool IsExpired return timeUntilExpiration < expirationThreshold; } } + + public DateTimeOffset ExpiresOn { get { return AuthResult.ExpiresOn; } } } } } diff --git a/src/Authentication/Authentication/UserTokenProvider.Netcore.cs b/src/Authentication/Authentication/UserTokenProvider.Netcore.cs index 49f4923170..108a7dbf10 100644 --- a/src/Authentication/Authentication/UserTokenProvider.Netcore.cs +++ b/src/Authentication/Authentication/UserTokenProvider.Netcore.cs @@ -238,9 +238,9 @@ private string GetExceptionMessage(Exception ex) } /// - /// Implementation of using data from ADAL + /// Implementation of using data from ADAL /// - private class AdalAccessToken : IAccessToken + private class AdalAccessToken : IRenewableToken { internal readonly AdalConfiguration Configuration; internal AuthenticationResult AuthResult; @@ -276,6 +276,8 @@ public string LoginType return Authentication.LoginType.OrgId; } } + + public DateTimeOffset ExpiresOn { get { return AuthResult.ExpiresOn; } } } } } diff --git a/src/Authentication/Authentication/UserTokenProvider.cs b/src/Authentication/Authentication/UserTokenProvider.cs index 9fcca0de5e..fbf85e76dd 100644 --- a/src/Authentication/Authentication/UserTokenProvider.cs +++ b/src/Authentication/Authentication/UserTokenProvider.cs @@ -294,9 +294,9 @@ private string GetExceptionMessage(Exception ex) } /// - /// Implementation of using data from ADAL + /// Implementation of using data from ADAL /// - private class AdalAccessToken : IAccessToken + private class AdalAccessToken : IRenewableToken { internal readonly AdalConfiguration Configuration; internal AuthenticationResult AuthResult; @@ -353,6 +353,8 @@ public string LoginType return Authentication.LoginType.OrgId; } } + + public DateTimeOffset ExpiresOn { get { return AuthResult.ExpiresOn; } } } public IAccessToken GetAccessTokenWithCertificate( diff --git a/src/ScenarioTest.ResourceManager/Mocks/MockAccessToken.cs b/src/ScenarioTest.ResourceManager/Mocks/MockAccessToken.cs index 1241197dc6..d7463ac720 100644 --- a/src/ScenarioTest.ResourceManager/Mocks/MockAccessToken.cs +++ b/src/ScenarioTest.ResourceManager/Mocks/MockAccessToken.cs @@ -17,7 +17,7 @@ namespace Microsoft.WindowsAzure.Commands.Common.Test.Mocks { - public class MockAccessToken : IAccessToken + public class MockAccessToken : IRenewableToken { private string _tenantId = String.Empty; public void AuthorizeRequest(Action authTokenSetter) @@ -34,5 +34,7 @@ public string TenantId get { return _tenantId; } set { _tenantId = value; } } + + public DateTimeOffset ExpiresOn { get; set; } } } diff --git a/src/ScenarioTest/Mocks/MockAccessToken.cs b/src/ScenarioTest/Mocks/MockAccessToken.cs index dfc6243901..faa8846bc4 100644 --- a/src/ScenarioTest/Mocks/MockAccessToken.cs +++ b/src/ScenarioTest/Mocks/MockAccessToken.cs @@ -17,7 +17,7 @@ namespace Microsoft.WindowsAzure.Commands.Common.Test.Mocks { - public class MockAccessToken : IAccessToken + public class MockAccessToken : IRenewableToken { public void AuthorizeRequest(Action authTokenSetter) { @@ -32,5 +32,7 @@ public string TenantId { get { return string.Empty; } } + + public DateTimeOffset ExpiresOn { get; set; } } }