Skip to content
This repository has been archived by the owner on Sep 18, 2021. It is now read-only.

Commit

Permalink
Merge pull request #2306 from IdentityServer/ConfigurableIntrospectio…
Browse files Browse the repository at this point in the history
…nRestriction

Configurable Scope Restriction for Introspection Endpoint
  • Loading branch information
leastprivilege committed Dec 16, 2015
2 parents a606fe6 + 0ff2e46 commit d297d0f
Show file tree
Hide file tree
Showing 17 changed files with 222 additions and 114 deletions.
1 change: 1 addition & 0 deletions source/Core/Configuration/Hosting/AutoFacConfig.cs
Expand Up @@ -153,6 +153,7 @@ public static IContainer Configure(IdentityServerOptions options)
builder.RegisterType<AuthorizeInteractionResponseGenerator>();
builder.RegisterType<UserInfoResponseGenerator>();
builder.RegisterType<EndSessionResponseGenerator>();
builder.RegisterType<IntrospectionResponseGenerator>();

// for authentication
var authenticationOptions = options.AuthenticationOptions ?? new AuthenticationOptions();
Expand Down
3 changes: 2 additions & 1 deletion source/Core/Core.csproj
Expand Up @@ -56,7 +56,7 @@
<HintPath>..\packages\Autofac.WebApi2.3.4.0\lib\net45\Autofac.Integration.WebApi.dll</HintPath>
</Reference>
<Reference Include="IdentityModel.Net45, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\IdentityModel.1.2.1\lib\net45\IdentityModel.Net45.dll</HintPath>
<HintPath>..\packages\IdentityModel.1.3.0\lib\net45\IdentityModel.Net45.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
Expand Down Expand Up @@ -225,6 +225,7 @@
<DesignTime>True</DesignTime>
<DependentUpon>T4resx.tt</DependentUpon>
</Compile>
<Compile Include="ResponseHandling\IntrospectionResponseGenerator.cs" />
<Compile Include="Results\CheckSessionResult.cs" />
<Compile Include="Results\RevocationErrorResult.cs" />
<Compile Include="Results\IntrospectionResult.cs" />
Expand Down
15 changes: 10 additions & 5 deletions source/Core/Endpoints/Connect/IntrospectionEndpointController.cs
Expand Up @@ -19,6 +19,7 @@
using IdentityServer3.Core.Extensions;
using IdentityServer3.Core.Logging;
using IdentityServer3.Core.Models;
using IdentityServer3.Core.ResponseHandling;
using IdentityServer3.Core.Results;
using IdentityServer3.Core.Services;
using IdentityServer3.Core.Validation;
Expand All @@ -42,17 +43,20 @@ internal class IntrospectionEndpointController : ApiController
private readonly IEventService _events;
private readonly ScopeSecretValidator _scopeSecretValidator;
private readonly IntrospectionRequestValidator _requestValidator;
private readonly IntrospectionResponseGenerator _generator;

public IntrospectionEndpointController(
IntrospectionRequestValidator requestValidator,
IdentityServerOptions options,
IEventService events,
ScopeSecretValidator scopeSecretValidator)
ScopeSecretValidator scopeSecretValidator,
IntrospectionResponseGenerator generator)
{
_requestValidator = requestValidator;
_scopeSecretValidator = scopeSecretValidator;
_options = options;
_events = events;
_generator = generator;
}

/// <summary>
Expand All @@ -77,11 +81,12 @@ public async Task<IHttpActionResult> Post()
internal async Task<IHttpActionResult> ProcessRequest(NameValueCollection parameters, Scope scope)
{
var validationResult = await _requestValidator.ValidateAsync(parameters, scope);
var response = await _generator.ProcessAsync(validationResult, scope);

if (validationResult.IsActive)
{
await RaiseSuccessEventAsync(validationResult.Token, "active", scope.Name);
return new IntrospectionResult(validationResult, scope);
await RaiseSuccessEventAsync(validationResult.Token, "active", scope.Name);
return new IntrospectionResult(response);
}

if (validationResult.IsError)
Expand All @@ -97,13 +102,13 @@ internal async Task<IHttpActionResult> ProcessRequest(NameValueCollection parame
if (validationResult.FailureReason == IntrospectionRequestValidationFailureReason.InvalidToken)
{
await RaiseSuccessEventAsync(validationResult.Token, "inactive", scope.Name);
return new IntrospectionResult();
return new IntrospectionResult(response);
}

if (validationResult.FailureReason == IntrospectionRequestValidationFailureReason.InvalidScope)
{
await RaiseFailureEventAsync("Scope not authorized to introspect token", validationResult.Token, scope.Name);
return new IntrospectionResult();
return new IntrospectionResult(response);
}
}

Expand Down
6 changes: 6 additions & 0 deletions source/Core/Models/Scope.cs
Expand Up @@ -86,6 +86,11 @@ public class Scope
/// </value>
public List<Secret> ScopeSecrets { get; set; }

/// <summary>
/// Specifies whether this scope is allowed to see other scopes when using the introspection endpoint
/// </summary>
public bool AllowUnrestrictedIntrospection { get; set; }

/// <summary>
/// Creates a Scope with default values
/// </summary>
Expand All @@ -97,6 +102,7 @@ public Scope()
IncludeAllClaimsForUser = false;
Enabled = true;
ShowInDiscoveryDocument = true;
AllowUnrestrictedIntrospection = false;
}
}
}
64 changes: 64 additions & 0 deletions source/Core/ResponseHandling/IntrospectionResponseGenerator.cs
@@ -0,0 +1,64 @@
/*
* Copyright 2014, 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.Core.Extensions;
using IdentityServer3.Core.Logging;
using IdentityServer3.Core.Models;
using IdentityServer3.Core.Validation;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IdentityServer3.Core.ResponseHandling
{
internal class IntrospectionResponseGenerator
{
private readonly static ILog Logger = LogProvider.GetCurrentClassLogger();

public Task<Dictionary<string, object>> ProcessAsync(IntrospectionRequestValidationResult validationResult, Scope scope)
{
Logger.Info("Creating introspection response");

var response = new Dictionary<string, object>();

if (validationResult.IsActive == false)
{
Logger.Info("Creating introspection response for inactive token.");

response.Add("active", false);
return Task.FromResult(response);
}

if (scope.AllowUnrestrictedIntrospection)
{
Logger.Info("Creating unrestricted introspection response for active token.");

response = validationResult.Claims.ToClaimsDictionary();
response.Add("active", true);
}
else
{
Logger.Info("Creating restricted introspection response for active token.");

response = validationResult.Claims.Where(c => c.Type != Constants.ClaimTypes.Scope).ToClaimsDictionary();
response.Add("active", true);
response.Add("scope", scope.Name);
}

return Task.FromResult(response);
}
}
}
35 changes: 4 additions & 31 deletions source/Core/Results/IntrospectionResult.cs
Expand Up @@ -30,23 +30,13 @@ namespace IdentityServer3.Core.Results
{
internal class IntrospectionResult : IHttpActionResult
{
private readonly static ILog Logger = LogProvider.GetCurrentClassLogger();
private readonly static JsonMediaTypeFormatter Formatter = new JsonMediaTypeFormatter();

public IntrospectionRequestValidationResult IntrospectionValidationResult { get; set; }
public Scope Scope { get; set; }
public Dictionary<string, object> Result { get; private set; }

private readonly bool _sendInactive;

public IntrospectionResult()
{
_sendInactive = true;
}

public IntrospectionResult(IntrospectionRequestValidationResult introspectionValidationResult, Scope scope)
public IntrospectionResult(Dictionary<string, object> result)
{
IntrospectionValidationResult = introspectionValidationResult;
Scope = scope;
Result = result;
}

public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
Expand All @@ -56,29 +46,12 @@ public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToke

private HttpResponseMessage Execute()
{
if (_sendInactive == true)
{
var inactiveContent = new ObjectContent<object>(new { active = false }, Formatter);
var inactiveMessage = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = inactiveContent
};

Logger.Info("Returning inactive introspection response.");
return inactiveMessage;
}

var response = IntrospectionValidationResult.Claims.ToClaimsDictionary();
response.Add("active", true);
response.Add("scope", Scope.Name);

var content = new ObjectContent<Dictionary<string, object>>(response, Formatter);
var content = new ObjectContent<Dictionary<string, object>>(Result, Formatter);
var message = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = content
};

Logger.Info("Returning active introspection response.");
return message;
}
}
Expand Down
Expand Up @@ -29,6 +29,7 @@ internal class IntrospectionRequestValidationResult : ValidationResult

enum IntrospectionRequestValidationFailureReason
{
None,
MissingToken,
InvalidToken,
InvalidScope
Expand Down
2 changes: 1 addition & 1 deletion source/Core/Validation/IntrospectionRequestValidator.cs
Expand Up @@ -75,7 +75,7 @@ public async Task<IntrospectionRequestValidationResult> ValidateAsync(NameValueC
IsActive = true,
IsError = false,
Token = token,
Claims = tokenValidationResult.Claims.Where(c => c.Type != Constants.ClaimTypes.Scope)
Claims = tokenValidationResult.Claims
};

return success;
Expand Down
40 changes: 20 additions & 20 deletions source/Core/app.config
@@ -1,43 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.5.0.0" newVersion="3.5.0.0"/>
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.5.0.0" newVersion="3.5.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.FileSystems" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
<assemblyIdentity name="Microsoft.Owin.FileSystems" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Cors" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
<assemblyIdentity name="System.Web.Cors" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
<assemblyIdentity name="System.Web.Http.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /></startup></configuration>
2 changes: 1 addition & 1 deletion source/Core/packages.config
Expand Up @@ -2,7 +2,7 @@
<packages>
<package id="Autofac" version="3.5.2" targetFramework="net45" />
<package id="Autofac.WebApi2" version="3.4.0" targetFramework="net45" />
<package id="IdentityModel" version="1.2.1" targetFramework="net45" />
<package id="IdentityModel" version="1.3.0" targetFramework="net452" />
<package id="ILMerge" version="2.14.1208" targetFramework="net45" />
<package id="LibLog" version="4.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.Cors" version="5.2.3" targetFramework="net45" />
Expand Down
28 changes: 14 additions & 14 deletions source/Host.Configuration/app.config
@@ -1,31 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Cors" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
<assemblyIdentity name="System.Web.Cors" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Protocol.Extensions" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.0.2.33" newVersion="1.0.2.33"/>
<assemblyIdentity name="Microsoft.IdentityModel.Protocol.Extensions" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.2.33" newVersion="1.0.2.33" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.20622.1351" newVersion="4.0.20622.1351"/>
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.20622.1351" newVersion="4.0.20622.1351" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /></startup></configuration>

0 comments on commit d297d0f

Please sign in to comment.