diff --git a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
index b43f7049..5b606cbe 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
@@ -201,6 +201,25 @@ namespace OpenIddict.Core
return Store.FindByIdAsync(identifier, cancellationToken);
}
+ ///
+ /// Retrieves the optional application identifier associated with an authorization.
+ ///
+ /// The authorization.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the application identifier associated with the authorization.
+ ///
+ public virtual Task GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
+ {
+ if (authorization == null)
+ {
+ throw new ArgumentNullException(nameof(authorization));
+ }
+
+ return Store.GetApplicationIdAsync(authorization, cancellationToken);
+ }
+
///
/// Executes the specified query.
///
@@ -376,6 +395,26 @@ namespace OpenIddict.Core
}
}
+ ///
+ /// Sets the application identifier associated with an authorization.
+ ///
+ /// The authorization.
+ /// The unique identifier associated with the client application.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation.
+ ///
+ 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);
+ }
+
///
/// Updates an existing authorization.
///
diff --git a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
index ea012aa1..646e4acb 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
@@ -236,6 +236,25 @@ namespace OpenIddict.Core
return Store.FindBySubjectAsync(subject, cancellationToken);
}
+ ///
+ /// Retrieves the optional application identifier associated with a token.
+ ///
+ /// The token.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the application identifier associated with the token.
+ ///
+ public virtual Task GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ {
+ if (token == null)
+ {
+ throw new ArgumentNullException(nameof(token));
+ }
+
+ return Store.GetApplicationIdAsync(token, cancellationToken);
+ }
+
///
/// Executes the specified query.
///
@@ -549,42 +568,42 @@ namespace OpenIddict.Core
}
///
- /// Sets the authorization associated with a token.
+ /// Sets the application identifier associated with a token.
///
/// The token.
- /// The unique identifier associated with the authorization.
+ /// The unique identifier associated with the client application.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- 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);
}
///
- /// Sets the client application associated with a token.
+ /// Sets the authorization identifier associated with a token.
///
/// The token.
- /// The unique identifier associated with the client application.
+ /// The unique identifier associated with the authorization.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- 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);
}
diff --git a/src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs b/src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs
index 09bee76f..d4fb16d8 100644
--- a/src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs
+++ b/src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs
@@ -94,6 +94,17 @@ namespace OpenIddict.Core
///
Task FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken);
+ ///
+ /// Retrieves the optional application identifier associated with an authorization.
+ ///
+ /// The authorization.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the application identifier associated with the authorization.
+ ///
+ Task GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken);
+
///
/// Executes the specified query.
///
@@ -187,6 +198,17 @@ namespace OpenIddict.Core
///
Task> ListInvalidAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken);
+ ///
+ /// Sets the application identifier associated with an authorization.
+ ///
+ /// The authorization.
+ /// The unique identifier associated with the client application.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation.
+ ///
+ Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken);
+
///
/// Sets the status associated with an authorization.
///
diff --git a/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs b/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
index 91d09f81..d35402f9 100644
--- a/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
+++ b/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
@@ -113,6 +113,17 @@ namespace OpenIddict.Core
///
Task> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken);
+ ///
+ /// Retrieves the optional application identifier associated with a token.
+ ///
+ /// The token.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the application identifier associated with the token.
+ ///
+ Task GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken);
+
///
/// Executes the specified query.
///
@@ -262,26 +273,26 @@ namespace OpenIddict.Core
Task> ListInvalidAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken);
///
- /// Sets the authorization associated with a token.
+ /// Sets the application identifier associated with a token.
///
/// The token.
- /// The unique identifier associated with the authorization.
+ /// The unique identifier associated with the client application.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
+ Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
///
- /// Sets the client application associated with a token.
+ /// Sets the authorization identifier associated with a token.
///
/// The token.
- /// The unique identifier associated with the client application.
+ /// The unique identifier associated with the authorization.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
+ Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
///
/// Sets the expiration date associated with a token.
diff --git a/src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
index d272f4ca..0d08b0ff 100644
--- a/src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
+++ b/src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
@@ -136,6 +136,35 @@ namespace OpenIddict.Core
return GetAsync(authorizations => authorizations.Where(authorization => authorization.Id.Equals(key)), cancellationToken);
}
+ ///
+ /// Retrieves the optional application identifier associated with an authorization.
+ ///
+ /// The authorization.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the application identifier associated with the authorization.
+ ///
+ public virtual async Task 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);
+ }
+
///
/// Executes the specified query.
///
@@ -301,6 +330,17 @@ namespace OpenIddict.Core
return ListAsync(Query, cancellationToken);
}
+ ///
+ /// Sets the application identifier associated with an authorization.
+ ///
+ /// The authorization.
+ /// The unique identifier associated with the client application.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation.
+ ///
+ public abstract Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken);
+
///
/// Sets the status associated with an authorization.
///
diff --git a/src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
index 80584071..71dd8fe6 100644
--- a/src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
+++ b/src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
@@ -174,6 +174,35 @@ namespace OpenIddict.Core
///
public abstract Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken);
+ ///
+ /// Retrieves the optional application identifier associated with a token.
+ ///
+ /// The token.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the application identifier associated with the token.
+ ///
+ public virtual async Task 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);
+ }
+
///
/// Retrieves the optional authorization identifier associated with a token.
///
@@ -437,7 +466,7 @@ namespace OpenIddict.Core
}
///
- /// Sets the authorization associated with a token.
+ /// Sets the authorization identifier associated with a token.
///
/// The token.
/// The unique identifier associated with the authorization.
@@ -445,10 +474,10 @@ namespace OpenIddict.Core
///
/// A that can be used to monitor the asynchronous operation.
///
- public abstract Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
+ public abstract Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
///
- /// Sets the client application associated with a token.
+ /// Sets the application identifier associated with a token.
///
/// The token.
/// The unique identifier associated with the client application.
@@ -456,7 +485,7 @@ namespace OpenIddict.Core
///
/// A that can be used to monitor the asynchronous operation.
///
- public abstract Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
+ public abstract Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
///
/// Sets the expiration date associated with a token.
diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs
index d40f511f..7cbd4857 100644
--- a/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs
+++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs
@@ -209,6 +209,38 @@ namespace OpenIddict.EntityFramework
return Authorizations.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
}
+ ///
+ /// Retrieves the optional application identifier associated with an authorization.
+ ///
+ /// The authorization.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the application identifier associated with the authorization.
+ ///
+ public override async Task 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);
+ }
+
///
/// Executes the specified query.
///
@@ -249,6 +281,47 @@ namespace OpenIddict.EntityFramework
return ImmutableArray.Create(await query.Invoke(Authorizations).ToArrayAsync(cancellationToken));
}
+ ///
+ /// Sets the application identifier associated with an authorization.
+ ///
+ /// The authorization.
+ /// The unique identifier associated with the client application.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation.
+ ///
+ 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);
+ }
+ }
+ }
+
///
/// Updates an existing authorization.
///
diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs
index ad4c2474..5d7c4f06 100644
--- a/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs
+++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs
@@ -223,6 +223,38 @@ namespace OpenIddict.EntityFramework
return Tokens.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
}
+ ///
+ /// Retrieves the optional application identifier associated with a token.
+ ///
+ /// The token.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the application identifier associated with the token.
+ ///
+ public override async Task 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);
+ }
+
///
/// Executes the specified query.
///
@@ -243,6 +275,38 @@ namespace OpenIddict.EntityFramework
return query.Invoke(Tokens).SingleOrDefaultAsync(cancellationToken);
}
+ ///
+ /// Retrieves the optional authorization identifier associated with a token.
+ ///
+ /// The token.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the authorization identifier associated with the token.
+ ///
+ public override async Task 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);
+ }
+
///
/// Executes the specified query.
///
@@ -264,15 +328,15 @@ namespace OpenIddict.EntityFramework
}
///
- /// Sets the authorization associated with a token.
+ /// Sets the application identifier associated with a token.
///
/// The token.
- /// The unique identifier associated with the authorization.
+ /// The unique identifier associated with the client application.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- 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);
}
}
}
///
- /// Sets the client application associated with a token.
+ /// Sets the authorization identifier associated with a token.
///
/// The token.
- /// The unique identifier associated with the client application.
+ /// The unique identifier associated with the authorization.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- 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);
}
}
}
diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
index b261dd4a..4e92ac93 100644
--- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
+++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
@@ -209,6 +209,38 @@ namespace OpenIddict.EntityFrameworkCore
return Authorizations.FindAsync(new object[] { ConvertIdentifierFromString(identifier) }, cancellationToken);
}
+ ///
+ /// Retrieves the optional application identifier associated with an authorization.
+ ///
+ /// The authorization.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the application identifier associated with the authorization.
+ ///
+ public override async Task 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);
+ }
+
///
/// Executes the specified query.
///
@@ -249,6 +281,47 @@ namespace OpenIddict.EntityFrameworkCore
return ImmutableArray.Create(await query.Invoke(Authorizations).ToArrayAsync(cancellationToken));
}
+ ///
+ /// Sets the application identifier associated with an authorization.
+ ///
+ /// The authorization.
+ /// The unique identifier associated with the client application.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation.
+ ///
+ 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);
+ }
+ }
+ }
+
///
/// Updates an existing authorization.
///
diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
index 2dd5186d..b2596619 100644
--- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
+++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
@@ -223,6 +223,38 @@ namespace OpenIddict.EntityFrameworkCore
return Tokens.FindAsync(new object[] { ConvertIdentifierFromString(identifier) }, cancellationToken);
}
+ ///
+ /// Retrieves the optional application identifier associated with a token.
+ ///
+ /// The token.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the application identifier associated with the token.
+ ///
+ public override async Task 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);
+ }
+
///
/// Executes the specified query.
///
@@ -243,6 +275,38 @@ namespace OpenIddict.EntityFrameworkCore
return query.Invoke(Tokens).SingleOrDefaultAsync(cancellationToken);
}
+ ///
+ /// Retrieves the optional authorization identifier associated with a token.
+ ///
+ /// The token.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation,
+ /// whose result returns the authorization identifier associated with the token.
+ ///
+ public override async Task 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);
+ }
+
///
/// Executes the specified query.
///
@@ -264,15 +328,15 @@ namespace OpenIddict.EntityFrameworkCore
}
///
- /// Sets the authorization associated with a token.
+ /// Sets the application identifier associated with a token.
///
/// The token.
- /// The unique identifier associated with the authorization.
+ /// The unique identifier associated with the client application.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- 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);
}
}
}
///
- /// Sets the client application associated with a token.
+ /// Sets the authorization identifier associated with a token.
///
/// The token.
- /// The unique identifier associated with the client application.
+ /// The unique identifier associated with the authorization.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- 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);
}
}
}
diff --git a/src/OpenIddict/OpenIddictProvider.Helpers.cs b/src/OpenIddict/OpenIddictProvider.Helpers.cs
index 34eb6ab0..c7613c06 100644
--- a/src/OpenIddict/OpenIddictProvider.Helpers.cs
+++ b/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))
{
diff --git a/src/OpenIddict/OpenIddictProvider.Signin.cs b/src/OpenIddict/OpenIddictProvider.Signin.cs
index 72c38136..ef04be79 100644
--- a/src/OpenIddict/OpenIddictProvider.Signin.cs
+++ b/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(