diff --git a/build.ps1 b/build.ps1 index df8d118..dd745da 100644 --- a/build.ps1 +++ b/build.ps1 @@ -5,10 +5,10 @@ Param( gci .\source -Recurse "packages.config" |% { "Restoring " + $_.FullName - .\source\.nuget\nuget.exe install $_.FullName -o .\source\packages + nuget.exe install $_.FullName -o .\source\packages } -Import-Module .\source\packages\psake.4.4.1\tools\psake.psm1 +Import-Module .\source\packages\psake.4.9.0\tools\psake if(Test-Path Env:\APPVEYOR_BUILD_NUMBER){ $buildNumber = [int]$Env:APPVEYOR_BUILD_NUMBER @@ -19,6 +19,6 @@ if(Test-Path Env:\APPVEYOR_BUILD_NUMBER){ "Build number $buildNumber" -Invoke-Psake .\default.ps1 $task -framework "4.0x64" -properties @{ buildNumber=$buildNumber; preRelease=$preRelease } +Invoke-Psake .\default.ps1 "default" -framework "4.8x64" -properties @{ buildNumber=$buildNumber; preRelease=$preRelease } Remove-Module psake \ No newline at end of file diff --git a/default.ps1 b/default.ps1 index f3b5368..de164ce 100644 --- a/default.ps1 +++ b/default.ps1 @@ -1,7 +1,7 @@ properties { $base_directory = Resolve-Path . $src_directory = "$base_directory\source" - $output_directory = "$base_directory\build" + $output_directory = "$base_directory\build\net48" $dist_directory = "$base_directory\distribution" $sln_file = "$src_directory\IdentityServer3.AccessTokenValidation.sln" $target_config = "Release" @@ -10,7 +10,7 @@ properties { $nuget_path = "$src_directory\.nuget\nuget.exe" $buildNumber = 0; - $version = "2.15.0.0" + $version = "2.15.1.0" $preRelease = $null } @@ -24,7 +24,7 @@ task Clean { } task Compile -depends UpdateVersion { - exec { msbuild /nologo /verbosity:q $sln_file /p:Configuration=$target_config /p:TargetFrameworkVersion=v4.5 } + exec { msbuild /nologo /verbosity:q $sln_file /p:Configuration=$target_config /p:TargetFrameworkVersion=v4.8 } } task RunTests -depends Compile { @@ -52,19 +52,19 @@ task UpdateVersion { } task ILMerge -depends Compile { - $input_dlls = "$output_directory\IdentityServer.v3.AccessTokenValidation.dll" + $input_dlls = "$output_directory\BIMOne.IdentityServer.v3.AccessTokenValidation.dll" Get-ChildItem -Path $output_directory -Filter *.dll | foreach-object { - # Exclude IdentityServer3.AccessTokenValidation.dll as that will be the primary assembly - if ("$_" -ne "IdentityServer3.AccessTokenValidation.dll" -and + # Exclude BIMOne.IdentityServer3.AccessTokenValidation.dll as that will be the primary assembly + if ("$_" -ne "BIMOne.IdentityServer3.AccessTokenValidation.dll" -and "$_" -ne "Owin.dll") { $input_dlls = "$input_dlls $output_directory\$_" } } - New-Item $dist_directory\lib\net45 -Type Directory - Invoke-Expression "$ilmerge_path /targetplatform:v4 /internalize:ilmerge.exclude /allowDup /target:library /out:$dist_directory\lib\net45\IdentityServer.v3.AccessTokenValidation.dll $input_dlls" + New-Item $dist_directory\lib\net48 -Type Directory + Invoke-Expression "$ilmerge_path /targetplatform:v4 /internalize:ilmerge.exclude /allowDup /target:library /out:$dist_directory\lib\net48\IdentityServer.v3.AccessTokenValidation.dll $input_dlls" } task CreateNuGetPackage -depends Compile { @@ -85,8 +85,8 @@ task CreateNuGetPackage -depends Compile { $packageVersion = $packageVersion + "-build" + $buildNumber.ToString().PadLeft(5,'0') } - New-Item $dist_directory\lib\net45 -Type Directory - copy-item $output_directory\IdentityServer3.AccessTokenValidation.* $dist_directory\lib\net45 + New-Item $dist_directory\lib\net48 -Type Directory + copy-item $output_directory\BIMOne.IdentityServer3.AccessTokenValidation.* $dist_directory\lib\net48 copy-item $src_directory\IdentityServer3.AccessTokenValidation.nuspec $dist_directory exec { . $nuget_path pack $dist_directory\IdentityServer3.AccessTokenValidation.nuspec -BasePath $dist_directory -o $dist_directory -version $packageVersion } diff --git a/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/.gitignore b/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/.gitignore new file mode 100644 index 0000000..2a0e20a --- /dev/null +++ b/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/modules.xml +/projectSettingsUpdater.xml +/contentModel.xml +/.idea.IdentityServer3.AccessTokenValidation.iml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/.name b/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/.name new file mode 100644 index 0000000..0332086 --- /dev/null +++ b/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/.name @@ -0,0 +1 @@ +IdentityServer3.AccessTokenValidation \ No newline at end of file diff --git a/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/indexLayout.xml b/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/vcs.xml b/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/source/.idea/.idea.IdentityServer3.AccessTokenValidation/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/source/.nuget/packages.config b/source/.nuget/packages.config index cb6ef5f..3f7f610 100644 --- a/source/.nuget/packages.config +++ b/source/.nuget/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/source/AccessTokenValidation.Tests/AccessTokenValidation.Tests.csproj b/source/AccessTokenValidation.Tests/AccessTokenValidation.Tests.csproj index c6bac5a..103d6e6 100644 --- a/source/AccessTokenValidation.Tests/AccessTokenValidation.Tests.csproj +++ b/source/AccessTokenValidation.Tests/AccessTokenValidation.Tests.csproj @@ -1,164 +1,29 @@ - - - - + - Debug - AnyCPU - {0243A9FA-E484-43AD-A86C-F399ED79CCF3} - Library - Properties - AccessTokenValidation.Tests - AccessTokenValidation.Tests - v4.5 - 512 - - - - - - true - full - false - ..\..\build\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true + net48 + AccessTokenValidation.Tests + Xero + AccessTokenValidation.Tests + Copyright © Xero 2014 ..\..\build\ - TRACE - prompt - 4 - - ..\packages\FluentAssertions.4.3.0\lib\net45\FluentAssertions.dll - True - - - ..\packages\FluentAssertions.4.3.0\lib\net45\FluentAssertions.Core.dll - True - - - ..\packages\IdentityModel.1.9.2\lib\net45\IdentityModel.dll - True - - - ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll - True - - - ..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll - True - - - ..\packages\Microsoft.Owin.Security.Jwt.3.0.1\lib\net45\Microsoft.Owin.Security.Jwt.dll - True - - - ..\packages\Microsoft.Owin.Security.OAuth.3.0.1\lib\net45\Microsoft.Owin.Security.OAuth.dll - True - - - ..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll - True - - - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll - True - - - False - ..\packages\Owin.1.0\lib\net40\Owin.dll - - - ..\packages\OwinHttpMessageHandler.1.3.4\lib\net45\OwinHttpMessageHandler.dll - True - - - - - ..\packages\System.IdentityModel.Tokens.Jwt.4.0.2.206221351\lib\net45\System.IdentityModel.Tokens.Jwt.dll - True - - - ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll - True - - - - - - - - ..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - True - - - ..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll - True - - - ..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll - True - - - ..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll - True - - - - - - - - - - - - - - - - - - - - - - - - {df867b5d-3a9e-443a-b95e-d8f11e2a88a3} - AccessTokenValidation - + - + + + + + + - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file diff --git a/source/AccessTokenValidation.Tests/InMemoryClaimsCacheTests.cs b/source/AccessTokenValidation.Tests/InMemoryClaimsCacheTests.cs index 0db91b2..4de1363 100644 --- a/source/AccessTokenValidation.Tests/InMemoryClaimsCacheTests.cs +++ b/source/AccessTokenValidation.Tests/InMemoryClaimsCacheTests.cs @@ -49,7 +49,7 @@ public void WhenTokenExpiryClaimExpiresBeforeClaimsCacheDuration_CacheExpiry_Sho Arrange(() => { // mimic the DateTimeOffset rounding that happens via serialisation/deserialisation in the actual implementation - ExpectedCacheExpiry = ExpiryClaimSaysTokenExpiresAt.ToEpochTime().ToDateTimeOffsetFromEpoch(); + ExpectedCacheExpiry = ExpiryClaimSaysTokenExpiresAt.ToUnixTimeSeconds().ToDateTimeFromEpoch(); }); // act @@ -84,7 +84,7 @@ void Arrange(Action specifyExpectedCacheExpiry) { CacheExpiryEvictsTokenAt = _clock.UtcNow.Add(_options.ValidationResultCacheDuration); // setup claims to include expiry claim - Claims = new[] {new Claim("bar","baz"), new Claim(ClaimTypes.Expiration,ExpiryClaimSaysTokenExpiresAt.ToEpochTime().ToString()) }; + Claims = new[] {new Claim("bar","baz"), new Claim(ClaimTypes.Expiration,ExpiryClaimSaysTokenExpiresAt.ToUnixTimeSeconds().ToString()) }; specifyExpectedCacheExpiry(); diff --git a/source/AccessTokenValidation.Tests/Integration Tests/DynamicBoth.cs b/source/AccessTokenValidation.Tests/Integration Tests/DynamicBoth.cs index 0620cef..bff748e 100644 --- a/source/AccessTokenValidation.Tests/Integration Tests/DynamicBoth.cs +++ b/source/AccessTokenValidation.Tests/Integration Tests/DynamicBoth.cs @@ -4,6 +4,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; +using IdentityModel.Client; using Xunit; namespace AccessTokenValidation.Tests.Integration_Tests diff --git a/source/AccessTokenValidation.Tests/Integration Tests/DynamicLocal.cs b/source/AccessTokenValidation.Tests/Integration Tests/DynamicLocal.cs index edae5d9..0da7cc7 100644 --- a/source/AccessTokenValidation.Tests/Integration Tests/DynamicLocal.cs +++ b/source/AccessTokenValidation.Tests/Integration Tests/DynamicLocal.cs @@ -3,8 +3,8 @@ using FluentAssertions; using IdentityServer3.AccessTokenValidation; using System.Net; -using System.Net.Http; using System.Threading.Tasks; +using IdentityModel.Client; using Xunit; namespace AccessTokenValidation.Tests.Integration_Tests @@ -29,11 +29,9 @@ public async Task WhenDelayLoadMetadataIsTrue_MetadataRetrievalIsRetriedAfterFai client.SetBearerToken(token); Func action = async () => await client.GetAsync("http://test"); - action. - ShouldThrow(). - And. - Message.Should().Contain("IDX10803"); // IDX10803: Unable to create to obtain configuration from: https://discodoc + Assert.ThrowsAsync(action) + .Result.Message.Should().Contain("IDX20803"); // IDX20803: Unable to create to obtain configuration from: https://discodoc _options.BackchannelHttpHandler = new DiscoveryEndpointHandler(); var result = await client.GetAsync("http://test"); diff --git a/source/AccessTokenValidation.Tests/Integration Tests/Introspection.cs b/source/AccessTokenValidation.Tests/Integration Tests/Introspection.cs index a4d5ca6..9d0cd57 100644 --- a/source/AccessTokenValidation.Tests/Integration Tests/Introspection.cs +++ b/source/AccessTokenValidation.Tests/Integration Tests/Introspection.cs @@ -2,8 +2,8 @@ using FluentAssertions; using IdentityServer3.AccessTokenValidation; using System.Net; -using System.Net.Http; using System.Threading.Tasks; +using IdentityModel.Client; using Xunit; namespace AccessTokenValidation.Tests.Integration_Tests diff --git a/source/AccessTokenValidation.Tests/Integration Tests/ResponseHeaders.cs b/source/AccessTokenValidation.Tests/Integration Tests/ResponseHeaders.cs index 8ca683c..54ccba2 100644 --- a/source/AccessTokenValidation.Tests/Integration Tests/ResponseHeaders.cs +++ b/source/AccessTokenValidation.Tests/Integration Tests/ResponseHeaders.cs @@ -3,44 +3,45 @@ using IdentityServer3.AccessTokenValidation; using Owin; using System; -using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; +using IdentityModel.Client; using Xunit; namespace AccessTokenValidation.Tests.Integration_Tests { public class ResponseHeaders { - IdentityServerBearerTokenAuthenticationOptions _options = new IdentityServerBearerTokenAuthenticationOptions + private readonly IdentityServerBearerTokenAuthenticationOptions _options = new IdentityServerBearerTokenAuthenticationOptions { IssuerName = TokenFactory.DefaultIssuer, SigningCertificate = new X509Certificate2(Convert.FromBase64String(TokenFactory.DefaultPublicKey)), ValidationMode = ValidationMode.Local, - RequiredScopes = new string[] { TokenFactory.Api2Scope } + RequiredScopes = new[] { TokenFactory.Api2Scope } }; [Fact] public async Task WhenCorsHeadersAreAlreadySetOnTheResponse_LeavesThemAsIs() { var client = PipelineFactory.CreateHttpClient(_options, x => - { - x.Use(async (context, next) => - { - context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "ACAO Value" }); - context.Response.Headers.Add("Access-Control-Allow-Method", new[] { "ACAM Value" }); - context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "ACAH Value" }); + { + x.Use(async (context, next) => + { + context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "ACAO Value" }); + context.Response.Headers.Add("Access-Control-Allow-Method", new[] { "ACAM Value" }); + context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "ACAH Value" }); - await next(); - }); - }); + await next(); + }); + }); - var token = TokenFactory.CreateTokenString(TokenFactory.CreateToken(scope: new string[] { TokenFactory.Api1Scope })); + string token = TokenFactory.CreateTokenString(TokenFactory.CreateToken(scope: new[] { TokenFactory.Api1Scope })); client.SetBearerToken(token); - var result = await client.GetAsync("http://test"); - var responseHeaders = result.Headers; + HttpResponseMessage result = await client.GetAsync("http://test"); + HttpResponseHeaders responseHeaders = result.Headers; responseHeaders.GetValues("Access-Control-Allow-Origin").Should().BeEquivalentTo("ACAO Value"); responseHeaders.GetValues("Access-Control-Allow-Method").Should().BeEquivalentTo("ACAM Value"); diff --git a/source/AccessTokenValidation.Tests/Integration Tests/StaticBoth.cs b/source/AccessTokenValidation.Tests/Integration Tests/StaticBoth.cs index ac28b1c..67e7ec1 100644 --- a/source/AccessTokenValidation.Tests/Integration Tests/StaticBoth.cs +++ b/source/AccessTokenValidation.Tests/Integration Tests/StaticBoth.cs @@ -6,6 +6,7 @@ using System.Net.Http; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; +using IdentityModel.Client; using Xunit; namespace AccessTokenValidation.Tests.Integration_Tests @@ -71,8 +72,8 @@ public async Task JWT_Sent_Api1_Scope_Api1_ScopeRequirements() { _options.RequiredScopes = new[] { TokenFactory.Api1Scope }; - var client = PipelineFactory.CreateHttpClient(_options); - var token = TokenFactory.CreateTokenString( + HttpClient client = PipelineFactory.CreateHttpClient(_options); + string token = TokenFactory.CreateTokenString( TokenFactory.CreateToken(scope: new[] { TokenFactory.Api1Scope })); client.SetBearerToken(token); diff --git a/source/AccessTokenValidation.Tests/Integration Tests/StaticLocal.cs b/source/AccessTokenValidation.Tests/Integration Tests/StaticLocal.cs index 5d261b7..76a70d4 100644 --- a/source/AccessTokenValidation.Tests/Integration Tests/StaticLocal.cs +++ b/source/AccessTokenValidation.Tests/Integration Tests/StaticLocal.cs @@ -3,9 +3,9 @@ using IdentityServer3.AccessTokenValidation; using System; using System.Net; -using System.Net.Http; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; +using IdentityModel.Client; using Xunit; namespace AccessTokenValidation.Tests.Integration_Tests diff --git a/source/AccessTokenValidation.Tests/Integration Tests/TokenProvider.cs b/source/AccessTokenValidation.Tests/Integration Tests/TokenProvider.cs index ce71916..818471f 100644 --- a/source/AccessTokenValidation.Tests/Integration Tests/TokenProvider.cs +++ b/source/AccessTokenValidation.Tests/Integration Tests/TokenProvider.cs @@ -1,16 +1,13 @@ using AccessTokenValidation.Tests.Util; using IdentityServer3.AccessTokenValidation; using System; -using System.Collections.Generic; -using System.Linq; using System.Security.Cryptography.X509Certificates; -using System.Text; using System.Threading.Tasks; using Xunit; using FluentAssertions; using Microsoft.Owin.Security.OAuth; using System.Net; -using System.Net.Http; +using IdentityModel.Client; namespace AccessTokenValidation.Tests.Integration_Tests { diff --git a/source/AccessTokenValidation.Tests/Properties/AssemblyInfo.cs b/source/AccessTokenValidation.Tests/Properties/AssemblyInfo.cs index 0150618..f1d10b9 100644 --- a/source/AccessTokenValidation.Tests/Properties/AssemblyInfo.cs +++ b/source/AccessTokenValidation.Tests/Properties/AssemblyInfo.cs @@ -1,18 +1,6 @@ using System.Reflection; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("AccessTokenValidation.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Xero")] -[assembly: AssemblyProduct("AccessTokenValidation.Tests")] -[assembly: AssemblyCopyright("Copyright © Xero 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. @@ -20,16 +8,3 @@ // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("647079bd-094e-4e11-abf2-0d66720c1ceb")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/source/AccessTokenValidation.Tests/Util/Cert.cs b/source/AccessTokenValidation.Tests/Util/Cert.cs index 281ce96..867b69c 100644 --- a/source/AccessTokenValidation.Tests/Util/Cert.cs +++ b/source/AccessTokenValidation.Tests/Util/Cert.cs @@ -16,7 +16,7 @@ public static X509Certificate2 Load() private static byte[] ReadStream(Stream input) { - var buffer = new byte[16 * 1024]; + byte[] buffer = new byte[16 * 1024]; using (var ms = new MemoryStream()) { int read; diff --git a/source/AccessTokenValidation.Tests/Util/TokenFactory.cs b/source/AccessTokenValidation.Tests/Util/TokenFactory.cs index 9e4515a..7133f1a 100644 --- a/source/AccessTokenValidation.Tests/Util/TokenFactory.cs +++ b/source/AccessTokenValidation.Tests/Util/TokenFactory.cs @@ -1,18 +1,18 @@ -using IdentityModel; -using System; +using System; using System.Collections.Generic; -using System.IdentityModel.Tokens; +using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Security.Cryptography.X509Certificates; +using Microsoft.IdentityModel.Tokens; namespace AccessTokenValidation.Tests.Util { - static class TokenFactory + internal static class TokenFactory { public const string DefaultIssuer = "https://issuer"; public const string DefaultAudience = "https://issuer/resources"; - public const string DefaultPublicKey = "MIIDBTCCAfGgAwIBAgIQNQb+T2ncIrNA6cKvUA1GWTAJBgUrDgMCHQUAMBIxEDAOBgNVBAMTB0RldlJvb3QwHhcNMTAwMTIwMjIwMDAwWhcNMjAwMTIwMjIwMDAwWjAVMRMwEQYDVQQDEwppZHNydjN0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqnTksBdxOiOlsmRNd+mMS2M3o1IDpK4uAr0T4/YqO3zYHAGAWTwsq4ms+NWynqY5HaB4EThNxuq2GWC5JKpO1YirOrwS97B5x9LJyHXPsdJcSikEI9BxOkl6WLQ0UzPxHdYTLpR4/O+0ILAlXw8NU4+jB4AP8Sn9YGYJ5w0fLw5YmWioXeWvocz1wHrZdJPxS8XnqHXwMUozVzQj+x6daOv5FmrHU1r9/bbp0a1GLv4BbTtSh4kMyz1hXylho0EvPg5p9YIKStbNAW9eNWvv5R8HN7PPei21AsUqxekK0oW9jnEdHewckToX7x5zULWKwwZIksll0XnVczVgy7fCFwIDAQABo1wwWjATBgNVHSUEDDAKBggrBgEFBQcDATBDBgNVHQEEPDA6gBDSFgDaV+Q2d2191r6A38tBoRQwEjEQMA4GA1UEAxMHRGV2Um9vdIIQLFk7exPNg41NRNaeNu0I9jAJBgUrDgMCHQUAA4IBAQBUnMSZxY5xosMEW6Mz4WEAjNoNv2QvqNmk23RMZGMgr516ROeWS5D3RlTNyU8FkstNCC4maDM3E0Bi4bbzW3AwrpbluqtcyMN3Pivqdxx+zKWKiORJqqLIvN8CT1fVPxxXb/e9GOdaR8eXSmB0PgNUhM4IjgNkwBbvWC9F/lzvwjlQgciR7d4GfXPYsE1vf8tmdQaY8/PtdAkExmbrb9MihdggSoGXlELrPA91Yce+fiRcKY3rQlNWVd4DOoJ/cPXsXwry8pWjNCo5JD8Q+RQ5yZEy7YPoifwemLhTdsBz3hlZr28oCGJ3kbnpW0xGvQb3VHSTVVbeei0CfXoW6iz1"; + public const string DefaultPublicKey = "MIIDGzCCAgOgAwIBAgIQH5CpsdJDH5ZJ89cWwFrMQDANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDAppZHNydjN0ZXN0MB4XDTIxMTExNzIyMjUwOVoXDTQxMTExNzIyMzUxMFowFTETMBEGA1UEAwwKaWRzcnYzdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOprPYDL9KJ2WxNjUQKzyEgI/BOHeoz9z/2IflLiK4VCVDYYLrd35tB1X1bbBxQ77M9cgA6eqS5w8uHlITMz5wNQE8NB8nOBBD6Z3uOUSYcwd7oi639wV4M9BJRhufGUFCEN1dzRfqhpDBRklYEx5RKGEbaeQHwwuMRmuzx8QQagUJ3DCclIx9OKyOzc1ipjDL1j0WI1Q61BfptelnKULaZQrLa6b1YCTgMrPyuL9pT1qDrRvNAX/uykmzN/Jt/ms4gQlqyIYcy8398QtS7XSGmuWYdoD87bOG5iBkvPqRgbA/9PbYOePujYXo0ljfm+oRdTmA1qGpAVkOsNduDOgx0CAwEAAaNnMGUwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAVBgNVHREEDjAMggppZHNydjN0ZXN0MB0GA1UdDgQWBBRqyXCUtb/Ou1Ml8gBChx4/NA2LGDANBgkqhkiG9w0BAQsFAAOCAQEAYZ3qLITEIe72vccldlsze6JM0YqvdezAigmUzNMrptQu38Jq+152Z1d23nfhvhoQN69aJaIHVSt//N1Yrnjh/hKqiuYRzSS4/7S7aWWN1RLv1DawEySZeqkfsYpJLc2oqQSlkqb/8dijRXopppS2tUYWxfgEf0FT278KK1e4Pt/iVJzBhhtI0ngqWUeR+KonLoSL+nv7cO9DZPWFfQRrcDlDcR5cmEC9g4paRP3kYT524nhMKsMeD7E8ooup3vrlG4+S3QFdZyf90cJKm46rLt0rBnc/L0uncay2wnX83N4TlaxUFMjgHSHLFw1tal7tF1DWEovG9RDO6Gbk65qpPw=="; public const string Api1Scope = "api1"; public const string Api2Scope = "api2"; @@ -45,30 +45,23 @@ public static JwtSecurityToken CreateToken( additionalClaims = new List(); } - if (scope != null && scope.Any()) - { - scope.ToList().ForEach(s => additionalClaims.Add(new Claim("scope", s))); - } - - var credential = new X509SigningCredentials(signingCertificate ?? DefaultSigningCertificate); - + scope?.ToList().ForEach(s => additionalClaims.Add(new Claim("scope", s))); + + var signingKey = new SigningCredentials(new X509SecurityKey(DefaultSigningCertificate), SecurityAlgorithms.RsaSha256Signature); var token = new JwtSecurityToken( issuer ?? DefaultIssuer, audience ?? DefaultAudience, additionalClaims, DateTime.UtcNow, DateTime.UtcNow.AddSeconds(ttl), - credential); - - token.Header.Add( - "kid", Base64Url.Encode(credential.Certificate.GetCertHash())); + signingKey); return token; } public static string CreateTokenString(JwtSecurityToken token) { - JwtSecurityTokenHandler.OutboundClaimTypeMap = new Dictionary(); + JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap = new Dictionary(); var handler = new JwtSecurityTokenHandler(); return handler.WriteToken(token); diff --git a/source/AccessTokenValidation.Tests/Util/idsrv3test.pfx b/source/AccessTokenValidation.Tests/Util/idsrv3test.pfx index 0247dea..a8dee29 100644 Binary files a/source/AccessTokenValidation.Tests/Util/idsrv3test.pfx and b/source/AccessTokenValidation.Tests/Util/idsrv3test.pfx differ diff --git a/source/AccessTokenValidation.Tests/app.config b/source/AccessTokenValidation.Tests/app.config deleted file mode 100644 index 587f735..0000000 --- a/source/AccessTokenValidation.Tests/app.config +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/AccessTokenValidation.Tests/packages.config b/source/AccessTokenValidation.Tests/packages.config deleted file mode 100644 index 472d8e2..0000000 --- a/source/AccessTokenValidation.Tests/packages.config +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/AccessTokenValidation/AccessTokenValidation.csproj b/source/AccessTokenValidation/AccessTokenValidation.csproj index 1387153..e2b75a0 100644 --- a/source/AccessTokenValidation/AccessTokenValidation.csproj +++ b/source/AccessTokenValidation/AccessTokenValidation.csproj @@ -1,130 +1,28 @@ - - - + - Debug - AnyCPU - {DF867B5D-3A9E-443A-B95E-D8F11E2A88A3} - Library - Properties IdentityServer3.AccessTokenValidation - IdentityServer3.AccessTokenValidation - v4.5 - 512 - - - true - full - false - ..\..\build\ - DEBUG;TRACE - prompt - 4 - ..\..\build\IdentityServer3.AccessTokenValidation.xml - - - pdbonly - true + BIMOne.IdentityServer3.AccessTokenValidation + net48 + ..\..\build\BIMOne.IdentityServer3.AccessTokenValidation.xml ..\..\build\ - TRACE - prompt - 4 - ..\..\build\IdentityServer3.AccessTokenValidation.xml + false - - ..\packages\IdentityModel.1.9.2\lib\net45\IdentityModel.dll - True - - - ..\packages\Microsoft.IdentityModel.Protocol.Extensions.1.0.2.206221351\lib\net45\Microsoft.IdentityModel.Protocol.Extensions.dll - True - - - ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll - True - - - ..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll - True - - - ..\packages\Microsoft.Owin.Security.Jwt.3.0.1\lib\net45\Microsoft.Owin.Security.Jwt.dll - True - - - ..\packages\Microsoft.Owin.Security.OAuth.3.0.1\lib\net45\Microsoft.Owin.Security.OAuth.dll - True - - - ..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll - True - - - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll - True - - - ..\packages\Owin.1.0\lib\net40\Owin.dll - True - - - - - - ..\packages\System.IdentityModel.Tokens.Jwt.4.0.2.206221351\lib\net45\System.IdentityModel.Tokens.Jwt.dll - True - - - - False - ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - default.licenseheader - - + + + + + + + + + - - \ No newline at end of file diff --git a/source/AccessTokenValidation/AccessTokenValidation.csproj.DotSettings b/source/AccessTokenValidation/AccessTokenValidation.csproj.DotSettings new file mode 100644 index 0000000..f6eb9d9 --- /dev/null +++ b/source/AccessTokenValidation/AccessTokenValidation.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/source/AccessTokenValidation/IdentityServerBearerTokenAuthenticationOptions.cs b/source/AccessTokenValidation/IdentityServerBearerTokenAuthenticationOptions.cs index eaef64c..367add5 100644 --- a/source/AccessTokenValidation/IdentityServerBearerTokenAuthenticationOptions.cs +++ b/source/AccessTokenValidation/IdentityServerBearerTokenAuthenticationOptions.cs @@ -18,10 +18,10 @@ using Microsoft.Owin.Security.OAuth; using System; using System.Collections.Generic; -using System.IdentityModel.Tokens; using System.Linq; using System.Net.Http; using System.Security.Cryptography.X509Certificates; +using Microsoft.IdentityModel.Tokens; namespace IdentityServer3.AccessTokenValidation { diff --git a/source/AccessTokenValidation/IdentityServerBearerTokenValidationAppBuilderExtensions.cs b/source/AccessTokenValidation/IdentityServerBearerTokenValidationAppBuilderExtensions.cs index 8f44eee..f5eeaa9 100644 --- a/source/AccessTokenValidation/IdentityServerBearerTokenValidationAppBuilderExtensions.cs +++ b/source/AccessTokenValidation/IdentityServerBearerTokenValidationAppBuilderExtensions.cs @@ -20,9 +20,10 @@ using Microsoft.Owin.Security.Jwt; using Microsoft.Owin.Security.OAuth; using System; -using System.IdentityModel.Tokens; using System.Linq; +using System.Security.Cryptography.X509Certificates; using System.Threading; +using Microsoft.IdentityModel.Tokens; namespace Owin { @@ -141,20 +142,21 @@ internal static Lazy ConfigureLocalValidation( { return new Lazy(() => { - JwtFormat tokenFormat = null; + JwtFormat tokenFormat; // use static configuration if (!string.IsNullOrWhiteSpace(options.IssuerName) && options.SigningCertificate != null) { - var audience = options.IssuerName.EnsureTrailingSlash(); + string audience = options.IssuerName.EnsureTrailingSlash(); audience += "resources"; + Microsoft.IdentityModel.Tokens.SecurityKey securityKey = new X509SecurityKey(new X509Certificate2(options.SigningCertificate)); var valParams = new TokenValidationParameters { ValidIssuer = options.IssuerName, ValidAudience = audience, - IssuerSigningToken = new X509SecurityToken(options.SigningCertificate), + IssuerSigningKey = securityKey, NameClaimType = options.NameClaimType, RoleClaimType = options.RoleClaimType, @@ -191,7 +193,7 @@ internal static Lazy ConfigureLocalValidation( } else { - valParams.IssuerSigningKeyResolver = ResolveRsaKeys; + valParams.IssuerSigningKeyResolver = options.IssuerSigningKeyResolver; } tokenFormat = new JwtFormat(valParams, issuerProvider); @@ -210,30 +212,5 @@ internal static Lazy ConfigureLocalValidation( }, LazyThreadSafetyMode.PublicationOnly); } - - private static SecurityKey ResolveRsaKeys( - string token, - SecurityToken securityToken, - SecurityKeyIdentifier keyIdentifier, - TokenValidationParameters validationParameters) - { - string id = null; - foreach (var keyId in keyIdentifier) - { - var nk = keyId as NamedKeySecurityKeyIdentifierClause; - if (nk != null) - { - id = nk.Id; - break; - } - } - - if (id == null) return null; - - var issuerToken = validationParameters.IssuerSigningTokens.FirstOrDefault(it => it.Id == id); - if (issuerToken == null) return null; - - return issuerToken.SecurityKeys.FirstOrDefault(); - } } } \ No newline at end of file diff --git a/source/AccessTokenValidation/Plumbing/DiscoveryDocumentIssuerSecurityTokenProvider.cs b/source/AccessTokenValidation/Plumbing/DiscoveryDocumentIssuerSecurityTokenProvider.cs index 75c7711..9c8c6aa 100644 --- a/source/AccessTokenValidation/Plumbing/DiscoveryDocumentIssuerSecurityTokenProvider.cs +++ b/source/AccessTokenValidation/Plumbing/DiscoveryDocumentIssuerSecurityTokenProvider.cs @@ -19,20 +19,20 @@ using Microsoft.Owin.Security.Jwt; using System; using System.Collections.Generic; -using System.IdentityModel.Tokens; using System.Net.Http; -using System.Security.Cryptography; using System.Threading; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Microsoft.IdentityModel.Tokens; namespace IdentityServer3.AccessTokenValidation { - internal class DiscoveryDocumentIssuerSecurityTokenProvider : IIssuerSecurityTokenProvider + internal class DiscoveryDocumentIssuerSecurityTokenProvider : IIssuerSecurityKeyProvider { private readonly ReaderWriterLockSlim _synclock = new ReaderWriterLockSlim(); private readonly ConfigurationManager _configurationManager; private readonly ILogger _logger; private string _issuer; - private IEnumerable _tokens; + private ICollection _keys; public DiscoveryDocumentIssuerSecurityTokenProvider(string discoveryEndpoint, IdentityServerBearerTokenAuthenticationOptions options, ILoggerFactory loggerFactory) { @@ -51,7 +51,7 @@ public DiscoveryDocumentIssuerSecurityTokenProvider(string discoveryEndpoint, Id webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate; } - _configurationManager = new ConfigurationManager(discoveryEndpoint, new HttpClient(handler)) + _configurationManager = new ConfigurationManager(discoveryEndpoint, new OpenIdConnectConfigurationRetriever(), new HttpClient(handler)) { AutomaticRefreshInterval = options.AutomaticRefreshInterval }; @@ -96,7 +96,7 @@ public string Audience _synclock.EnterReadLock(); try { - var issuer = _issuer.EnsureTrailingSlash(); + string issuer = _issuer.EnsureTrailingSlash(); return issuer + "resources"; } finally @@ -106,13 +106,7 @@ public string Audience } } - /// - /// Gets all known security tokens. - /// - /// - /// All known security tokens. - /// - public IEnumerable SecurityTokens + public IEnumerable SecurityKeys { get { @@ -120,7 +114,7 @@ public IEnumerable SecurityTokens _synclock.EnterReadLock(); try { - return _tokens; + return _keys; } finally { @@ -134,7 +128,7 @@ private void RetrieveMetadata() _synclock.EnterWriteLock(); try { - var result = AsyncHelper.RunSync(async () => await _configurationManager.GetConfigurationAsync()); + OpenIdConnectConfiguration result = AsyncHelper.RunSync(async () => await _configurationManager.GetConfigurationAsync()); if (result.JsonWebKeySet == null) { @@ -142,21 +136,8 @@ private void RetrieveMetadata() throw new InvalidOperationException("Discovery document has no configured signing key. aborting."); } - var tokens = new List(); - foreach (var key in result.JsonWebKeySet.Keys) - { - var rsa = RSA.Create(); - rsa.ImportParameters(new RSAParameters - { - Exponent = Base64UrlEncoder.DecodeBytes(key.E), - Modulus = Base64UrlEncoder.DecodeBytes(key.N) - }); - - tokens.Add(new RsaSecurityToken(rsa, key.Kid)); - } - _issuer = result.Issuer; - _tokens = tokens; + _keys = result.SigningKeys; } catch (Exception ex) { diff --git a/source/AccessTokenValidation/Plumbing/IntrospectionEndpointTokenProvider.cs b/source/AccessTokenValidation/Plumbing/IntrospectionEndpointTokenProvider.cs index f2e4eb2..203660a 100644 --- a/source/AccessTokenValidation/Plumbing/IntrospectionEndpointTokenProvider.cs +++ b/source/AccessTokenValidation/Plumbing/IntrospectionEndpointTokenProvider.cs @@ -18,10 +18,8 @@ using Microsoft.Owin.Logging; using Microsoft.Owin.Security; using Microsoft.Owin.Security.Infrastructure; -using Newtonsoft.Json; using System; using System.Collections.Generic; -using System.Net; using System.Net.Http; using System.Security.Claims; using System.Threading.Tasks; @@ -43,11 +41,12 @@ public IntrospectionEndpointTokenProvider(IdentityServerBearerTokenAuthenticatio throw new Exception("Authority must be set to use validation endpoint."); } - var baseAddress = options.Authority.EnsureTrailingSlash(); + string baseAddress = options.Authority.EnsureTrailingSlash(); baseAddress += "connect/introspect"; - var introspectionEndpoint = baseAddress; + string introspectionEndpoint = baseAddress; - var handler = options.IntrospectionHttpHandler ?? new WebRequestHandler(); + HttpMessageHandler handler = options.IntrospectionHttpHandler ?? new WebRequestHandler(); + var invoker = new HttpMessageInvoker(handler); if (options.BackchannelCertificateValidator != null) { @@ -60,20 +59,26 @@ public IntrospectionEndpointTokenProvider(IdentityServerBearerTokenAuthenticatio webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate; } - + if (!string.IsNullOrEmpty(options.ClientId)) { _client = new IntrospectionClient( - introspectionEndpoint, - options.ClientId, - options.ClientSecret, - handler); + invoker, + new IntrospectionClientOptions() + { + Address = introspectionEndpoint, + ClientId = options.ClientId, + ClientSecret = options.ClientSecret + }); } else { _client = new IntrospectionClient( - introspectionEndpoint, - innerHttpMessageHandler: handler); + invoker, + new IntrospectionClientOptions + { + Address = introspectionEndpoint + }); } _options = options; @@ -91,10 +96,10 @@ public override async Task ReceiveAsync(AuthenticationTokenReceiveContext contex } } - IntrospectionResponse response; + TokenIntrospectionResponse response; try { - response = await _client.SendAsync(new IntrospectionRequest { Token = context.Token }); + response = await _client.Introspect(context.Token); if (response.IsError) { _logger.WriteError("Error returned from introspection endpoint: " + response.Error); @@ -113,11 +118,11 @@ public override async Task ReceiveAsync(AuthenticationTokenReceiveContext contex } var claims = new List(); - foreach (var claim in response.Claims) + foreach (Claim claim in response.Claims) { - if (!string.Equals(claim.Item1, "active", StringComparison.Ordinal)) + if (!string.Equals(claim.Type, "active", StringComparison.Ordinal)) { - claims.Add(new Claim(claim.Item1, claim.Item2)); + claims.Add(new Claim(claim.Type, claim.Value)); } } diff --git a/source/AccessTokenValidation/Plumbing/ValidationEndpointTokenProvider.cs b/source/AccessTokenValidation/Plumbing/ValidationEndpointTokenProvider.cs index 39aa72d..b04d1e9 100644 --- a/source/AccessTokenValidation/Plumbing/ValidationEndpointTokenProvider.cs +++ b/source/AccessTokenValidation/Plumbing/ValidationEndpointTokenProvider.cs @@ -14,7 +14,6 @@ * limitations under the License. */ -using IdentityModel.Extensions; using Microsoft.Owin.Logging; using Microsoft.Owin.Security; using Microsoft.Owin.Security.Infrastructure; @@ -25,6 +24,7 @@ using System.Net.Http; using System.Security.Claims; using System.Threading.Tasks; +using IdentityModel; namespace IdentityServer3.AccessTokenValidation { diff --git a/source/AccessTokenValidation/Properties/AssemblyInfo.cs b/source/AccessTokenValidation/Properties/AssemblyInfo.cs index 3d09885..866f4a7 100644 --- a/source/AccessTokenValidation/Properties/AssemblyInfo.cs +++ b/source/AccessTokenValidation/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright 2015 Dominick Baier, Brock Allen * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,7 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("Access Toke Validation Middleware for IdentityServer3")] +[assembly: AssemblyTitle("Access Token Validation Middleware for IdentityServer3")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] @@ -43,9 +43,4 @@ // Minor Version // Build Number // Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +// \ No newline at end of file diff --git a/source/AccessTokenValidation/packages.config b/source/AccessTokenValidation/packages.config deleted file mode 100644 index 2578a68..0000000 --- a/source/AccessTokenValidation/packages.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/IdentityServer3.AccessTokenValidation.nuspec b/source/IdentityServer3.AccessTokenValidation.nuspec index 6fddcf2..9d679f0 100644 --- a/source/IdentityServer3.AccessTokenValidation.nuspec +++ b/source/IdentityServer3.AccessTokenValidation.nuspec @@ -1,17 +1,17 @@ - IdentityServer3.AccessTokenValidation + BIMOne.IdentityServer3.AccessTokenValidation 0.0.0 - IdentityServer3 - Access Token Validation - Brock Allen, Dominick Baier + IdentityServer3 - Access Token Validation (Upgraded for BIM Track) + BIM One Brock Allen, Dominick Baier - https://github.com/identityserver/IdentityServer3.AccessTokenValidation + https://github.com/bimone/IdentityServer3.AccessTokenValidation https://identityserver.github.io/Documentation/assets/images/icons/IDserver_icon128.jpg false https://github.com/IdentityServer/IdentityServer3.AccessTokenValidation/blob/master/LICENSE Access token validation middleware for JWT and reference tokens issued by IdentityServer3. - Copyright 2015 + Copyright 2021 IdentityServer OpenID Connect OpenIDConnect OAuth2 OWIN ASP.NET Katana WebApi SSO Federation Claims Identity JWT token @@ -20,13 +20,11 @@ - - - - - - - + + + + + diff --git a/source/IdentityServer3.AccessTokenValidation.sln.DotSettings b/source/IdentityServer3.AccessTokenValidation.sln.DotSettings new file mode 100644 index 0000000..4ff30ed --- /dev/null +++ b/source/IdentityServer3.AccessTokenValidation.sln.DotSettings @@ -0,0 +1,3 @@ + + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> \ No newline at end of file