Browse Source

Introduce a new OpenIddictAuthorization.Type property and the corresponding stores methods

pull/486/head
Kévin Chalet 9 years ago
parent
commit
acfcef6817
  1. 5
      src/OpenIddict.Core/Descriptors/OpenIddictAuthorizationDescriptor.cs
  2. 24
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  3. 6
      src/OpenIddict.Core/OpenIddictConstants.cs
  4. 22
      src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs
  5. 45
      src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
  6. 10
      src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
  7. 75
      src/OpenIddict.EntityFramework/OpenIddictExtensions.cs
  8. 3
      src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs
  9. 24
      src/OpenIddict.EntityFrameworkCore/OpenIddictExtensions.cs
  10. 3
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
  11. 5
      src/OpenIddict.Models/OpenIddictAuthorization.cs
  12. 7
      src/OpenIddict/OpenIddictProvider.Serialization.cs
  13. 5
      test/OpenIddict.Tests/OpenIddictProviderTests.Serialization.cs

5
src/OpenIddict.Core/Descriptors/OpenIddictAuthorizationDescriptor.cs

@ -28,5 +28,10 @@ namespace OpenIddict.Core
/// Gets or sets the subject associated with the authorization.
/// </summary>
public string Subject { get; set; }
/// <summary>
/// Gets or sets the type of the authorization.
/// </summary>
public virtual string Type { get; set; }
}
}

24
src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs

@ -85,6 +85,12 @@ namespace OpenIddict.Core
throw new ArgumentNullException(nameof(authorization));
}
// If no type was explicitly specified, assume that the authorization is a permanent authorization.
if (string.IsNullOrEmpty(await Store.GetTypeAsync(authorization, cancellationToken)))
{
await Store.SetTypeAsync(authorization, OpenIddictConstants.AuthorizationTypes.Permanent, cancellationToken);
}
await ValidateAsync(authorization, cancellationToken);
return await Store.CreateAsync(authorization, cancellationToken);
}
@ -104,6 +110,13 @@ namespace OpenIddict.Core
throw new ArgumentNullException(nameof(descriptor));
}
// If no type was explicitly specified, assume that
// the authorization is a permanent authorization.
if (string.IsNullOrEmpty(descriptor.Type))
{
descriptor.Type = OpenIddictConstants.AuthorizationTypes.Permanent;
}
await ValidateAsync(descriptor, cancellationToken);
return await Store.CreateAsync(descriptor, cancellationToken);
}
@ -309,6 +322,17 @@ namespace OpenIddict.Core
throw new ArgumentNullException(nameof(descriptor));
}
if (string.IsNullOrEmpty(descriptor.Type))
{
throw new ArgumentException("The authorization type cannot be null or empty.", nameof(descriptor));
}
if (!string.Equals(descriptor.Type, OpenIddictConstants.AuthorizationTypes.AdHoc, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(descriptor.Type, OpenIddictConstants.AuthorizationTypes.Permanent, StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("The specified authorization type is not supported by the default token manager.");
}
if (string.IsNullOrEmpty(descriptor.Status))
{
throw new ArgumentException("The status cannot be null or empty.");

6
src/OpenIddict.Core/OpenIddictConstants.cs

@ -8,6 +8,12 @@ namespace OpenIddict.Core
{
public static class OpenIddictConstants
{
public static class AuthorizationTypes
{
public const string AdHoc = "ad-hoc";
public const string Permanent = "permanent";
}
public static class Claims
{
public const string Roles = "roles";

22
src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs

@ -138,6 +138,17 @@ namespace OpenIddict.Core
/// </returns>
Task<string> GetSubjectAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the type associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the type associated with the specified authorization.
/// </returns>
Task<string> GetTypeAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
@ -173,6 +184,17 @@ namespace OpenIddict.Core
/// </returns>
Task SetStatusAsync([NotNull] TAuthorization authorization, [NotNull] string status, CancellationToken cancellationToken);
/// <summary>
/// Sets the type associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="type">The type associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task SetTypeAsync([NotNull] TAuthorization authorization, [NotNull] string type, CancellationToken cancellationToken);
/// <summary>
/// Updates an existing authorization.
/// </summary>

45
src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs

@ -199,6 +199,25 @@ namespace OpenIddict.Core
return Task.FromResult(authorization.Subject);
}
/// <summary>
/// Retrieves the type associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the type associated with the specified authorization.
/// </returns>
public virtual Task<string> GetTypeAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Task.FromResult(authorization.Type);
}
/// <summary>
/// Executes the specified query.
/// </summary>
@ -254,11 +273,37 @@ namespace OpenIddict.Core
/// </returns>
public virtual Task SetStatusAsync([NotNull] TAuthorization authorization, [NotNull] string status, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
authorization.Status = status;
return Task.CompletedTask;
}
/// <summary>
/// Sets the type associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="type">The type associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual Task SetTypeAsync([NotNull] TAuthorization authorization, [NotNull] string type, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
authorization.Type = type;
return Task.FromResult(0);
}
/// <summary>
/// Updates an existing authorization.
/// </summary>

10
src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs

@ -432,6 +432,11 @@ namespace OpenIddict.Core
public virtual Task SetExpirationDateAsync([NotNull] TToken token,
[CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
token.ExpirationDate = date;
return Task.CompletedTask;
@ -448,6 +453,11 @@ namespace OpenIddict.Core
/// </returns>
public virtual Task SetStatusAsync([NotNull] TToken token, [NotNull] string status, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
token.Status = status;
return Task.CompletedTask;

75
src/OpenIddict.EntityFramework/OpenIddictExtensions.cs

@ -184,56 +184,85 @@ namespace Microsoft.Extensions.DependencyInjection
// Configure the TApplication entity.
builder.Entity<TApplication>()
.HasKey(application => application.Id);
.HasKey(application => application.Id);
builder.Entity<TApplication>()
.Property(application => application.ClientId)
.HasMaxLength(450)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
.Property(application => application.ClientId)
.IsRequired()
.HasMaxLength(450)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
builder.Entity<TApplication>()
.HasMany(application => application.Authorizations)
.WithOptional(authorization => authorization.Application)
.Map(association => association.MapKey("ApplicationId"));
.Property(application => application.Type)
.IsRequired();
builder.Entity<TApplication>()
.HasMany(application => application.Tokens)
.WithOptional(token => token.Application)
.Map(association => association.MapKey("ApplicationId"));
.HasMany(application => application.Authorizations)
.WithOptional(authorization => authorization.Application)
.Map(association => association.MapKey("ApplicationId"));
builder.Entity<TApplication>()
.ToTable("OpenIddictApplications");
.HasMany(application => application.Tokens)
.WithOptional(token => token.Application)
.Map(association => association.MapKey("ApplicationId"));
builder.Entity<TApplication>()
.ToTable("OpenIddictApplications");
// Configure the TAuthorization entity.
builder.Entity<TAuthorization>()
.HasKey(authorization => authorization.Id);
.HasKey(authorization => authorization.Id);
builder.Entity<TAuthorization>()
.Property(authorization => authorization.Status)
.IsRequired();
builder.Entity<TAuthorization>()
.Property(authorization => authorization.Subject)
.IsRequired();
builder.Entity<TAuthorization>()
.Property(authorization => authorization.Type)
.IsRequired();
builder.Entity<TAuthorization>()
.HasMany(application => application.Tokens)
.WithOptional(token => token.Authorization)
.Map(association => association.MapKey("AuthorizationId"));
.HasMany(application => application.Tokens)
.WithOptional(token => token.Authorization)
.Map(association => association.MapKey("AuthorizationId"));
builder.Entity<TAuthorization>()
.ToTable("OpenIddictAuthorizations");
.ToTable("OpenIddictAuthorizations");
// Configure the TScope entity.
builder.Entity<TScope>()
.HasKey(scope => scope.Id);
.HasKey(scope => scope.Id);
builder.Entity<TScope>()
.Property(scope => scope.Name)
.IsRequired();
builder.Entity<TScope>()
.ToTable("OpenIddictScopes");
.ToTable("OpenIddictScopes");
// Configure the TToken entity.
builder.Entity<TToken>()
.HasKey(token => token.Id);
.HasKey(token => token.Id);
builder.Entity<TToken>()
.Property(token => token.Hash)
.HasMaxLength(450)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
builder.Entity<TToken>()
.Property(token => token.Subject)
.IsRequired();
builder.Entity<TToken>()
.Property(token => token.Hash)
.HasMaxLength(450)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
.Property(token => token.Type)
.IsRequired();
builder.Entity<TToken>()
.ToTable("OpenIddictTokens");
.ToTable("OpenIddictTokens");
return builder;
}

3
src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs

@ -146,7 +146,8 @@ namespace OpenIddict.EntityFramework
var authorization = new TAuthorization
{
Status = descriptor.Status,
Subject = descriptor.Subject
Subject = descriptor.Subject,
Type = descriptor.Type
};
if (descriptor.Scopes.Count != 0)

24
src/OpenIddict.EntityFrameworkCore/OpenIddictExtensions.cs

@ -225,6 +225,12 @@ namespace Microsoft.Extensions.DependencyInjection
entity.HasIndex(application => application.ClientId)
.IsUnique(unique: true);
entity.Property(application => application.ClientId)
.IsRequired(required: true);
entity.Property(application => application.Type)
.IsRequired();
entity.HasMany(application => application.Authorizations)
.WithOne(authorization => authorization.Application)
.HasForeignKey("ApplicationId")
@ -243,6 +249,15 @@ namespace Microsoft.Extensions.DependencyInjection
{
entity.HasKey(authorization => authorization.Id);
entity.Property(authorization => authorization.Status)
.IsRequired();
entity.Property(authorization => authorization.Subject)
.IsRequired();
entity.Property(authorization => authorization.Type)
.IsRequired();
entity.HasMany(application => application.Tokens)
.WithOne(token => token.Authorization)
.HasForeignKey("AuthorizationId")
@ -256,6 +271,9 @@ namespace Microsoft.Extensions.DependencyInjection
{
entity.HasKey(scope => scope.Id);
entity.Property(scope => scope.Name)
.IsRequired();
entity.ToTable("OpenIddictScopes");
});
@ -267,6 +285,12 @@ namespace Microsoft.Extensions.DependencyInjection
entity.HasIndex(token => token.Hash)
.IsUnique(unique: true);
entity.Property(token => token.Subject)
.IsRequired();
entity.Property(token => token.Type)
.IsRequired();
entity.ToTable("OpenIddictTokens");
});

3
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs

@ -145,7 +145,8 @@ namespace OpenIddict.EntityFrameworkCore
var authorization = new TAuthorization
{
Status = descriptor.Status,
Subject = descriptor.Subject
Subject = descriptor.Subject,
Type = descriptor.Type
};
if (descriptor.Scopes.Count != 0)

5
src/OpenIddict.Models/OpenIddictAuthorization.cs

@ -65,5 +65,10 @@ namespace OpenIddict.Models
/// associated with the current authorization.
/// </summary>
public virtual IList<TToken> Tokens { get; } = new List<TToken>();
/// <summary>
/// Gets or sets the type of the current authorization.
/// </summary>
public virtual string Type { get; set; }
}
}

7
src/OpenIddict/OpenIddictProvider.Serialization.cs

@ -251,7 +251,7 @@ namespace OpenIddict
descriptor.AuthorizationId = ticket.GetProperty(OpenIddictConstants.Properties.AuthorizationId);
}
// Otherwise, create an ad-hoc authorization if the token is an authorization code.
// Otherwise, create an ad hoc authorization if the token is an authorization code.
else if (type == OpenIdConnectConstants.TokenUsages.AuthorizationCode)
{
Debug.Assert(!string.IsNullOrEmpty(descriptor.ApplicationId), "The client identifier shouldn't be null.");
@ -261,7 +261,7 @@ namespace OpenIddict
{
descriptor.AuthorizationId = await Authorizations.GetIdAsync(authorization, context.RequestAborted);
Logger.LogInformation("An ad-hoc authorization was automatically created and " +
Logger.LogInformation("An ad hoc authorization was automatically created and " +
"associated with the '{ClientId}' application: {Identifier}.",
request.ClientId, descriptor.AuthorizationId);
}
@ -401,7 +401,8 @@ namespace OpenIddict
{
ApplicationId = token.ApplicationId,
Status = OpenIddictConstants.Statuses.Valid,
Subject = token.Subject
Subject = token.Subject,
Type = OpenIddictConstants.AuthorizationTypes.AdHoc
};
foreach (var scope in request.GetScopes())

5
test/OpenIddict.Tests/OpenIddictProviderTests.Serialization.cs

@ -571,7 +571,7 @@ namespace OpenIddict.Tests
builder.Services.AddSingleton(CreateTokenManager(instance =>
{
instance.Setup(mock => mock.CreateAsync(It.IsAny<OpenIddictTokenDescriptor>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(token);
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny<CancellationToken>()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
@ -596,7 +596,8 @@ namespace OpenIddict.Tests
Mock.Get(manager).Verify(mock => mock.CreateAsync(
It.Is<OpenIddictAuthorizationDescriptor>(descriptor =>
descriptor.ApplicationId == "3E228451-1555-46F7-A471-951EFBA23A56" &&
descriptor.Subject == "Bob le Magnifique"),
descriptor.Subject == "Bob le Magnifique" &&
descriptor.Type == OpenIddictConstants.AuthorizationTypes.AdHoc),
It.IsAny<CancellationToken>()), Times.Once());
}

Loading…
Cancel
Save