Skip to content

Commit 988f79f

Browse files
committed
Merge pull request ServiceStack#842 from Its-Tyson/auth-redirect-virtual-directory-issue
Auth redirect virtual directory issue
2 parents 31cbe0d + 20adce2 commit 988f79f

File tree

2 files changed

+48
-12
lines changed

2 files changed

+48
-12
lines changed

src/ServiceStack.ServiceInterface/AuthenticateAttribute.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Specialized;
23
using System.Linq;
34
using ServiceStack.Common;
45
using ServiceStack.Common.Web;
@@ -93,7 +94,7 @@ protected bool DoHtmlRedirectIfConfigured(IHttpRequest req, IHttpResponse res, b
9394
var url = req.ResolveAbsoluteUrl(htmlRedirect);
9495
if (includeRedirectParam)
9596
{
96-
var absoluteRequestPath = req.ResolveAbsoluteUrl("~" + req.RawUrl);
97+
var absoluteRequestPath = req.ResolveAbsoluteUrl("~" + req.PathInfo + ToQueryString(req.QueryString));
9798
url = url.AddQueryParam("redirect", absoluteRequestPath);
9899
}
99100

@@ -144,5 +145,14 @@ public static void AuthenticateIfDigestAuth(IHttpRequest req, IHttpResponse res)
144145
});
145146
}
146147
}
148+
149+
// Not sure if this should be made re-useable within SS.Text with the other NVC extension methods?
150+
private static string ToQueryString(NameValueCollection queryStringCollection)
151+
{
152+
if (queryStringCollection == null || queryStringCollection.Count == 0)
153+
return String.Empty;
154+
155+
return "?" + queryStringCollection.ToFormUrlEncoded();
156+
}
147157
}
148158
}

tests/ServiceStack.WebHost.Endpoints.Tests/AuthTests.cs

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using NUnit.Framework;
88
using ServiceStack.CacheAccess;
99
using ServiceStack.CacheAccess.Providers;
10+
using ServiceStack.Common;
1011
using ServiceStack.Common.Tests.ServiceClient.Web;
1112
using ServiceStack.Common.Utils;
1213
using ServiceStack.Common.Web;
@@ -262,29 +263,36 @@ public CustomAuthAttrResponse Any(CustomAuthAttr request)
262263

263264
public class AuthTests
264265
{
265-
private const string ListeningOn = "http://localhost:82/";
266+
protected virtual string VirtualDirectory { get { return ""; } }
267+
protected virtual string ListeningOn { get { return "http://localhost:82/"; } }
268+
protected virtual string WebHostUrl { get { return "http://mydomain.com"; } }
266269

267270
private const string UserName = "user";
268271
private const string Password = "p@55word";
269272
public const string UserNameWithSessionRedirect = "user2";
270273
public const string PasswordForSessionRedirect = "p@55word2";
271274
public const string SessionRedirectUrl = "specialLandingPage.html";
272275
public const string LoginUrl = "specialLoginPage.html";
273-
public const string WebHostUrl = "http://mydomain.com";
274276
private const string EmailBasedUsername = "[email protected]";
275277
private const string PasswordForEmailBasedAccount = "p@55word3";
276278

279+
277280
public class AuthAppHostHttpListener
278281
: AppHostHttpListenerBase
279282
{
280-
public AuthAppHostHttpListener()
281-
: base("Validation Tests", typeof(CustomerService).Assembly) { }
283+
private readonly string webHostUrl;
284+
285+
public AuthAppHostHttpListener(string webHostUrl)
286+
: base("Validation Tests", typeof (CustomerService).Assembly)
287+
{
288+
this.webHostUrl = webHostUrl;
289+
}
282290

283291
private InMemoryAuthRepository userRep;
284292

285293
public override void Configure(Container container)
286294
{
287-
SetConfig(new EndpointHostConfig { WebHostUrl = WebHostUrl });
295+
SetConfig(new EndpointHostConfig { WebHostUrl = webHostUrl });
288296

289297
Plugins.Add(new AuthFeature(() => new CustomUserSession(),
290298
new IAuthProvider[] { //Www-Authenticate should contain basic auth, therefore register this provider first
@@ -322,14 +330,21 @@ private void CreateUser(int id, string username, string email, string password,
322330
Permissions = permissions
323331
}, password);
324332
}
333+
334+
protected override void Dispose(bool disposing)
335+
{
336+
// Needed so that when the derived class tests run the same users can be added again.
337+
userRep.Clear();
338+
base.Dispose(disposing);
339+
}
325340
}
326341

327342
AuthAppHostHttpListener appHost;
328343

329344
[TestFixtureSetUp]
330345
public void OnTestFixtureSetUp()
331346
{
332-
appHost = new AuthAppHostHttpListener();
347+
appHost = new AuthAppHostHttpListener(WebHostUrl);
333348
appHost.Init();
334349
appHost.Start(ListeningOn);
335350
}
@@ -737,7 +752,8 @@ public void Html_clients_receive_redirect_to_login_page_when_accessing_unauthent
737752
client.Send<SecureResponse>(request);
738753

739754
var locationUri = new Uri(lastResponseLocationHeader);
740-
Assert.That(locationUri.AbsolutePath, Contains.Substring(LoginUrl));
755+
var loginPath = "/".CombineWith(VirtualDirectory).CombineWith(LoginUrl);
756+
Assert.That(locationUri.AbsolutePath, Is.EqualTo(loginPath).IgnoreCase);
741757
}
742758

743759
[Test]
@@ -760,10 +776,13 @@ public void Html_clients_receive_secured_url_attempt_in_login_page_redirect_quer
760776
var redirectUri = new Uri(redirectQueryString);
761777

762778
// Should contain the url attempted to access before the redirect to the login page.
763-
Assert.That(redirectUri.AbsolutePath, Contains.Substring("/secured").IgnoreCase);
764-
// Should also obey the WebHostUrl setting.
765-
var schemeAndHost = redirectUri.Scheme + "://" + redirectUri.Authority;
766-
Assert.That(schemeAndHost, Contains.Substring(WebHostUrl).IgnoreCase);
779+
var securedPath = "/".CombineWith(VirtualDirectory).CombineWith("secured");
780+
Assert.That(redirectUri.AbsolutePath, Is.EqualTo(securedPath).IgnoreCase);
781+
// The url should also obey the WebHostUrl setting for the domain.
782+
var redirectSchemeAndHost = redirectUri.Scheme + "://" + redirectUri.Authority;
783+
var webHostUri = new Uri(WebHostUrl);
784+
var webHostSchemeAndHost = webHostUri.Scheme + "://" + webHostUri.Authority;
785+
Assert.That(redirectSchemeAndHost, Is.EqualTo(webHostSchemeAndHost).IgnoreCase);
767786
}
768787

769788
[Test]
@@ -1010,4 +1029,11 @@ public void Calling_AddSessionIdToRequest_from_a_custom_auth_attribute_does_not_
10101029
);
10111030
}
10121031
}
1032+
1033+
public class AuthTestsWithinVirtualDirectory : AuthTests
1034+
{
1035+
protected override string VirtualDirectory { get { return "somevirtualdirectory"; } }
1036+
protected override string ListeningOn { get { return "http://localhost:82/" + VirtualDirectory + "/"; } }
1037+
protected override string WebHostUrl { get { return "http://mydomain.com/" + VirtualDirectory; } }
1038+
}
10131039
}

0 commit comments

Comments
 (0)