Fix base path issue with OAuthHandler

This commit is contained in:
Hao Kung 2015-06-29 10:43:43 -07:00
parent 102f113e2b
commit 78cf7f99ff
5 changed files with 84 additions and 18 deletions

View File

@ -117,7 +117,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
{
Domain = Options.CookieDomain,
HttpOnly = Options.CookieHttpOnly,
Path = Options.CookiePath ?? (RequestPathBase.HasValue ? RequestPathBase.ToString() : "/"),
Path = Options.CookiePath ?? (OriginalPathBase.HasValue ? OriginalPathBase.ToString() : "/"),
};
if (Options.CookieSecure == CookieSecureOption.SameAsRequest)
{

View File

@ -116,10 +116,7 @@ namespace Microsoft.AspNet.Authentication.OAuth
return new AuthenticationTicket(properties, Options.AuthenticationScheme);
}
var requestPrefix = Request.Scheme + "://" + Request.Host;
var redirectUri = requestPrefix + RequestPathBase + Options.CallbackPath;
var tokens = await ExchangeCodeAsync(code, redirectUri);
var tokens = await ExchangeCodeAsync(code, BuildRedirectUri(Options.CallbackPath));
if (string.IsNullOrWhiteSpace(tokens.AccessToken))
{
@ -172,20 +169,16 @@ namespace Microsoft.AspNet.Authentication.OAuth
protected override Task<bool> HandleUnauthorizedAsync([NotNull] ChallengeContext context)
{
var baseUri = Request.Scheme + "://" + Request.Host + Request.PathBase;
var currentUri = baseUri + Request.Path + Request.QueryString;
var redirectUri = baseUri + Options.CallbackPath;
var properties = new AuthenticationProperties(context.Properties);
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
properties.RedirectUri = CurrentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
var authorizationEndpoint = BuildChallengeUrl(properties, redirectUri);
var authorizationEndpoint = BuildChallengeUrl(properties, BuildRedirectUri(Options.CallbackPath));
var redirectContext = new OAuthApplyRedirectContext(
Context, Options,

View File

@ -120,16 +120,13 @@ namespace Microsoft.AspNet.Authentication.Twitter
}
protected override async Task<bool> HandleUnauthorizedAsync([NotNull] ChallengeContext context)
{
var requestPrefix = Request.Scheme + "://" + Request.Host;
var callBackUrl = requestPrefix + RequestPathBase + Options.CallbackPath;
var properties = new AuthenticationProperties(context.Properties);
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = requestPrefix + Request.PathBase + Request.Path + Request.QueryString;
properties.RedirectUri = CurrentUri;
}
var requestToken = await ObtainRequestTokenAsync(Options.ConsumerKey, Options.ConsumerSecret, callBackUrl, properties);
var requestToken = await ObtainRequestTokenAsync(Options.ConsumerKey, Options.ConsumerSecret, BuildRedirectUri(Options.CallbackPath), properties);
if (requestToken.CallbackConfirmed)
{
var twitterAuthenticationEndpoint = AuthenticationEndpoint + requestToken.Token;

View File

@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Authentication
get { return Context.Response; }
}
protected PathString RequestPathBase { get; private set; }
protected PathString OriginalPathBase { get; private set; }
protected ILogger Logger { get; private set; }
@ -48,11 +48,19 @@ namespace Microsoft.AspNet.Authentication
public IAuthenticationHandler PriorHandler { get; set; }
protected string CurrentUri
{
get
{
return Request.Scheme + "://" + Request.Host + Request.PathBase + Request.Path + Request.QueryString;
}
}
protected async Task BaseInitializeAsync([NotNull] AuthenticationOptions options, [NotNull] HttpContext context, [NotNull] ILogger logger, [NotNull] IUrlEncoder encoder)
{
_baseOptions = options;
Context = context;
RequestPathBase = Request.PathBase;
OriginalPathBase = Request.PathBase;
Logger = logger;
UrlEncoder = encoder;
@ -70,6 +78,11 @@ namespace Microsoft.AspNet.Authentication
}
}
protected string BuildRedirectUri(string targetPath)
{
return Request.Scheme + "://" + Request.Host + OriginalPathBase + targetPath;
}
private static async Task OnStartingCallback(object state)
{
var handler = (AuthenticationHandler)state;

View File

@ -6,8 +6,10 @@ using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.TestHost;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.WebEncoders;
using Shouldly;
using Xunit;
@ -61,6 +63,67 @@ namespace Microsoft.AspNet.Authentication.Facebook
query.ShouldContain("custom=test");
}
[Fact]
public async Task NestedMapWillNotAffectRedirect()
{
var server = CreateServer(app =>
app.Map("/base", map => {
map.UseFacebookAuthentication();
map.Map("/login", signoutApp => signoutApp.Run(context => context.Authentication.ChallengeAsync("Facebook", new AuthenticationProperties() { RedirectUri = "/" })));
}),
services =>
{
services.AddAuthentication();
services.ConfigureFacebookAuthentication(options =>
{
options.AppId = "Test App Id";
options.AppSecret = "Test App Secret";
options.SignInScheme = "External";
});
},
handler: null);
var transaction = await server.SendAsync("http://example.com/base/login");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var location = transaction.Response.Headers.Location.AbsoluteUri;
location.ShouldContain("https://www.facebook.com/v2.2/dialog/oauth");
location.ShouldContain("response_type=code");
location.ShouldContain("client_id=");
location.ShouldContain("redirect_uri=" + UrlEncoder.Default.UrlEncode("http://example.com/base/signin-facebook"));
location.ShouldContain("scope=");
location.ShouldContain("state=");
}
[Fact]
public async Task MapWillNotAffectRedirect()
{
var server = CreateServer(
app =>
{
app.UseFacebookAuthentication();
app.Map("/login", signoutApp => signoutApp.Run(context => context.Authentication.ChallengeAsync("Facebook", new AuthenticationProperties() { RedirectUri = "/" })));
},
services =>
{
services.AddAuthentication();
services.ConfigureFacebookAuthentication(options =>
{
options.AppId = "Test App Id";
options.AppSecret = "Test App Secret";
options.SignInScheme = "External";
});
},
handler: null);
var transaction = await server.SendAsync("http://example.com/login");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var location = transaction.Response.Headers.Location.AbsoluteUri;
location.ShouldContain("https://www.facebook.com/v2.2/dialog/oauth");
location.ShouldContain("response_type=code");
location.ShouldContain("client_id=");
location.ShouldContain("redirect_uri="+ UrlEncoder.Default.UrlEncode("http://example.com/signin-facebook"));
location.ShouldContain("scope=");
location.ShouldContain("state=");
}
[Fact]
public async Task ChallengeWillTriggerRedirection()
{