Auth: Validate acks.

This commit is contained in:
Chris Ross 2014-03-31 11:09:38 -07:00
parent 4347ddfd0f
commit 097138e813
5 changed files with 82 additions and 22 deletions

View File

@ -19,19 +19,25 @@ namespace Microsoft.AspNet.PipelineCore.Security
}
AuthenticationTypes = authenticationTypes;
Results = new List<AuthenticationResult>();
Acked = new List<string>();
}
public IList<string> AuthenticationTypes { get; private set; }
public IList<AuthenticationResult> Results { get; private set; }
public IList<string> Acked { get; private set; }
public void Authenticated(ClaimsIdentity identity, IDictionary<string, string> properties, IDictionary<string, object> description)
{
Results.Add(new AuthenticationResult(identity, new AuthenticationProperties(properties), new AuthenticationDescription(description)));
var descrip = new AuthenticationDescription(description);
Acked.Add(descrip.AuthenticationType);
Results.Add(new AuthenticationResult(identity, new AuthenticationProperties(properties), descrip));
}
public void NotAuthenticated(string authenticationType, IDictionary<string, string> properties, IDictionary<string, object> description)
{
Acked.Add(authenticationType);
}
}
}

View File

@ -17,14 +17,18 @@ namespace Microsoft.AspNet.PipelineCore.Security
}
AuthenticationTypes = authenticationTypes;
Properties = properties ?? new Dictionary<string, string>(StringComparer.Ordinal);
Acked = new List<string>();
}
public IList<string> AuthenticationTypes { get; private set; }
public IDictionary<string, string> Properties { get; private set; }
public IList<string> Acked { get; private set; }
public void Ack(string authenticationType, IDictionary<string, object> description)
{
Acked.Add(authenticationType);
}
}
}

View File

@ -17,6 +17,8 @@ namespace Microsoft.AspNet.PipelineCore.Security
{
public class DefaultAuthenticationManager : AuthenticationManager
{
private static DescriptionDelegate GetAuthenticationTypesDelegate = GetAuthenticationTypesCallback;
private readonly DefaultHttpContext _context;
private readonly IFeatureCollection _features;
@ -52,8 +54,7 @@ namespace Microsoft.AspNet.PipelineCore.Security
var handler = HttpAuthentication.Handler;
if (handler != null)
{
// TODO: static delegate field
handler.GetDescriptions(GetAuthenticationTypesCallback, descriptions);
handler.GetDescriptions(GetAuthenticationTypesDelegate, descriptions);
}
return descriptions;
}
@ -71,17 +72,25 @@ namespace Microsoft.AspNet.PipelineCore.Security
public override IEnumerable<AuthenticationResult> Authenticate(IList<string> authenticationTypes)
{
HttpResponseInformation.StatusCode = 401;
if (authenticationTypes == null)
{
throw new ArgumentNullException();
}
var handler = HttpAuthentication.Handler;
if (handler == null)
{
// TODO: InvalidOperationException? No auth types supported?
return new AuthenticationResult[0];
throw new InvalidOperationException("No authentication handlers present.");
}
var authenticateContext = new AuthenticateContext(authenticationTypes);
handler.Authenticate(authenticateContext);
// TODO: Verify all types ack'd
// Verify all types ack'd
IEnumerable<string> leftovers = authenticationTypes.Except(authenticateContext.Acked);
if (leftovers.Any())
{
throw new InvalidOperationException("The following authentication types did not ack: " + string.Join(", ", leftovers));
}
return authenticateContext.Results;
}
@ -93,17 +102,25 @@ namespace Microsoft.AspNet.PipelineCore.Security
public override async Task<IEnumerable<AuthenticationResult>> AuthenticateAsync(IList<string> authenticationTypes)
{
HttpResponseInformation.StatusCode = 401;
if (authenticationTypes == null)
{
throw new ArgumentNullException();
}
var handler = HttpAuthentication.Handler;
if (handler == null)
{
// TODO: InvalidOperationException? No auth types supported?
return new AuthenticationResult[0];
throw new InvalidOperationException("No authentication handlers present.");
}
var authenticateContext = new AuthenticateContext(authenticationTypes);
await handler.AuthenticateAsync(authenticateContext);
// TODO: Verify all types ack'd
// Verify all types ack'd
IEnumerable<string> leftovers = authenticationTypes.Except(authenticateContext.Acked);
if (leftovers.Any())
{
throw new InvalidOperationException("The following authentication types did not ack: " + string.Join(", ", leftovers));
}
return authenticateContext.Results;
}
@ -135,17 +152,26 @@ namespace Microsoft.AspNet.PipelineCore.Security
public override void Challenge(IList<string> authenticationTypes, AuthenticationProperties properties)
{
if (authenticationTypes == null)
{
throw new ArgumentNullException();
}
HttpResponseInformation.StatusCode = 401;
var handler = HttpAuthentication.Handler;
if (handler == null)
{
// TODO: InvalidOperationException? No auth types supported? If authTypes.Length > 1?
return;
throw new InvalidOperationException("No authentication handlers present.");
}
var challengeContext = new ChallengeContext(authenticationTypes, properties == null ? null : properties.Dictionary);
handler.Challenge(challengeContext);
// TODO: Verify all types ack'd
// Verify all types ack'd
IEnumerable<string> leftovers = authenticationTypes.Except(challengeContext.Acked);
if (leftovers.Any())
{
throw new InvalidOperationException("The following authentication types did not ack: " + string.Join(", ", leftovers));
}
}
public override void SignIn(ClaimsPrincipal user)
@ -155,17 +181,25 @@ namespace Microsoft.AspNet.PipelineCore.Security
public override void SignIn(ClaimsPrincipal user, AuthenticationProperties properties)
{
HttpResponseInformation.StatusCode = 401;
if (user == null)
{
throw new ArgumentNullException();
}
var handler = HttpAuthentication.Handler;
if (handler == null)
{
// TODO: InvalidOperationException? No auth types supported?
return;
throw new InvalidOperationException("No authentication handlers present.");
}
var signInContext = new SignInContext(user, properties == null ? null : properties.Dictionary);
handler.SignIn(signInContext);
// TODO: Verify all types ack'd
// Verify all types ack'd
IEnumerable<string> leftovers = user.Identities.Select(identity => identity.AuthenticationType).Except(signInContext.Acked);
if (leftovers.Any())
{
throw new InvalidOperationException("The following authentication types did not ack: " + string.Join(", ", leftovers));
}
}
public override void SignOut()
@ -180,17 +214,25 @@ namespace Microsoft.AspNet.PipelineCore.Security
public override void SignOut(IList<string> authenticationTypes)
{
HttpResponseInformation.StatusCode = 401;
if (authenticationTypes == null)
{
throw new ArgumentNullException();
}
var handler = HttpAuthentication.Handler;
if (handler == null)
{
// TODO: InvalidOperationException? No auth types supported?
return;
throw new InvalidOperationException("No authentication handlers present.");
}
var signOutContext = new SignOutContext(authenticationTypes);
handler.SignOut(signOutContext);
// TODO: Verify all types ack'd
// Verify all types ack'd
IEnumerable<string> leftovers = authenticationTypes.Except(signOutContext.Acked);
if (leftovers.Any())
{
throw new InvalidOperationException("The following authentication types did not ack: " + string.Join(", ", leftovers));
}
}
}
}

View File

@ -15,14 +15,18 @@ namespace Microsoft.AspNet.PipelineCore.Security
}
User = user;
Properties = dictionary ?? new Dictionary<string, string>(StringComparer.Ordinal);
Acked = new List<string>();
}
public ClaimsPrincipal User { get; private set; }
public IDictionary<string, string> Properties { get; private set; }
public IList<string> Acked { get; private set; }
public void Ack(string authenticationType, IDictionary<string, object> description)
{
Acked.Add(authenticationType);
}
}
}

View File

@ -13,12 +13,16 @@ namespace Microsoft.AspNet.PipelineCore.Security
throw new ArgumentNullException("authenticationTypes");
}
AuthenticationTypes = authenticationTypes;
Acked = new List<string>();
}
public IList<string> AuthenticationTypes { get; private set; }
public IList<string> Acked { get; private set; }
public void Ack(string authenticationType, IDictionary<string, object> description)
{
Acked.Add(authenticationType);
}
}
}