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

Configurable Scope Restriction for Introspection Endpoint #2306

Merged
merged 2 commits into from Dec 16, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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>