< Summary

Class:Azure.Identity.ChainedTokenCredential
Assembly:Azure.Identity
File(s):C:\Git\azure-sdk-for-net\sdk\identity\Azure.Identity\src\ChainedTokenCredential.cs
Covered lines:20
Uncovered lines:11
Coverable lines:31
Total lines:111
Line coverage:64.5% (20 of 31)
Covered branches:10
Total branches:12
Branch coverage:83.3% (10 of 12)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor(...)-100%100%
GetToken(...)-0%0%
GetTokenAsync()-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\identity\Azure.Identity\src\ChainedTokenCredential.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using Azure.Core;
 5using System;
 6using System.Collections.Generic;
 7using System.Linq;
 8using System.Threading;
 9using System.Threading.Tasks;
 10
 11namespace Azure.Identity
 12{
 13    /// <summary>
 14    /// Provides a <see cref="TokenCredential"/> implementation which chains multiple <see cref="TokenCredential"/> impl
 15    /// until one of the getToken methods returns a non-default <see cref="AccessToken"/>.
 16    /// </summary>
 17    public class ChainedTokenCredential : TokenCredential
 18    {
 19        private const string AggregateAllUnavailableErrorMessage = "The ChainedTokenCredential failed to retrieve a toke
 20
 21        private const string AggregateCredentialFailedErrorMessage = "The ChainedTokenCredential failed due to an unhand
 22
 23        private readonly TokenCredential[] _sources;
 24
 25        /// <summary>
 26        /// Creates an instance with the specified <see cref="TokenCredential"/> sources.
 27        /// </summary>
 28        /// <param name="sources">The ordered chain of <see cref="TokenCredential"/> implementations to tried when calli
 1429        public ChainedTokenCredential(params TokenCredential[] sources)
 30        {
 1631            if (sources is null) throw new ArgumentNullException(nameof(sources));
 32
 1233            if (sources.Length == 0)
 34            {
 435                throw new ArgumentException("sources must not be empty", nameof(sources));
 36            }
 37
 5238            for (int i = 0; i < sources.Length; i++)
 39            {
 2040                if (sources[i] == null)
 41                {
 242                    throw new ArgumentException("sources must not contain null", nameof(sources));
 43                }
 44
 45            }
 646            _sources = sources;
 647        }
 48
 49        /// <summary>
 50        /// Sequentially calls <see cref="TokenCredential.GetToken"/> on all the specified sources, returning the first 
 51        /// </summary>
 52        /// <param name="requestContext">The details of the authentication request.</param>
 53        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 54        /// <returns>The first <see cref="AccessToken"/> returned by the specified sources. Any credential which raises 
 55        public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken = d
 56        {
 057            List<Exception> exceptions = new List<Exception>();
 58
 059            for (int i = 0; i < _sources.Length; i++)
 60            {
 61                try
 62                {
 063                    return _sources[i].GetToken(requestContext, cancellationToken);
 64                }
 065                catch (CredentialUnavailableException e)
 66                {
 067                    exceptions.Add(e);
 068                }
 069                catch (Exception e) when (!(e is OperationCanceledException))
 70                {
 071                    exceptions.Add(e);
 72
 073                    throw AuthenticationFailedException.CreateAggregateException(AggregateCredentialFailedErrorMessage +
 74                }
 75            }
 76
 077            throw AuthenticationFailedException.CreateAggregateException(AggregateAllUnavailableErrorMessage, exceptions
 078        }
 79
 80        /// <summary>
 81        /// Sequentially calls <see cref="TokenCredential.GetToken"/> on all the specified sources, returning the first 
 82        /// </summary>
 83        /// <param name="requestContext">The details of the authentication request.</param>
 84        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 85        /// <returns>The first <see cref="AccessToken"/> returned by the specified sources. Any credential which raises 
 86        public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken
 87        {
 1688            List<Exception> exceptions = new List<Exception>();
 89
 8090            for (int i = 0; i < _sources.Length; i++)
 91            {
 92                try
 93                {
 3694                    return await _sources[i].GetTokenAsync(requestContext, cancellationToken).ConfigureAwait(false);
 95                }
 2496                catch (CredentialUnavailableException e)
 97                {
 2498                    exceptions.Add(e);
 2499                }
 4100                catch (Exception e) when (!(e is OperationCanceledException))
 101                {
 4102                    exceptions.Add(e);
 103
 4104                    throw AuthenticationFailedException.CreateAggregateException(AggregateCredentialFailedErrorMessage +
 105                }
 106            }
 107
 4108            throw AuthenticationFailedException.CreateAggregateException(AggregateAllUnavailableErrorMessage, exceptions
 8109        }
 110    }
 111}