Skip to content

Commit 7920932

Browse files
committed
Loosen up the Scope Regex to be a little more compliant with rfc6749#3.3
e.g. https://datatracker.ietf.org/doc/html/rfc6749#section-3.3
1 parent 9953eb1 commit 7920932

2 files changed

Lines changed: 42 additions & 5 deletions

File tree

  • access-token-management

access-token-management/src/AccessTokenManagement/Scope.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ namespace Duende.AccessTokenManagement;
2323

2424
public override string ToString() => Value;
2525

26-
// According to RFC 6749, the scope is a space-separated list of strings.
27-
// it can only contain characters in the set [A-Za-z0-9\-._~+/:\^|`!#$%&'*]
28-
[GeneratedRegex(@"^([A-Za-z0-9\-._~+/:\^|`!#$%&'*]+ ?)+$")]
26+
// According to RFC 6749, the scope is a space-separated list of scope-token(s).
27+
// Reference: https://datatracker.ietf.org/doc/html/rfc6749#section-3.3
28+
// scope = scope-token *( SP scope-token )
29+
// scope-token = 1*( %x21 / %x23-5B / %x5D-7E )
30+
[GeneratedRegex(@"^[\x21\x23-\x5B\x5D-\x7E]+(?: [\x21\x23-\x5B\x5D-\x7E]+)*$")]
2931
private static partial Regex _validScope();
3032

3133
private static readonly ValidationRule<string>[] Validators = [
@@ -34,7 +36,7 @@ namespace Duende.AccessTokenManagement;
3436
];
3537

3638
/// <summary>
37-
/// You can't directly create this type.
39+
/// You can't directly create this type.
3840
/// </summary>
3941
/// <exception cref="InvalidOperationException"></exception>
4042
public Scope() => throw new InvalidOperationException("Can't create null value");
@@ -60,7 +62,7 @@ public static bool TryParse(string value, [NotNullWhen(true)] out Scope? parsed,
6062
/// <summary>
6163
/// Parses a value to a <see cref="Scope"/>. This will return null if the provided string
6264
/// is null or whitespace. This is a convenience method for when you want to parse a value that may
63-
/// contain null or whitespace strings.
65+
/// contain null or whitespace strings.
6466
/// </summary>
6567
public static Scope? ParseOrDefault(string? value) => StringParsers<Scope>.ParseOrDefault(value);
6668
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) Duende Software. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
4+
namespace Duende.AccessTokenManagement.Types;
5+
6+
public class ScopeTests
7+
{
8+
[Theory]
9+
[InlineData("!")]
10+
[InlineData("#")]
11+
[InlineData("$")]
12+
[InlineData("[")]
13+
[InlineData("]")]
14+
[InlineData("^")]
15+
[InlineData("~")]
16+
[InlineData("[word]")]
17+
[InlineData("path/to/resource")]
18+
[InlineData("<tag>")]
19+
[InlineData("{foo:bar}")]
20+
[InlineData(":foo.v1.baz.{{bar}}.*")]
21+
public void Scope_with_valid_value_should_not_throw(string scopeValue) => Should.NotThrow(() => Scope.Parse(scopeValue));
22+
23+
[Theory]
24+
[InlineData("")]
25+
[InlineData(" ")]
26+
//Control Characters
27+
[InlineData("\t")]
28+
[InlineData("\n")]
29+
//Backslash and double quote
30+
[InlineData("\"")]
31+
[InlineData("\\")]
32+
[InlineData(" leadingspace")]
33+
[InlineData("trailingspace ")]
34+
public void Scope_with_invalid_value_should_throw(string scopeValue) => Should.Throw<InvalidOperationException>(() => Scope.Parse(scopeValue));
35+
}

0 commit comments

Comments
 (0)