Browse Source

Add non-GUID/string primary keys support for OpenIddictToken and add new log messages

pull/132/head
Kévin Chalet 10 years ago
parent
commit
3204c31560
  1. 2
      samples/Mvc.Server/Startup.cs
  2. 16
      src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Revocation.cs
  3. 18
      src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Serialization.cs
  4. 36
      src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
  5. 26
      src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
  6. 37
      src/OpenIddict.Core/Stores/IOpenIddictApplicationStore.cs
  7. 13
      src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
  8. 2
      src/OpenIddict.EntityFramework/Models/OpenIddictApplication.cs
  9. 42
      src/OpenIddict.EntityFramework/Stores/OpenIddictApplicationStore.cs
  10. 31
      src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs

2
samples/Mvc.Server/Startup.cs

@ -142,7 +142,7 @@ namespace Mvc.Server {
// context.Applications.Add(new OpenIddictApplication { // context.Applications.Add(new OpenIddictApplication {
// Id = "resource_server", // Id = "resource_server",
// DisplayName = "Main resource server", // DisplayName = "Main resource server",
// Secret = "875sqd4s5d748z78z7ds1ff8zz8814ff88ed8ea4z4zzd", // Secret = Crypto.HashPassword("secret_secret_secret"),
// Type = OpenIddictConstants.ClientTypes.Confidential // Type = OpenIddictConstants.ClientTypes.Confidential
// }); // });

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

@ -5,11 +5,13 @@
*/ */
using System; using System;
using System.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Extensions; 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.Extensions.Logging;
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
@ -88,24 +90,24 @@ namespace OpenIddict.Infrastructure {
// If the received token is not a refresh token, set Revoked // If the received token is not a refresh token, set Revoked
// to false to indicate that the token cannot be revoked. // to false to indicate that the token cannot be revoked.
if (!context.Ticket.IsRefreshToken()) { if (!context.Ticket.IsRefreshToken()) {
services.Logger.LogError("The revocation request was rejected because the token was not a refresh token.");
context.Revoked = false; context.Revoked = false;
return; return;
} }
// Extract the token identifier from the authentication ticket. // Extract the token identifier from the authentication ticket.
// If the identifier cannot be extracted, abort the revocation.
var identifier = context.Ticket.GetTicketId(); var identifier = context.Ticket.GetTicketId();
if (string.IsNullOrEmpty(identifier)) { Debug.Assert(!string.IsNullOrEmpty(identifier),
context.Revoked = true; "The refresh token should contain a ticket identifier.");
return;
}
// Retrieve the token from the database. If the token cannot be found, // Retrieve the token from the database. If the token cannot be found,
// assume it is invalid and consider the revocation as successful. // assume it is invalid and consider the revocation as successful.
var token = await services.Tokens.FindByIdAsync(identifier); var token = await services.Tokens.FindByIdAsync(identifier);
if (token == null) { if (token == null) {
services.Logger.LogInformation("The refresh token '{Identifier}' was already revoked.", identifier);
context.Revoked = true; context.Revoked = true;
return; return;
@ -114,6 +116,8 @@ namespace OpenIddict.Infrastructure {
// Revoke the refresh token. // Revoke the refresh token.
await services.Tokens.RevokeAsync(token); await services.Tokens.RevokeAsync(token);
services.Logger.LogInformation("The refresh token '{Identifier}' was revoked.", identifier);
context.Revoked = true; context.Revoked = true;
} }
} }

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

@ -4,7 +4,7 @@
* the license and the contributors participating to this project. * the license and the contributors participating to this project.
*/ */
using System.Diagnostics; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Extensions; using AspNet.Security.OpenIdConnect.Extensions;
using AspNet.Security.OpenIdConnect.Server; using AspNet.Security.OpenIdConnect.Server;
@ -17,14 +17,16 @@ 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>>();
// Note: the identifier cannot be null as it's always // Persist a new token entry in the database.
// generated by the OpenID Connect server middleware var identifier = await services.Tokens.CreateAsync(OpenIdConnectConstants.TokenTypeHints.RefreshToken);
// before invoking the SerializeRefreshToken event. if (string.IsNullOrEmpty(identifier)) {
Debug.Assert(!string.IsNullOrEmpty(context.Ticket.GetTicketId()), throw new InvalidOperationException("The unique key associated with a refresh token cannot be null or empty.");
"The unique identifier associated with the refresh token was missing or empty."); }
// Only persist the refresh token identifier in the database. // Attach the key returned by the underlying store
await services.Tokens.CreateAsync(context.Ticket.GetTicketId(), OpenIdConnectConstants.TokenTypeHints.RefreshToken); // to the refresh token to override the default GUID
// generated by the OpenID Connect server middleware.
context.Ticket.SetTicketId(identifier);
} }
} }
} }

36
src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs

@ -52,8 +52,11 @@ namespace OpenIddict {
/// Creates a new application. /// Creates a new application.
/// </summary> /// </summary>
/// <param name="application">The application to create.</param> /// <param name="application">The application to create.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>
public virtual Task CreateAsync(TApplication application) { /// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the application.
/// </returns>
public virtual Task<string> CreateAsync(TApplication application) {
if (application == null) { if (application == null) {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
@ -65,7 +68,10 @@ namespace OpenIddict {
/// Retrieves an application using its unique identifier. /// Retrieves an application using its unique identifier.
/// </summary> /// </summary>
/// <param name="identifier">The unique identifier associated with the application.</param> /// <param name="identifier">The unique identifier associated with the application.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
/// </returns>
public virtual Task<TApplication> FindByIdAsync(string identifier) { public virtual Task<TApplication> FindByIdAsync(string identifier) {
return Store.FindByIdAsync(identifier, CancellationToken); return Store.FindByIdAsync(identifier, CancellationToken);
} }
@ -74,7 +80,10 @@ namespace OpenIddict {
/// Retrieves an application using its post_logout_redirect_uri. /// Retrieves an application using its post_logout_redirect_uri.
/// </summary> /// </summary>
/// <param name="url">The post_logout_redirect_uri associated with the application.</param> /// <param name="url">The post_logout_redirect_uri associated with the application.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result
/// returns the client application corresponding to the post_logout_redirect_uri.
/// </returns>
public virtual Task<TApplication> FindByLogoutRedirectUri(string url) { public virtual Task<TApplication> FindByLogoutRedirectUri(string url) {
return Store.FindByLogoutRedirectUri(url, CancellationToken); return Store.FindByLogoutRedirectUri(url, CancellationToken);
} }
@ -83,7 +92,10 @@ namespace OpenIddict {
/// Retrieves the client type associated with an application. /// Retrieves the client type associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client type of the application (by default, "public").
/// </returns>
public virtual async Task<string> GetClientTypeAsync(TApplication application) { public virtual async Task<string> GetClientTypeAsync(TApplication application) {
if (application == null) { if (application == null) {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
@ -105,7 +117,10 @@ namespace OpenIddict {
/// Retrieves the display name associated with an application. /// Retrieves the display name associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the display name associated with the application.
/// </returns>
public virtual Task<string> GetDisplayNameAsync(TApplication application) { public virtual Task<string> GetDisplayNameAsync(TApplication application) {
if (application == null) { if (application == null) {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
@ -119,7 +134,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="address">The address that should be compared to the redirect_uri stored in the database.</param> /// <param name="address">The address that should be compared to the redirect_uri stored in the database.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns a boolean indicating whether the redirect_uri was valid.
/// </returns>
public virtual async Task<bool> ValidateRedirectUriAsync(TApplication application, string address) { public virtual async Task<bool> ValidateRedirectUriAsync(TApplication application, string address) {
if (application == null) { if (application == null) {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
@ -141,6 +159,10 @@ namespace OpenIddict {
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="secret">The secret that should be compared to the client_secret stored in the database.</param> /// <param name="secret">The secret that should be compared to the client_secret stored in the database.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns a boolean indicating whether the client secret was valid.
/// </returns>
public virtual async Task<bool> ValidateSecretAsync(TApplication application, string secret) { public virtual async Task<bool> ValidateSecretAsync(TApplication application, string secret) {
if (application == null) { if (application == null) {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));

26
src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs

@ -75,7 +75,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="user">The user corresponding to the identity.</param> /// <param name="user">The user corresponding to the identity.</param>
/// <param name="scopes">The scopes granted by the resource owner.</param> /// <param name="scopes">The scopes granted by the resource owner.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the <see cref="ClaimsIdentity"/> corresponding to the user.
/// </returns>
public virtual async Task<ClaimsIdentity> CreateIdentityAsync(TUser user, IEnumerable<string> scopes) { public virtual async Task<ClaimsIdentity> CreateIdentityAsync(TUser user, IEnumerable<string> scopes) {
if (user == null) { if (user == null) {
throw new ArgumentNullException(nameof(user)); throw new ArgumentNullException(nameof(user));
@ -145,26 +148,27 @@ namespace OpenIddict {
/// <summary> /// <summary>
/// Creates a new token, defined by a unique identifier and a token type. /// Creates a new token, defined by a unique identifier and a token type.
/// </summary> /// </summary>
/// <param name="identifier">The unique identifier associated with the token to create.</param>
/// <param name="type">The token type.</param> /// <param name="type">The token type.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>
public virtual Task CreateAsync(string identifier, string type) { /// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
if (string.IsNullOrEmpty(identifier)) { /// whose result returns the unique identifier associated with the token.
throw new ArgumentException("The identifier cannot be null or empty", nameof(identifier)); /// </returns>
} public virtual Task<string> CreateAsync(string type) {
if (string.IsNullOrEmpty(type)) { if (string.IsNullOrEmpty(type)) {
throw new ArgumentException("The token type cannot be null or empty", nameof(type)); throw new ArgumentException("The token type cannot be null or empty", nameof(type));
} }
return Store.CreateAsync(identifier, type, CancellationToken); return Store.CreateAsync(type, CancellationToken);
} }
/// <summary> /// <summary>
/// Retrieves an token using its unique identifier. /// Retrieves a token using its unique identifier.
/// </summary> /// </summary>
/// <param name="identifier">The unique identifier associated with the token.</param> /// <param name="identifier">The unique identifier associated with the token.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the token corresponding to the unique identifier.
/// </returns>
public virtual Task<TToken> FindByIdAsync(string identifier) { public virtual Task<TToken> FindByIdAsync(string identifier) {
if (string.IsNullOrEmpty(identifier)) { if (string.IsNullOrEmpty(identifier)) {
throw new ArgumentException("The identifier cannot be null or empty", nameof(identifier)); throw new ArgumentException("The identifier cannot be null or empty", nameof(identifier));

37
src/OpenIddict.Core/Stores/IOpenIddictApplicationStore.cs

@ -18,15 +18,21 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="application">The application to create.</param> /// <param name="application">The application to create.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
Task CreateAsync(TApplication application, CancellationToken cancellationToken); /// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the application.
/// </returns>
Task<string> CreateAsync(TApplication application, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Retrieves an application using its unique identifier. /// Retrieves an application using its unique identifier.
/// </summary> /// </summary>
/// <param name="identifier">The unique identifier associated with the application.</param> /// <param name="identifier">The unique identifier associated with the application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
/// </returns>
Task<TApplication> FindByIdAsync(string identifier, CancellationToken cancellationToken); Task<TApplication> FindByIdAsync(string identifier, CancellationToken cancellationToken);
/// <summary> /// <summary>
@ -34,7 +40,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="url">The post_logout_redirect_uri associated with the application.</param> /// <param name="url">The post_logout_redirect_uri associated with the application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result
/// returns the client application corresponding to the post_logout_redirect_uri.
/// </returns>
Task<TApplication> FindByLogoutRedirectUri(string url, CancellationToken cancellationToken); Task<TApplication> FindByLogoutRedirectUri(string url, CancellationToken cancellationToken);
/// <summary> /// <summary>
@ -42,7 +51,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client type of the application (by default, "public").
/// </returns>
Task<string> GetClientTypeAsync(TApplication application, CancellationToken cancellationToken); Task<string> GetClientTypeAsync(TApplication application, CancellationToken cancellationToken);
/// <summary> /// <summary>
@ -50,7 +62,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the display name associated with the application.
/// </returns>
Task<string> GetDisplayNameAsync(TApplication application, CancellationToken cancellationToken); Task<string> GetDisplayNameAsync(TApplication application, CancellationToken cancellationToken);
/// <summary> /// <summary>
@ -58,7 +73,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the redirect_uri associated with the application.
/// </returns>
Task<string> GetRedirectUriAsync(TApplication application, CancellationToken cancellationToken); Task<string> GetRedirectUriAsync(TApplication application, CancellationToken cancellationToken);
/// <summary> /// <summary>
@ -66,7 +84,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the hashed secret associated with the application.
/// </returns>
Task<string> GetHashedSecretAsync(TApplication application, CancellationToken cancellationToken); Task<string> GetHashedSecretAsync(TApplication application, CancellationToken cancellationToken);
} }
} }

13
src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs

@ -16,18 +16,23 @@ namespace OpenIddict {
/// <summary> /// <summary>
/// Creates a new token, defined by a unique identifier and a token type. /// Creates a new token, defined by a unique identifier and a token type.
/// </summary> /// </summary>
/// <param name="identifier">The unique identifier associated with the token to create.</param>
/// <param name="type">The token type.</param> /// <param name="type">The token type.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
Task CreateAsync(string identifier, string type, CancellationToken cancellationToken); /// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the token.
/// </returns>
Task<string> CreateAsync(string type, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Retrieves an token using its unique identifier. /// Retrieves an token using its unique identifier.
/// </summary> /// </summary>
/// <param name="identifier">The unique identifier associated with the token.</param> /// <param name="identifier">The unique identifier associated with the token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the token corresponding to the unique identifier.
/// </returns>
Task<TToken> FindByIdAsync(string identifier, CancellationToken cancellationToken); Task<TToken> FindByIdAsync(string identifier, CancellationToken cancellationToken);
/// <summary> /// <summary>

2
src/OpenIddict.EntityFramework/Models/OpenIddictApplication.cs

@ -55,6 +55,6 @@ namespace OpenIddict {
/// Gets or sets the application type /// Gets or sets the application type
/// associated with the current application. /// associated with the current application.
/// </summary> /// </summary>
public virtual string Type { get; set; } public virtual string Type { get; set; } = OpenIddictConstants.ClientTypes.Public;
} }
} }

42
src/OpenIddict.EntityFramework/Stores/OpenIddictApplicationStore.cs

@ -41,14 +41,22 @@ namespace OpenIddict {
/// <param name="application">The application to create.</param> /// <param name="application">The application to create.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
public virtual Task CreateAsync(TApplication application, CancellationToken cancellationToken) { public virtual async Task<string> CreateAsync(TApplication application, CancellationToken cancellationToken) {
if (application == null) { if (application == null) {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
// Ensure that the key type can be serialized.
var converter = TypeDescriptor.GetConverter(typeof(TKey));
if (!converter.CanConvertTo(typeof(string))) {
throw new InvalidOperationException($"The '{typeof(TKey).Name}' key type is not supported.");
}
Context.Add(application); Context.Add(application);
return Context.SaveChangesAsync(cancellationToken); await Context.SaveChangesAsync(cancellationToken);
return converter.ConvertToInvariantString(application.Id);
} }
/// <summary> /// <summary>
@ -56,7 +64,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="identifier">The unique identifier associated with the application.</param> /// <param name="identifier">The unique identifier associated with the application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
/// </returns>
public virtual Task<TApplication> FindByIdAsync(string identifier, CancellationToken cancellationToken) { public virtual Task<TApplication> FindByIdAsync(string identifier, CancellationToken cancellationToken) {
var converter = TypeDescriptor.GetConverter(typeof(TKey)); var converter = TypeDescriptor.GetConverter(typeof(TKey));
@ -76,7 +87,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="url">The post_logout_redirect_uri associated with the application.</param> /// <param name="url">The post_logout_redirect_uri associated with the application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result
/// returns the client application corresponding to the post_logout_redirect_uri.
/// </returns>
public virtual Task<TApplication> FindByLogoutRedirectUri(string url, CancellationToken cancellationToken) { public virtual Task<TApplication> FindByLogoutRedirectUri(string url, CancellationToken cancellationToken) {
return Applications.SingleOrDefaultAsync(application => application.LogoutRedirectUri == url, cancellationToken); return Applications.SingleOrDefaultAsync(application => application.LogoutRedirectUri == url, cancellationToken);
} }
@ -86,7 +100,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client type of the application (by default, "public").
/// </returns>
public virtual Task<string> GetClientTypeAsync(TApplication application, CancellationToken cancellationToken) { public virtual Task<string> GetClientTypeAsync(TApplication application, CancellationToken cancellationToken) {
if (application == null) { if (application == null) {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
@ -100,7 +117,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the display name associated with the application.
/// </returns>
public virtual Task<string> GetDisplayNameAsync(TApplication application, CancellationToken cancellationToken) { public virtual Task<string> GetDisplayNameAsync(TApplication application, CancellationToken cancellationToken) {
if (application == null) { if (application == null) {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
@ -114,7 +134,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the redirect_uri associated with the application.
/// </returns>
public virtual Task<string> GetRedirectUriAsync(TApplication application, CancellationToken cancellationToken) { public virtual Task<string> GetRedirectUriAsync(TApplication application, CancellationToken cancellationToken) {
if (application == null) { if (application == null) {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
@ -128,7 +151,10 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the hashed secret associated with the application.
/// </returns>
public virtual Task<string> GetHashedSecretAsync(TApplication application, CancellationToken cancellationToken) { public virtual Task<string> GetHashedSecretAsync(TApplication application, CancellationToken cancellationToken) {
if (application == null) { if (application == null) {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));

31
src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs

@ -38,24 +38,25 @@ namespace OpenIddict {
/// <summary> /// <summary>
/// Creates a new token, defined by a unique identifier and a token type. /// Creates a new token, defined by a unique identifier and a token type.
/// </summary> /// </summary>
/// <param name="identifier">The unique identifier associated with the token to create.</param>
/// <param name="type">The token type.</param> /// <param name="type">The token type.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
public virtual Task CreateAsync(string identifier, string type, CancellationToken cancellationToken) { /// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the token.
/// </returns>
public virtual async Task<string> CreateAsync(string type, CancellationToken cancellationToken) {
// Ensure that the key type can be serialized.
var converter = TypeDescriptor.GetConverter(typeof(TKey)); var converter = TypeDescriptor.GetConverter(typeof(TKey));
if (!converter.CanConvertTo(typeof(string))) {
// Ensure that the key type is compatible with string keys. throw new InvalidOperationException($"The '{typeof(TKey).Name}' key type is not supported.");
if (!converter.CanConvertFrom(typeof(string))) {
return Task.FromResult(0);
} }
var key = (TKey) converter.ConvertFromInvariantString(identifier); var token = new TToken { Type = type };
var token = new TToken { Id = key, Type = type };
Tokens.Add(token); Tokens.Add(token);
return Context.SaveChangesAsync(cancellationToken); await Context.SaveChangesAsync(cancellationToken);
return converter.ConvertToInvariantString(token.Id);
} }
/// <summary> /// <summary>
@ -63,12 +64,14 @@ namespace OpenIddict {
/// </summary> /// </summary>
/// <param name="identifier">The unique identifier associated with the token.</param> /// <param name="identifier">The unique identifier associated with the token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</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> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the token corresponding to the unique identifier.
/// </returns>
public virtual Task<TToken> FindByIdAsync(string identifier, CancellationToken cancellationToken) { public virtual Task<TToken> FindByIdAsync(string identifier, CancellationToken cancellationToken) {
var converter = TypeDescriptor.GetConverter(typeof(TKey));
// If the string key cannot be converted to TKey, return null // If the string key cannot be converted to TKey, return null
// to indicate that the requested token doesn't exist. // to indicate that the requested token doesn't exist.
var converter = TypeDescriptor.GetConverter(typeof(TKey));
if (!converter.CanConvertFrom(typeof(string))) { if (!converter.CanConvertFrom(typeof(string))) {
return Task.FromResult<TToken>(null); return Task.FromResult<TToken>(null);
} }

Loading…
Cancel
Save