Skip to content

Commit c8b6e02

Browse files
committed
Added failing tests that show IsLocalUrl bug
1 parent 9dfb7e9 commit c8b6e02

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using Duende.IdentityServer.Configuration;
2+
using Duende.IdentityServer.Extensions;
3+
using Duende.IdentityServer.Services;
4+
using Duende.IdentityServer.Validation;
5+
using FluentAssertions;
6+
using Microsoft.Extensions.Logging;
7+
using UnitTests.Common;
8+
using UnitTests.Endpoints.Authorize;
9+
using Xunit;
10+
11+
public class IsLocalUrlTests
12+
{
13+
private const string queryParameters = "?client_id=mvc.code" +
14+
"&redirect_uri=https%3A%2F%2Flocalhost%3A44302%2Fsignin-oidc" +
15+
"&response_type=code" +
16+
"&scope=openid%20profile%20email%20custom.profile%20resource1.scope1%20resource2.scope1%20offline_access" +
17+
"&code_challenge=LcJN1shWmezC0J5EU7QOi7N_amBuvMDb6PcTY0sB2YY" +
18+
"&code_challenge_method=S256" +
19+
"&response_mode=form_post" +
20+
"&nonce=nonce" +
21+
"&state=state";
22+
private const string ExternalWithControlCharacters =
23+
"/ /evil.com/connect/authorize/callback" + // Note tab character between slashes
24+
queryParameters;
25+
private const string ExternalWithoutControlCharacters =
26+
"//evil.com/"
27+
+ queryParameters;
28+
private const string Local =
29+
"/connect/authorize/callback"
30+
+ queryParameters;
31+
32+
[Fact]
33+
public void IsLocalUrl()
34+
{
35+
Local.IsLocalUrl().Should().BeTrue();
36+
ExternalWithoutControlCharacters.IsLocalUrl().Should().BeFalse();
37+
ExternalWithControlCharacters.IsLocalUrl().Should().BeFalse();
38+
}
39+
40+
[Fact]
41+
public void GetIdentityServerRelativeUrl()
42+
{
43+
var serverUrls = new MockServerUrls
44+
{
45+
Origin = "https://localhost:5001",
46+
BasePath = "/"
47+
};
48+
49+
serverUrls.GetIdentityServerRelativeUrl(Local).Should().NotBeNull();
50+
serverUrls.GetIdentityServerRelativeUrl(ExternalWithoutControlCharacters).Should().BeNull();
51+
serverUrls.GetIdentityServerRelativeUrl(ExternalWithControlCharacters).Should().BeNull();
52+
}
53+
54+
[Fact]
55+
public async void OidcReturnUrlParser()
56+
{
57+
var oidcParser = GetOidcParser();
58+
59+
(await oidcParser.ParseAsync(Local)).Should().NotBeNull();
60+
oidcParser.IsValidReturnUrl(Local).Should().BeTrue();
61+
(await oidcParser.ParseAsync(ExternalWithoutControlCharacters)).Should().BeNull();
62+
oidcParser.IsValidReturnUrl(ExternalWithoutControlCharacters).Should().BeFalse();
63+
(await oidcParser.ParseAsync(ExternalWithControlCharacters)).Should().BeNull();
64+
oidcParser.IsValidReturnUrl(ExternalWithControlCharacters).Should().BeFalse();
65+
}
66+
67+
[Fact]
68+
public async void ReturnUrlParser()
69+
{
70+
var oidcParser = GetOidcParser();
71+
var parser = new ReturnUrlParser([oidcParser]);
72+
73+
(await parser.ParseAsync(Local)).Should().NotBeNull();
74+
parser.IsValidReturnUrl(Local).Should().BeTrue();
75+
(await parser.ParseAsync(ExternalWithoutControlCharacters)).Should().BeNull();
76+
parser.IsValidReturnUrl(ExternalWithoutControlCharacters).Should().BeFalse();
77+
(await parser.ParseAsync(ExternalWithControlCharacters)).Should().BeNull();
78+
parser.IsValidReturnUrl(ExternalWithControlCharacters).Should().BeFalse();
79+
}
80+
81+
private static OidcReturnUrlParser GetOidcParser()
82+
{
83+
return new OidcReturnUrlParser(
84+
new IdentityServerOptions(),
85+
new StubAuthorizeRequestValidator
86+
{
87+
Result = new AuthorizeRequestValidationResult
88+
(
89+
new ValidatedAuthorizeRequest()
90+
)
91+
},
92+
new MockUserSession(),
93+
new MockServerUrls(),
94+
new LoggerFactory().CreateLogger<OidcReturnUrlParser>());
95+
}
96+
}

0 commit comments

Comments
 (0)