Browse Source

Update OpenIddict.Core to target the ASOS beta7 nightly builds

pull/178/head
Kévin Chalet 10 years ago
parent
commit
b96fa64f44
  1. 9
      samples/Mvc.Server/Controllers/AuthorizationController.cs
  2. 42
      src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Authentication.cs
  3. 6
      src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Revocation.cs
  4. 15
      src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Serialization.cs
  5. 8
      src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Session.cs
  6. 46
      src/OpenIddict.Core/OpenIddictBuilder.cs
  7. 3
      src/OpenIddict.Core/OpenIddictOptions.cs
  8. 2
      src/OpenIddict.Core/project.json

9
samples/Mvc.Server/Controllers/AuthorizationController.cs

@ -5,6 +5,7 @@
*/ */
using System; using System;
using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -52,7 +53,9 @@ namespace Mvc.Server {
return View(new AuthorizeViewModel { return View(new AuthorizeViewModel {
ApplicationName = application.DisplayName, ApplicationName = application.DisplayName,
Parameters = request.Parameters, Parameters = request.ToDictionary(
parameter => parameter.Key,
parameter => (string) parameter.Value),
Scope = request.Scope Scope = request.Scope
}); });
} }
@ -101,7 +104,9 @@ namespace Mvc.Server {
var request = HttpContext.GetOpenIdConnectRequest(); var request = HttpContext.GetOpenIdConnectRequest();
return View(new LogoutViewModel { return View(new LogoutViewModel {
Parameters = request.Parameters Parameters = request.ToDictionary(
parameter => parameter.Key,
parameter => (string) parameter.Value)
}); });
} }

42
src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Authentication.cs

@ -6,6 +6,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -20,6 +21,8 @@ using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
namespace OpenIddict.Infrastructure { namespace OpenIddict.Infrastructure {
public partial class OpenIddictProvider<TUser, TApplication, TAuthorization, TScope, TToken> : OpenIdConnectServerProvider public partial class OpenIddictProvider<TUser, TApplication, TAuthorization, TScope, TToken> : OpenIdConnectServerProvider
@ -28,7 +31,7 @@ namespace OpenIddict.Infrastructure {
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>(); var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>();
// Reject requests using the unsupported request parameter. // Reject requests using the unsupported request parameter.
if (!string.IsNullOrEmpty(context.Request.GetParameter(OpenIdConnectConstants.Parameters.Request))) { if (!string.IsNullOrEmpty(context.Request.Request)) {
services.Logger.LogError("The authorization request was rejected because it contained " + services.Logger.LogError("The authorization request was rejected because it contained " +
"an unsupported parameter: {Parameter}.", "request"); "an unsupported parameter: {Parameter}.", "request");
@ -53,8 +56,8 @@ namespace OpenIddict.Infrastructure {
// If a request_id parameter can be found in the authorization request, // If a request_id parameter can be found in the authorization request,
// restore the complete authorization request stored in the distributed cache. // restore the complete authorization request stored in the distributed cache.
if (!string.IsNullOrEmpty(context.Request.GetRequestId())) { if (!string.IsNullOrEmpty(context.Request.RequestId)) {
var payload = await services.Options.Cache.GetAsync(OpenIddictConstants.Environment.Request + context.Request.GetRequestId()); var payload = await services.Options.Cache.GetAsync(OpenIddictConstants.Environment.Request + context.Request.RequestId);
if (payload == null) { if (payload == null) {
services.Logger.LogError("The authorization request was rejected because an unknown " + services.Logger.LogError("The authorization request was rejected because an unknown " +
"or invalid request_id parameter was specified."); "or invalid request_id parameter was specified.");
@ -67,7 +70,14 @@ namespace OpenIddict.Infrastructure {
} }
// Restore the authorization request parameters from the serialized payload. // Restore the authorization request parameters from the serialized payload.
context.Request.Import(payload); using (var reader = new BsonReader(new MemoryStream(payload))) {
var serializer = JsonSerializer.CreateDefault();
// Note: JsonSerializer.Populate() automatically preserves
// the original request parameters resolved from the cache
// when parameters with the same names are specified.
serializer.Populate(reader, context.Request);
}
} }
} }
@ -344,18 +354,26 @@ namespace OpenIddict.Infrastructure {
// If no request_id parameter can be found in the current request, assume the OpenID Connect request // If no request_id parameter can be found in the current request, assume the OpenID Connect request
// was not serialized yet and store the entire payload in the distributed cache to make it easier // was not serialized yet and store the entire payload in the distributed cache to make it easier
// to flow across requests and internal/external authentication/registration workflows. // to flow across requests and internal/external authentication/registration workflows.
if (string.IsNullOrEmpty(context.Request.GetRequestId())) { if (string.IsNullOrEmpty(context.Request.RequestId)) {
// Generate a request identifier. Note: using a crypto-secure // Generate a request identifier. Note: using a crypto-secure
// random number generator is not necessary in this case. // random number generator is not necessary in this case.
var identifier = Guid.NewGuid().ToString(); var identifier = Guid.NewGuid().ToString();
// Store the serialized authorization request parameters in the distributed cache.
var stream = new MemoryStream();
using (var writer = new BsonWriter(stream)) {
writer.CloseOutput = false;
var serializer = JsonSerializer.CreateDefault();
serializer.Serialize(writer, context.Request);
}
var options = new DistributedCacheEntryOptions { var options = new DistributedCacheEntryOptions {
AbsoluteExpiration = context.Options.SystemClock.UtcNow + TimeSpan.FromMinutes(30), AbsoluteExpiration = context.Options.SystemClock.UtcNow + TimeSpan.FromMinutes(30),
SlidingExpiration = TimeSpan.FromMinutes(10) SlidingExpiration = TimeSpan.FromMinutes(10)
}; };
// Store the serialized authorization request parameters in the distributed cache. await services.Options.Cache.SetAsync(OpenIddictConstants.Environment.Request + identifier, stream.ToArray(), options);
await services.Options.Cache.SetAsync(OpenIddictConstants.Environment.Request + identifier, context.Request.Export(), options);
// Create a new authorization request containing only the request_id parameter. // Create a new authorization request containing only the request_id parameter.
var address = QueryHelpers.AddQueryString( var address = QueryHelpers.AddQueryString(
@ -378,27 +396,23 @@ namespace OpenIddict.Infrastructure {
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>(); var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>();
// Remove the authorization request from the distributed cache. // Remove the authorization request from the distributed cache.
if (!string.IsNullOrEmpty(context.Request.GetRequestId())) { if (!string.IsNullOrEmpty(context.Request.RequestId)) {
// Note: the ApplyAuthorizationResponse event is called for both successful // Note: the ApplyAuthorizationResponse event is called for both successful
// and errored authorization responses but discrimination is not necessary here, // and errored authorization responses but discrimination is not necessary here,
// as the authorization request must be removed from the distributed cache in both cases. // as the authorization request must be removed from the distributed cache in both cases.
await services.Options.Cache.RemoveAsync(OpenIddictConstants.Environment.Request + context.Request.GetRequestId()); await services.Options.Cache.RemoveAsync(OpenIddictConstants.Environment.Request + context.Request.RequestId);
} }
if (!context.Options.ApplicationCanDisplayErrors && !string.IsNullOrEmpty(context.Response.Error) && if (!context.Options.ApplicationCanDisplayErrors && !string.IsNullOrEmpty(context.Response.Error) &&
string.IsNullOrEmpty(context.Response.RedirectUri)) { string.IsNullOrEmpty(context.Response.RedirectUri)) {
// Determine if the status code pages middleware has been enabled for this request. // Determine if the status code pages middleware has been enabled for this request.
// If it was not registered or disabled, let the OpenID Connect server middleware render // If it was not registered or enabled, let the OpenID Connect server middleware render
// a default error page instead of delegating the rendering to the status code middleware. // a default error page instead of delegating the rendering to the status code middleware.
var feature = context.HttpContext.Features.Get<IStatusCodePagesFeature>(); var feature = context.HttpContext.Features.Get<IStatusCodePagesFeature>();
if (feature != null && feature.Enabled) { if (feature != null && feature.Enabled) {
// Replace the default status code to return a 400 response. // Replace the default status code to return a 400 response.
context.HttpContext.Response.StatusCode = 400; context.HttpContext.Response.StatusCode = 400;
// Store the OpenID Connect response in the HTTP context to allow retrieving it
// from user code (e.g from an ASP.NET Core MVC controller or a Nancy module).
context.HttpContext.SetOpenIdConnectResponse(context.Response);
// Mark the request as fully handled to prevent the OpenID Connect server middleware // Mark the request as fully handled to prevent the OpenID Connect server middleware
// from displaying the default error page and to allow the status code pages middleware // from displaying the default error page and to allow the status code pages middleware
// to rewrite the response using the logic defined by the developer when registering it. // to rewrite the response using the logic defined by the developer when registering it.

6
src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Revocation.cs

@ -20,9 +20,9 @@ namespace OpenIddict.Infrastructure {
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>(); var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>();
// When token_type_hint is specified, reject the request if it doesn't correspond to a revocable token. // When token_type_hint is specified, reject the request if it doesn't correspond to a revocable token.
if (!string.IsNullOrEmpty(context.Request.GetTokenTypeHint()) && if (!string.IsNullOrEmpty(context.Request.TokenTypeHint) &&
!string.Equals(context.Request.GetTokenTypeHint(), OpenIdConnectConstants.TokenTypeHints.AuthorizationCode) && !string.Equals(context.Request.TokenTypeHint, OpenIdConnectConstants.TokenTypeHints.AuthorizationCode) &&
!string.Equals(context.Request.GetTokenTypeHint(), OpenIdConnectConstants.TokenTypeHints.RefreshToken)) { !string.Equals(context.Request.TokenTypeHint, OpenIdConnectConstants.TokenTypeHints.RefreshToken)) {
context.Reject( context.Reject(
error: OpenIdConnectConstants.Errors.UnsupportedTokenType, error: OpenIdConnectConstants.Errors.UnsupportedTokenType,
description: "Only authorization codes and refresh tokens can be revoked. When specifying a token_type_hint " + description: "Only authorization codes and refresh tokens can be revoked. When specifying a token_type_hint " +

15
src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Serialization.cs

@ -12,7 +12,6 @@ using AspNet.Security.OpenIdConnect.Extensions;
using AspNet.Security.OpenIdConnect.Server; using AspNet.Security.OpenIdConnect.Server;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace OpenIddict.Infrastructure { namespace OpenIddict.Infrastructure {
public partial class OpenIddictProvider<TUser, TApplication, TAuthorization, TScope, TToken> : OpenIdConnectServerProvider public partial class OpenIddictProvider<TUser, TApplication, TAuthorization, TScope, TToken> : OpenIdConnectServerProvider
@ -20,7 +19,7 @@ namespace OpenIddict.Infrastructure {
public override async Task SerializeAuthorizationCode([NotNull] SerializeAuthorizationCodeContext context) { public override async Task SerializeAuthorizationCode([NotNull] SerializeAuthorizationCodeContext context) {
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>(); var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>();
Debug.Assert(context.Request.RequestType == OpenIdConnectRequestType.Authentication, "The request should be an authorization request."); Debug.Assert(context.Request.IsAuthorizationRequest(), "The request should be an authorization request.");
Debug.Assert(!string.IsNullOrEmpty(context.Request.ClientId), "The client_id parameter shouldn't be null or empty."); Debug.Assert(!string.IsNullOrEmpty(context.Request.ClientId), "The client_id parameter shouldn't be null or empty.");
// Note: a null value could be returned by FindByIdAsync. In this case, throw an exception to abort the token request. // Note: a null value could be returned by FindByIdAsync. In this case, throw an exception to abort the token request.
@ -35,8 +34,11 @@ namespace OpenIddict.Infrastructure {
throw new InvalidOperationException("The application cannot be retrieved from the database."); throw new InvalidOperationException("The application cannot be retrieved from the database.");
} }
// Persist a new token entry in the database and attach it to the user and the client application it is issued to. // Persist a new token entry in the database and attach it
var identifier = await services.Users.CreateTokenAsync(user, context.Request.ClientId, OpenIdConnectConstants.TokenTypeHints.AuthorizationCode); // to the user and the client application it is issued to.
var identifier = await services.Users.CreateTokenAsync(user, context.Request.ClientId,
OpenIdConnectConstants.TokenTypeHints.AuthorizationCode);
if (string.IsNullOrEmpty(identifier)) { if (string.IsNullOrEmpty(identifier)) {
throw new InvalidOperationException("The unique key associated with an authorization code cannot be null or empty."); throw new InvalidOperationException("The unique key associated with an authorization code cannot be null or empty.");
} }
@ -50,8 +52,9 @@ namespace OpenIddict.Infrastructure {
public override async Task SerializeRefreshToken([NotNull] SerializeRefreshTokenContext context) { public override async Task SerializeRefreshToken([NotNull] SerializeRefreshTokenContext context) {
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>(); var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>();
Debug.Assert(context.Request.RequestType == OpenIdConnectRequestType.Token, "The request should be a token request."); Debug.Assert(context.Request.IsTokenRequest(), "The request should be a token request.");
Debug.Assert(!context.Request.IsClientCredentialsGrantType(), "A refresh token should not be issued when using grant_type=client_credentials."); Debug.Assert(!context.Request.IsClientCredentialsGrantType(),
"A refresh token should not be issued when using grant_type=client_credentials.");
// Note: a null value could be returned by FindByIdAsync if the user was removed after the initial // Note: a null value could be returned by FindByIdAsync if the user was removed after the initial
// check made by HandleTokenRequest. In this case, throw an exception to abort the token request. // check made by HandleTokenRequest. In this case, throw an exception to abort the token request.

8
src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Session.cs

@ -112,17 +112,13 @@ namespace OpenIddict.Infrastructure {
if (!context.Options.ApplicationCanDisplayErrors && !string.IsNullOrEmpty(context.Response.Error) && if (!context.Options.ApplicationCanDisplayErrors && !string.IsNullOrEmpty(context.Response.Error) &&
string.IsNullOrEmpty(context.Response.PostLogoutRedirectUri)) { string.IsNullOrEmpty(context.Response.PostLogoutRedirectUri)) {
// Determine if the status code pages middleware has been enabled for this request. // Determine if the status code pages middleware has been enabled for this request.
// If it was not registered or disabled, let the OpenID Connect server middleware render // If it was not registered or enabled, let the OpenID Connect server middleware render
// a default error page instead of delegating the rendering to the status code middleware. // a default error page instead of delegating the rendering to the status code middleware.
var feature = context.HttpContext.Features.Get<IStatusCodePagesFeature>(); var feature = context.HttpContext.Features.Get<IStatusCodePagesFeature>();
if (feature != null && feature.Enabled) { if (feature != null && feature.Enabled) {
// Replace the default status code to return a 400 response. // Replace the default status code by a 400 response.
context.HttpContext.Response.StatusCode = 400; context.HttpContext.Response.StatusCode = 400;
// Store the OpenID Connect response in the HTTP context to allow retrieving it
// from user code (e.g from an ASP.NET Core MVC controller or a Nancy module).
context.HttpContext.SetOpenIdConnectResponse(context.Response);
// Mark the request as fully handled to prevent the OpenID Connect server middleware // Mark the request as fully handled to prevent the OpenID Connect server middleware
// from displaying the default error page and to allow the status code pages middleware // from displaying the default error page and to allow the status code pages middleware
// to rewrite the response using the logic defined by the developer when registering it. // to rewrite the response using the logic defined by the developer when registering it.

46
src/OpenIddict.Core/OpenIddictBuilder.cs

@ -10,13 +10,11 @@ using System.IdentityModel.Tokens.Jwt;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using AspNet.Security.OpenIdConnect.Extensions; using AspNet.Security.OpenIdConnect.Extensions;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using OpenIddict; using OpenIddict;
namespace Microsoft.AspNetCore.Builder { namespace Microsoft.AspNetCore.Builder {
@ -286,49 +284,7 @@ namespace Microsoft.AspNetCore.Builder {
/// </summary> /// </summary>
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
public virtual OpenIddictBuilder AddEphemeralSigningKey() { public virtual OpenIddictBuilder AddEphemeralSigningKey() {
// Note: a 1024-bit key might be returned by RSA.Create() on .NET Desktop/Mono, return Configure(options => options.SigningCredentials.AddEphemeralKey());
// where RSACryptoServiceProvider is still the default implementation and
// where custom implementations can be registered via CryptoConfig.
// To ensure the key size is always acceptable, replace it if necessary.
var algorithm = RSA.Create();
if (algorithm.KeySize < 2048) {
algorithm.KeySize = 2048;
}
#if NET451
// Note: RSACng cannot be used as it's not available on Mono.
if (algorithm.KeySize < 2048 && algorithm is RSACryptoServiceProvider) {
algorithm.Dispose();
algorithm = new RSACryptoServiceProvider(2048);
}
#endif
if (algorithm.KeySize < 2048) {
throw new InvalidOperationException("The ephemeral key generation failed.");
}
// Note: the RSA instance cannot be flowed as-is due to a bug in IdentityModel that disposes
// the underlying algorithm when it can be cast to RSACryptoServiceProvider. To work around
// this bug, the RSA public/private parameters are manually exported and re-imported when needed.
SecurityKey key;
#if NET451
if (algorithm is RSACryptoServiceProvider) {
var parameters = algorithm.ExportParameters(includePrivateParameters: true);
key = new RsaSecurityKey(parameters);
// Dispose the algorithm instance.
algorithm.Dispose();
}
else {
#endif
key = new RsaSecurityKey(algorithm);
#if NET451
}
#endif
return Configure(options => options.SigningCredentials.AddKey(key));
} }
/// <summary> /// <summary>

3
src/OpenIddict.Core/OpenIddictOptions.cs

@ -16,9 +16,6 @@ namespace OpenIddict {
/// </summary> /// </summary>
public class OpenIddictOptions : OpenIdConnectServerOptions { public class OpenIddictOptions : OpenIdConnectServerOptions {
public OpenIddictOptions() { public OpenIddictOptions() {
AuthorizationEndpointPath = IntrospectionEndpointPath = LogoutEndpointPath =
RevocationEndpointPath = TokenEndpointPath = UserinfoEndpointPath = PathString.Empty;
// Use the same lifespan as the default security stamp // Use the same lifespan as the default security stamp
// verification interval used by ASP.NET Core Identity. // verification interval used by ASP.NET Core Identity.
AccessTokenLifetime = TimeSpan.FromMinutes(30); AccessTokenLifetime = TimeSpan.FromMinutes(30);

2
src/OpenIddict.Core/project.json

@ -33,7 +33,7 @@
}, },
"dependencies": { "dependencies": {
"AspNet.Security.OpenIdConnect.Server": "1.0.0-beta6-final", "AspNet.Security.OpenIdConnect.Server": "1.0.0-beta7-*",
"CryptoHelper": "2.0.0", "CryptoHelper": "2.0.0",
"JetBrains.Annotations": { "type": "build", "version": "10.1.4" }, "JetBrains.Annotations": { "type": "build", "version": "10.1.4" },
"Microsoft.AspNetCore.Diagnostics.Abstractions": "1.0.0", "Microsoft.AspNetCore.Diagnostics.Abstractions": "1.0.0",

Loading…
Cancel
Save