Browse Source

Add new GetApplicationIdAsync()/SetApplicationIdAsync() methods in the authorization/token managers/stores

pull/490/head
Kévin Chalet 9 years ago
parent
commit
1bddda9cdb
  1. 39
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  2. 35
      src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
  3. 22
      src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs
  4. 23
      src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
  5. 40
      src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
  6. 37
      src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
  7. 73
      src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs
  8. 112
      src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs
  9. 73
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
  10. 116
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
  11. 7
      src/OpenIddict/OpenIddictProvider.Helpers.cs
  12. 4
      src/OpenIddict/OpenIddictProvider.Signin.cs

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

@ -201,6 +201,25 @@ namespace OpenIddict.Core
return Store.FindByIdAsync(identifier, cancellationToken);
}
/// <summary>
/// Retrieves the optional application identifier 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 application identifier associated with the authorization.
/// </returns>
public virtual Task<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Store.GetApplicationIdAsync(authorization, cancellationToken);
}
/// <summary>
/// Executes the specified query.
/// </summary>
@ -376,6 +395,26 @@ namespace OpenIddict.Core
}
}
/// <summary>
/// Sets the application identifier associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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 async Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
await Store.SetApplicationIdAsync(authorization, identifier, cancellationToken);
await UpdateAsync(authorization, cancellationToken);
}
/// <summary>
/// Updates an existing authorization.
/// </summary>

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

@ -236,6 +236,25 @@ namespace OpenIddict.Core
return Store.FindBySubjectAsync(subject, cancellationToken);
}
/// <summary>
/// Retrieves the optional application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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 application identifier associated with the token.
/// </returns>
public virtual Task<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetApplicationIdAsync(token, cancellationToken);
}
/// <summary>
/// Executes the specified query.
/// </summary>
@ -549,42 +568,42 @@ namespace OpenIddict.Core
}
/// <summary>
/// Sets the authorization associated with a token.
/// Sets the application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the authorization.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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 async Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
public virtual async Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
await Store.SetAuthorizationAsync(token, identifier, cancellationToken);
await Store.SetApplicationIdAsync(token, identifier, cancellationToken);
await UpdateAsync(token, cancellationToken);
}
/// <summary>
/// Sets the client application associated with a token.
/// Sets the authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</param>
/// <param name="identifier">The unique identifier 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 async Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
public virtual async Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
await Store.SetClientAsync(token, identifier, cancellationToken);
await Store.SetAuthorizationIdAsync(token, identifier, cancellationToken);
await UpdateAsync(token, cancellationToken);
}

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

@ -94,6 +94,17 @@ namespace OpenIddict.Core
/// </returns>
Task<TAuthorization> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the optional application identifier 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 application identifier associated with the authorization.
/// </returns>
Task<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
@ -187,6 +198,17 @@ namespace OpenIddict.Core
/// </returns>
Task<ImmutableArray<TAuthorization>> ListInvalidAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken);
/// <summary>
/// Sets the application identifier associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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 SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary>
/// Sets the status associated with an authorization.
/// </summary>

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

@ -113,6 +113,17 @@ namespace OpenIddict.Core
/// </returns>
Task<ImmutableArray<TToken>> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the optional application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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 application identifier associated with the token.
/// </returns>
Task<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
@ -262,26 +273,26 @@ namespace OpenIddict.Core
Task<ImmutableArray<TToken>> ListInvalidAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken);
/// <summary>
/// Sets the authorization associated with a token.
/// Sets the application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the authorization.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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 SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary>
/// Sets the client application associated with a token.
/// Sets the authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</param>
/// <param name="identifier">The unique identifier 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 SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary>
/// Sets the expiration date associated with a token.

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

@ -136,6 +136,35 @@ namespace OpenIddict.Core
return GetAsync(authorizations => authorizations.Where(authorization => authorization.Id.Equals(key)), cancellationToken);
}
/// <summary>
/// Retrieves the optional application identifier 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 application identifier associated with the authorization.
/// </returns>
public virtual async Task<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (authorization.Application != null)
{
return ConvertIdentifierToString(authorization.Application.Id);
}
var key = await GetAsync(authorizations =>
from element in authorizations
where element.Id.Equals(authorization.Id)
select element.Application.Id, cancellationToken);
return ConvertIdentifierToString(key);
}
/// <summary>
/// Executes the specified query.
/// </summary>
@ -301,6 +330,17 @@ namespace OpenIddict.Core
return ListAsync(Query, cancellationToken);
}
/// <summary>
/// Sets the application identifier associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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 abstract Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary>
/// Sets the status associated with an authorization.
/// </summary>

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

@ -174,6 +174,35 @@ namespace OpenIddict.Core
/// </returns>
public abstract Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the optional application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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 application identifier associated with the token.
/// </returns>
public virtual async Task<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
if (token.Application != null)
{
return ConvertIdentifierToString(token.Application.Id);
}
var key = await GetAsync(tokens =>
from element in tokens
where element.Id.Equals(token.Id)
select element.Application.Id, cancellationToken);
return ConvertIdentifierToString(key);
}
/// <summary>
/// Retrieves the optional authorization identifier associated with a token.
/// </summary>
@ -437,7 +466,7 @@ namespace OpenIddict.Core
}
/// <summary>
/// Sets the authorization associated with a token.
/// Sets the authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the authorization.</param>
@ -445,10 +474,10 @@ namespace OpenIddict.Core
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public abstract Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
public abstract Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary>
/// Sets the client application associated with a token.
/// Sets the application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</param>
@ -456,7 +485,7 @@ namespace OpenIddict.Core
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public abstract Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
public abstract Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary>
/// Sets the expiration date associated with a token.

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

@ -209,6 +209,38 @@ namespace OpenIddict.EntityFramework
return Authorizations.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
}
/// <summary>
/// Retrieves the optional application identifier 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 application identifier associated with the authorization.
/// </returns>
public override async Task<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
// If the application is not attached to the authorization instance (which is expected
// if the token was retrieved using the default FindBy*Async APIs as they don't
// eagerly load the application from the database), try to load it manually.
if (authorization.Application == null)
{
return ConvertIdentifierToString(
await Context.Entry(authorization)
.Reference(entry => entry.Application)
.Query()
.Select(application => application.Id)
.FirstOrDefaultAsync());
}
return ConvertIdentifierToString(authorization.Application.Id);
}
/// <summary>
/// Executes the specified query.
/// </summary>
@ -249,6 +281,47 @@ namespace OpenIddict.EntityFramework
return ImmutableArray.Create(await query.Invoke(Authorizations).ToArrayAsync(cancellationToken));
}
/// <summary>
/// Sets the application identifier associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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 override async Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (!string.IsNullOrEmpty(identifier))
{
var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
if (application == null)
{
throw new InvalidOperationException("The application associated with the authorization cannot be found.");
}
authorization.Application = application;
}
else
{
var key = await GetIdAsync(authorization, cancellationToken);
// Try to retrieve the application associated with the authorization.
// If none can be found, assume that no application is attached.
var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (application != null)
{
application.Authorizations.Remove(authorization);
}
}
}
/// <summary>
/// Updates an existing authorization.
/// </summary>

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

@ -223,6 +223,38 @@ namespace OpenIddict.EntityFramework
return Tokens.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
}
/// <summary>
/// Retrieves the optional application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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 application identifier associated with the token.
/// </returns>
public override async Task<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
// If the application is not attached to the token instance (which is expected
// if the token was retrieved using the default FindBy*Async APIs as they don't
// eagerly load the application from the database), try to load it manually.
if (token.Application == null)
{
return ConvertIdentifierToString(
await Context.Entry(token)
.Reference(entry => entry.Application)
.Query()
.Select(application => application.Id)
.FirstOrDefaultAsync());
}
return ConvertIdentifierToString(token.Application.Id);
}
/// <summary>
/// Executes the specified query.
/// </summary>
@ -243,6 +275,38 @@ namespace OpenIddict.EntityFramework
return query.Invoke(Tokens).SingleOrDefaultAsync(cancellationToken);
}
/// <summary>
/// Retrieves the optional authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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 authorization identifier associated with the token.
/// </returns>
public override async Task<string> GetAuthorizationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
// If the authorization is not attached to the token instance (which is expected
// if the token was retrieved using the default FindBy*Async APIs as they don't
// eagerly load the authorization from the database), try to load it manually.
if (token.Authorization == null)
{
return ConvertIdentifierToString(
await Context.Entry(token)
.Reference(entry => entry.Authorization)
.Query()
.Select(authorization => authorization.Id)
.FirstOrDefaultAsync());
}
return ConvertIdentifierToString(token.Authorization.Id);
}
/// <summary>
/// Executes the specified query.
/// </summary>
@ -264,15 +328,15 @@ namespace OpenIddict.EntityFramework
}
/// <summary>
/// Sets the authorization associated with a token.
/// Sets the application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the authorization.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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 override async Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
public override async Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (token == null)
{
@ -281,39 +345,39 @@ namespace OpenIddict.EntityFramework
if (!string.IsNullOrEmpty(identifier))
{
var authorization = await Authorizations.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
if (authorization == null)
var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
if (application == null)
{
throw new InvalidOperationException("The authorization associated with the token cannot be found.");
throw new InvalidOperationException("The application associated with the token cannot be found.");
}
token.Authorization = authorization;
token.Application = application;
}
else
{
var key = await GetIdAsync(token, cancellationToken);
// Try to retrieve the authorization associated with the token.
// If none can be found, assume that no authorization is attached.
var authorization = await Authorizations.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (authorization != null)
// Try to retrieve the application associated with the token.
// If none can be found, assume that no application is attached.
var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (application != null)
{
authorization.Tokens.Remove(token);
application.Tokens.Remove(token);
}
}
}
/// <summary>
/// Sets the client application associated with a token.
/// Sets the authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</param>
/// <param name="identifier">The unique identifier 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 override async Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
public override async Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (token == null)
{
@ -322,25 +386,25 @@ namespace OpenIddict.EntityFramework
if (!string.IsNullOrEmpty(identifier))
{
var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
if (application == null)
var authorization = await Authorizations.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
if (authorization == null)
{
throw new InvalidOperationException("The application associated with the token cannot be found.");
throw new InvalidOperationException("The authorization associated with the token cannot be found.");
}
token.Application = application;
token.Authorization = authorization;
}
else
{
var key = await GetIdAsync(token, cancellationToken);
// Try to retrieve the application associated with the token.
// If none can be found, assume that no application is attached.
var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (application != null)
// Try to retrieve the authorization associated with the token.
// If none can be found, assume that no authorization is attached.
var authorization = await Authorizations.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (authorization != null)
{
application.Tokens.Remove(token);
authorization.Tokens.Remove(token);
}
}
}

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

@ -209,6 +209,38 @@ namespace OpenIddict.EntityFrameworkCore
return Authorizations.FindAsync(new object[] { ConvertIdentifierFromString(identifier) }, cancellationToken);
}
/// <summary>
/// Retrieves the optional application identifier 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 application identifier associated with the authorization.
/// </returns>
public override async Task<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
// If the application is not attached to the authorization instance (which is expected
// if the token was retrieved using the default FindBy*Async APIs as they don't
// eagerly load the application from the database), try to load it manually.
if (authorization.Application == null)
{
return ConvertIdentifierToString(
await Context.Entry(authorization)
.Reference(entry => entry.Application)
.Query()
.Select(application => application.Id)
.FirstOrDefaultAsync());
}
return ConvertIdentifierToString(authorization.Application.Id);
}
/// <summary>
/// Executes the specified query.
/// </summary>
@ -249,6 +281,47 @@ namespace OpenIddict.EntityFrameworkCore
return ImmutableArray.Create(await query.Invoke(Authorizations).ToArrayAsync(cancellationToken));
}
/// <summary>
/// Sets the application identifier associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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 override async Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (!string.IsNullOrEmpty(identifier))
{
var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
if (application == null)
{
throw new InvalidOperationException("The application associated with the authorization cannot be found.");
}
authorization.Application = application;
}
else
{
var key = await GetIdAsync(authorization, cancellationToken);
// Try to retrieve the application associated with the authorization.
// If none can be found, assume that no application is attached.
var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (application != null)
{
application.Authorizations.Remove(authorization);
}
}
}
/// <summary>
/// Updates an existing authorization.
/// </summary>

116
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs

@ -223,6 +223,38 @@ namespace OpenIddict.EntityFrameworkCore
return Tokens.FindAsync(new object[] { ConvertIdentifierFromString(identifier) }, cancellationToken);
}
/// <summary>
/// Retrieves the optional application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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 application identifier associated with the token.
/// </returns>
public override async Task<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
// If the application is not attached to the token instance (which is expected
// if the token was retrieved using the default FindBy*Async APIs as they don't
// eagerly load the application from the database), try to load it manually.
if (token.Application == null)
{
return ConvertIdentifierToString(
await Context.Entry(token)
.Reference(entry => entry.Application)
.Query()
.Select(application => application.Id)
.FirstOrDefaultAsync());
}
return ConvertIdentifierToString(token.Application.Id);
}
/// <summary>
/// Executes the specified query.
/// </summary>
@ -243,6 +275,38 @@ namespace OpenIddict.EntityFrameworkCore
return query.Invoke(Tokens).SingleOrDefaultAsync(cancellationToken);
}
/// <summary>
/// Retrieves the optional authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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 authorization identifier associated with the token.
/// </returns>
public override async Task<string> GetAuthorizationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
// If the authorization is not attached to the token instance (which is expected
// if the token was retrieved using the default FindBy*Async APIs as they don't
// eagerly load the authorization from the database), try to load it manually.
if (token.Authorization == null)
{
return ConvertIdentifierToString(
await Context.Entry(token)
.Reference(entry => entry.Authorization)
.Query()
.Select(authorization => authorization.Id)
.FirstOrDefaultAsync());
}
return ConvertIdentifierToString(token.Authorization.Id);
}
/// <summary>
/// Executes the specified query.
/// </summary>
@ -264,15 +328,15 @@ namespace OpenIddict.EntityFrameworkCore
}
/// <summary>
/// Sets the authorization associated with a token.
/// Sets the application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the authorization.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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 override async Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
public override async Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (token == null)
{
@ -281,39 +345,41 @@ namespace OpenIddict.EntityFrameworkCore
if (!string.IsNullOrEmpty(identifier))
{
var authorization = await Authorizations.FindAsync(new object[] { ConvertIdentifierFromString(identifier) }, cancellationToken);
if (authorization == null)
var key = ConvertIdentifierFromString(identifier);
var application = await Applications.FindAsync(new object[] { ConvertIdentifierFromString(identifier) }, cancellationToken);
if (application == null)
{
throw new InvalidOperationException("The authorization associated with the token cannot be found.");
throw new InvalidOperationException("The application associated with the token cannot be found.");
}
token.Authorization = authorization;
token.Application = application;
}
else
{
var key = await GetIdAsync(token, cancellationToken);
// Try to retrieve the authorization associated with the token.
// If none can be found, assume that no authorization is attached.
var authorization = await Authorizations.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (authorization != null)
// Try to retrieve the application associated with the token.
// If none can be found, assume that no application is attached.
var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (application != null)
{
authorization.Tokens.Remove(token);
application.Tokens.Remove(token);
}
}
}
/// <summary>
/// Sets the client application associated with a token.
/// Sets the authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</param>
/// <param name="identifier">The unique identifier 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 override async Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
public override async Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (token == null)
{
@ -322,27 +388,25 @@ namespace OpenIddict.EntityFrameworkCore
if (!string.IsNullOrEmpty(identifier))
{
var key = ConvertIdentifierFromString(identifier);
var application = await Applications.FindAsync(new object[] { ConvertIdentifierFromString(identifier) }, cancellationToken);
if (application == null)
var authorization = await Authorizations.FindAsync(new object[] { ConvertIdentifierFromString(identifier) }, cancellationToken);
if (authorization == null)
{
throw new InvalidOperationException("The application associated with the token cannot be found.");
throw new InvalidOperationException("The authorization associated with the token cannot be found.");
}
token.Application = application;
token.Authorization = authorization;
}
else
{
var key = await GetIdAsync(token, cancellationToken);
// Try to retrieve the application associated with the token.
// If none can be found, assume that no application is attached.
var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (application != null)
// Try to retrieve the authorization associated with the token.
// If none can be found, assume that no authorization is attached.
var authorization = await Authorizations.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (authorization != null)
{
application.Tokens.Remove(token);
authorization.Tokens.Remove(token);
}
}
}

7
src/OpenIddict/OpenIddictProvider.Helpers.cs

@ -197,12 +197,11 @@ namespace OpenIddict
ticket.SetTokenId(identifier);
// Dynamically set the creation and expiration dates.
ticket.Properties.IssuedUtc = await Tokens.GetCreationDateAsync(token, context.RequestAborted);
ticket.Properties.ExpiresUtc = await Tokens.GetExpirationDateAsync(token, context.RequestAborted);
ticket.Properties.IssuedUtc = descriptor.CreationDate;
ticket.Properties.ExpiresUtc = descriptor.ExpirationDate;
// Restore the authorization identifier using the identifier attached with the database entry.
ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId,
await Tokens.GetAuthorizationIdAsync(token, context.RequestAborted));
ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId, descriptor.AuthorizationId);
if (!string.IsNullOrEmpty(result))
{

4
src/OpenIddict/OpenIddictProvider.Signin.cs

@ -29,8 +29,8 @@ namespace OpenIddict
// the OpenID Connect server middleware allows creating authentication tickets
// that are completely disconnected from the original code or refresh token ticket.
// This scenario is deliberately not supported in OpenIddict and all the tickets
// must be linked. To ensure the properties are preserved from an authorization code
// or a refresh token to the new ticket, they are manually restored if necessary.
// must be linked. To ensure the properties are flowed from the authorization code
// or the refresh token to the new ticket, they are manually restored if necessary.
// Retrieve the original authentication ticket from the request properties.
var ticket = context.Request.GetProperty<AuthenticationTicket>(

Loading…
Cancel
Save