diff --git a/common/src/service/IotHubConnectionString.cs b/common/src/service/IotHubConnectionString.cs
index a23c509351..2ea31ebf95 100644
--- a/common/src/service/IotHubConnectionString.cs
+++ b/common/src/service/IotHubConnectionString.cs
@@ -14,11 +14,12 @@ namespace Microsoft.Azure.Devices
///
/// The properties required for authentication to IoT hub using a connection string.
///
- internal sealed class IotHubConnectionString : IotHubCredential
+ internal sealed class IotHubConnectionString
+ : IotHubConnectionProperties
{
private static readonly TimeSpan _tokenTimeToLive = TimeSpan.FromHours(1);
- public IotHubConnectionString(IotHubConnectionStringBuilder builder) : base(builder.HostName)
+ public IotHubConnectionString(IotHubConnectionStringBuilder builder) : base(builder?.HostName)
{
if (builder == null)
{
@@ -29,9 +30,6 @@ public IotHubConnectionString(IotHubConnectionStringBuilder builder) : base(buil
SharedAccessKeyName = builder.SharedAccessKeyName;
SharedAccessKey = builder.SharedAccessKey;
SharedAccessSignature = builder.SharedAccessSignature;
- DeviceId = builder.DeviceId;
- ModuleId = builder.ModuleId;
- GatewayHostName = builder.GatewayHostName;
}
public string Audience { get; private set; }
@@ -42,12 +40,6 @@ public IotHubConnectionString(IotHubConnectionStringBuilder builder) : base(buil
public string SharedAccessSignature { get; private set; }
- public string DeviceId { get; private set; }
-
- public string ModuleId { get; private set; }
-
- public string GatewayHostName { get; private set; }
-
public string GetPassword()
{
return string.IsNullOrWhiteSpace(SharedAccessSignature) ? BuildToken(out _) : SharedAccessSignature;
@@ -92,13 +84,6 @@ private string BuildToken(out TimeSpan ttl)
Target = Audience
};
- if (DeviceId != null)
- {
- builder.Target = string.IsNullOrEmpty(ModuleId)
- ? "{0}/devices/{1}".FormatInvariant(Audience, WebUtility.UrlEncode(DeviceId))
- : "{0}/devices/{1}/modules/{2}".FormatInvariant(Audience, WebUtility.UrlEncode(DeviceId), WebUtility.UrlEncode(ModuleId));
- }
-
ttl = builder.TimeToLive;
return builder.ToSignature();
diff --git a/iothub/service/src/IoTHubSasCredential.cs b/iothub/service/src/IoTHubSasCredential.cs
new file mode 100644
index 0000000000..1079d063c2
--- /dev/null
+++ b/iothub/service/src/IoTHubSasCredential.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#if !NET451
+
+using Azure;
+
+namespace Microsoft.Azure.Devices
+{
+ ///
+ /// Shared access signature credential used to authenticate to an IoT hub.
+ ///
+ public abstract class IoTHubSasCredential : AzureSasCredential
+ {
+ ///
+ /// Creates and instance of .
+ ///
+ /// Shared access signature to use to authenticate with the IoT hub.
+ /// The shared access signature expiry in UTC.
+ public IoTHubSasCredential(string signature, DateTime expiresOnUtc) : base(signature)
+ {
+ ExpiresOnUtc = expiresOnUtc;
+ }
+
+ ///
+ /// Updates the shared access signature. This is intended to be used when you've
+ /// regenerated your shared access signature and want to update clients.
+ ///
+ /// Shared access signature to use to authenticate with the IoT hub.
+ /// The shared access signature expiry in UTC.
+ public void Update(string signature, DateTime expiresOnUtc)
+ {
+ Update(signature);
+ ExpiresOnUtc = expiresOnUtc;
+ }
+
+ ///
+ /// The shared access signature expiry in UTC.
+ ///
+ public DateTime ExpiresOnUtc { get; private set; }
+ }
+}
+
+#endif
diff --git a/iothub/service/src/IotHubConnection.cs b/iothub/service/src/IotHubConnection.cs
index 5a17e2ede5..645f634345 100644
--- a/iothub/service/src/IotHubConnection.cs
+++ b/iothub/service/src/IotHubConnection.cs
@@ -51,7 +51,7 @@ internal sealed class IotHubConnection : IDisposable
private IOThreadTimer _refreshTokenTimer;
#endif
- public IotHubConnection(IotHubCredential credential, AccessRights accessRights, bool useWebSocketOnly, ServiceClientTransportSettings transportSettings)
+ public IotHubConnection(IotHubConnectionProperties credential, AccessRights accessRights, bool useWebSocketOnly, ServiceClientTransportSettings transportSettings)
{
#if !NET451
_refreshTokenTimer = new IOThreadTimerSlim(s => ((IotHubConnection)s).OnRefreshTokenAsync(), this);
@@ -71,7 +71,7 @@ internal IotHubConnection(Func> onCreate, Action(onCreate, onClose);
}
- internal IotHubCredential Credential { get; private set; }
+ internal IotHubConnectionProperties Credential { get; private set; }
public Task OpenAsync(TimeSpan timeout)
{
diff --git a/iothub/service/src/IotHubCredential.cs b/iothub/service/src/IotHubConnectionProperties.cs
similarity index 85%
rename from iothub/service/src/IotHubCredential.cs
rename to iothub/service/src/IotHubConnectionProperties.cs
index 42ec547ae7..9f32b6b374 100644
--- a/iothub/service/src/IotHubCredential.cs
+++ b/iothub/service/src/IotHubConnectionProperties.cs
@@ -12,7 +12,7 @@ namespace Microsoft.Azure.Devices
///
/// The properties required for authentication to IoT hub that are independent of the authentication type.
///
- internal abstract class IotHubCredential
+ internal abstract class IotHubConnectionProperties
: IAuthorizationHeaderProvider, ICbsTokenProvider
{
private const string HostNameSeparator = ".";
@@ -20,12 +20,17 @@ internal abstract class IotHubCredential
// Azure.Core (used in IotHubTokenCredential) is not available in NET451.
// So we need this constructor for the build to pass.
- protected IotHubCredential()
+ protected IotHubConnectionProperties()
{
}
- protected IotHubCredential(string hostName)
+ protected IotHubConnectionProperties(string hostName)
{
+ if (string.IsNullOrWhiteSpace(hostName))
+ {
+ throw new ArgumentNullException(nameof(hostName));
+ }
+
HostName = hostName;
IotHubName = GetIotHubName(hostName);
AmqpEndpoint = new UriBuilder(CommonConstants.AmqpsScheme, HostName, AmqpConstants.DefaultSecurePort).Uri;
@@ -54,7 +59,7 @@ public Uri BuildLinkAddress(string path)
return builder.Uri;
}
- private static string GetIotHubName(string hostName)
+ public static string GetIotHubName(string hostName)
{
if (string.IsNullOrWhiteSpace(hostName))
{
diff --git a/iothub/service/src/IotHubSasCredentialProperties.cs b/iothub/service/src/IotHubSasCredentialProperties.cs
new file mode 100644
index 0000000000..948543ec23
--- /dev/null
+++ b/iothub/service/src/IotHubSasCredentialProperties.cs
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Azure.Amqp;
+
+#if !NET451
+
+using Azure;
+
+#endif
+
+namespace Microsoft.Azure.Devices
+{
+ internal class IotHubSasCredentialProperties : IotHubConnectionProperties
+ {
+#if NET451
+
+ public IotHubSasCredentialProperties()
+ {
+ throw new InvalidOperationException("nameof(AzureSasCredential) is not supported in NET451");
+ }
+#else
+ private readonly IoTHubSasCredential _credential;
+
+ public IotHubSasCredentialProperties(string hostName, IoTHubSasCredential credential) : base(hostName)
+ {
+ _credential = credential;
+ }
+
+#endif
+
+ public override string GetAuthorizationHeader()
+ {
+#if NET451
+ throw new InvalidOperationException($"AzureSasCredential is not supported on NET451");
+
+#else
+ return _credential.Signature;
+#endif
+ }
+
+ public override Task GetTokenAsync(Uri namespaceAddress, string appliesTo, string[] requiredClaims)
+ {
+#if NET451
+ throw new InvalidOperationException($"AzureSasCredential is not supported on NET451");
+
+#else
+ var token = new CbsToken(
+ _credential.Signature,
+ CbsConstants.IotHubSasTokenType,
+ _credential.ExpiresOnUtc);
+ return Task.FromResult(token);
+#endif
+ }
+ }
+}
diff --git a/iothub/service/src/IotHubTokenCredential.cs b/iothub/service/src/IotHubTokenCredentialProperties.cs
similarity index 79%
rename from iothub/service/src/IotHubTokenCredential.cs
rename to iothub/service/src/IotHubTokenCredentialProperties.cs
index bb2c1bdde5..8a62a53bef 100644
--- a/iothub/service/src/IotHubTokenCredential.cs
+++ b/iothub/service/src/IotHubTokenCredentialProperties.cs
@@ -18,11 +18,12 @@ namespace Microsoft.Azure.Devices
///
/// The properties required for authentication to IoT hub using a token credential.
///
- internal class IotHubTokenCredential : IotHubCredential
+ internal class IotHubTokenCrendentialProperties
+ : IotHubConnectionProperties
{
#if NET451
- public IotHubTokenCredential()
+ public IotHubTokenCrendentialProperties()
{
throw new InvalidOperationException("nameof(TokenCredential) is not supported in NET451");
}
@@ -30,7 +31,7 @@ public IotHubTokenCredential()
private const string _tokenType = "jwt";
private readonly TokenCredential _credential;
- public IotHubTokenCredential(string hostName, TokenCredential credential) : base(hostName)
+ public IotHubTokenCrendentialProperties(string hostName, TokenCredential credential) : base(hostName)
{
_credential = credential;
}
@@ -40,7 +41,7 @@ public IotHubTokenCredential(string hostName, TokenCredential credential) : base
public override string GetAuthorizationHeader()
{
#if NET451
- throw new InvalidOperationException($"{nameof(GetAuthorizationHeader)} is not supported on NET451");
+ throw new InvalidOperationException($"TokenCredential is not supported on NET451");
#else
AccessToken token = _credential.GetToken(new TokenRequestContext(), new CancellationToken());
@@ -55,7 +56,7 @@ public async override Task GetTokenAsync(Uri namespaceAddress, string
{
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
#if NET451
- throw new InvalidOperationException($"{nameof(GetTokenAsync)} is not supported on NET451");
+ throw new InvalidOperationException($"TokenCredential is not supported on NET451");
#else
AccessToken token = await _credential.GetTokenAsync(new TokenRequestContext(), new CancellationToken()).ConfigureAwait(false);
diff --git a/iothub/service/tests/ConnectionString/ServiceClientConnectionStringTests.cs b/iothub/service/tests/ConnectionString/ServiceClientConnectionStringTests.cs
index c542f86aea..0feae6597f 100644
--- a/iothub/service/tests/ConnectionString/ServiceClientConnectionStringTests.cs
+++ b/iothub/service/tests/ConnectionString/ServiceClientConnectionStringTests.cs
@@ -186,10 +186,7 @@ public void ServiceClient_ConnectionString_ModuleIdentity_SharedAccessKeyCredent
Assert.IsNotNull(iotHubConnectionString);
Assert.AreEqual("testhub.azure-devices-int.net", iotHubConnectionString.Audience);
Assert.AreEqual("testhub.azure-devices-int.net", iotHubConnectionString.HostName);
- Assert.AreEqual("edgecapabledevice1", iotHubConnectionString.DeviceId);
- Assert.AreEqual("testModule", iotHubConnectionString.ModuleId);
Assert.AreEqual("dGVzdFN0cmluZzE=", iotHubConnectionString.SharedAccessKey);
- Assert.AreEqual("edgehub1.ms.com", iotHubConnectionString.GatewayHostName);
Assert.IsNotNull(iotHubConnectionString.GetPassword());
}
}
diff --git a/iothub/service/tests/IotHubConnectionPropertiesTests.cs b/iothub/service/tests/IotHubConnectionPropertiesTests.cs
new file mode 100644
index 0000000000..3ba9c652e6
--- /dev/null
+++ b/iothub/service/tests/IotHubConnectionPropertiesTests.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System;
+using System.Collections.Generic;
+using System.Text;
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Microsoft.Azure.Devices.Tests
+{
+ [TestClass]
+ [TestCategory("Unit")]
+ public class IotHubConnectionPropertiesTests
+ {
+ [TestMethod]
+ [DataRow("acme.azure-devices.net", "acme")]
+ [DataRow("Acme-1.azure-devices.net", "Acme-1")]
+ [DataRow("acme2.azure-devices.net", "acme2")]
+ [DataRow("3acme.azure-devices.net", "3acme")]
+ [DataRow("4-acme.azure-devices.net", "4-acme")]
+ public void IotHubConnectionPropertiesGetHubNameTest(string hostName, string expectedHubName)
+ {
+ // act
+ string hubName = IotHubConnectionProperties.GetIotHubName(hostName);
+
+ // assert
+ hubName.Should().Be(expectedHubName);
+ }
+ }
+}