92 lines
4.3 KiB
C#
92 lines
4.3 KiB
C#
// 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;
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
/// <param name="authorization">The authorization service.</param>
|
|
public PolicyEvaluator(IAuthorizationService authorization)
|
|
{
|
|
_authorization = authorization;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Does authentication for <see cref="AuthorizationPolicy.AuthenticationSchemes"/> and sets the resulting
|
|
/// <see cref="ClaimsPrincipal"/> to <see cref="HttpContext.User"/>. If no schemes are set, this is a no-op.
|
|
/// </summary>
|
|
/// <param name="policy">The <see cref="AuthorizationPolicy"/>.</param>
|
|
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
|
/// <returns><see cref="AuthenticateResult.Success"/> unless all schemes specified by <see cref="AuthorizationPolicy.AuthenticationSchemes"/> failed to authenticate. </returns>
|
|
public virtual async Task<AuthenticateResult> 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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attempts authorization for a policy using <see cref="IAuthorizationService"/>.
|
|
/// </summary>
|
|
/// <param name="policy">The <see cref="AuthorizationPolicy"/>.</param>
|
|
/// <param name="authenticationResult">The result of a call to <see cref="AuthenticateAsync(AuthorizationPolicy, HttpContext)"/>.</param>
|
|
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
|
/// <returns>Returns <see cref="PolicyAuthorizationResult.Success"/> if authorization succeeds.
|
|
/// Otherwise returns <see cref="PolicyAuthorizationResult.Forbid"/> if <see cref="AuthenticateResult.Succeeded"/>, otherwise
|
|
/// returns <see cref="PolicyAuthorizationResult.Challenge"/></returns>
|
|
public virtual async Task<PolicyAuthorizationResult> 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();
|
|
}
|
|
}
|
|
} |