#266 Consolidate authentication APIs.
This commit is contained in:
parent
25aed6f88e
commit
4637a95157
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Http.Authentication
|
||||
{
|
||||
public abstract class AuthenticationManager
|
||||
{
|
||||
public abstract IEnumerable<AuthenticationDescription> GetAuthenticationSchemes();
|
||||
|
||||
public abstract AuthenticationResult Authenticate(string authenticationScheme);
|
||||
|
||||
public abstract Task<AuthenticationResult> AuthenticateAsync(string authenticationScheme);
|
||||
|
||||
public virtual void Challenge()
|
||||
{
|
||||
Challenge(properties: null, authenticationScheme: null);
|
||||
}
|
||||
|
||||
public virtual void Challenge(AuthenticationProperties properties)
|
||||
{
|
||||
Challenge(properties, "");
|
||||
}
|
||||
|
||||
public virtual void Challenge(string authenticationScheme)
|
||||
{
|
||||
Challenge(properties: null, authenticationScheme: authenticationScheme);
|
||||
}
|
||||
|
||||
public abstract void Challenge(AuthenticationProperties properties, string authenticationScheme);
|
||||
|
||||
public abstract void SignIn(string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties = null);
|
||||
|
||||
public virtual void SignOut()
|
||||
{
|
||||
SignOut(authenticationScheme: null, properties: null);
|
||||
}
|
||||
|
||||
public abstract void SignOut(string authenticationScheme);
|
||||
|
||||
public abstract void SignOut(string authenticationScheme, AuthenticationProperties properties);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.WebSockets;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
|
|
@ -20,6 +19,8 @@ namespace Microsoft.AspNet.Http
|
|||
|
||||
public abstract ConnectionInfo Connection { get; }
|
||||
|
||||
public abstract AuthenticationManager Authentication { get; }
|
||||
|
||||
public abstract ClaimsPrincipal User { get; set; }
|
||||
|
||||
public abstract IDictionary<object, object> Items { get; }
|
||||
|
|
@ -54,12 +55,6 @@ namespace Microsoft.AspNet.Http
|
|||
SetFeature(typeof(T), instance);
|
||||
}
|
||||
|
||||
public abstract IEnumerable<AuthenticationDescription> GetAuthenticationSchemes();
|
||||
|
||||
public abstract AuthenticationResult Authenticate(string authenticationScheme);
|
||||
|
||||
public abstract Task<AuthenticationResult> AuthenticateAsync(string authenticationScheme);
|
||||
|
||||
public virtual Task<WebSocket> AcceptWebSocketAsync()
|
||||
{
|
||||
return AcceptWebSocketAsync(subProtocol: null);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. 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;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -12,8 +9,6 @@ namespace Microsoft.AspNet.Http
|
|||
{
|
||||
public abstract class HttpRequest
|
||||
{
|
||||
// TODO - review IOwinRequest for properties
|
||||
|
||||
public abstract HttpContext HttpContext { get; }
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -2,23 +2,22 @@
|
|||
// 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.IO;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNet.Http.Authentication;
|
||||
|
||||
namespace Microsoft.AspNet.Http
|
||||
{
|
||||
public abstract class HttpResponse
|
||||
{
|
||||
// TODO - review IOwinResponse for completeness
|
||||
|
||||
public abstract HttpContext HttpContext { get; }
|
||||
|
||||
public abstract int StatusCode { get; set; }
|
||||
|
||||
public abstract IHeaderDictionary Headers { get; }
|
||||
|
||||
public abstract Stream Body { get; set; }
|
||||
|
||||
public abstract long? ContentLength { get; set; }
|
||||
|
||||
public abstract string ContentType { get; set; }
|
||||
|
||||
public abstract IResponseCookies Cookies { get; }
|
||||
|
|
@ -35,33 +34,5 @@ namespace Microsoft.AspNet.Http
|
|||
}
|
||||
|
||||
public abstract void Redirect(string location, bool permanent);
|
||||
|
||||
public virtual void Challenge()
|
||||
{
|
||||
Challenge(properties: null, authenticationScheme: null);
|
||||
}
|
||||
|
||||
public virtual void Challenge(AuthenticationProperties properties)
|
||||
{
|
||||
Challenge(properties, "");
|
||||
}
|
||||
|
||||
public virtual void Challenge(string authenticationScheme)
|
||||
{
|
||||
Challenge(properties: null, authenticationScheme: authenticationScheme);
|
||||
}
|
||||
|
||||
public abstract void Challenge(AuthenticationProperties properties, string authenticationScheme);
|
||||
|
||||
public abstract void SignIn(string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties = null);
|
||||
|
||||
public virtual void SignOut()
|
||||
{
|
||||
SignOut(authenticationScheme: null, properties: null);
|
||||
}
|
||||
|
||||
public abstract void SignOut(string authenticationScheme);
|
||||
|
||||
public abstract void SignOut(string authenticationScheme, AuthenticationProperties properties);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. 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.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.FeatureModel;
|
||||
using Microsoft.AspNet.Http.Infrastructure;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Http.Authentication
|
||||
{
|
||||
public class DefaultAuthenticationManager : AuthenticationManager
|
||||
{
|
||||
private readonly IFeatureCollection _features;
|
||||
private FeatureReference<IHttpAuthenticationFeature> _authentication = FeatureReference<IHttpAuthenticationFeature>.Default;
|
||||
private FeatureReference<IHttpResponseFeature> _response = FeatureReference<IHttpResponseFeature>.Default;
|
||||
|
||||
public DefaultAuthenticationManager(IFeatureCollection features)
|
||||
{
|
||||
_features = features;
|
||||
}
|
||||
|
||||
private IHttpAuthenticationFeature HttpAuthenticationFeature
|
||||
{
|
||||
get { return _authentication.Fetch(_features) ?? _authentication.Update(_features, new HttpAuthenticationFeature()); }
|
||||
}
|
||||
|
||||
private IHttpResponseFeature HttpResponseFeature
|
||||
{
|
||||
get { return _response.Fetch(_features); }
|
||||
}
|
||||
|
||||
public override IEnumerable<AuthenticationDescription> GetAuthenticationSchemes()
|
||||
{
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
if (handler == null)
|
||||
{
|
||||
return new AuthenticationDescription[0];
|
||||
}
|
||||
|
||||
var describeContext = new DescribeSchemesContext();
|
||||
handler.GetDescriptions(describeContext);
|
||||
return describeContext.Results;
|
||||
}
|
||||
|
||||
public override AuthenticationResult Authenticate([NotNull] string authenticationScheme)
|
||||
{
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
|
||||
var authenticateContext = new AuthenticateContext(authenticationScheme);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.Authenticate(authenticateContext);
|
||||
}
|
||||
|
||||
if (!authenticateContext.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException("The following authentication scheme was not accepted: " + authenticationScheme);
|
||||
}
|
||||
|
||||
return authenticateContext.Result;
|
||||
}
|
||||
|
||||
public override async Task<AuthenticationResult> AuthenticateAsync([NotNull] string authenticationScheme)
|
||||
{
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
|
||||
var authenticateContext = new AuthenticateContext(authenticationScheme);
|
||||
if (handler != null)
|
||||
{
|
||||
await handler.AuthenticateAsync(authenticateContext);
|
||||
}
|
||||
|
||||
// Verify all types ack'd
|
||||
if (!authenticateContext.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException("The following authentication scheme was not accepted: " + authenticationScheme);
|
||||
}
|
||||
|
||||
return authenticateContext.Result;
|
||||
}
|
||||
|
||||
public override void Challenge(AuthenticationProperties properties, string authenticationScheme)
|
||||
{
|
||||
HttpResponseFeature.StatusCode = 401;
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
|
||||
var challengeContext = new ChallengeContext(authenticationScheme, properties == null ? null : properties.Dictionary);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.Challenge(challengeContext);
|
||||
}
|
||||
|
||||
if (!challengeContext.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException("The following authentication type was not accepted: " + authenticationScheme);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SignIn(string authenticationScheme, [NotNull] ClaimsPrincipal principal, AuthenticationProperties properties)
|
||||
{
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
|
||||
var signInContext = new SignInContext(authenticationScheme, principal, properties == null ? null : properties.Dictionary);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.SignIn(signInContext);
|
||||
}
|
||||
|
||||
// Verify all types ack'd
|
||||
if (!signInContext.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException("The following authentication scheme was not accepted: " + authenticationScheme);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SignOut(string authenticationScheme, AuthenticationProperties properties)
|
||||
{
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
|
||||
var signOutContext = new SignOutContext(authenticationScheme, properties?.Dictionary);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.SignOut(signOutContext);
|
||||
}
|
||||
|
||||
// Verify all types ack'd
|
||||
if (!string.IsNullOrWhiteSpace(authenticationScheme) && !signOutContext.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException("The following authentication scheme was not accepted: " + authenticationScheme);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SignOut(string authenticationScheme)
|
||||
{
|
||||
SignOut(authenticationScheme, properties: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,6 @@ using Microsoft.AspNet.FeatureModel;
|
|||
using Microsoft.AspNet.Http.Authentication;
|
||||
using Microsoft.AspNet.Http.Collections;
|
||||
using Microsoft.AspNet.Http.Infrastructure;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Http
|
||||
|
|
@ -23,6 +22,7 @@ namespace Microsoft.AspNet.Http
|
|||
private readonly HttpRequest _request;
|
||||
private readonly HttpResponse _response;
|
||||
private readonly ConnectionInfo _connection;
|
||||
private readonly AuthenticationManager _authenticationManager;
|
||||
|
||||
private FeatureReference<IItemsFeature> _items;
|
||||
private FeatureReference<IServiceProvidersFeature> _serviceProviders;
|
||||
|
|
@ -45,6 +45,7 @@ namespace Microsoft.AspNet.Http
|
|||
_request = new DefaultHttpRequest(this, features);
|
||||
_response = new DefaultHttpResponse(this, features);
|
||||
_connection = new DefaultConnectionInfo(features);
|
||||
_authenticationManager = new DefaultAuthenticationManager(features);
|
||||
|
||||
_items = FeatureReference<IItemsFeature>.Default;
|
||||
_serviceProviders = FeatureReference<IServiceProvidersFeature>.Default;
|
||||
|
|
@ -90,6 +91,8 @@ namespace Microsoft.AspNet.Http
|
|||
|
||||
public override ConnectionInfo Connection { get { return _connection; } }
|
||||
|
||||
public override AuthenticationManager Authentication { get { return _authenticationManager; } }
|
||||
|
||||
public override ClaimsPrincipal User
|
||||
{
|
||||
get
|
||||
|
|
@ -201,56 +204,6 @@ namespace Microsoft.AspNet.Http
|
|||
_features[type] = instance;
|
||||
}
|
||||
|
||||
public override IEnumerable<AuthenticationDescription> GetAuthenticationSchemes()
|
||||
{
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
if (handler == null)
|
||||
{
|
||||
return new AuthenticationDescription[0];
|
||||
}
|
||||
|
||||
var describeContext = new DescribeSchemesContext();
|
||||
handler.GetDescriptions(describeContext);
|
||||
return describeContext.Results;
|
||||
}
|
||||
|
||||
public override AuthenticationResult Authenticate([NotNull] string authenticationScheme)
|
||||
{
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
|
||||
var authenticateContext = new AuthenticateContext(authenticationScheme);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.Authenticate(authenticateContext);
|
||||
}
|
||||
|
||||
if (!authenticateContext.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException("The following authentication scheme was not accepted: " + authenticationScheme);
|
||||
}
|
||||
|
||||
return authenticateContext.Result;
|
||||
}
|
||||
|
||||
public override async Task<AuthenticationResult> AuthenticateAsync([NotNull] string authenticationScheme)
|
||||
{
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
|
||||
var authenticateContext = new AuthenticateContext(authenticationScheme);
|
||||
if (handler != null)
|
||||
{
|
||||
await handler.AuthenticateAsync(authenticateContext);
|
||||
}
|
||||
|
||||
// Verify all types ack'd
|
||||
if (!authenticateContext.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException("The following authentication scheme was not accepted: " + authenticationScheme);
|
||||
}
|
||||
|
||||
return authenticateContext.Result;
|
||||
}
|
||||
|
||||
public override Task<WebSocket> AcceptWebSocketAsync(string subProtocol)
|
||||
{
|
||||
var webSocketFeature = WebSocketFeature;
|
||||
|
|
|
|||
|
|
@ -2,15 +2,10 @@
|
|||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNet.FeatureModel;
|
||||
using Microsoft.AspNet.Http.Authentication;
|
||||
using Microsoft.AspNet.Http.Collections;
|
||||
using Microsoft.AspNet.Http.Infrastructure;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Http
|
||||
|
|
@ -21,7 +16,6 @@ namespace Microsoft.AspNet.Http
|
|||
private readonly IFeatureCollection _features;
|
||||
private FeatureReference<IHttpResponseFeature> _response = FeatureReference<IHttpResponseFeature>.Default;
|
||||
private FeatureReference<IResponseCookiesFeature> _cookies = FeatureReference<IResponseCookiesFeature>.Default;
|
||||
private FeatureReference<IHttpAuthenticationFeature> _authentication = FeatureReference<IHttpAuthenticationFeature>.Default;
|
||||
|
||||
public DefaultHttpResponse(DefaultHttpContext context, IFeatureCollection features)
|
||||
{
|
||||
|
|
@ -39,11 +33,6 @@ namespace Microsoft.AspNet.Http
|
|||
get { return _cookies.Fetch(_features) ?? _cookies.Update(_features, new ResponseCookiesFeature(_features)); }
|
||||
}
|
||||
|
||||
private IHttpAuthenticationFeature HttpAuthenticationFeature
|
||||
{
|
||||
get { return _authentication.Fetch(_features) ?? _authentication.Update(_features, new HttpAuthenticationFeature()); }
|
||||
}
|
||||
|
||||
public override HttpContext HttpContext { get { return _context; } }
|
||||
|
||||
public override int StatusCode
|
||||
|
|
@ -128,61 +117,5 @@ namespace Microsoft.AspNet.Http
|
|||
|
||||
Headers.Set(HeaderNames.Location, location);
|
||||
}
|
||||
|
||||
public override void Challenge(AuthenticationProperties properties, string authenticationScheme)
|
||||
{
|
||||
HttpResponseFeature.StatusCode = 401;
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
|
||||
var challengeContext = new ChallengeContext(authenticationScheme, properties == null ? null : properties.Dictionary);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.Challenge(challengeContext);
|
||||
}
|
||||
|
||||
if (!challengeContext.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException("The following authentication type was not accepted: " + authenticationScheme);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SignIn(string authenticationScheme, [NotNull] ClaimsPrincipal principal, AuthenticationProperties properties)
|
||||
{
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
|
||||
var signInContext = new SignInContext(authenticationScheme, principal, properties == null ? null : properties.Dictionary);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.SignIn(signInContext);
|
||||
}
|
||||
|
||||
// Verify all types ack'd
|
||||
if (!signInContext.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException("The following authentication scheme was not accepted: " + authenticationScheme);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SignOut(string authenticationScheme, AuthenticationProperties properties)
|
||||
{
|
||||
var handler = HttpAuthenticationFeature.Handler;
|
||||
|
||||
var signOutContext = new SignOutContext(authenticationScheme, properties?.Dictionary);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.SignOut(signOutContext);
|
||||
}
|
||||
|
||||
// Verify all types ack'd
|
||||
if (!string.IsNullOrWhiteSpace(authenticationScheme) && !signOutContext.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException("The following authentication scheme was not accepted: " + authenticationScheme);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SignOut(string authenticationScheme)
|
||||
{
|
||||
SignOut(authenticationScheme, properties: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -46,34 +46,34 @@ namespace Microsoft.AspNet.Http
|
|||
public async Task AuthenticateWithNoAuthMiddlewareThrows()
|
||||
{
|
||||
var context = CreateContext();
|
||||
Assert.Throws<InvalidOperationException>(() => context.Authenticate("Foo"));
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(async () => await context.AuthenticateAsync("Foo"));
|
||||
Assert.Throws<InvalidOperationException>(() => context.Authentication.Authenticate("Foo"));
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(async () => await context.Authentication.AuthenticateAsync("Foo"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ChallengeWithNoAuthMiddlewareMayThrow()
|
||||
{
|
||||
var context = CreateContext();
|
||||
context.Response.Challenge();
|
||||
context.Authentication.Challenge();
|
||||
Assert.Equal(401, context.Response.StatusCode);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => context.Response.Challenge("Foo"));
|
||||
Assert.Throws<InvalidOperationException>(() => context.Authentication.Challenge("Foo"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SignInWithNoAuthMiddlewareThrows()
|
||||
{
|
||||
var context = CreateContext();
|
||||
Assert.Throws<InvalidOperationException>(() => context.Response.SignIn("Foo", new ClaimsPrincipal()));
|
||||
Assert.Throws<InvalidOperationException>(() => context.Authentication.SignIn("Foo", new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SignOutWithNoAuthMiddlewareMayThrow()
|
||||
{
|
||||
var context = CreateContext();
|
||||
context.Response.SignOut();
|
||||
context.Authentication.SignOut();
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => context.Response.SignOut("Foo"));
|
||||
Assert.Throws<InvalidOperationException>(() => context.Authentication.SignOut("Foo"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -83,13 +83,13 @@ namespace Microsoft.AspNet.Http
|
|||
var handler = new AuthHandler();
|
||||
context.SetFeature<IHttpAuthenticationFeature>(new HttpAuthenticationFeature() { Handler = handler });
|
||||
var user = new ClaimsPrincipal();
|
||||
context.Response.SignIn("ignored", user);
|
||||
context.Authentication.SignIn("ignored", user);
|
||||
Assert.True(handler.SignedIn);
|
||||
context.Response.SignOut("ignored");
|
||||
context.Authentication.SignOut("ignored");
|
||||
Assert.False(handler.SignedIn);
|
||||
context.Response.SignIn("ignored", user);
|
||||
context.Authentication.SignIn("ignored", user);
|
||||
Assert.True(handler.SignedIn);
|
||||
context.Response.SignOut("ignored", new AuthenticationProperties() { RedirectUri = "~/logout" });
|
||||
context.Authentication.SignOut("ignored", new AuthenticationProperties() { RedirectUri = "~/logout" });
|
||||
Assert.False(handler.SignedIn);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue