// 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.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Authorization.Policy
{
public class PolicyEvaluator : IPolicyEvaluator
{
private readonly IAuthorizationService _authorization;
///
/// Constructor
///
/// The authorization service.
public PolicyEvaluator(IAuthorizationService authorization)
{
_authorization = authorization;
}
///
/// Does authentication for and sets the resulting
/// to . If no schemes are set, this is a no-op.
///
/// The .
/// The .
/// unless all schemes specified by failed to authenticate.
public virtual async Task AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
{
if (policy.AuthenticationSchemes != null && policy.AuthenticationSchemes.Count > 0)
{
ClaimsPrincipal newPrincipal = null;
foreach (var scheme in policy.AuthenticationSchemes)
{
var result = await context.AuthenticateAsync(scheme);
if (result != null && result.Succeeded)
{
newPrincipal = SecurityHelper.MergeUserPrincipal(newPrincipal, result.Principal);
}
}
if (newPrincipal != null)
{
context.User = newPrincipal;
return AuthenticateResult.Success(new AuthenticationTicket(newPrincipal, string.Join(";", policy.AuthenticationSchemes)));
}
else
{
context.User = new ClaimsPrincipal(new ClaimsIdentity());
return AuthenticateResult.NoResult();
}
}
return (context.User?.Identity?.IsAuthenticated ?? false)
? AuthenticateResult.Success(new AuthenticationTicket(context.User, "context.User"))
: AuthenticateResult.NoResult();
}
///
/// Attempts authorization for a policy using .
///
/// The .
/// The result of a call to .
/// The .
/// Returns if authorization succeeds.
/// Otherwise returns if , otherwise
/// returns
public virtual async Task AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context)
{
if (policy == null)
{
throw new ArgumentNullException(nameof(policy));
}
var result = await _authorization.AuthorizeAsync(context.User, context, policy);
if (result.Succeeded)
{
return PolicyAuthorizationResult.Success();
}
// If authentication was successful, return forbidden, otherwise challenge
return (authenticationResult.Succeeded)
? PolicyAuthorizationResult.Forbid()
: PolicyAuthorizationResult.Challenge();
}
}
}