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; AuthenticationTypes = authenticationTypes;
Results = new List<AuthenticationResult>(); Results = new List<AuthenticationResult>();
Acked = new List<string>();
} }
public IList<string> AuthenticationTypes { get; private set; } public IList<string> AuthenticationTypes { get; private set; }
public IList<AuthenticationResult> Results { 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) 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) 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; AuthenticationTypes = authenticationTypes;
Properties = properties ?? new Dictionary<string, string>(StringComparer.Ordinal); Properties = properties ?? new Dictionary<string, string>(StringComparer.Ordinal);
Acked = new List<string>();
} }
public IList<string> AuthenticationTypes { get; private set; } public IList<string> AuthenticationTypes { get; private set; }
public IDictionary<string, string> Properties { 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) 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 public class DefaultAuthenticationManager : AuthenticationManager
{ {
private static DescriptionDelegate GetAuthenticationTypesDelegate = GetAuthenticationTypesCallback;
private readonly DefaultHttpContext _context; private readonly DefaultHttpContext _context;
private readonly IFeatureCollection _features; private readonly IFeatureCollection _features;
@ -52,8 +54,7 @@ namespace Microsoft.AspNet.PipelineCore.Security
var handler = HttpAuthentication.Handler; var handler = HttpAuthentication.Handler;
if (handler != null) if (handler != null)
{ {
// TODO: static delegate field handler.GetDescriptions(GetAuthenticationTypesDelegate, descriptions);
handler.GetDescriptions(GetAuthenticationTypesCallback, descriptions);
} }
return descriptions; return descriptions;
} }
@ -71,17 +72,25 @@ namespace Microsoft.AspNet.PipelineCore.Security
public override IEnumerable<AuthenticationResult> Authenticate(IList<string> authenticationTypes) public override IEnumerable<AuthenticationResult> Authenticate(IList<string> authenticationTypes)
{ {
HttpResponseInformation.StatusCode = 401; if (authenticationTypes == null)
{
throw new ArgumentNullException();
}
var handler = HttpAuthentication.Handler; var handler = HttpAuthentication.Handler;
if (handler == null) if (handler == null)
{ {
// TODO: InvalidOperationException? No auth types supported? throw new InvalidOperationException("No authentication handlers present.");
return new AuthenticationResult[0];
} }
var authenticateContext = new AuthenticateContext(authenticationTypes); var authenticateContext = new AuthenticateContext(authenticationTypes);
handler.Authenticate(authenticateContext); 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; return authenticateContext.Results;
} }
@ -93,17 +102,25 @@ namespace Microsoft.AspNet.PipelineCore.Security
public override async Task<IEnumerable<AuthenticationResult>> AuthenticateAsync(IList<string> authenticationTypes) public override async Task<IEnumerable<AuthenticationResult>> AuthenticateAsync(IList<string> authenticationTypes)
{ {
HttpResponseInformation.StatusCode = 401; if (authenticationTypes == null)
{
throw new ArgumentNullException();
}
var handler = HttpAuthentication.Handler; var handler = HttpAuthentication.Handler;
if (handler == null) if (handler == null)
{ {
// TODO: InvalidOperationException? No auth types supported? throw new InvalidOperationException("No authentication handlers present.");
return new AuthenticationResult[0];
} }
var authenticateContext = new AuthenticateContext(authenticationTypes); var authenticateContext = new AuthenticateContext(authenticationTypes);
await handler.AuthenticateAsync(authenticateContext); 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; return authenticateContext.Results;
} }
@ -135,17 +152,26 @@ namespace Microsoft.AspNet.PipelineCore.Security
public override void Challenge(IList<string> authenticationTypes, AuthenticationProperties properties) public override void Challenge(IList<string> authenticationTypes, AuthenticationProperties properties)
{ {
if (authenticationTypes == null)
{
throw new ArgumentNullException();
}
HttpResponseInformation.StatusCode = 401; HttpResponseInformation.StatusCode = 401;
var handler = HttpAuthentication.Handler; var handler = HttpAuthentication.Handler;
if (handler == null) if (handler == null)
{ {
// TODO: InvalidOperationException? No auth types supported? If authTypes.Length > 1? throw new InvalidOperationException("No authentication handlers present.");
return;
} }
var challengeContext = new ChallengeContext(authenticationTypes, properties == null ? null : properties.Dictionary); var challengeContext = new ChallengeContext(authenticationTypes, properties == null ? null : properties.Dictionary);
handler.Challenge(challengeContext); 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) public override void SignIn(ClaimsPrincipal user)
@ -155,17 +181,25 @@ namespace Microsoft.AspNet.PipelineCore.Security
public override void SignIn(ClaimsPrincipal user, AuthenticationProperties properties) public override void SignIn(ClaimsPrincipal user, AuthenticationProperties properties)
{ {
HttpResponseInformation.StatusCode = 401; if (user == null)
{
throw new ArgumentNullException();
}
var handler = HttpAuthentication.Handler; var handler = HttpAuthentication.Handler;
if (handler == null) if (handler == null)
{ {
// TODO: InvalidOperationException? No auth types supported? throw new InvalidOperationException("No authentication handlers present.");
return;
} }
var signInContext = new SignInContext(user, properties == null ? null : properties.Dictionary); var signInContext = new SignInContext(user, properties == null ? null : properties.Dictionary);
handler.SignIn(signInContext); 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() public override void SignOut()
@ -180,17 +214,25 @@ namespace Microsoft.AspNet.PipelineCore.Security
public override void SignOut(IList<string> authenticationTypes) public override void SignOut(IList<string> authenticationTypes)
{ {
HttpResponseInformation.StatusCode = 401; if (authenticationTypes == null)
{
throw new ArgumentNullException();
}
var handler = HttpAuthentication.Handler; var handler = HttpAuthentication.Handler;
if (handler == null) if (handler == null)
{ {
// TODO: InvalidOperationException? No auth types supported? throw new InvalidOperationException("No authentication handlers present.");
return;
} }
var signOutContext = new SignOutContext(authenticationTypes); var signOutContext = new SignOutContext(authenticationTypes);
handler.SignOut(signOutContext); 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; User = user;
Properties = dictionary ?? new Dictionary<string, string>(StringComparer.Ordinal); Properties = dictionary ?? new Dictionary<string, string>(StringComparer.Ordinal);
Acked = new List<string>();
} }
public ClaimsPrincipal User { get; private set; } public ClaimsPrincipal User { get; private set; }
public IDictionary<string, string> Properties { 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) 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"); throw new ArgumentNullException("authenticationTypes");
} }
AuthenticationTypes = authenticationTypes; AuthenticationTypes = authenticationTypes;
Acked = new List<string>();
} }
public IList<string> AuthenticationTypes { get; private set; } public IList<string> AuthenticationTypes { get; private set; }
public IList<string> Acked { get; private set; }
public void Ack(string authenticationType, IDictionary<string, object> description) public void Ack(string authenticationType, IDictionary<string, object> description)
{ {
Acked.Add(authenticationType);
} }
} }
} }