You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
520 lines
17 KiB
520 lines
17 KiB
/*
|
|
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|
* the license and the contributors participating to this project.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Text.Encodings.Web;
|
|
using System.Text.Json;
|
|
using Xunit;
|
|
using static OpenIddict.Abstractions.OpenIddictConstants;
|
|
using SR = OpenIddict.Abstractions.OpenIddictResources;
|
|
|
|
namespace OpenIddict.Abstractions.Tests.Primitives
|
|
{
|
|
public class OpenIddictMessageTests
|
|
{
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
public void Constructor_ThrowsAnExceptionForNullOrEmptyParameterNames(string name)
|
|
{
|
|
// Arrange, act and assert
|
|
var exception = Assert.Throws<ArgumentException>(delegate
|
|
{
|
|
return new OpenIddictMessage(new[]
|
|
{
|
|
new KeyValuePair<string, OpenIddictParameter>(name, "Fabrikam")
|
|
});
|
|
});
|
|
|
|
Assert.Equal("name", exception.ParamName);
|
|
Assert.StartsWith(SR.GetResourceString(SR.ID0190), exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_ThrowsAnExceptionForInvalidJsonElement()
|
|
{
|
|
// Arrange, act and assert
|
|
var exception = Assert.Throws<ArgumentException>(delegate
|
|
{
|
|
return new OpenIddictMessage(JsonSerializer.Deserialize<JsonElement>("[0,1,2,3]"));
|
|
});
|
|
|
|
Assert.Equal("parameters", exception.ParamName);
|
|
Assert.StartsWith(SR.GetResourceString(SR.ID0189), exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_ThrowsAnExceptionForDuplicateParameters()
|
|
{
|
|
// Arrange, act and assert
|
|
var exception = Assert.Throws<ArgumentException>(delegate
|
|
{
|
|
return new OpenIddictMessage(new[]
|
|
{
|
|
new KeyValuePair<string, OpenIddictParameter>("parameter", "Fabrikam"),
|
|
new KeyValuePair<string, OpenIddictParameter>("parameter", "Contoso")
|
|
});
|
|
});
|
|
|
|
Assert.Equal("name", exception.ParamName);
|
|
Assert.StartsWith(SR.GetResourceString(SR.ID0191), exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_ImportsParameters()
|
|
{
|
|
// Arrange and act
|
|
var message = new OpenIddictMessage(new[]
|
|
{
|
|
new KeyValuePair<string, OpenIddictParameter>("parameter", 42)
|
|
});
|
|
|
|
// Assert
|
|
Assert.Equal(42, (long) message.GetParameter("parameter"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_PreservesEmptyParameters()
|
|
{
|
|
// Arrange and act
|
|
var message = new OpenIddictMessage(new[]
|
|
{
|
|
new KeyValuePair<string, OpenIddictParameter>("null-parameter", (string?) null),
|
|
new KeyValuePair<string, OpenIddictParameter>("empty-parameter", string.Empty)
|
|
});
|
|
|
|
// Assert
|
|
Assert.Equal(2, message.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_AllowsDuplicateParameters()
|
|
{
|
|
// Arrange and act
|
|
var message = new OpenIddictMessage(new[]
|
|
{
|
|
new KeyValuePair<string, string?>("parameter", "Fabrikam"),
|
|
new KeyValuePair<string, string?>("parameter", "Contoso")
|
|
});
|
|
|
|
// Assert
|
|
Assert.Equal(1, message.Count);
|
|
Assert.Equal(new[] { "Fabrikam", "Contoso" }, (string[]?) message.GetParameter("parameter"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_SupportsMultiValuedParameters()
|
|
{
|
|
// Arrange and act
|
|
var message = new OpenIddictMessage(new[]
|
|
{
|
|
new KeyValuePair<string, string?[]?>("parameter", new[] { "Fabrikam", "Contoso" })
|
|
});
|
|
|
|
// Assert
|
|
Assert.Equal(1, message.Count);
|
|
Assert.Equal(new[] { "Fabrikam", "Contoso" }, (string[]?) message.GetParameter("parameter"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_ExtractsSingleValuedParameters()
|
|
{
|
|
// Arrange and act
|
|
var message = new OpenIddictMessage(new[]
|
|
{
|
|
new KeyValuePair<string, string?[]?>("parameter", new[] { "Fabrikam" })
|
|
});
|
|
|
|
// Assert
|
|
Assert.Equal(1, message.Count);
|
|
Assert.Equal("Fabrikam", message.GetParameter("parameter")?.Value);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
public void AddParameter_ThrowsAnExceptionForNullOrEmptyName(string name)
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act and assert
|
|
var exception = Assert.Throws<ArgumentException>(() =>
|
|
{
|
|
message.AddParameter(name, new OpenIddictParameter());
|
|
});
|
|
|
|
Assert.Equal("name", exception.ParamName);
|
|
Assert.StartsWith(SR.GetResourceString(SR.ID0190), exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void AddParameter_AddsExpectedParameter()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act
|
|
message.AddParameter("parameter", 42);
|
|
|
|
// Assert
|
|
Assert.Equal(42, message.GetParameter("parameter"));
|
|
}
|
|
|
|
[Fact]
|
|
public void AddParameter_IsCaseSensitive()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act
|
|
message.AddParameter("PARAMETER", 42);
|
|
|
|
// Assert
|
|
Assert.Null(message.GetParameter("parameter"));
|
|
}
|
|
|
|
[Fact]
|
|
public void AddParameter_PreservesEmptyParameters()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act
|
|
message.AddParameter("string", string.Empty);
|
|
message.AddParameter("array", JsonSerializer.Deserialize<JsonElement>("[]"));
|
|
message.AddParameter("object", JsonSerializer.Deserialize<JsonElement>("{}"));
|
|
message.AddParameter("value", JsonSerializer.Deserialize<JsonElement>(
|
|
@"{""property"":""""}").GetProperty("property").GetString());
|
|
|
|
// Assert
|
|
Assert.Empty((string?) message.GetParameter("string"));
|
|
Assert.NotNull((JsonElement?) message.GetParameter("array"));
|
|
Assert.NotNull((JsonElement?) message.GetParameter("object"));
|
|
Assert.NotNull((JsonElement?) message.GetParameter("value"));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
public void GetParameter_ThrowsAnExceptionForNullOrEmptyName(string name)
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act and assert
|
|
var exception = Assert.Throws<ArgumentException>(() => message.GetParameter(name));
|
|
|
|
Assert.Equal("name", exception.ParamName);
|
|
Assert.StartsWith(SR.GetResourceString(SR.ID0190), exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetParameter_ReturnsExpectedParameter()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
message.SetParameter("parameter", 42);
|
|
|
|
// Act and assert
|
|
Assert.Equal(42, (int) message.GetParameter("parameter"));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetParameter_IsCaseSensitive()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
message.SetParameter("parameter", 42);
|
|
|
|
// Act and assert
|
|
Assert.Null(message.GetParameter("PARAMETER"));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetParameter_ReturnsNullForUnsetParameter()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act and assert
|
|
Assert.Null(message.GetParameter("parameter"));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetParameters_EnumeratesParameters()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, OpenIddictParameter>
|
|
{
|
|
["int"] = int.MaxValue,
|
|
["long"] = long.MaxValue,
|
|
["string"] = "value"
|
|
};
|
|
|
|
var message = new OpenIddictMessage(parameters);
|
|
|
|
// Act and assert
|
|
Assert.Equal(parameters, message.GetParameters());
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
public void HasParameter_ThrowsAnExceptionForNullOrEmptyName(string name)
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act and assert
|
|
var exception = Assert.Throws<ArgumentException>(() => message.HasParameter(name));
|
|
|
|
Assert.Equal("name", exception.ParamName);
|
|
Assert.StartsWith(SR.GetResourceString(SR.ID0190), exception.Message);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("parameter", true)]
|
|
[InlineData("PARAMETER", false)]
|
|
[InlineData("missing_parameter", false)]
|
|
public void HasParameter_ReturnsExpectedResult(string parameter, bool result)
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
message.SetParameter("parameter", "value");
|
|
|
|
// Act and assert
|
|
Assert.Equal(result, message.HasParameter(parameter));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
public void RemoveParameter_ThrowsAnExceptionForNullOrEmptyName(string name)
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act and assert
|
|
var exception = Assert.Throws<ArgumentException>(() => message.RemoveParameter(name));
|
|
|
|
Assert.Equal("name", exception.ParamName);
|
|
Assert.StartsWith(SR.GetResourceString(SR.ID0190), exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveParameter_RemovesExpectedParameter()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
message.AddParameter("parameter", 42);
|
|
|
|
// Act
|
|
message.RemoveParameter("parameter");
|
|
|
|
// Assert
|
|
Assert.Null(message.GetParameter("parameter"));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
public void SetParameter_ThrowsAnExceptionForNullOrEmptyName(string name)
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act and assert
|
|
var exception = Assert.Throws<ArgumentException>(() => message.SetParameter(name, null));
|
|
|
|
Assert.Equal("name", exception.ParamName);
|
|
Assert.StartsWith(SR.GetResourceString(SR.ID0190), exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetParameter_AddsExpectedParameter()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act
|
|
message.SetParameter("parameter", 42);
|
|
|
|
// Assert
|
|
Assert.Equal(42, message.GetParameter("parameter"));
|
|
}
|
|
|
|
[Fact]
|
|
public void SetParameter_IsCaseSensitive()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act
|
|
message.SetParameter("PARAMETER", 42);
|
|
|
|
// Assert
|
|
Assert.Null(message.GetParameter("parameter"));
|
|
}
|
|
|
|
[Fact]
|
|
public void SetParameter_RemovesNullParameters()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act
|
|
message.SetParameter("null", null);
|
|
|
|
// Assert
|
|
Assert.Empty(message.GetParameters());
|
|
}
|
|
|
|
[Fact]
|
|
public void SetParameter_RemovesEmptyParameters()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act
|
|
message.SetParameter("string", string.Empty);
|
|
message.SetParameter("array", JsonSerializer.Deserialize<JsonElement>("[]"));
|
|
message.SetParameter("object", JsonSerializer.Deserialize<JsonElement>("{}"));
|
|
message.SetParameter("value", JsonSerializer.Deserialize<JsonElement>(
|
|
@"{""property"":""""}").GetProperty("property").GetString());
|
|
|
|
// Assert
|
|
Assert.Empty(message.GetParameters());
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
public void TryGetParameter_ThrowsAnExceptionForNullOrEmptyName(string name)
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act
|
|
var exception = Assert.Throws<ArgumentException>(() => message.TryGetParameter(name, out var parameter));
|
|
|
|
// Assert
|
|
Assert.Equal("name", exception.ParamName);
|
|
Assert.StartsWith(SR.GetResourceString(SR.ID0190), exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGetParameter_ReturnsTrueAndExpectedParameter()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
message.SetParameter("parameter", 42);
|
|
|
|
// Act and assert
|
|
Assert.True(message.TryGetParameter("parameter", out var parameter));
|
|
Assert.Equal(42, (long?) parameter.Value);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGetParameter_ReturnsFalseForUnsetParameter()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act and assert
|
|
Assert.False(message.TryGetParameter("parameter", out OpenIddictParameter parameter));
|
|
Assert.Null(parameter.Value);
|
|
}
|
|
|
|
[Fact]
|
|
public void ToString_ReturnsJsonRepresentation()
|
|
{
|
|
// Arrange
|
|
var message = JsonSerializer.Deserialize<OpenIddictMessage>(@"{
|
|
""redirect_uris"": [
|
|
""https://client.example.org/callback"",
|
|
""https://client.example.org/callback2""
|
|
],
|
|
""client_name"": ""My Example Client"",
|
|
""token_endpoint_auth_method"": ""client_secret_basic"",
|
|
""logo_uri"": ""https://client.example.org/logo.png"",
|
|
""jwks_uri"": ""https://client.example.org/my_public_keys.jwks"",
|
|
""example_extension_parameter"": ""example_value""
|
|
}");
|
|
|
|
var options = new JsonSerializerOptions
|
|
{
|
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
|
WriteIndented = true
|
|
};
|
|
|
|
// Act and assert
|
|
Assert.Equal(JsonSerializer.Serialize(message, options), message.ToString());
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(Parameters.AccessToken)]
|
|
[InlineData(Parameters.Assertion)]
|
|
[InlineData(Parameters.ClientAssertion)]
|
|
[InlineData(Parameters.ClientSecret)]
|
|
[InlineData(Parameters.Code)]
|
|
[InlineData(Parameters.IdToken)]
|
|
[InlineData(Parameters.IdTokenHint)]
|
|
[InlineData(Parameters.Password)]
|
|
[InlineData(Parameters.RefreshToken)]
|
|
[InlineData(Parameters.Token)]
|
|
public void ToString_ExcludesSensitiveParameters(string parameter)
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
message.AddParameter(parameter, "secret value");
|
|
|
|
// Act and assert
|
|
var element = JsonSerializer.Deserialize<JsonElement>(message.ToString());
|
|
Assert.DoesNotContain("secret value", message.ToString());
|
|
Assert.Equal("[redacted]", element.GetProperty(parameter).GetString());
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteTo_ThrowsAnExceptionForNullWriter()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage();
|
|
|
|
// Act and assert
|
|
var exception = Assert.Throws<ArgumentNullException>(() => message.WriteTo(writer: null!));
|
|
Assert.Equal("writer", exception.ParamName);
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteTo_WritesUtf8JsonRepresentation()
|
|
{
|
|
// Arrange
|
|
var message = new OpenIddictMessage
|
|
{
|
|
["redirect_uris"] = new[] { "https://abc.org/callback" },
|
|
["client_name"] = "My Example Client"
|
|
};
|
|
|
|
using var stream = new MemoryStream();
|
|
using var writer = new Utf8JsonWriter(stream);
|
|
|
|
// Act
|
|
message.WriteTo(writer);
|
|
writer.Flush();
|
|
|
|
// Assert
|
|
Assert.Equal(@"{""redirect_uris"":[""https://abc.org/callback""],""client_name"":""My Example Client""}",
|
|
Encoding.UTF8.GetString(stream.ToArray()));
|
|
}
|
|
}
|
|
}
|
|
|