Skip to content
This repository has been archived by the owner on Dec 14, 2017. It is now read-only.

Commit

Permalink
Merge pull request #62 from tugberkugurlu/lazy-metadata
Browse files Browse the repository at this point in the history
added DelayLoadMetadata option to IdentityServerBearerTokenAuthenticationOptions
  • Loading branch information
leastprivilege committed Jan 22, 2016
2 parents b4f7387 + 4f64663 commit abcc599
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public IdentityServerBearerTokenAuthenticationOptions() : base("Bearer")
RequiredScopes = Enumerable.Empty<string>();
ValidationResultCacheDuration = TimeSpan.FromMinutes(5);
PreserveAccessToken = false;
DelayLoadMetadata = false;
}

/// <summary>
Expand Down Expand Up @@ -180,5 +181,11 @@ public IdentityServerBearerTokenAuthenticationOptions() : base("Bearer")
/// The introspection HTTP handler.
/// </value>
public WebRequestHandler IntrospectionHttpHandler { get; set; }

/// <summary>
/// Indicates whether the discovery metadata sync to be delayed during the construction of
/// the pipeline. <c>false</c> by default.
/// </summary>
public bool DelayLoadMetadata { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ public static IAppBuilder UseIdentityServerBearerTokenAuthentication(this IAppBu
throw new Exception("ValidationMode has invalid value");
}

if (!options.DelayLoadMetadata)
{
// evaluate the lazy members so that they can do their job

if (middlewareOptions.LocalValidationOptions != null)
{
var ignore = middlewareOptions.LocalValidationOptions.Value;
}

if (middlewareOptions.EndpointValidationOptions != null)
{
var ignore = middlewareOptions.EndpointValidationOptions.Value;
}
}

if (options.TokenProvider != null)
{
middlewareOptions.TokenProvider = options.TokenProvider;
Expand All @@ -85,94 +100,102 @@ public static IAppBuilder UseIdentityServerBearerTokenAuthentication(this IAppBu
return app;
}

private static OAuthBearerAuthenticationOptions ConfigureEndpointValidation(IdentityServerBearerTokenAuthenticationOptions options, ILoggerFactory loggerFactory)
private static Lazy<OAuthBearerAuthenticationOptions> ConfigureEndpointValidation(IdentityServerBearerTokenAuthenticationOptions options, ILoggerFactory loggerFactory)
{
if (options.EnableValidationResultCache)
return new Lazy<OAuthBearerAuthenticationOptions>(() =>
{
if (options.ValidationResultCache == null)
if (options.EnableValidationResultCache)
{
options.ValidationResultCache = new InMemoryValidationResultCache(options);
if (options.ValidationResultCache == null)
{
options.ValidationResultCache = new InMemoryValidationResultCache(options);
}
}
}

var bearerOptions = new OAuthBearerAuthenticationOptions
{
AuthenticationMode = options.AuthenticationMode,
AuthenticationType = options.AuthenticationType,
Provider = new ContextTokenProvider(options.TokenProvider),
};
var bearerOptions = new OAuthBearerAuthenticationOptions
{
AuthenticationMode = options.AuthenticationMode,
AuthenticationType = options.AuthenticationType,
Provider = new ContextTokenProvider(options.TokenProvider),
};

if (!string.IsNullOrEmpty(options.ClientId) || options.IntrospectionHttpHandler != null)
{
bearerOptions.AccessTokenProvider = new IntrospectionEndpointTokenProvider(options, loggerFactory);
}
else
{
bearerOptions.AccessTokenProvider = new ValidationEndpointTokenProvider(options, loggerFactory);
}
if (!string.IsNullOrEmpty(options.ClientId) || options.IntrospectionHttpHandler != null)
{
bearerOptions.AccessTokenProvider = new IntrospectionEndpointTokenProvider(options, loggerFactory);
}
else
{
bearerOptions.AccessTokenProvider = new ValidationEndpointTokenProvider(options, loggerFactory);
}

return bearerOptions;

return bearerOptions;
}, true);
}

internal static OAuthBearerAuthenticationOptions ConfigureLocalValidation(IdentityServerBearerTokenAuthenticationOptions options, ILoggerFactory loggerFactory)
internal static Lazy<OAuthBearerAuthenticationOptions> ConfigureLocalValidation(IdentityServerBearerTokenAuthenticationOptions options, ILoggerFactory loggerFactory)
{
JwtFormat tokenFormat = null;

// use static configuration
if (!string.IsNullOrWhiteSpace(options.IssuerName) &&
options.SigningCertificate != null)
return new Lazy<OAuthBearerAuthenticationOptions>(() =>
{
var audience = options.IssuerName.EnsureTrailingSlash();
audience += "resources";
JwtFormat tokenFormat = null;

var valParams = new TokenValidationParameters
{
ValidIssuer = options.IssuerName,
ValidAudience = audience,
IssuerSigningToken = new X509SecurityToken(options.SigningCertificate),
// use static configuration
if (!string.IsNullOrWhiteSpace(options.IssuerName) &&
options.SigningCertificate != null)
{
var audience = options.IssuerName.EnsureTrailingSlash();
audience += "resources";

NameClaimType = options.NameClaimType,
RoleClaimType = options.RoleClaimType,
};
var valParams = new TokenValidationParameters
{
ValidIssuer = options.IssuerName,
ValidAudience = audience,
IssuerSigningToken = new X509SecurityToken(options.SigningCertificate),

tokenFormat = new JwtFormat(valParams);
}
else
{
// use discovery endpoint
if (string.IsNullOrWhiteSpace(options.Authority))
NameClaimType = options.NameClaimType,
RoleClaimType = options.RoleClaimType,
};

tokenFormat = new JwtFormat(valParams);
}
else
{
throw new Exception("Either set IssuerName and SigningCertificate - or Authority");
// use discovery endpoint
if (string.IsNullOrWhiteSpace(options.Authority))
{
throw new Exception("Either set IssuerName and SigningCertificate - or Authority");
}

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
};

tokenFormat = new JwtFormat(valParams, issuerProvider);
}

var discoveryEndpoint = options.Authority.EnsureTrailingSlash();
discoveryEndpoint += ".well-known/openid-configuration";

var issuerProvider = new DiscoveryDocumentIssuerSecurityTokenProvider(
discoveryEndpoint,
options,
loggerFactory);

var valParams = new TokenValidationParameters
var bearerOptions = new OAuthBearerAuthenticationOptions
{
ValidAudience = issuerProvider.Audience,
NameClaimType = options.NameClaimType,
RoleClaimType = options.RoleClaimType
AccessTokenFormat = tokenFormat,
AuthenticationMode = options.AuthenticationMode,
AuthenticationType = options.AuthenticationType,
Provider = new ContextTokenProvider(options.TokenProvider)
};

tokenFormat = new JwtFormat(valParams, issuerProvider);
}


var bearerOptions = new OAuthBearerAuthenticationOptions
{
AccessTokenFormat = tokenFormat,
AuthenticationMode = options.AuthenticationMode,
AuthenticationType = options.AuthenticationType,
Provider = new ContextTokenProvider(options.TokenProvider)
};
return bearerOptions;

return bearerOptions;
}, true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ namespace IdentityServer3.AccessTokenValidation
public class IdentityServerBearerTokenValidationMiddleware
{
private readonly AppFunc _next;
private readonly AppFunc _localValidationFunc;
private readonly AppFunc _endpointValidationFunc;
private readonly Lazy<AppFunc> _localValidationFunc;
private readonly Lazy<AppFunc> _endpointValidationFunc;
private readonly IdentityServerOAuthBearerAuthenticationOptions _options;
private readonly ILogger _logger;

Expand All @@ -53,20 +53,28 @@ public IdentityServerBearerTokenValidationMiddleware(AppFunc next, IAppBuilder a

if (options.LocalValidationOptions != null)
{
var localBuilder = app.New();
localBuilder.UseOAuthBearerAuthentication(options.LocalValidationOptions);
localBuilder.Run(ctx => next(ctx.Environment));
_localValidationFunc = localBuilder.Build();
_localValidationFunc = new Lazy<AppFunc>(() =>
{
var localBuilder = app.New();
localBuilder.UseOAuthBearerAuthentication(options.LocalValidationOptions.Value);
localBuilder.Run(ctx => next(ctx.Environment));
return localBuilder.Build();

}, true);
}

if (options.EndpointValidationOptions != null)
{
var endpointBuilder = app.New();
endpointBuilder.Properties["host.AppName"] = "foobar";
_endpointValidationFunc = new Lazy<AppFunc>(() =>
{
var endpointBuilder = app.New();
endpointBuilder.Properties["host.AppName"] = "foobar";

endpointBuilder.UseOAuthBearerAuthentication(options.EndpointValidationOptions.Value);
endpointBuilder.Run(ctx => next(ctx.Environment));
return endpointBuilder.Build();

endpointBuilder.UseOAuthBearerAuthentication(options.EndpointValidationOptions);
endpointBuilder.Run(ctx => next(ctx.Environment));
_endpointValidationFunc = endpointBuilder.Build();
}, true);
}
}

Expand Down Expand Up @@ -95,13 +103,13 @@ public async Task Invoke(IDictionary<string, object> environment)
// see if local validation is setup
if (_localValidationFunc != null)
{
await _localValidationFunc(environment);
await _localValidationFunc.Value(environment);
return;
}
// otherwise use validation endpoint
if (_endpointValidationFunc != null)
{
await _endpointValidationFunc(environment);
await _endpointValidationFunc.Value(environment);
return;
}

Expand All @@ -112,7 +120,7 @@ public async Task Invoke(IDictionary<string, object> environment)
// use validation endpoint
if (_endpointValidationFunc != null)
{
await _endpointValidationFunc(environment);
await _endpointValidationFunc.Value(environment);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ public DiscoveryDocumentIssuerSecurityTokenProvider(string discoveryEndpoint, Id
}

_configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(discoveryEndpoint, new HttpClient(handler));
RetrieveMetadata();

if (!options.DelayLoadMetadata)
{
RetrieveMetadata();
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

using Microsoft.Owin.Security.OAuth;
using System;

namespace IdentityServer3.AccessTokenValidation
{
Expand All @@ -37,14 +38,14 @@ public class IdentityServerOAuthBearerAuthenticationOptions
/// <value>
/// The local validation options.
/// </value>
public OAuthBearerAuthenticationOptions LocalValidationOptions { get; set; }
public Lazy<OAuthBearerAuthenticationOptions> LocalValidationOptions { get; set; }

/// <summary>
/// Gets or sets the endpoint validation options.
/// </summary>
/// <value>
/// The endpoint validation options.
/// </value>
public OAuthBearerAuthenticationOptions EndpointValidationOptions { get; set; }
public Lazy<OAuthBearerAuthenticationOptions> EndpointValidationOptions { get; set; }
}
}

0 comments on commit abcc599

Please sign in to comment.