diff --git a/.gitignore b/.gitignore index cffd936..8fc0f31 100644 --- a/.gitignore +++ b/.gitignore @@ -153,3 +153,4 @@ distribution/ #Roslyn compiler temp folders *.sln.ide/ +source/IdentityServer3.AccessTokenValidation.sln.GhostDoc.xml diff --git a/README.md b/README.md index 6c16606..30de880 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ You can either validate the tokens locally (JWTs only) or use the IdentityServer ```csharp app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions { - Authority = "https://identityserver.io" + Authority = "https://identity.identityserver.io" }); ``` @@ -20,7 +20,7 @@ The middleware can also do the scope validation in one go. ```csharp app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions { - Authority = "https://identityserver.io", + Authority = "https://identity.identityserver.io", RequiredScopes = new[] { "api1", "api2" } }); ``` diff --git a/default.ps1 b/default.ps1 index 16ac260..5f84f0f 100644 --- a/default.ps1 +++ b/default.ps1 @@ -3,7 +3,7 @@ properties { $src_directory = "$base_directory\source" $output_directory = "$base_directory\build" $dist_directory = "$base_directory\distribution" - $sln_file = "$src_directory\Thinktecture.IdentityServer3.AccessTokenValidation.sln" + $sln_file = "$src_directory\IdentityServer3.AccessTokenValidation.sln" $target_config = "Release" $framework_version = "v4.5" $xunit_path = "$src_directory\packages\xunit.runners.1.9.2\tools\xunit.console.clr4.exe" @@ -11,7 +11,7 @@ properties { $nuget_path = "$src_directory\.nuget\nuget.exe" $buildNumber = 0; - $version = "1.2.3.0" + $version = "2.0.0.0" $preRelease = $null } @@ -53,19 +53,19 @@ task UpdateVersion { } task ILMerge -depends Compile { - $input_dlls = "$output_directory\Thinktecture.IdentityServer.v3.AccessTokenValidation.dll" + $input_dlls = "$output_directory\IdentityServer.v3.AccessTokenValidation.dll" Get-ChildItem -Path $output_directory -Filter *.dll | foreach-object { - # Exclude Thinktecture.IdentityServer.Core.dll as that will be the primary assembly - if ("$_" -ne "Thinktecture.IdentityServer.v3.AccessTokenValidation.dll" -and + # Exclude IdentityServer3.AccessTokenValidation.dll as that will be the primary assembly + if ("$_" -ne "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\Thinktecture.IdentityServer.v3.AccessTokenValidation.dll $input_dlls" + Invoke-Expression "$ilmerge_path /targetplatform:v4 /internalize:ilmerge.exclude /allowDup /target:library /out:$dist_directory\lib\net45\IdentityServer.v3.AccessTokenValidation.dll $input_dlls" } task CreateNuGetPackage -depends Compile { @@ -87,8 +87,8 @@ task CreateNuGetPackage -depends Compile { } New-Item $dist_directory\lib\net45 -Type Directory - copy-item $output_directory\Thinktecture.IdentityServer3.AccessTokenValidation.* $dist_directory\lib\net45 + copy-item $output_directory\IdentityServer3.AccessTokenValidation.* $dist_directory\lib\net45 - copy-item $src_directory\Thinktecture.IdentityServer3.AccessTokenValidation.nuspec $dist_directory - exec { . $nuget_path pack $dist_directory\Thinktecture.IdentityServer3.AccessTokenValidation.nuspec -BasePath $dist_directory -o $dist_directory -version $packageVersion } + 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/mygetpush.cmd b/mygetpush.cmd index abe28bc..6166665 100644 --- a/mygetpush.cmd +++ b/mygetpush.cmd @@ -1 +1 @@ -nuget push distribution\*.nupkg -Source https://www.myget.org/F/thinktecture/ +nuget push distribution\*.nupkg -Source https://www.myget.org/F/identity/ diff --git a/source/AccessTokenValidation.Tests/AccessTokenValidation.Tests.csproj b/source/AccessTokenValidation.Tests/AccessTokenValidation.Tests.csproj index 317974b..ea6eadd 100644 --- a/source/AccessTokenValidation.Tests/AccessTokenValidation.Tests.csproj +++ b/source/AccessTokenValidation.Tests/AccessTokenValidation.Tests.csproj @@ -33,24 +33,33 @@ 4 - - False - ..\packages\FluentAssertions.3.2.2\lib\net45\FluentAssertions.dll + + ..\packages\FluentAssertions.3.4.1\lib\net45\FluentAssertions.dll + True - - False - ..\packages\FluentAssertions.3.2.2\lib\net45\FluentAssertions.Core.dll + + ..\packages\FluentAssertions.3.4.1\lib\net45\FluentAssertions.Core.dll + True - + + ..\packages\IdentityModel.1.0.0\lib\net45\IdentityModel.Net45.dll + True + + False - ..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll + ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll - + False - ..\packages\Microsoft.Owin.Security.3.0.0\lib\net45\Microsoft.Owin.Security.dll + ..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll - - ..\packages\Moq.4.2.1409.1722\lib\net40\Moq.dll + + ..\packages\Moq.4.2.1507.0118\lib\net40\Moq.dll + True + + + False + ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll False @@ -59,15 +68,12 @@ + - - False - ..\packages\Thinktecture.IdentityModel.Core.1.3.0\lib\net45\Thinktecture.IdentityModel.Core.dll - ..\packages\xunit.1.9.2\lib\net20\xunit.dll @@ -77,6 +83,7 @@ + diff --git a/source/AccessTokenValidation.Tests/InMemoryClaimsCacheTests.cs b/source/AccessTokenValidation.Tests/InMemoryClaimsCacheTests.cs index 2d11ba8..0db91b2 100644 --- a/source/AccessTokenValidation.Tests/InMemoryClaimsCacheTests.cs +++ b/source/AccessTokenValidation.Tests/InMemoryClaimsCacheTests.cs @@ -1,9 +1,9 @@ -using Moq; +using IdentityModel; +using IdentityServer3.AccessTokenValidation; +using Moq; using System; using System.Collections.Generic; using System.Security.Claims; -using Thinktecture.IdentityModel.Extensions; -using Thinktecture.IdentityServer.AccessTokenValidation; using Xunit; namespace AccessTokenValidation.Tests diff --git a/source/AccessTokenValidation.Tests/app.config b/source/AccessTokenValidation.Tests/app.config new file mode 100644 index 0000000..8f9af70 --- /dev/null +++ b/source/AccessTokenValidation.Tests/app.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/AccessTokenValidation.Tests/packages.config b/source/AccessTokenValidation.Tests/packages.config index 4de2f7d..42d4f8d 100644 --- a/source/AccessTokenValidation.Tests/packages.config +++ b/source/AccessTokenValidation.Tests/packages.config @@ -1,11 +1,12 @@  - - - - + + + + + + - \ No newline at end of file diff --git a/source/AccessTokenValidation/AccessTokenValidation.csproj b/source/AccessTokenValidation/AccessTokenValidation.csproj index 49a37df..9127837 100644 --- a/source/AccessTokenValidation/AccessTokenValidation.csproj +++ b/source/AccessTokenValidation/AccessTokenValidation.csproj @@ -7,8 +7,8 @@ {DF867B5D-3A9E-443A-B95E-D8F11E2A88A3} Library Properties - Thinktecture.IdentityServer.AccessTokenValidation - Thinktecture.IdentityServer3.AccessTokenValidation + IdentityServer3.AccessTokenValidation + IdentityServer3.AccessTokenValidation v4.5 512 @@ -20,7 +20,7 @@ DEBUG;TRACE prompt 4 - ..\..\build\Thinktecture.IdentityServer3.AccessTokenValidation.XML + ..\..\build\IdentityServer3.AccessTokenValidation.xml pdbonly @@ -29,43 +29,48 @@ TRACE prompt 4 - ..\..\build\Thinktecture.IdentityServer3.AccessTokenValidation.XML + ..\..\build\IdentityServer3.AccessTokenValidation.xml - False - ..\packages\Microsoft.IdentityModel.Protocol.Extensions.1.0.1\lib\net45\Microsoft.IdentityModel.Protocol.Extensions.dll + ..\packages\Microsoft.IdentityModel.Protocol.Extensions.1.0.0\lib\net45\Microsoft.IdentityModel.Protocol.Extensions.dll + True - + ..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll + True - + ..\packages\Microsoft.Owin.Security.3.0.0\lib\net45\Microsoft.Owin.Security.dll + True - + ..\packages\Microsoft.Owin.Security.Jwt.3.0.0\lib\net45\Microsoft.Owin.Security.Jwt.dll + True - + ..\packages\Microsoft.Owin.Security.OAuth.3.0.0\lib\net45\Microsoft.Owin.Security.OAuth.dll + True False ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll - + ..\packages\Owin.1.0\lib\net40\Owin.dll + True - False - ..\packages\System.IdentityModel.Tokens.Jwt.4.0.1\lib\net45\System.IdentityModel.Tokens.Jwt.dll + ..\packages\System.IdentityModel.Tokens.Jwt.4.0.0\lib\net45\System.IdentityModel.Tokens.Jwt.dll + True - + False - ..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll @@ -76,27 +81,31 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + + - - default.licenseheader + diff --git a/source/AccessTokenValidation/IdentityServerAccessTokenValidationAppBuilderExtensions.cs b/source/AccessTokenValidation/IdentityServerAccessTokenValidationAppBuilderExtensions.cs deleted file mode 100644 index 4ea258d..0000000 --- a/source/AccessTokenValidation/IdentityServerAccessTokenValidationAppBuilderExtensions.cs +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2015 Dominick Baier, Brock Allen - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using Microsoft.Owin.Security.Jwt; -using Microsoft.Owin.Security.OAuth; -using System; -using System.IdentityModel.Tokens; -using System.Linq; -using Thinktecture.IdentityServer.AccessTokenValidation; - -namespace Owin -{ - /// - /// Extension method for wiring up the access token validation middleware to the OWIN pipeline - /// - public static class IdentityServerAccessTokenValidationAppBuilderExtensions - { - /// - /// Adds the access token validation middleware to the OWIN pipeline. - /// - /// The application. - /// The options. - /// - /// options - public static IAppBuilder UseIdentityServerBearerTokenAuthentication(this IAppBuilder app, IdentityServerBearerTokenAuthenticationOptions options) - { - if (options == null) - { - throw new ArgumentNullException("options"); - } - - if (options.ValidationMode == ValidationMode.Local) - { - app.UseLocalValidation(options); - } - else if (options.ValidationMode == ValidationMode.ValidationEndpoint) - { - app.UseValidationEndpoint(options); - } - - if (options.RequiredScopes.Any()) - { - app.Use(options.RequiredScopes); - } - - return app; - } - - internal static void UseLocalValidation(this IAppBuilder app, IdentityServerBearerTokenAuthenticationOptions options) - { - JwtFormat tokenFormat = null; - - // use discovery document to fully configure middleware - if (!string.IsNullOrEmpty(options.Authority)) - { - var discoveryEndpoint = options.Authority.EnsureTrailingSlash(); - discoveryEndpoint += ".well-known/openid-configuration"; - - var issuerProvider = new CachingDiscoveryIssuerSecurityTokenProvider( - discoveryEndpoint, - options); - - if (options.TokenValidationParameters != null) - { - tokenFormat = new JwtFormat(options.TokenValidationParameters, issuerProvider); - } - else - { - var valParams = new TokenValidationParameters - { - ValidAudience = issuerProvider.Audience, - NameClaimType = options.NameClaimType, - RoleClaimType = options.RoleClaimType - }; - - tokenFormat = new JwtFormat(valParams, issuerProvider); - } - } - // use token validation parameters - else if (options.TokenValidationParameters != null) - { - tokenFormat = new JwtFormat(options.TokenValidationParameters); - } - // use simplified manual configuration - else - { - var valParams = new TokenValidationParameters - { - ValidIssuer = options.IssuerName, - ValidAudience = options.IssuerName.EnsureTrailingSlash() + "resources", - IssuerSigningToken = new X509SecurityToken(options.IssuerCertificate), - NameClaimType = options.NameClaimType, - RoleClaimType = options.RoleClaimType - }; - - tokenFormat = new JwtFormat(valParams); - } - - if (options.TokenHandler != null) - { - tokenFormat.TokenHandler = options.TokenHandler; - } - - var bearerOptions = new OAuthBearerAuthenticationOptions - { - Provider = options.Provider, - AccessTokenFormat = tokenFormat, - AuthenticationMode = options.AuthenticationMode, - AuthenticationType = options.AuthenticationType, - Description = options.Description - }; - - app.UseOAuthBearerAuthentication(bearerOptions); - } - - internal static void UseValidationEndpoint(this IAppBuilder app, IdentityServerBearerTokenAuthenticationOptions options) - { - if (options.EnableValidationResultCache) - { - if (options.ValidationResultCache == null) - { - options.ValidationResultCache = new InMemoryValidationResultCache(options); - } - } - - app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions - { - AccessTokenProvider = new ValidationEndpointTokenProvider(options), - Provider = options.Provider - }); - } - } -} \ No newline at end of file diff --git a/source/AccessTokenValidation/IdentityServerBearerTokensAuthenticationOptions.cs b/source/AccessTokenValidation/IdentityServerBearerTokenAuthenticationOptions.cs similarity index 52% rename from source/AccessTokenValidation/IdentityServerBearerTokensAuthenticationOptions.cs rename to source/AccessTokenValidation/IdentityServerBearerTokenAuthenticationOptions.cs index a5fa250..f8f0f71 100644 --- a/source/AccessTokenValidation/IdentityServerBearerTokensAuthenticationOptions.cs +++ b/source/AccessTokenValidation/IdentityServerBearerTokenAuthenticationOptions.cs @@ -18,15 +18,13 @@ 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; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { /// - /// Options class for configuring the access token validation middleware + /// Configures identity server token validation /// public class IdentityServerBearerTokenAuthenticationOptions : AuthenticationOptions { @@ -35,19 +33,24 @@ public class IdentityServerBearerTokenAuthenticationOptions : AuthenticationOpti /// public IdentityServerBearerTokenAuthenticationOptions() : base("Bearer") { - ValidationMode = ValidationMode.ValidationEndpoint; - RequiredScopes = Enumerable.Empty(); - - ValidationResultCacheDuration = TimeSpan.FromMinutes(5); - NameClaimType = "name"; RoleClaimType = "role"; + + ValidationMode = ValidationMode.Both; + RequiredScopes = Enumerable.Empty(); + ValidationResultCacheDuration = TimeSpan.FromMinutes(5); } - // common for local and validation endpoint + /// + /// Gets or sets the base address of identity server (required) + /// + /// + /// The authority. + /// + public string Authority { get; set; } /// - /// Gets or sets the validation mode (either local for JWT tokens, or using the validation endpoint for both JWT and reference tokens. + /// Gets or sets the validation mode. /// /// /// The validation mode. @@ -55,20 +58,20 @@ public IdentityServerBearerTokenAuthenticationOptions() : base("Bearer") public ValidationMode ValidationMode { get; set; } /// - /// Gets or sets the base adress of IdentityServer - this is used to construct the URLs to the discovery document and the validation endpoint + /// Gets or sets the backchannel HTTP handler. /// /// - /// The authority. + /// The backchannel HTTP handler. /// - public string Authority { get; set; } + public WebRequestHandler BackchannelHttpHandler { get; set; } /// - /// Gets or sets one of the required scopes to access the API + /// Gets or sets the backchannel certificate validator. /// /// - /// The required scopes. + /// The backchannel certificate validator. /// - public IEnumerable RequiredScopes { get; set; } + public ICertificateValidator BackchannelCertificateValidator { get; set; } /// /// Gets or sets the type of the name claim. @@ -87,78 +90,43 @@ public IdentityServerBearerTokenAuthenticationOptions() : base("Bearer") public string RoleClaimType { get; set; } /// - /// Gets or sets the name of the issuer (only use if authority is not set). + /// Gets or sets the token provider. /// /// - /// The name of the issuer. + /// The token provider. /// - public string IssuerName { get; set; } + public IOAuthBearerAuthenticationProvider TokenProvider { get; set; } /// - /// Gets or sets the issuer certificate (only used if authority is not set). + /// Gets or sets the duration of the validation result cache. /// /// - /// The issuer certificate. + /// The duration of the validation result cache. /// - public X509Certificate2 IssuerCertificate { get; set; } + public TimeSpan ValidationResultCacheDuration { get; set; } /// - /// Gets or sets a value indicating whether the result of the validation endpoint should be cached. + /// Gets or sets a value indicating whether to enable validation result caching. /// /// - /// true if caching should be enabled; otherwise, false. + /// true if [enable validation result cache]; otherwise, false. /// public bool EnableValidationResultCache { get; set; } /// - /// Gets or sets the claims cache implementation (defaults to in-memory). + /// Gets or sets the validation result cache. /// /// - /// The claims cache. + /// The validation result cache. /// public IValidationResultCache ValidationResultCache { get; set; } /// - /// Specifies for how long the validation results should be cached. - /// - /// - /// The duration of the claims cache. - /// - public TimeSpan ValidationResultCacheDuration { get; set; } - - /// - /// Gets or sets the authentication provider. + /// Gets or sets the required scopes. /// /// - /// The provider. - /// - public IOAuthBearerAuthenticationProvider Provider { get; set; } - - /// - /// Gets or sets the a certificate validator to use to validate the metadata endpoint. - /// - /// - /// The certificate validator. + /// The required scopes. /// - /// If this property is null then the default certificate checks are performed, - /// validating the subject name and if the signing chain is a trusted party. - public ICertificateValidator BackchannelCertificateValidator { get; set; } - - /// - /// The HttpMessageHandler used to communicate with the metadata endpoint. - /// This cannot be set at the same time as BackchannelCertificateValidator unless the value - /// can be downcast to a WebRequestHandler. - /// - public HttpMessageHandler BackchannelHttpHandler { get; set; } - - /// - /// Gets or sets the used to determine if a token is valid. - /// - public TokenValidationParameters TokenValidationParameters { get; set; } - - /// - /// A System.IdentityModel.Tokens.SecurityTokenHandler designed for creating and validating Json Web Tokens. - /// - public JwtSecurityTokenHandler TokenHandler { get; set; } + public IEnumerable RequiredScopes { get; set; } } } \ No newline at end of file diff --git a/source/AccessTokenValidation/IdentityServerBearerTokenValidationAppBuilderExtensions.cs b/source/AccessTokenValidation/IdentityServerBearerTokenValidationAppBuilderExtensions.cs new file mode 100644 index 0000000..3bfa289 --- /dev/null +++ b/source/AccessTokenValidation/IdentityServerBearerTokenValidationAppBuilderExtensions.cs @@ -0,0 +1,125 @@ +/* + * Copyright 2015 Dominick Baier, Brock Allen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using IdentityServer3.AccessTokenValidation; +using Microsoft.Owin.Logging; +using Microsoft.Owin.Security.Jwt; +using Microsoft.Owin.Security.OAuth; +using System; +using System.IdentityModel.Tokens; +using System.Linq; + +namespace Owin +{ + /// + /// AppBuilder extensions for identity server token validation + /// + public static class IdentityServerBearerTokenValidationAppBuilderExtensions + { + /// + /// Add identity server token authentication to the pipeline. + /// + /// The application. + /// The options. + /// + public static IAppBuilder UseIdentityServerBearerTokenAuthentication(this IAppBuilder app, IdentityServerBearerTokenAuthenticationOptions options) + { + if (app == null) throw new ArgumentNullException("app"); + if (options == null) throw new ArgumentNullException("options"); + if (string.IsNullOrEmpty(options.Authority)) throw new ArgumentException("Authority must be set", "authority"); + + var loggerFactory = app.GetLoggerFactory(); + var middlewareOptions = new IdentityServerOAuthBearerAuthenticationOptions(); + + if (options.ValidationMode == ValidationMode.Both || + options.ValidationMode == ValidationMode.Local) + { + middlewareOptions.LocalValidationOptions = ConfigureLocalValidation(options, loggerFactory); + } + + if (options.ValidationMode == ValidationMode.Both || + options.ValidationMode == ValidationMode.ValidationEndpoint) + { + middlewareOptions.EndpointValidationOptions = ConfigureEndpointValidation(options, loggerFactory); + } + + if (options.TokenProvider != null) + { + middlewareOptions.TokenProvider = options.TokenProvider; + } + + app.Use(middlewareOptions); + + if (options.RequiredScopes.Any()) + { + app.Use(options.RequiredScopes); + } + + return app; + } + + private static OAuthBearerAuthenticationOptions ConfigureEndpointValidation(IdentityServerBearerTokenAuthenticationOptions options, ILoggerFactory loggerFactory) + { + if (options.EnableValidationResultCache) + { + if (options.ValidationResultCache == null) + { + options.ValidationResultCache = new InMemoryValidationResultCache(options); + } + } + + var bearerOptions = new OAuthBearerAuthenticationOptions + { + AuthenticationMode = options.AuthenticationMode, + AuthenticationType = options.AuthenticationType, + AccessTokenProvider = new ValidationEndpointTokenProvider(options, loggerFactory), + Provider = new ContextTokenProvider(), + }; + + return bearerOptions; + } + + internal static OAuthBearerAuthenticationOptions ConfigureLocalValidation(IdentityServerBearerTokenAuthenticationOptions options, ILoggerFactory loggerFactory) + { + var discoveryEndpoint = options.Authority.EnsureTrailingSlash(); + discoveryEndpoint += ".well-known/openid-configuration"; + + var issuerProvider = new DiscoveryDocumentIssuerSecurityTokenProvider( + discoveryEndpoint, + options, + loggerFactory); + + var valParams = new TokenValidationParameters + { + ValidAudience = issuerProvider.Audience, + NameClaimType = options.NameClaimType, + RoleClaimType = options.RoleClaimType + }; + + var tokenFormat = new JwtFormat(valParams, issuerProvider); + + var bearerOptions = new OAuthBearerAuthenticationOptions + { + AccessTokenFormat = tokenFormat, + AuthenticationMode = options.AuthenticationMode, + AuthenticationType = options.AuthenticationType, + Provider = new ContextTokenProvider() + }; + + return bearerOptions; + } + } +} \ No newline at end of file diff --git a/source/AccessTokenValidation/IdentityServerBearerTokenValidationMiddleware.cs b/source/AccessTokenValidation/IdentityServerBearerTokenValidationMiddleware.cs new file mode 100644 index 0000000..006a4d2 --- /dev/null +++ b/source/AccessTokenValidation/IdentityServerBearerTokenValidationMiddleware.cs @@ -0,0 +1,148 @@ +/* + * Copyright 2015 Dominick Baier, Brock Allen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Microsoft.Owin; +using Microsoft.Owin.Builder; +using Microsoft.Owin.Security.OAuth; +using Owin; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using AppFunc = System.Func, System.Threading.Tasks.Task>; + +namespace IdentityServer3.AccessTokenValidation +{ + /// + /// Middleware for validating identityserver access tokens + /// + public class IdentityServerBearerTokenValidationMiddleware + { + private readonly AppFunc _next; + private readonly AppFunc _localValidationFunc; + private readonly AppFunc _endpointValidationFunc; + private IdentityServerOAuthBearerAuthenticationOptions _options; + + /// + /// Initializes a new instance of the class. + /// + /// The next middleware. + /// The options. + public IdentityServerBearerTokenValidationMiddleware(AppFunc next, IdentityServerOAuthBearerAuthenticationOptions options) + { + _next = next; + _options = options; + + if (options.LocalValidationOptions != null) + { + var localBuilder = new AppBuilder(); + localBuilder.UseOAuthBearerAuthentication(options.LocalValidationOptions); + localBuilder.Run(ctx => next(ctx.Environment)); + _localValidationFunc = localBuilder.Build(); + } + + if (options.EndpointValidationOptions != null) + { + var endpointBuilder = new AppBuilder(); + endpointBuilder.Properties["host.AppName"] = "foobar"; + + endpointBuilder.UseOAuthBearerAuthentication(options.EndpointValidationOptions); + endpointBuilder.Run(ctx => next(ctx.Environment)); + _endpointValidationFunc = endpointBuilder.Build(); + } + } + + /// + /// Invokes the middleware. + /// + /// The environment. + /// + public async Task Invoke(IDictionary environment) + { + var context = new OwinContext(environment); + + var token = await GetTokenAsync(context); + + if (token == null) + { + await _next(environment); + return; + } + + context.Set("idsrv:tokenvalidation:token", token); + + + // seems to be a JWT + if (token.Contains('.')) + { + // see if local validation is setup + if (_localValidationFunc != null) + { + await _localValidationFunc(environment); + return; + } + // otherwise use validation endpoint + if (_endpointValidationFunc != null) + { + await _endpointValidationFunc(environment); + return; + } + } + else + { + // use validation endpoint + if (_endpointValidationFunc != null) + { + await _endpointValidationFunc(environment); + return; + } + } + + await _next(environment); + } + + private async Task GetTokenAsync(OwinContext context) + { + // find token in default location + string requestToken = null; + string authorization = context.Request.Headers.Get("Authorization"); + if (!string.IsNullOrEmpty(authorization)) + { + if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) + { + requestToken = authorization.Substring("Bearer ".Length).Trim(); + } + } + + // give application opportunity to find from a different location, adjust, or reject token + if (_options.TokenProvider != null) + { + var requestTokenContext = new OAuthRequestTokenContext(context, requestToken); + await _options.TokenProvider.RequestToken(requestTokenContext); + + // if no token found, no further work possible + if (string.IsNullOrEmpty(requestTokenContext.Token)) + { + return null; + } + + return requestTokenContext.Token; + } + + return requestToken; + } + } +} \ No newline at end of file diff --git a/source/AccessTokenValidation/IdentityServerOAuthBearerAuthenticationOptions.cs b/source/AccessTokenValidation/IdentityServerOAuthBearerAuthenticationOptions.cs new file mode 100644 index 0000000..3d3c0f3 --- /dev/null +++ b/source/AccessTokenValidation/IdentityServerOAuthBearerAuthenticationOptions.cs @@ -0,0 +1,50 @@ +/* + * Copyright 2015 Dominick Baier, Brock Allen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Microsoft.Owin.Security.OAuth; + +namespace IdentityServer3.AccessTokenValidation +{ + /// + /// Options that wraps OAuth2BearerAuthenticationOptions for local and remote token validation + /// + public class IdentityServerOAuthBearerAuthenticationOptions + { + /// + /// Gets or sets the token provider (set this if the access token is NOT on the authorization header using a Bearer scheme. + /// + /// + /// The token provider. + /// + public IOAuthBearerAuthenticationProvider TokenProvider { get; set; } + + /// + /// Gets or sets the local validation options. + /// + /// + /// The local validation options. + /// + public OAuthBearerAuthenticationOptions LocalValidationOptions { get; set; } + + /// + /// Gets or sets the endpoint validation options. + /// + /// + /// The endpoint validation options. + /// + public OAuthBearerAuthenticationOptions EndpointValidationOptions { get; set; } + } +} \ No newline at end of file diff --git a/source/AccessTokenValidation/AsyncHelper.cs b/source/AccessTokenValidation/Plumbing/AsyncHelper.cs similarity index 95% rename from source/AccessTokenValidation/AsyncHelper.cs rename to source/AccessTokenValidation/Plumbing/AsyncHelper.cs index 67657c7..8b6bcb4 100644 --- a/source/AccessTokenValidation/AsyncHelper.cs +++ b/source/AccessTokenValidation/Plumbing/AsyncHelper.cs @@ -18,7 +18,7 @@ using System.Threading; using System.Threading.Tasks; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { internal static class AsyncHelper { diff --git a/source/AccessTokenValidation/Cache.cs b/source/AccessTokenValidation/Plumbing/Cache.cs similarity index 92% rename from source/AccessTokenValidation/Cache.cs rename to source/AccessTokenValidation/Plumbing/Cache.cs index 3c35dd7..339fcca 100644 --- a/source/AccessTokenValidation/Cache.cs +++ b/source/AccessTokenValidation/Plumbing/Cache.cs @@ -17,14 +17,14 @@ using System; using System.Runtime.Caching; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { /// /// Cache implementation using System.Runtime.Cachine.MemoryCache /// public class Cache : ICache { - const string CacheName = "thinktecture.validationCache"; + const string CacheName = "IdentityServer3.validationCache"; readonly MemoryCache _cache = new MemoryCache(CacheName); /// diff --git a/source/AccessTokenValidation/Clock.cs b/source/AccessTokenValidation/Plumbing/Clock.cs similarity index 94% rename from source/AccessTokenValidation/Clock.cs rename to source/AccessTokenValidation/Plumbing/Clock.cs index 457684c..5ffbd8f 100644 --- a/source/AccessTokenValidation/Clock.cs +++ b/source/AccessTokenValidation/Plumbing/Clock.cs @@ -16,7 +16,7 @@ using System; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { /// /// Default clock implementation based on DateTimeOffset diff --git a/source/AccessTokenValidation/Plumbing/ContextTokenProvider.cs b/source/AccessTokenValidation/Plumbing/ContextTokenProvider.cs new file mode 100644 index 0000000..d25a3b6 --- /dev/null +++ b/source/AccessTokenValidation/Plumbing/ContextTokenProvider.cs @@ -0,0 +1,69 @@ +/* + * Copyright 2015 Dominick Baier, Brock Allen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Microsoft.Owin.Security.OAuth; +using System; +using System.Threading.Tasks; + +namespace IdentityServer3.AccessTokenValidation +{ + /// + /// Token provider that returns the token already found by the identityserver token middleware + /// + public class ContextTokenProvider : IOAuthBearerAuthenticationProvider + { + /// + /// Invoked before the is created. Gives the application an + /// opportunity to find the identity from a different location, adjust, or reject the token. + /// + /// Contains the token string. + /// + /// A representing the completed operation. + /// + public Task RequestToken(OAuthRequestTokenContext context) + { + context.Token = context.OwinContext.Get("idsrv:tokenvalidation:token"); + return Task.FromResult(0); + } + + /// + /// Called each time a challenge is being sent to the client. By implementing this method the application + /// may modify the challenge as needed. + /// + /// Contains the default challenge. + /// + /// A representing the completed operation. + /// + /// + public Task ApplyChallenge(OAuthChallengeContext context) + { + return Task.FromResult(0); + } + + /// + /// Called each time a request identity has been validated by the middleware. By implementing this method the + /// application may alter or reject the identity which has arrived with the request. + /// + /// Contains information about the login session as well as the user . + /// + /// A representing the completed operation. + /// + public Task ValidateIdentity(OAuthValidateIdentityContext context) + { + return Task.FromResult(0); + } + } +} \ No newline at end of file diff --git a/source/AccessTokenValidation/CachingDiscoveryIssuerSecurityTokenProvider.cs b/source/AccessTokenValidation/Plumbing/DiscoveryDocumentIssuerSecurityTokenProvider.cs similarity index 79% rename from source/AccessTokenValidation/CachingDiscoveryIssuerSecurityTokenProvider.cs rename to source/AccessTokenValidation/Plumbing/DiscoveryDocumentIssuerSecurityTokenProvider.cs index c8962e6..35c62ac 100644 --- a/source/AccessTokenValidation/CachingDiscoveryIssuerSecurityTokenProvider.cs +++ b/source/AccessTokenValidation/Plumbing/DiscoveryDocumentIssuerSecurityTokenProvider.cs @@ -15,6 +15,7 @@ */ using Microsoft.IdentityModel.Protocols; +using Microsoft.Owin.Logging; using Microsoft.Owin.Security.Jwt; using System; using System.Collections.Generic; @@ -24,20 +25,23 @@ using System.Security.Cryptography.X509Certificates; using System.Threading; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { - internal class CachingDiscoveryIssuerSecurityTokenProvider : IIssuerSecurityTokenProvider + internal class DiscoveryDocumentIssuerSecurityTokenProvider : IIssuerSecurityTokenProvider { private readonly TimeSpan _refreshInterval = new TimeSpan(1, 0, 0, 0); private readonly ReaderWriterLockSlim _synclock = new ReaderWriterLockSlim(); private readonly ConfigurationManager _configurationManager; - + private readonly ILogger _logger; + private DateTimeOffset _syncAfter = new DateTimeOffset(new DateTime(2001, 1, 1)); private string _issuer; private IEnumerable _tokens; - public CachingDiscoveryIssuerSecurityTokenProvider(string discoveryEndpoint, IdentityServerBearerTokenAuthenticationOptions options) + public DiscoveryDocumentIssuerSecurityTokenProvider(string discoveryEndpoint, IdentityServerBearerTokenAuthenticationOptions options, ILoggerFactory loggerFactory) { + _logger = loggerFactory.Create("IdentityServer3.AccessTokenValidation.DiscoveryDocumentIssuerSecurityTokenProvider"); + var handler = options.BackchannelHttpHandler ?? new WebRequestHandler(); if (options.BackchannelCertificateValidator != null) @@ -133,13 +137,25 @@ private void RetrieveMetadata() try { var result = AsyncHelper.RunSync(async () => await _configurationManager.GetConfigurationAsync()); + + if (result.JsonWebKeySet == null) + { + _logger.WriteError("Discovery document has no configured signing key. aborting."); + throw new InvalidOperationException("Discovery document has no configured signing key. aborting."); + } + var tokens = from key in result.JsonWebKeySet.Keys - select new X509SecurityToken(new X509Certificate2(Convert.FromBase64String(key.X5c.First()))); + select new X509SecurityToken(new X509Certificate2(Convert.FromBase64String(key.X5c.First()))); _issuer = result.Issuer; _tokens = tokens; _syncAfter = DateTimeOffset.UtcNow + _refreshInterval; } + catch (Exception ex) + { + _logger.WriteError("Error contacting discovery endpoint: " + ex.ToString()); + throw; + } finally { _synclock.ExitWriteLock(); diff --git a/source/AccessTokenValidation/EpochTimeExtensions.cs b/source/AccessTokenValidation/Plumbing/EpochTimeExtensions.cs similarity index 97% rename from source/AccessTokenValidation/EpochTimeExtensions.cs rename to source/AccessTokenValidation/Plumbing/EpochTimeExtensions.cs index 09b4b84..936bee2 100644 --- a/source/AccessTokenValidation/EpochTimeExtensions.cs +++ b/source/AccessTokenValidation/Plumbing/EpochTimeExtensions.cs @@ -16,7 +16,7 @@ using System; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { internal static class EpochTimeExtensions { diff --git a/source/AccessTokenValidation/ICache.cs b/source/AccessTokenValidation/Plumbing/ICache.cs similarity index 95% rename from source/AccessTokenValidation/ICache.cs rename to source/AccessTokenValidation/Plumbing/ICache.cs index 8e90bbb..8b425d0 100644 --- a/source/AccessTokenValidation/ICache.cs +++ b/source/AccessTokenValidation/Plumbing/ICache.cs @@ -16,7 +16,7 @@ using System; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { /// /// Abstraction for a cache diff --git a/source/AccessTokenValidation/IClock.cs b/source/AccessTokenValidation/Plumbing/IClock.cs similarity index 93% rename from source/AccessTokenValidation/IClock.cs rename to source/AccessTokenValidation/Plumbing/IClock.cs index 8a28f35..a1a3f74 100644 --- a/source/AccessTokenValidation/IClock.cs +++ b/source/AccessTokenValidation/Plumbing/IClock.cs @@ -16,7 +16,7 @@ using System; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { /// /// Interface to abstract the clock diff --git a/source/AccessTokenValidation/IValidationResultCache.cs b/source/AccessTokenValidation/Plumbing/IValidationResultCache.cs similarity index 95% rename from source/AccessTokenValidation/IValidationResultCache.cs rename to source/AccessTokenValidation/Plumbing/IValidationResultCache.cs index d550406..7d6d23f 100644 --- a/source/AccessTokenValidation/IValidationResultCache.cs +++ b/source/AccessTokenValidation/Plumbing/IValidationResultCache.cs @@ -18,7 +18,7 @@ using System.Security.Claims; using System.Threading.Tasks; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { /// /// Interface for caching then token validation result diff --git a/source/AccessTokenValidation/InMemoryValidationResultCache.cs b/source/AccessTokenValidation/Plumbing/InMemoryValidationResultCache.cs similarity index 65% rename from source/AccessTokenValidation/InMemoryValidationResultCache.cs rename to source/AccessTokenValidation/Plumbing/InMemoryValidationResultCache.cs index 13d4019..6c34162 100644 --- a/source/AccessTokenValidation/InMemoryValidationResultCache.cs +++ b/source/AccessTokenValidation/Plumbing/InMemoryValidationResultCache.cs @@ -20,7 +20,7 @@ using System.Security.Claims; using System.Threading.Tasks; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { /// /// In-memory cache for validation results @@ -29,15 +29,15 @@ public class InMemoryValidationResultCache : IValidationResultCache { private readonly IdentityServerBearerTokenAuthenticationOptions _options; private readonly ICache _cache; - private readonly IClock _clock; + private readonly IClock _clock; /// /// Initializes a new instance of the class. /// /// The options. - public InMemoryValidationResultCache(IdentityServerBearerTokenAuthenticationOptions options) + public InMemoryValidationResultCache(IdentityServerBearerTokenAuthenticationOptions options) : this(options, new Clock(), new Cache()) - { } + { } /// /// Initializes a new instance of the class. @@ -52,16 +52,16 @@ public InMemoryValidationResultCache(IdentityServerBearerTokenAuthenticationOpti /// or /// cache /// - public InMemoryValidationResultCache(IdentityServerBearerTokenAuthenticationOptions options, IClock clock, ICache cache) - { - if (clock == null) { throw new ArgumentNullException("clock"); } - if (options == null) { throw new ArgumentNullException("options"); } - if (cache == null) { throw new ArgumentNullException("cache"); } + public InMemoryValidationResultCache(IdentityServerBearerTokenAuthenticationOptions options, IClock clock, ICache cache) + { + if (clock == null) { throw new ArgumentNullException("clock"); } + if (options == null) { throw new ArgumentNullException("options"); } + if (cache == null) { throw new ArgumentNullException("cache"); } - _options = options; - _cache = cache; - _clock = clock; - } + _options = options; + _cache = cache; + _clock = clock; + } /// /// Add a validation result @@ -69,25 +69,26 @@ public InMemoryValidationResultCache(IdentityServerBearerTokenAuthenticationOpti /// The token. /// The claims. /// - public Task AddAsync(string token, IEnumerable claims) + public Task AddAsync(string token, IEnumerable claims) { - var expiryClaim = claims.FirstOrDefault(c => c.Type == ClaimTypes.Expiration); - var cacheExpirySetting = _clock.UtcNow.Add(_options.ValidationResultCacheDuration); - - if (expiryClaim != null) { - long epoch; - if (long.TryParse(expiryClaim.Value, out epoch)) + var expiryClaim = claims.FirstOrDefault(c => c.Type == ClaimTypes.Expiration); + var cacheExpirySetting = _clock.UtcNow.Add(_options.ValidationResultCacheDuration); + + if (expiryClaim != null) + { + long epoch; + if (long.TryParse(expiryClaim.Value, out epoch)) { - var tokenExpiresAt = epoch.ToDateTimeOffsetFromEpoch(); - - if (tokenExpiresAt < cacheExpirySetting) + var tokenExpiresAt = epoch.ToDateTimeOffsetFromEpoch(); + + if (tokenExpiresAt < cacheExpirySetting) { - _cache.Add(token, claims, tokenExpiresAt); - return Task.FromResult(null); - } - } - } - + _cache.Add(token, claims, tokenExpiresAt); + return Task.FromResult(null); + } + } + } + _cache.Add(token, claims, cacheExpirySetting); return Task.FromResult(null); diff --git a/source/AccessTokenValidation/StringExtensions.cs b/source/AccessTokenValidation/Plumbing/StringExtensions.cs similarity index 93% rename from source/AccessTokenValidation/StringExtensions.cs rename to source/AccessTokenValidation/Plumbing/StringExtensions.cs index d2cbddd..f60d561 100644 --- a/source/AccessTokenValidation/StringExtensions.cs +++ b/source/AccessTokenValidation/Plumbing/StringExtensions.cs @@ -14,7 +14,7 @@ * limitations under the License. */ -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { internal static class StringExtensions { diff --git a/source/AccessTokenValidation/ValidationEndpointTokenProvider.cs b/source/AccessTokenValidation/Plumbing/ValidationEndpointTokenProvider.cs similarity index 79% rename from source/AccessTokenValidation/ValidationEndpointTokenProvider.cs rename to source/AccessTokenValidation/Plumbing/ValidationEndpointTokenProvider.cs index b2c163b..87555aa 100644 --- a/source/AccessTokenValidation/ValidationEndpointTokenProvider.cs +++ b/source/AccessTokenValidation/Plumbing/ValidationEndpointTokenProvider.cs @@ -14,6 +14,7 @@ * limitations under the License. */ +using Microsoft.Owin.Logging; using Microsoft.Owin.Security; using Microsoft.Owin.Security.Infrastructure; using Newtonsoft.Json; @@ -24,19 +25,22 @@ using System.Security.Claims; using System.Threading.Tasks; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { internal class ValidationEndpointTokenProvider : AuthenticationTokenProvider { private readonly HttpClient _client; private readonly string _tokenValidationEndpoint; private readonly IdentityServerBearerTokenAuthenticationOptions _options; + private readonly ILogger _logger; - public ValidationEndpointTokenProvider(IdentityServerBearerTokenAuthenticationOptions options) + public ValidationEndpointTokenProvider(IdentityServerBearerTokenAuthenticationOptions options, ILoggerFactory loggerFactory) { + _logger = loggerFactory.Create("ValidationEndpointTokenProvider"); + var baseAddress = options.Authority.EnsureTrailingSlash(); baseAddress += "connect/accesstokenvalidation"; - _tokenValidationEndpoint = baseAddress + "?token={0}"; + _tokenValidationEndpoint = baseAddress; var handler = options.BackchannelHttpHandler ?? new WebRequestHandler(); @@ -68,11 +72,24 @@ public override async Task ReceiveAsync(AuthenticationTokenReceiveContext contex } } - var url = string.Format(_tokenValidationEndpoint, context.Token); + var form = new Dictionary + { + { "token", context.Token } + }; - var response = await _client.GetAsync(url); - if (response.StatusCode != HttpStatusCode.OK) + HttpResponseMessage response = null; + try + { + response = await _client.PostAsync(_tokenValidationEndpoint, new FormUrlEncodedContent(form)); + if (response.StatusCode != HttpStatusCode.OK) + { + _logger.WriteInformation("Error returned from token validation endpoint: " + response.ReasonPhrase); + return; + } + } + catch (Exception ex) { + _logger.WriteError("Exception while contacting token validation endpoint: " + ex.ToString()); return; } diff --git a/source/AccessTokenValidation/ScopeRequirementMiddleware.cs b/source/AccessTokenValidation/ScopeRequirementMiddleware.cs index d57e709..907021d 100644 --- a/source/AccessTokenValidation/ScopeRequirementMiddleware.cs +++ b/source/AccessTokenValidation/ScopeRequirementMiddleware.cs @@ -19,20 +19,34 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using AppFunc = System.Func, System.Threading.Tasks.Task>; -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { - internal class ScopeRequirementMiddleware + /// + /// Middleware to check for scope claims in access token + /// + public class ScopeRequirementMiddleware { - private readonly Func, Task> _next; + private readonly AppFunc _next; private readonly IEnumerable _scopes; - public ScopeRequirementMiddleware(Func, Task> next, params string[] scopes) + /// + /// Initializes a new instance of the class. + /// + /// The next midleware. + /// The scopes. + public ScopeRequirementMiddleware(AppFunc next, IEnumerable scopes) { _next = next; _scopes = scopes; } + /// + /// Invokes the middleware. + /// + /// The OWIN environment. + /// public async Task Invoke(IDictionary env) { var context = new OwinContext(env); @@ -90,7 +104,7 @@ private bool ScopesFound(OwinContext context) foreach (var scope in scopeClaims) { - if (_scopes.Contains(scope.Value)) + if (_scopes.Contains(scope.Value, StringComparer.Ordinal)) { return true; } diff --git a/source/AccessTokenValidation/ValidationMode.cs b/source/AccessTokenValidation/ValidationMode.cs index 44d9444..6af8c23 100644 --- a/source/AccessTokenValidation/ValidationMode.cs +++ b/source/AccessTokenValidation/ValidationMode.cs @@ -14,7 +14,7 @@ * limitations under the License. */ -namespace Thinktecture.IdentityServer.AccessTokenValidation +namespace IdentityServer3.AccessTokenValidation { /// /// Enum for specifying where to validate the access token @@ -22,13 +22,18 @@ namespace Thinktecture.IdentityServer.AccessTokenValidation public enum ValidationMode { /// - /// Use local validation (only suitable for JWT tokens) + /// Use local validation for JWTs and the validation endpoint for reference tokens + /// + Both, + + /// + /// Use local validation oly (only suitable for JWT tokens) /// Local, /// - /// Use the validation endpoint (works for both JWT and reference tokens) + /// Use the validation endpoint only (works for both JWT and reference tokens) /// - ValidationEndpoint, + ValidationEndpoint } } \ No newline at end of file diff --git a/source/AccessTokenValidation/app.config b/source/AccessTokenValidation/app.config new file mode 100644 index 0000000..b39636f --- /dev/null +++ b/source/AccessTokenValidation/app.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/AccessTokenValidation/packages.config b/source/AccessTokenValidation/packages.config index 6742dc2..3cb139b 100644 --- a/source/AccessTokenValidation/packages.config +++ b/source/AccessTokenValidation/packages.config @@ -1,12 +1,12 @@  - - + + - + \ No newline at end of file diff --git a/source/Thinktecture.IdentityServer3.AccessTokenValidation.nuspec b/source/IdentityServer3.AccessTokenValidation.nuspec similarity index 59% rename from source/Thinktecture.IdentityServer3.AccessTokenValidation.nuspec rename to source/IdentityServer3.AccessTokenValidation.nuspec index 3f82672..b479871 100644 --- a/source/Thinktecture.IdentityServer3.AccessTokenValidation.nuspec +++ b/source/IdentityServer3.AccessTokenValidation.nuspec @@ -1,18 +1,18 @@ - Thinktecture.IdentityServer3.AccessTokenValidation + IdentityServer3.AccessTokenValidation 0.0.0 - Thinktecture IdentityServer3 - Access Token Validation + IdentityServer3 - Access Token Validation Brock Allen, Dominick Baier Brock Allen, Dominick Baier - https://github.com/identityserver/Thinktecture.IdentityServer3.AccessTokenValidation - http://www.thinktecture.com/images/favicon.ico + https://github.com/identityserver/IdentityServer3.AccessTokenValidation + https://identityserver.github.io/Documentation/assets/images/icons/IDserver_icon128.jpg false - https://github.com/IdentityServer/Thinktecture.IdentityServer3.AccessTokenValidation/blob/master/LICENSE + https://github.com/IdentityServer/IdentityServer3.AccessTokenValidation/blob/master/LICENSE Access token validation middleware for JWT and reference tokens issued by IdentityServer3. Copyright 2015 - Thinktecture IdentityServer OpenID Connect OpenIDConnect OAuth2 OWIN ASP.NET Katana WebApi SSO Federation Claims Identity JWT token + IdentityServer OpenID Connect OpenIDConnect OAuth2 OWIN ASP.NET Katana WebApi SSO Federation Claims Identity JWT token @@ -22,7 +22,7 @@ - + diff --git a/source/Thinktecture.IdentityServer3.AccessTokenValidation.sln b/source/IdentityServer3.AccessTokenValidation.sln similarity index 100% rename from source/Thinktecture.IdentityServer3.AccessTokenValidation.sln rename to source/IdentityServer3.AccessTokenValidation.sln diff --git a/source/VersionAssemblyInfo.cs b/source/VersionAssemblyInfo.cs index ac95a1d..1ceeba7 100644 Binary files a/source/VersionAssemblyInfo.cs and b/source/VersionAssemblyInfo.cs differ