|  |  | 1 |  | // Copyright (c) Microsoft Corporation. All rights reserved. | 
|  |  | 2 |  | // Licensed under the MIT License. | 
|  |  | 3 |  |  | 
|  |  | 4 |  | using System; | 
|  |  | 5 |  | using System.Threading; | 
|  |  | 6 |  | using System.Threading.Tasks; | 
|  |  | 7 |  | using Azure.Core; | 
|  |  | 8 |  |  | 
|  |  | 9 |  | namespace Azure.Messaging.ServiceBus.Authorization | 
|  |  | 10 |  | { | 
|  |  | 11 |  |     /// <summary> | 
|  |  | 12 |  |     ///   Provides a credential based on a shared access signature for a given | 
|  |  | 13 |  |     ///   Service Bus entity instance. | 
|  |  | 14 |  |     /// </summary> | 
|  |  | 15 |  |     /// | 
|  |  | 16 |  |     /// <seealso cref="SharedAccessSignature" /> | 
|  |  | 17 |  |     /// <seealso cref="Azure.Core.TokenCredential" /> | 
|  |  | 18 |  |     /// | 
|  |  | 19 |  |     internal class SharedAccessSignatureCredential : TokenCredential | 
|  |  | 20 |  |     { | 
|  |  | 21 |  |         /// <summary>The buffer to apply when considering refreshing; signatures that expire less than this duration wil | 
|  | 2 | 22 |  |         private static readonly TimeSpan SignatureRefreshBuffer = TimeSpan.FromMinutes(10); | 
|  |  | 23 |  |  | 
|  |  | 24 |  |         /// <summary>The length of time extend signature validity, if a token was requested.</summary> | 
|  | 2 | 25 |  |         private static readonly TimeSpan SignatureExtensionDuration = TimeSpan.FromMinutes(30); | 
|  |  | 26 |  |  | 
|  |  | 27 |  |         /// <summary>Provides a target for synchronization to guard against concurrent token expirations.</summary> | 
|  | 78 | 28 |  |         private readonly object SignatureSyncRoot = new object(); | 
|  |  | 29 |  |  | 
|  |  | 30 |  |         /// <summary> | 
|  |  | 31 |  |         ///   The shared access signature that forms the basis of this security token. | 
|  |  | 32 |  |         /// </summary> | 
|  |  | 33 |  |         /// | 
|  | 1038 | 34 |  |         private SharedAccessSignature SharedAccessSignature { get; set; } | 
|  |  | 35 |  |  | 
|  |  | 36 |  |         /// <summary> | 
|  |  | 37 |  |         ///   Initializes a new instance of the <see cref="SharedAccessSignatureCredential"/> class. | 
|  |  | 38 |  |         /// </summary> | 
|  |  | 39 |  |         /// | 
|  |  | 40 |  |         /// <param name="signature">The shared access signature on which to base the token.</param> | 
|  |  | 41 |  |         /// | 
|  | 78 | 42 |  |         public SharedAccessSignatureCredential(SharedAccessSignature signature) | 
|  |  | 43 |  |         { | 
|  | 78 | 44 |  |             Argument.AssertNotNull(signature, nameof(signature)); | 
|  | 78 | 45 |  |             SharedAccessSignature = signature; | 
|  | 78 | 46 |  |         } | 
|  |  | 47 |  |  | 
|  |  | 48 |  |         /// <summary> | 
|  |  | 49 |  |         ///   Retrieves the token that represents the shared access signature credential, for | 
|  |  | 50 |  |         ///   use in authorization against an Service Bus entity. | 
|  |  | 51 |  |         /// </summary> | 
|  |  | 52 |  |         /// | 
|  |  | 53 |  |         /// <param name="requestContext">The details of the authentication request.</param> | 
|  |  | 54 |  |         /// <param name="cancellationToken">The token used to request cancellation of the operation.</param> | 
|  |  | 55 |  |         /// | 
|  |  | 56 |  |         /// <returns>The token representing the shared access signature for this credential.</returns> | 
|  |  | 57 |  |         /// | 
|  |  | 58 |  |         public override AccessToken GetToken( | 
|  |  | 59 |  |             TokenRequestContext requestContext, | 
|  |  | 60 |  |             CancellationToken cancellationToken) | 
|  |  | 61 |  |         { | 
|  | 320 | 62 |  |             if (SharedAccessSignature.SignatureExpiration <= DateTimeOffset.UtcNow.Add(SignatureRefreshBuffer)) | 
|  |  | 63 |  |             { | 
|  | 0 | 64 |  |                 lock (SignatureSyncRoot) | 
|  |  | 65 |  |                 { | 
|  | 0 | 66 |  |                     if (SharedAccessSignature.SignatureExpiration <= DateTimeOffset.UtcNow.Add(SignatureRefreshBuffer)) | 
|  |  | 67 |  |                     { | 
|  | 0 | 68 |  |                         SharedAccessSignature = SharedAccessSignature.CloneWithNewExpiration(SignatureExtensionDuration) | 
|  |  | 69 |  |                     } | 
|  | 0 | 70 |  |                 } | 
|  |  | 71 |  |             } | 
|  |  | 72 |  |  | 
|  | 320 | 73 |  |             return new AccessToken(SharedAccessSignature.Value, SharedAccessSignature.SignatureExpiration); | 
|  |  | 74 |  |         } | 
|  |  | 75 |  |  | 
|  |  | 76 |  |         /// <summary> | 
|  |  | 77 |  |         ///   Retrieves the token that represents the shared access signature credential, for | 
|  |  | 78 |  |         ///   use in authorization against an Service Bus entity. | 
|  |  | 79 |  |         /// </summary> | 
|  |  | 80 |  |         /// | 
|  |  | 81 |  |         /// <param name="requestContext">The details of the authentication request.</param> | 
|  |  | 82 |  |         /// <param name="cancellationToken">The token used to request cancellation of the operation.</param> | 
|  |  | 83 |  |         /// | 
|  |  | 84 |  |         /// <returns>The token representing the shared access signature for this credential.</returns> | 
|  |  | 85 |  |         /// | 
|  |  | 86 |  |         public override ValueTask<AccessToken> GetTokenAsync( | 
|  |  | 87 |  |             TokenRequestContext requestContext, | 
|  |  | 88 |  |             CancellationToken cancellationToken) => | 
|  | 320 | 89 |  |             new ValueTask<AccessToken>(GetToken(requestContext, cancellationToken)); | 
|  |  | 90 |  |  | 
|  |  | 91 |  |         /// <summary> | 
|  |  | 92 |  |         ///   It creates a new shared signature using the key name and the key value passed as | 
|  |  | 93 |  |         ///   input allowing credentials rotation. A call will not extend the signature duration. | 
|  |  | 94 |  |         /// </summary> | 
|  |  | 95 |  |         /// | 
|  |  | 96 |  |         /// <param name="keyName">The name of the shared access key that the signature should be based on.</param> | 
|  |  | 97 |  |         /// <param name="keyValue">The value of the shared access key for the signature.</param> | 
|  |  | 98 |  |         /// | 
|  |  | 99 |  |         internal void UpdateSharedAccessKey(string keyName, string keyValue) | 
|  |  | 100 |  |         { | 
|  | 0 | 101 |  |             lock (SignatureSyncRoot) | 
|  |  | 102 |  |             { | 
|  | 0 | 103 |  |                 SharedAccessSignature = new SharedAccessSignature(SharedAccessSignature.Resource, | 
|  | 0 | 104 |  |                                                                   keyName, | 
|  | 0 | 105 |  |                                                                   keyValue, | 
|  | 0 | 106 |  |                                                                   SharedAccessSignature.Value, | 
|  | 0 | 107 |  |                                                                   SharedAccessSignature.SignatureExpiration); | 
|  | 0 | 108 |  |             } | 
|  | 0 | 109 |  |         } | 
|  |  | 110 |  |     } | 
|  |  | 111 |  | } |