// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Microsoft.AspNetCore.Authorization { /// /// Represents a collection of authorization requirements and the scheme or /// schemes they are evaluated against, all of which must succeed /// for authorization to succeed. /// public class AuthorizationPolicy { /// /// Creates a new instance of . /// /// /// The list of s which must succeed for /// this policy to be successful. /// /// /// The authentication schemes the are evaluated against. /// public AuthorizationPolicy(IEnumerable requirements, IEnumerable authenticationSchemes) { if (requirements == null) { throw new ArgumentNullException(nameof(requirements)); } if (authenticationSchemes == null) { throw new ArgumentNullException(nameof(authenticationSchemes)); } if (requirements.Count() == 0) { throw new InvalidOperationException(Resources.Exception_AuthorizationPolicyEmpty); } Requirements = new List(requirements).AsReadOnly(); AuthenticationSchemes = new List(authenticationSchemes).AsReadOnly(); } /// /// Gets a readonly list of s which must succeed for /// this policy to be successful. /// public IReadOnlyList Requirements { get; } /// /// Gets a readonly list of the authentication schemes the /// are evaluated against. /// public IReadOnlyList AuthenticationSchemes { get; } /// /// Combines the specified into a single policy. /// /// The authorization policies to combine. /// /// A new which represents the combination of the /// specified . /// public static AuthorizationPolicy Combine(params AuthorizationPolicy[] policies) { if (policies == null) { throw new ArgumentNullException(nameof(policies)); } return Combine((IEnumerable)policies); } /// /// Combines the specified into a single policy. /// /// The authorization policies to combine. /// /// A new which represents the combination of the /// specified . /// public static AuthorizationPolicy Combine(IEnumerable policies) { if (policies == null) { throw new ArgumentNullException(nameof(policies)); } var builder = new AuthorizationPolicyBuilder(); foreach (var policy in policies) { builder.Combine(policy); } return builder.Build(); } /// /// Combines the provided by the specified /// . /// /// A which provides the policies to combine. /// A collection of authorization data used to apply authorization to a resource. /// /// A new which represents the combination of the /// authorization policies provided by the specified . /// public static async Task CombineAsync(IAuthorizationPolicyProvider policyProvider, IEnumerable authorizeData) { if (policyProvider == null) { throw new ArgumentNullException(nameof(policyProvider)); } if (authorizeData == null) { throw new ArgumentNullException(nameof(authorizeData)); } var policyBuilder = new AuthorizationPolicyBuilder(); var any = false; foreach (var authorizeDatum in authorizeData) { any = true; var useDefaultPolicy = true; if (!string.IsNullOrWhiteSpace(authorizeDatum.Policy)) { var policy = await policyProvider.GetPolicyAsync(authorizeDatum.Policy); if (policy == null) { throw new InvalidOperationException(Resources.FormatException_AuthorizationPolicyNotFound(authorizeDatum.Policy)); } policyBuilder.Combine(policy); useDefaultPolicy = false; } var rolesSplit = authorizeDatum.Roles?.Split(','); if (rolesSplit != null && rolesSplit.Any()) { var trimmedRolesSplit = rolesSplit.Where(r => !string.IsNullOrWhiteSpace(r)).Select(r => r.Trim()); policyBuilder.RequireRole(trimmedRolesSplit); useDefaultPolicy = false; } var authTypesSplit = authorizeDatum.AuthenticationSchemes?.Split(','); if (authTypesSplit != null && authTypesSplit.Any()) { foreach (var authType in authTypesSplit) { if (!string.IsNullOrWhiteSpace(authType)) { policyBuilder.AuthenticationSchemes.Add(authType.Trim()); } } } if (useDefaultPolicy) { policyBuilder.Combine(await policyProvider.GetDefaultPolicyAsync()); } } return any ? policyBuilder.Build() : null; } } }