58 changed files with 2509 additions and 1197 deletions
@ -1,6 +1,6 @@ |
|||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; |
|||
using OpenIddict; |
|||
|
|||
namespace Mvc.Server.Models { |
|||
// Add profile data for application users by adding properties to the ApplicationUser class
|
|||
public class ApplicationUser : IdentityUser { } |
|||
public class ApplicationUser : OpenIddictUser { } |
|||
} |
|||
|
|||
@ -1,13 +0,0 @@ |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace OpenIddict { |
|||
public interface IOpenIddictStore<TUser, TApplication> where TApplication : class { |
|||
Task<TApplication> FindApplicationByIdAsync(string identifier, CancellationToken cancellationToken); |
|||
Task<TApplication> FindApplicationByLogoutRedirectUri(string url, CancellationToken cancellationToken); |
|||
Task<string> GetApplicationTypeAsync(TApplication application, CancellationToken cancellationToken); |
|||
Task<string> GetDisplayNameAsync(TApplication application, CancellationToken cancellationToken); |
|||
Task<string> GetRedirectUriAsync(TApplication application, CancellationToken cancellationToken); |
|||
Task<string> GetHashedSecretAsync(TApplication application, CancellationToken cancellationToken); |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Identity; |
|||
|
|||
namespace OpenIddict.Infrastructure { |
|||
public static class OpenIddictHelpers { |
|||
public static async Task<string> FindClaimAsync<TUser>( |
|||
[NotNull] this UserManager<TUser> manager, |
|||
[NotNull] TUser user, [NotNull] string type) where TUser : class { |
|||
if (manager == null) { |
|||
throw new ArgumentNullException(nameof(manager)); |
|||
} |
|||
|
|||
if (user == null) { |
|||
throw new ArgumentNullException(nameof(user)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(type)) { |
|||
throw new ArgumentNullException(nameof(type)); |
|||
} |
|||
|
|||
// Note: GetClaimsAsync will automatically throw an exception
|
|||
// if the underlying store doesn't support custom claims.
|
|||
return (from claim in await manager.GetClaimsAsync(user) |
|||
where string.Equals(claim.Type, type, StringComparison.OrdinalIgnoreCase) |
|||
select claim.Value).FirstOrDefault(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,120 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using AspNet.Security.OpenIdConnect.Extensions; |
|||
using AspNet.Security.OpenIdConnect.Server; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
|
|||
namespace OpenIddict.Infrastructure { |
|||
public partial class OpenIddictProvider<TUser, TApplication, TAuthorization, TScope, TToken> : OpenIdConnectServerProvider |
|||
where TUser : class where TApplication : class where TAuthorization : class where TScope : class where TToken : class { |
|||
public override async Task ValidateRevocationRequest([NotNull] ValidateRevocationRequestContext context) { |
|||
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>(); |
|||
|
|||
// When token_type_hint is specified, reject the request
|
|||
// if token_type_hint is not equal to "refresh_token".
|
|||
if (!string.IsNullOrEmpty(context.Request.GetTokenTypeHint()) && |
|||
!string.Equals(context.Request.GetTokenTypeHint(), OpenIdConnectConstants.TokenTypeHints.RefreshToken)) { |
|||
context.Reject( |
|||
error: OpenIdConnectConstants.Errors.UnsupportedTokenType, |
|||
description: "Only refresh tokens can be revoked. When specifying a token_type_hint " + |
|||
"parameter, its value must be equal to 'refresh_token'."); |
|||
|
|||
return; |
|||
} |
|||
|
|||
// Skip client authentication if the client identifier is missing.
|
|||
// Note: ASOS will automatically ensure that the calling application
|
|||
// cannot revoke a refresh token if it's not the intended audience,
|
|||
// even if client authentication was skipped.
|
|||
if (string.IsNullOrEmpty(context.ClientId)) { |
|||
context.Skip(); |
|||
|
|||
return; |
|||
} |
|||
|
|||
// Retrieve the application details corresponding to the requested client_id.
|
|||
var application = await services.Applications.FindByIdAsync(context.ClientId); |
|||
if (application == null) { |
|||
context.Reject( |
|||
error: OpenIdConnectConstants.Errors.InvalidClient, |
|||
description: "Application not found in the database: ensure that your client_id is correct."); |
|||
|
|||
return; |
|||
} |
|||
|
|||
// Reject tokens requests containing a client_secret if the client application is not confidential.
|
|||
var type = await services.Applications.GetClientTypeAsync(application); |
|||
if (!string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase) && |
|||
!string.IsNullOrEmpty(context.ClientSecret)) { |
|||
context.Reject( |
|||
error: OpenIdConnectConstants.Errors.InvalidRequest, |
|||
description: "Public clients are not allowed to send a client_secret."); |
|||
|
|||
return; |
|||
} |
|||
|
|||
// Confidential applications MUST authenticate to protect them from impersonation attacks.
|
|||
else if (!string.Equals(type, OpenIddictConstants.ClientTypes.Public)) { |
|||
if (string.IsNullOrEmpty(context.ClientSecret)) { |
|||
context.Reject( |
|||
error: OpenIdConnectConstants.Errors.InvalidClient, |
|||
description: "Missing credentials: ensure that you specified a client_secret."); |
|||
|
|||
return; |
|||
} |
|||
|
|||
if (!await services.Applications.ValidateSecretAsync(application, context.ClientSecret)) { |
|||
context.Reject( |
|||
error: OpenIdConnectConstants.Errors.InvalidClient, |
|||
description: "Invalid credentials: ensure that you specified a correct client_secret."); |
|||
|
|||
return; |
|||
} |
|||
} |
|||
|
|||
context.Validate(); |
|||
} |
|||
|
|||
public override async Task HandleRevocationRequest([NotNull] HandleRevocationRequestContext context) { |
|||
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>(); |
|||
|
|||
// If the received token is not a refresh token, set Revoked
|
|||
// to false to indicate that the token cannot be revoked.
|
|||
if (!context.Ticket.IsRefreshToken()) { |
|||
context.Revoked = false; |
|||
|
|||
return; |
|||
} |
|||
|
|||
// Extract the token identifier from the authentication ticket.
|
|||
// If the identifier cannot be extracted, abort the revocation.
|
|||
var identifier = context.Ticket.GetTicketId(); |
|||
if (string.IsNullOrEmpty(identifier)) { |
|||
context.Revoked = true; |
|||
|
|||
return; |
|||
} |
|||
|
|||
// Retrieve the token from the database. If the token cannot be found,
|
|||
// assume it is invalid and consider the revocation as successful.
|
|||
var token = await services.Tokens.FindByIdAsync(identifier); |
|||
if (token == null) { |
|||
context.Revoked = true; |
|||
|
|||
return; |
|||
} |
|||
|
|||
// Revoke the refresh token.
|
|||
await services.Tokens.RevokeAsync(token); |
|||
|
|||
context.Revoked = true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System.Diagnostics; |
|||
using System.Threading.Tasks; |
|||
using AspNet.Security.OpenIdConnect.Extensions; |
|||
using AspNet.Security.OpenIdConnect.Server; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
|
|||
namespace OpenIddict.Infrastructure { |
|||
public partial class OpenIddictProvider<TUser, TApplication, TAuthorization, TScope, TToken> : OpenIdConnectServerProvider |
|||
where TUser : class where TApplication : class where TAuthorization : class where TScope : class where TToken : class { |
|||
public override async Task SerializeRefreshToken([NotNull] SerializeRefreshTokenContext context) { |
|||
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>(); |
|||
|
|||
// Note: the identifier cannot be null as it's always
|
|||
// generated by the OpenID Connect server middleware
|
|||
// before invoking the SerializeRefreshToken event.
|
|||
Debug.Assert(!string.IsNullOrEmpty(context.Ticket.GetTicketId()), |
|||
"The unique identifier associated with the refresh token was missing or empty."); |
|||
|
|||
// Only persist the refresh token identifier in the database.
|
|||
await services.Tokens.CreateAsync(context.Ticket.GetTicketId(), OpenIdConnectConstants.TokenTypeHints.RefreshToken); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,173 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using CryptoHelper; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the applications stored in the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|||
public class OpenIddictApplicationManager<TApplication> where TApplication : class { |
|||
public OpenIddictApplicationManager( |
|||
[NotNull] IServiceProvider services, |
|||
[NotNull] IOpenIddictApplicationStore<TApplication> store, |
|||
[NotNull] ILogger<OpenIddictApplicationManager<TApplication>> logger) { |
|||
Context = services?.GetRequiredService<IHttpContextAccessor>()?.HttpContext; |
|||
Store = store; |
|||
Logger = logger; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the HTTP context associated with the current manager.
|
|||
/// </summary>
|
|||
protected HttpContext Context { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the cancellation token used to abort async operations.
|
|||
/// </summary>
|
|||
protected CancellationToken CancellationToken => Context?.RequestAborted ?? CancellationToken.None; |
|||
|
|||
/// <summary>
|
|||
/// Gets the logger associated with the current manager.
|
|||
/// </summary>
|
|||
protected ILogger Logger { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the store associated with the current manager.
|
|||
/// </summary>
|
|||
protected IOpenIddictApplicationStore<TApplication> Store { get; } |
|||
|
|||
/// <summary>
|
|||
/// Creates a new application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application to create.</param>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual Task CreateAsync(TApplication application) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Store.CreateAsync(application, CancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its unique identifier.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
public virtual Task<TApplication> FindByIdAsync(string identifier) { |
|||
return Store.FindByIdAsync(identifier, CancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its post_logout_redirect_uri.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
public virtual Task<TApplication> FindByLogoutRedirectUri(string url) { |
|||
return Store.FindByLogoutRedirectUri(url, CancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the client type associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual async Task<string> GetClientTypeAsync(TApplication application) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
var type = await Store.GetClientTypeAsync(application, CancellationToken); |
|||
|
|||
// Ensure the application type returned by the store is supported by the manager.
|
|||
if (!string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase) && |
|||
!string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) { |
|||
throw new InvalidOperationException("Only 'confidential' or 'public' applications are " + |
|||
"supported by the default application manager."); |
|||
} |
|||
|
|||
return type; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the display name associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual Task<string> GetDisplayNameAsync(TApplication application) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Store.GetDisplayNameAsync(application, CancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validates the redirect_uri associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</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>
|
|||
public virtual async Task<bool> ValidateRedirectUriAsync(TApplication application, string address) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (!string.Equals(address, await Store.GetRedirectUriAsync(application, CancellationToken), StringComparison.Ordinal)) { |
|||
Logger.LogWarning("Client validation failed because {RedirectUri} was not a valid redirect_uri " + |
|||
"for {Client}", address, await GetDisplayNameAsync(application)); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validates the client_secret associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</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>
|
|||
public virtual async Task<bool> ValidateSecretAsync(TApplication application, string secret) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
var type = await GetClientTypeAsync(application); |
|||
if (type != OpenIddictConstants.ClientTypes.Confidential) { |
|||
Logger.LogWarning("Client authentication cannot be enforced for non-confidential applications."); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
var hash = await Store.GetHashedSecretAsync(application, CancellationToken); |
|||
if (string.IsNullOrEmpty(hash)) { |
|||
Logger.LogError("Client authentication failed for {Client} because " + |
|||
"no client secret was associated with the application."); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
if (!Crypto.VerifyHashedPassword(hash, secret)) { |
|||
Logger.LogWarning("Client authentication failed for {Client}.", await GetDisplayNameAsync(application)); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Threading; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the authorizations stored in the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|||
public class OpenIddictAuthorizationManager<TAuthorization> where TAuthorization : class { |
|||
public OpenIddictAuthorizationManager( |
|||
[NotNull] IServiceProvider services, |
|||
[NotNull] IOpenIddictAuthorizationStore<TAuthorization> store, |
|||
[NotNull] ILogger<OpenIddictAuthorizationManager<TAuthorization>> logger) { |
|||
Context = services?.GetRequiredService<IHttpContextAccessor>()?.HttpContext; |
|||
Logger = logger; |
|||
Store = store; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the HTTP context associated with the current manager.
|
|||
/// </summary>
|
|||
protected HttpContext Context { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the cancellation token used to abort async operations.
|
|||
/// </summary>
|
|||
protected CancellationToken CancellationToken => Context?.RequestAborted ?? CancellationToken.None; |
|||
|
|||
/// <summary>
|
|||
/// Gets the logger associated with the current manager.
|
|||
/// </summary>
|
|||
protected ILogger Logger { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the store associated with the current manager.
|
|||
/// </summary>
|
|||
protected IOpenIddictAuthorizationStore<TAuthorization> Store { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Threading; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the scopes stored in the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|||
public class OpenIddictScopeManager<TScope> where TScope : class { |
|||
public OpenIddictScopeManager( |
|||
[NotNull] IServiceProvider services, |
|||
[NotNull] IOpenIddictAuthorizationStore<TScope> store, |
|||
[NotNull] ILogger<OpenIddictAuthorizationManager<TScope>> logger) { |
|||
Context = services?.GetRequiredService<IHttpContextAccessor>()?.HttpContext; |
|||
Logger = logger; |
|||
Store = store; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the HTTP context associated with the current manager.
|
|||
/// </summary>
|
|||
protected HttpContext Context { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the cancellation token used to abort async operations.
|
|||
/// </summary>
|
|||
protected CancellationToken CancellationToken => Context?.RequestAborted ?? CancellationToken.None; |
|||
|
|||
/// <summary>
|
|||
/// Gets the logger associated with the current manager.
|
|||
/// </summary>
|
|||
protected ILogger Logger { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the store associated with the current manager.
|
|||
/// </summary>
|
|||
protected IOpenIddictAuthorizationStore<TScope> Store { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,189 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Security.Claims; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using AspNet.Security.OpenIdConnect.Extensions; |
|||
using AspNet.Security.OpenIdConnect.Server; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the tokens stored in the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
/// <typeparam name="TUser">The type of the User entity.</typeparam>
|
|||
public class OpenIddictTokenManager<TToken, TUser> where TToken : class where TUser : class { |
|||
public OpenIddictTokenManager( |
|||
[NotNull] IServiceProvider services, |
|||
[NotNull] IOpenIddictTokenStore<TToken> store, |
|||
[NotNull] UserManager<TUser> users, |
|||
[NotNull] IOptions<IdentityOptions> options, |
|||
[NotNull] ILogger<OpenIddictTokenManager<TToken, TUser>> logger) { |
|||
Context = services?.GetRequiredService<IHttpContextAccessor>()?.HttpContext; |
|||
Logger = logger; |
|||
Options = options.Value; |
|||
Store = store; |
|||
Users = users; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the cancellation token used to abort async operations.
|
|||
/// </summary>
|
|||
protected CancellationToken CancellationToken => Context?.RequestAborted ?? CancellationToken.None; |
|||
|
|||
/// <summary>
|
|||
/// Gets the HTTP context associated with the current manager.
|
|||
/// </summary>
|
|||
protected HttpContext Context { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the logger associated with the current manager.
|
|||
/// </summary>
|
|||
protected ILogger Logger { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the identity options.
|
|||
/// </summary>
|
|||
protected IdentityOptions Options { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the store associated with the current manager.
|
|||
/// </summary>
|
|||
protected IOpenIddictTokenStore<TToken> Store { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the user manager.
|
|||
/// </summary>
|
|||
protected UserManager<TUser> Users { get; } |
|||
|
|||
/// <summary>
|
|||
/// Creates a new <see cref="ClaimsIdentity"/> used to create new tokens.
|
|||
/// </summary>
|
|||
/// <param name="user">The user corresponding to the identity.</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>
|
|||
public virtual async Task<ClaimsIdentity> CreateIdentityAsync(TUser user, IEnumerable<string> scopes) { |
|||
if (user == null) { |
|||
throw new ArgumentNullException(nameof(user)); |
|||
} |
|||
|
|||
if (scopes == null) { |
|||
throw new ArgumentNullException(nameof(scopes)); |
|||
} |
|||
|
|||
var identity = new ClaimsIdentity( |
|||
OpenIdConnectServerDefaults.AuthenticationScheme, |
|||
Options.ClaimsIdentity.UserNameClaimType, |
|||
Options.ClaimsIdentity.RoleClaimType); |
|||
|
|||
// Note: the name identifier is always included in both identity and
|
|||
// access tokens, even if an explicit destination is not specified.
|
|||
identity.AddClaim(ClaimTypes.NameIdentifier, await Users.GetUserIdAsync(user)); |
|||
|
|||
// Resolve the email address associated with the user if the underlying store supports it.
|
|||
var email = Users.SupportsUserEmail ? await Users.GetEmailAsync(user) : null; |
|||
|
|||
// Only add the name claim if the "profile" scope was granted.
|
|||
if (scopes.Contains(OpenIdConnectConstants.Scopes.Profile)) { |
|||
var username = await Users.GetUserNameAsync(user); |
|||
|
|||
// Throw an exception if the username corresponds to the registered
|
|||
// email address and if the "email" scope has not been requested.
|
|||
if (!scopes.Contains(OpenIdConnectConstants.Scopes.Email) && |
|||
!string.IsNullOrEmpty(email) && |
|||
string.Equals(username, email, StringComparison.OrdinalIgnoreCase)) { |
|||
throw new InvalidOperationException("The 'email' scope is required."); |
|||
} |
|||
|
|||
identity.AddClaim(ClaimTypes.Name, username, |
|||
OpenIdConnectConstants.Destinations.AccessToken, |
|||
OpenIdConnectConstants.Destinations.IdentityToken); |
|||
} |
|||
|
|||
// Only add the email address if the "email" scope was granted.
|
|||
if (!string.IsNullOrEmpty(email) && scopes.Contains(OpenIdConnectConstants.Scopes.Email)) { |
|||
identity.AddClaim(ClaimTypes.Email, email, |
|||
OpenIdConnectConstants.Destinations.AccessToken, |
|||
OpenIdConnectConstants.Destinations.IdentityToken); |
|||
} |
|||
|
|||
if (Users.SupportsUserRole && scopes.Contains(OpenIddictConstants.Scopes.Roles)) { |
|||
foreach (var role in await Users.GetRolesAsync(user)) { |
|||
identity.AddClaim(identity.RoleClaimType, role, |
|||
OpenIdConnectConstants.Destinations.AccessToken, |
|||
OpenIdConnectConstants.Destinations.IdentityToken); |
|||
} |
|||
} |
|||
|
|||
if (Users.SupportsUserSecurityStamp) { |
|||
var stamp = await Users.GetSecurityStampAsync(user); |
|||
|
|||
if (!string.IsNullOrEmpty(stamp)) { |
|||
identity.AddClaim(Options.ClaimsIdentity.SecurityStampClaimType, stamp, |
|||
OpenIdConnectConstants.Destinations.AccessToken, |
|||
OpenIdConnectConstants.Destinations.IdentityToken); |
|||
} |
|||
} |
|||
|
|||
return identity; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a new token, defined by a unique identifier and a token type.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the token to create.</param>
|
|||
/// <param name="type">The token type.</param>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual Task CreateAsync(string identifier, string type) { |
|||
if (string.IsNullOrEmpty(identifier)) { |
|||
throw new ArgumentException("The identifier cannot be null or empty", nameof(identifier)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(type)) { |
|||
throw new ArgumentException("The token type cannot be null or empty", nameof(type)); |
|||
} |
|||
|
|||
return Store.CreateAsync(identifier, type, CancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an token using its unique identifier.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
public virtual Task<TToken> FindByIdAsync(string identifier) { |
|||
if (string.IsNullOrEmpty(identifier)) { |
|||
throw new ArgumentException("The identifier cannot be null or empty", nameof(identifier)); |
|||
} |
|||
|
|||
return Store.FindByIdAsync(identifier, CancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Revokes a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token to revoke.</param>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual Task RevokeAsync(TToken token) { |
|||
if (token == null) { |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
return Store.RevokeAsync(token, CancellationToken); |
|||
} |
|||
} |
|||
} |
|||
@ -1,19 +1,431 @@ |
|||
using System.Collections.Generic; |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using System.Security.Cryptography.X509Certificates; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using OpenIddict; |
|||
|
|||
namespace Microsoft.AspNetCore.Builder { |
|||
/// <summary>
|
|||
/// Holds various properties allowing to configure OpenIddict.
|
|||
/// Exposes the necessary methods required to configure OpenIddict.
|
|||
/// </summary>
|
|||
public class OpenIddictBuilder { |
|||
/// <summary>
|
|||
/// Gets the list of the OpenIddict modules.
|
|||
/// Initializes a new instance of <see cref="OpenIddictBuilder"/>.
|
|||
/// </summary>
|
|||
/// <param name="services">The services collection.</param>
|
|||
public OpenIddictBuilder(IServiceCollection services) { |
|||
Services = services; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type corresponding to the Application entity.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public Type ApplicationType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type corresponding to the Authorization entity.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public Type AuthorizationType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type corresponding to the Scope entity.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public Type ScopeType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type corresponding to the Token entity.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public Type TokenType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type corresponding to the User entity.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public Type UserType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the services collection.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public IServiceCollection Services { get; } |
|||
|
|||
/// <summary>
|
|||
/// Amends the default OpenIddict configuration.
|
|||
/// </summary>
|
|||
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder Configure([NotNull] Action<OpenIddictOptions> configuration) { |
|||
if (configuration == null) { |
|||
throw new ArgumentNullException(nameof(configuration)); |
|||
} |
|||
|
|||
Services.Configure(configuration); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds a custom application manager.
|
|||
/// </summary>
|
|||
/// <typeparam name="TManager">The type of the custom manager.</typeparam>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddApplicationManager<TManager>() { |
|||
var contract = typeof(OpenIddictApplicationManager<>).MakeGenericType(ApplicationType); |
|||
if (!contract.IsAssignableFrom(typeof(TManager))) { |
|||
throw new InvalidOperationException("Custom managers must be derived from OpenIddictApplicationManager."); |
|||
} |
|||
|
|||
Services.AddScoped(contract, typeof(TManager)); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds a custom application store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TStore">The type of the custom store.</typeparam>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddApplicationStore<TStore>() { |
|||
var contract = typeof(IOpenIddictApplicationStore<>).MakeGenericType(ApplicationType); |
|||
if (!contract.IsAssignableFrom(typeof(TStore))) { |
|||
throw new InvalidOperationException("Custom stores must implement IOpenIddictApplicationStore."); |
|||
} |
|||
|
|||
Services.AddScoped(contract, typeof(TStore)); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds a custom authorization manager.
|
|||
/// </summary>
|
|||
/// <typeparam name="TManager">The type of the custom manager.</typeparam>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddAuthorizationManager<TManager>() { |
|||
var contract = typeof(OpenIddictAuthorizationManager<>).MakeGenericType(AuthorizationType); |
|||
if (!contract.IsAssignableFrom(typeof(TManager))) { |
|||
throw new InvalidOperationException("Custom managers must be derived from OpenIddictAuthorizationManager."); |
|||
} |
|||
|
|||
Services.AddScoped(contract, typeof(TManager)); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds a custom authorization store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TStore">The type of the custom store.</typeparam>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddAuthorizationStore<TStore>() { |
|||
var contract = typeof(IOpenIddictAuthorizationStore<>).MakeGenericType(AuthorizationType); |
|||
if (!contract.IsAssignableFrom(typeof(TStore))) { |
|||
throw new InvalidOperationException("Custom stores must implement IOpenIddictAuthorizationStore."); |
|||
} |
|||
|
|||
Services.AddScoped(contract, typeof(TStore)); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds a custom scope manager.
|
|||
/// </summary>
|
|||
/// <typeparam name="TManager">The type of the custom manager.</typeparam>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddScopeManager<TManager>() { |
|||
var contract = typeof(OpenIddictScopeManager<>).MakeGenericType(ScopeType); |
|||
if (!contract.IsAssignableFrom(typeof(TManager))) { |
|||
throw new InvalidOperationException("Custom managers must be derived from OpenIddictScopeManager."); |
|||
} |
|||
|
|||
Services.AddScoped(contract, typeof(TManager)); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds a custom scope store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TStore">The type of the custom store.</typeparam>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddScopeStore<TStore>() { |
|||
var contract = typeof(IOpenIddictScopeStore<>).MakeGenericType(ScopeType); |
|||
if (!contract.IsAssignableFrom(typeof(TStore))) { |
|||
throw new InvalidOperationException("Custom stores must implement IOpenIddictScopeStore."); |
|||
} |
|||
|
|||
Services.AddScoped(contract, typeof(TStore)); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds a custom token manager.
|
|||
/// </summary>
|
|||
/// <typeparam name="TManager">The type of the custom manager.</typeparam>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddTokenManager<TManager>() { |
|||
var contract = typeof(OpenIddictTokenManager<,>).MakeGenericType(TokenType, UserType); |
|||
if (!contract.IsAssignableFrom(typeof(TManager))) { |
|||
throw new InvalidOperationException("Custom managers must be derived from OpenIddictTokenManager."); |
|||
} |
|||
|
|||
Services.AddScoped(contract, typeof(TManager)); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds a custom token store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TStore">The type of the custom store.</typeparam>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddTokenStore<TStore>() { |
|||
var contract = typeof(IOpenIddictTokenStore<>).MakeGenericType(TokenType); |
|||
if (!contract.IsAssignableFrom(typeof(TStore))) { |
|||
throw new InvalidOperationException("Custom stores must implement IOpenIddictTokenStore."); |
|||
} |
|||
|
|||
Services.AddScoped(contract, typeof(TStore)); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers a new OpenIddict module. If a module with the same name already
|
|||
/// exists, the new instance is ignored and this extension has no effect.
|
|||
/// </summary>
|
|||
/// <param name="name">The name of the OpenIddict module.</param>
|
|||
/// <param name="position">The relative position of the OpenIddict module in the ASP.NET Core pipeline.</param>
|
|||
/// <param name="registration">The delegate used to register the module in the ASP.NET Core pipeline.</param>
|
|||
/// <returns>The<see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddModule( |
|||
[NotNull] string name, int position, |
|||
[NotNull] Action<IApplicationBuilder> registration) { |
|||
if (string.IsNullOrEmpty(name)) { |
|||
throw new ArgumentNullException(nameof(name)); |
|||
} |
|||
|
|||
if (registration == null) { |
|||
throw new ArgumentNullException(nameof(registration)); |
|||
} |
|||
|
|||
return Configure(options => { |
|||
if (options.Modules.Any(module => module.Name == name)) { |
|||
return; |
|||
} |
|||
|
|||
options.Modules.Add(new OpenIddictModule(name, position, registration)); |
|||
}); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers a <see cref="X509Certificate2"/> used to sign the tokens issued by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="certificate">The certificate used to sign the security tokens issued by the server.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddSigningCertificate([NotNull] X509Certificate2 certificate) { |
|||
if (certificate == null) { |
|||
throw new ArgumentNullException(nameof(certificate)); |
|||
} |
|||
|
|||
if (!certificate.HasPrivateKey) { |
|||
throw new InvalidOperationException("The certificate doesn't contain the required private key."); |
|||
} |
|||
|
|||
return Configure(options => options.SigningCredentials.AddCertificate(certificate)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers a <see cref="X509Certificate2"/> retrieved from
|
|||
/// an embedded resource to sign the tokens issued by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="assembly">The assembly containing the certificate.</param>
|
|||
/// <param name="resource">The name of the embedded resource.</param>
|
|||
/// <param name="password">The password used to open the certificate.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddSigningCertificate( |
|||
[NotNull] Assembly assembly, [NotNull] string resource, [NotNull] string password) { |
|||
if (assembly == null) { |
|||
throw new ArgumentNullException(nameof(assembly)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(resource)) { |
|||
throw new ArgumentNullException(nameof(resource)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(password)) { |
|||
throw new ArgumentNullException(nameof(password)); |
|||
} |
|||
|
|||
return Configure(options => options.SigningCredentials.AddCertificate(assembly, resource, password)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers a <see cref="X509Certificate2"/> extracted
|
|||
/// from a stream to sign the tokens issued by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="stream">The stream containing the certificate.</param>
|
|||
/// <param name="password">The password used to open the certificate.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddSigningCertificate([NotNull] Stream stream, [NotNull] string password) { |
|||
if (stream == null) { |
|||
throw new ArgumentNullException(nameof(stream)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(password)) { |
|||
throw new ArgumentNullException(nameof(password)); |
|||
} |
|||
|
|||
return Configure(options => options.SigningCredentials.AddCertificate(stream, password)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers a <see cref="X509Certificate2"/> extracted
|
|||
/// from a stream to sign the tokens issued by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="stream">The stream containing the certificate.</param>
|
|||
/// <param name="password">The password used to open the certificate.</param>
|
|||
/// <param name="flags">
|
|||
/// An enumeration of flags indicating how and where
|
|||
/// to store the private key of the certificate.
|
|||
/// </param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddSigningCertificate( |
|||
[NotNull] Stream stream, [NotNull] string password, X509KeyStorageFlags flags) { |
|||
if (stream == null) { |
|||
throw new ArgumentNullException(nameof(stream)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(password)) { |
|||
throw new ArgumentNullException(nameof(password)); |
|||
} |
|||
|
|||
return Configure(options => options.SigningCredentials.AddCertificate(stream, password, flags)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers a <see cref="X509Certificate2"/> retrieved from the
|
|||
/// X.509 machine store to sign the tokens issued by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="thumbprint">The thumbprint of the certificate used to identify it in the X.509 store.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddSigningCertificate([NotNull] string thumbprint) { |
|||
if (string.IsNullOrEmpty(thumbprint)) { |
|||
throw new ArgumentNullException(nameof(thumbprint)); |
|||
} |
|||
|
|||
return Configure(options => options.SigningCredentials.AddCertificate(thumbprint)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers a <see cref="X509Certificate2"/> retrieved from the
|
|||
/// given X.509 store to sign the tokens issued by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="thumbprint">The thumbprint of the certificate used to identify it in the X.509 store.</param>
|
|||
/// <param name="name">The name of the X.509 store.</param>
|
|||
/// <param name="location">The location of the X.509 store.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder AddSigningCertificate( |
|||
[NotNull] string thumbprint, StoreName name, StoreLocation location) { |
|||
if (string.IsNullOrEmpty(thumbprint)) { |
|||
throw new ArgumentNullException(nameof(thumbprint)); |
|||
} |
|||
|
|||
return Configure(options => options.SigningCredentials.AddCertificate(thumbprint, name, location)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disables the HTTPS requirement during development.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder DisableHttpsRequirement() { |
|||
return Configure(options => options.AllowInsecureHttp = true); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disables sliding expiration, which prevents OpenIddict from issuing a new
|
|||
/// refresh token when receiving a grant_type=refresh_token token request.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder DisableSlidingExpiration() { |
|||
return Configure(options => options.UseSlidingExpiration = false); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the relative path corresponding to the authorization endpoint.
|
|||
/// </summary>
|
|||
/// <param name="path">The relative path of the authorization endpoint.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder SetAuthorizationEndpointPath(PathString path) { |
|||
return Configure(options => options.AuthorizationEndpointPath = path); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the relative path corresponding to the logout endpoint.
|
|||
/// </summary>
|
|||
/// <param name="path">The relative path of the logout endpoint.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder SetLogoutEndpointPath(PathString path) { |
|||
return Configure(options => options.LogoutEndpointPath = path); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the relative path corresponding to the token endpoint.
|
|||
/// </summary>
|
|||
/// <param name="path">The relative path of the token endpoint.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder SetTokenEndpointPath(PathString path) { |
|||
return Configure(options => options.TokenEndpointPath = path); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the access token lifetime, after which client applications must retrieve
|
|||
/// a new access token by making a grant_type=refresh_token token request
|
|||
/// or a prompt=none authorization request, depending on the selected flow.
|
|||
/// Using long-lived access tokens or tokens that never expire is not recommended.
|
|||
/// </summary>
|
|||
/// <param name="lifetime">The access token lifetime.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder SetAccessTokenLifetime(TimeSpan lifetime) { |
|||
return Configure(options => options.AccessTokenLifetime = lifetime); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the refresh token lifetime, after which client applications must get
|
|||
/// a new authorization from the user. When sliding expiration is enabled,
|
|||
/// a new refresh token is always issued to the client application,
|
|||
/// which prolongs the validity period of the refresh token.
|
|||
/// </summary>
|
|||
public ICollection<OpenIddictModule> Modules { get; } = new List<OpenIddictModule>(); |
|||
/// <param name="lifetime">The refresh token lifetime.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder SetRefreshTokenLifetime(TimeSpan lifetime) { |
|||
return Configure(options => options.RefreshTokenLifetime = lifetime); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the options used by OpenIddict.
|
|||
/// Sets JWT as the default token format for access tokens.
|
|||
/// </summary>
|
|||
public OpenIddictOptions Options { get; set; } = new OpenIddictOptions(); |
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public virtual OpenIddictBuilder UseJsonWebTokens() { |
|||
return Configure(options => options.UseJwtTokens()); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,36 +0,0 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
|
|||
namespace OpenIddict { |
|||
public class OpenIddictConfiguration { |
|||
public OpenIddictConfiguration(IServiceCollection services) { |
|||
Services = services; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type corresponding to the Application entity.
|
|||
/// </summary>
|
|||
public Type ApplicationType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type corresponding to the Role entity.
|
|||
/// </summary>
|
|||
public Type RoleType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type corresponding to the User entity.
|
|||
/// </summary>
|
|||
public Type UserType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the services used by OpenIddict.
|
|||
/// </summary>
|
|||
public IServiceCollection Services { get; } |
|||
} |
|||
} |
|||
@ -1,68 +0,0 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Identity; |
|||
|
|||
namespace OpenIddict { |
|||
public static class OpenIddictHelpers { |
|||
public static async Task<bool> IsConfidentialApplicationAsync<TUser, TApplication>( |
|||
[NotNull] this OpenIddictManager<TUser, TApplication> manager, [NotNull] TApplication application) |
|||
where TUser : class |
|||
where TApplication : class { |
|||
if (manager == null) { |
|||
throw new ArgumentNullException(nameof(manager)); |
|||
} |
|||
|
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
var type = await manager.GetApplicationTypeAsync(application); |
|||
|
|||
return string.Equals(type, OpenIddictConstants.ApplicationTypes.Confidential, StringComparison.OrdinalIgnoreCase); |
|||
} |
|||
|
|||
public static async Task<bool> IsPublicApplicationAsync<TUser, TApplication>( |
|||
[NotNull] this OpenIddictManager<TUser, TApplication> manager, [NotNull] TApplication application) |
|||
where TUser : class |
|||
where TApplication : class { |
|||
if (manager == null) { |
|||
throw new ArgumentNullException(nameof(manager)); |
|||
} |
|||
|
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
var type = await manager.GetApplicationTypeAsync(application); |
|||
|
|||
return string.Equals(type, OpenIddictConstants.ApplicationTypes.Public, StringComparison.OrdinalIgnoreCase); |
|||
} |
|||
|
|||
public static async Task<string> FindClaimAsync<TUser>( |
|||
[NotNull] this UserManager<TUser> manager, |
|||
[NotNull] TUser user, [NotNull] string type) where TUser : class { |
|||
if (manager == null) { |
|||
throw new ArgumentNullException(nameof(manager)); |
|||
} |
|||
|
|||
if (user == null) { |
|||
throw new ArgumentNullException(nameof(user)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(type)) { |
|||
throw new ArgumentNullException(nameof(type)); |
|||
} |
|||
|
|||
// Note: GetClaimsAsync will automatically throw an exception
|
|||
// if the underlying store doesn't support custom claims.
|
|||
|
|||
var claims = await manager.GetClaimsAsync(user); |
|||
if (claims.Count != 0) { |
|||
return claims[0]?.Value; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -1,195 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Security.Claims; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using AspNet.Security.OpenIdConnect.Extensions; |
|||
using AspNet.Security.OpenIdConnect.Server; |
|||
using CryptoHelper; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
|
|||
namespace OpenIddict { |
|||
public class OpenIddictManager<TUser, TApplication> where TUser : class where TApplication : class { |
|||
public OpenIddictManager([NotNull] OpenIddictServices<TUser, TApplication> services) { |
|||
Services = services; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the HTTP context associated with the current manager.
|
|||
/// </summary>
|
|||
protected virtual HttpContext Context => Services.Context; |
|||
|
|||
/// <summary>
|
|||
/// Gets the cancellation token used to abort async operations.
|
|||
/// </summary>
|
|||
protected virtual CancellationToken CancellationToken => Context?.RequestAborted ?? CancellationToken.None; |
|||
|
|||
/// <summary>
|
|||
/// Gets the logger associated with the current manager.
|
|||
/// </summary>
|
|||
protected virtual ILogger Logger => Services.Logger; |
|||
|
|||
/// <summary>
|
|||
/// Gets the options associated with the current manager.
|
|||
/// </summary>
|
|||
protected virtual IdentityOptions Options => Services.Services.GetRequiredService<IOptions<IdentityOptions>>().Value; |
|||
|
|||
/// <summary>
|
|||
/// Gets the servuces associated with the current manager.
|
|||
/// </summary>
|
|||
protected virtual OpenIddictServices<TUser, TApplication> Services { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the store associated with the current manager.
|
|||
/// </summary>
|
|||
protected virtual IOpenIddictStore<TUser, TApplication> Store => Services.Store; |
|||
|
|||
public virtual async Task<ClaimsIdentity> CreateIdentityAsync(TUser user, IEnumerable<string> scopes) { |
|||
if (user == null) { |
|||
throw new ArgumentNullException(nameof(user)); |
|||
} |
|||
|
|||
if (scopes == null) { |
|||
throw new ArgumentNullException(nameof(scopes)); |
|||
} |
|||
|
|||
var identity = new ClaimsIdentity( |
|||
OpenIdConnectServerDefaults.AuthenticationScheme, |
|||
Options.ClaimsIdentity.UserNameClaimType, |
|||
Options.ClaimsIdentity.RoleClaimType); |
|||
|
|||
// Note: the name identifier is always included in both identity and
|
|||
// access tokens, even if an explicit destination is not specified.
|
|||
identity.AddClaim(ClaimTypes.NameIdentifier, await Services.Users.GetUserIdAsync(user)); |
|||
|
|||
// Resolve the email address associated with the user if the underlying store supports it.
|
|||
var email = Services.Users.SupportsUserEmail ? await Services.Users.GetEmailAsync(user) : null; |
|||
|
|||
// Only add the name claim if the "profile" scope was granted.
|
|||
if (scopes.Contains(OpenIdConnectConstants.Scopes.Profile)) { |
|||
var username = await Services.Users.GetUserNameAsync(user); |
|||
|
|||
// Throw an exception if the username corresponds to the registered
|
|||
// email address and if the "email" scope has not been requested.
|
|||
if (!scopes.Contains(OpenIdConnectConstants.Scopes.Email) && |
|||
!string.IsNullOrEmpty(email) && |
|||
string.Equals(username, email, StringComparison.OrdinalIgnoreCase)) { |
|||
throw new InvalidOperationException("The 'email' scope is required."); |
|||
} |
|||
|
|||
identity.AddClaim(ClaimTypes.Name, username, |
|||
OpenIdConnectConstants.Destinations.AccessToken, |
|||
OpenIdConnectConstants.Destinations.IdentityToken); |
|||
} |
|||
|
|||
// Only add the email address if the "email" scope was granted.
|
|||
if (!string.IsNullOrEmpty(email) && scopes.Contains(OpenIdConnectConstants.Scopes.Email)) { |
|||
identity.AddClaim(ClaimTypes.Email, email, |
|||
OpenIdConnectConstants.Destinations.AccessToken, |
|||
OpenIdConnectConstants.Destinations.IdentityToken); |
|||
} |
|||
|
|||
if (Services.Users.SupportsUserRole && scopes.Contains(OpenIddictConstants.Scopes.Roles)) { |
|||
foreach (var role in await Services.Users.GetRolesAsync(user)) { |
|||
identity.AddClaim(identity.RoleClaimType, role, |
|||
OpenIdConnectConstants.Destinations.AccessToken, |
|||
OpenIdConnectConstants.Destinations.IdentityToken); |
|||
} |
|||
} |
|||
|
|||
if (Services.Users.SupportsUserSecurityStamp) { |
|||
var identifier = await Services.Users.GetSecurityStampAsync(user); |
|||
|
|||
if (!string.IsNullOrEmpty(identifier)) { |
|||
identity.AddClaim(Options.ClaimsIdentity.SecurityStampClaimType, identifier, |
|||
OpenIdConnectConstants.Destinations.AccessToken, |
|||
OpenIdConnectConstants.Destinations.IdentityToken); |
|||
} |
|||
} |
|||
|
|||
return identity; |
|||
} |
|||
|
|||
public virtual Task<TApplication> FindApplicationByIdAsync(string identifier) { |
|||
return Store.FindApplicationByIdAsync(identifier, CancellationToken); |
|||
} |
|||
|
|||
public virtual Task<TApplication> FindApplicationByLogoutRedirectUri(string url) { |
|||
return Store.FindApplicationByLogoutRedirectUri(url, CancellationToken); |
|||
} |
|||
|
|||
public virtual async Task<string> GetApplicationTypeAsync(TApplication application) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
var type = await Store.GetApplicationTypeAsync(application, CancellationToken); |
|||
|
|||
// Ensure the application type returned by the store is supported by the manager.
|
|||
if (!string.Equals(type, OpenIddictConstants.ApplicationTypes.Confidential, StringComparison.OrdinalIgnoreCase) && |
|||
!string.Equals(type, OpenIddictConstants.ApplicationTypes.Public, StringComparison.OrdinalIgnoreCase)) { |
|||
throw new InvalidOperationException("Only 'confidential' or 'public' applications are " + |
|||
"supported by the default OpenIddict manager."); |
|||
} |
|||
|
|||
return type; |
|||
} |
|||
|
|||
public virtual Task<string> GetDisplayNameAsync(TApplication application) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Store.GetDisplayNameAsync(application, CancellationToken); |
|||
} |
|||
|
|||
public virtual async Task<bool> ValidateRedirectUriAsync(TApplication application, string address) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (!string.Equals(address, await Store.GetRedirectUriAsync(application, CancellationToken), StringComparison.Ordinal)) { |
|||
Logger.LogWarning("Client validation failed because {RedirectUri} was not a valid redirect_uri " + |
|||
"for {Client}", address, await GetDisplayNameAsync(application)); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public virtual async Task<bool> ValidateSecretAsync(TApplication application, string secret) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (!await this.IsConfidentialApplicationAsync(application)) { |
|||
Logger.LogWarning("Client authentication cannot be enforced for non-confidential applications."); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
var hash = await Store.GetHashedSecretAsync(application, CancellationToken); |
|||
if (string.IsNullOrEmpty(hash)) { |
|||
Logger.LogError("Client authentication failed for {Client} because " + |
|||
"no client secret was associated with the application."); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
if (!Crypto.VerifyHashedPassword(hash, secret)) { |
|||
Logger.LogWarning("Client authentication failed for {Client}.", await GetDisplayNameAsync(application)); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
@ -1,25 +1,56 @@ |
|||
using System; |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Builder; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Defines an OpenIddict module.
|
|||
/// Represents an OpenIddict module.
|
|||
/// </summary>
|
|||
[DebuggerDisplay("{Name,nq}")] |
|||
public class OpenIddictModule { |
|||
/// <summary>
|
|||
/// Initializes a new OpenIddict module.
|
|||
/// </summary>
|
|||
/// <param name="name">The name of the module.</param>
|
|||
/// <param name="position">The position of the module in the ASP.NET Core pipeline.</param>
|
|||
/// <param name="registration">The delegate used to register the module in the pipeline.</param>
|
|||
public OpenIddictModule( |
|||
[NotNull] string name, int position, |
|||
[NotNull] Action<IApplicationBuilder> registration) { |
|||
Name = name; |
|||
Position = position; |
|||
Registration = registration; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new OpenIddict module.
|
|||
/// </summary>
|
|||
/// <param name="registration">The delegate used to register the module in the pipeline.</param>
|
|||
public OpenIddictModule([NotNull] Action<IApplicationBuilder> registration) { |
|||
Registration = registration; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the name of the module.
|
|||
/// </summary>
|
|||
public string Name { get; set; } |
|||
public string Name { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the position of the module in the ASP.NET pipeline.
|
|||
/// Gets or sets the position of the module in the ASP.NET Core pipeline.
|
|||
/// </summary>
|
|||
public int Position { get; set; } |
|||
public int Position { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the delegate used to register
|
|||
/// the OpenIddict module in the ASP.NET pipeline.
|
|||
/// Gets or sets the delegate used to register the
|
|||
/// OpenIddict module in the ASP.NET Core pipeline.
|
|||
/// </summary>
|
|||
public Action<IApplicationBuilder> Registration { get; set; } |
|||
public Action<IApplicationBuilder> Registration { get; } |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,72 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the applications stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|||
public interface IOpenIddictApplicationStore<TApplication> where TApplication : class { |
|||
/// <summary>
|
|||
/// Creates a new application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application to create.</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 CreateAsync(TApplication application, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its unique identifier.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
Task<TApplication> FindByIdAsync(string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its post_logout_redirect_uri.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
Task<TApplication> FindByLogoutRedirectUri(string url, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the client type associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The 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<string> GetClientTypeAsync(TApplication application, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the display name associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The 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<string> GetDisplayNameAsync(TApplication application, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the callback address associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The 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<string> GetRedirectUriAsync(TApplication application, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the hashed secret associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The 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<string> GetHashedSecretAsync(TApplication application, CancellationToken cancellationToken); |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the authorizations stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|||
public interface IOpenIddictAuthorizationStore<TAuthorization> where TAuthorization : class { } |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the scopes stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|||
public interface IOpenIddictScopeStore<TScope> where TScope : class { } |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the tokens stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
public interface IOpenIddictTokenStore<TToken> where TToken : class { |
|||
/// <summary>
|
|||
/// Creates a new token, defined by a unique identifier and a token type.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the token to create.</param>
|
|||
/// <param name="type">The token type.</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 CreateAsync(string identifier, string type, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an token using its unique identifier.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
Task<TToken> FindByIdAsync(string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Revokes a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token to revoke.</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 RevokeAsync(TToken token, CancellationToken cancellationToken); |
|||
} |
|||
} |
|||
@ -1,39 +0,0 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using OpenIddict.Models; |
|||
|
|||
namespace OpenIddict { |
|||
public class OpenIddictContext<TUser, TApplication, TRole, TKey> : IdentityDbContext<TUser, TRole, TKey> |
|||
where TUser : IdentityUser<TKey> |
|||
where TApplication : Application<TKey> |
|||
where TRole : IdentityRole<TKey> |
|||
where TKey : IEquatable<TKey> { |
|||
protected OpenIddictContext() { } |
|||
|
|||
public OpenIddictContext(DbContextOptions options) |
|||
: base(options) { } |
|||
|
|||
public DbSet<TApplication> Applications { get; set; } |
|||
} |
|||
|
|||
public class OpenIddictContext<TUser> : OpenIddictContext<TUser, Application, IdentityRole, string> where TUser : IdentityUser { |
|||
protected OpenIddictContext() { } |
|||
|
|||
public OpenIddictContext(DbContextOptions options) |
|||
: base(options) { } |
|||
} |
|||
|
|||
public class OpenIddictContext : OpenIddictContext<IdentityUser> { |
|||
protected OpenIddictContext() { } |
|||
|
|||
public OpenIddictContext(DbContextOptions options) |
|||
: base(options) { } |
|||
} |
|||
} |
|||
@ -1,117 +0,0 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using OpenIddict; |
|||
using OpenIddict.Models; |
|||
|
|||
namespace Microsoft.AspNetCore.Builder { |
|||
public static class OpenIddictExtensions { |
|||
public static OpenIddictConfiguration UseEntityFramework([NotNull] this OpenIddictConfiguration configuration) { |
|||
if (configuration == null) { |
|||
throw new ArgumentNullException(nameof(configuration)); |
|||
} |
|||
|
|||
if (!IsSubclassOf(configuration.ApplicationType, typeof(Application<>))) { |
|||
throw new InvalidOperationException("The default store cannot be used with application " + |
|||
"entities that are not derived from Application<TKey>."); |
|||
} |
|||
|
|||
configuration.Services.AddScoped( |
|||
typeof(IOpenIddictStore<,>).MakeGenericType(configuration.UserType, configuration.ApplicationType), |
|||
typeof(OpenIddictStore<,,,>).MakeGenericType( |
|||
/* TUser: */ configuration.UserType, |
|||
/* TApplication: */ configuration.ApplicationType, |
|||
/* TContext: */ ResolveContextType(configuration), |
|||
/* TKey: */ ResolveKeyType(configuration))); |
|||
|
|||
return configuration; |
|||
} |
|||
|
|||
private static Type ResolveContextType([NotNull] OpenIddictConfiguration configuration) { |
|||
var service = (from registration in configuration.Services |
|||
where registration.ServiceType.IsConstructedGenericType |
|||
let definition = registration.ServiceType.GetGenericTypeDefinition() |
|||
where definition == typeof(IUserStore<>) |
|||
select registration.ImplementationType).FirstOrDefault(); |
|||
|
|||
if (service == null) { |
|||
throw new InvalidOperationException( |
|||
"The type of the database context cannot be automatically inferred. " + |
|||
"Make sure 'AddOpenIddict()' is the last chained call when configuring the services."); |
|||
} |
|||
|
|||
TypeInfo type; |
|||
for (type = service.GetTypeInfo(); type != null; type = type.BaseType?.GetTypeInfo()) { |
|||
if (!type.IsGenericType) { |
|||
continue; |
|||
} |
|||
|
|||
var definition = type.GetGenericTypeDefinition(); |
|||
if (definition == null) { |
|||
continue; |
|||
} |
|||
|
|||
if (definition != typeof(UserStore<,,,>)) { |
|||
continue; |
|||
} |
|||
|
|||
return (from argument in type.AsType().GetGenericArguments() |
|||
where typeof(DbContext).IsAssignableFrom(argument) |
|||
select argument).Single(); |
|||
} |
|||
|
|||
throw new InvalidOperationException("The type of the database context cannot be automatically inferred."); |
|||
} |
|||
|
|||
private static Type ResolveKeyType([NotNull] OpenIddictConfiguration configuration) { |
|||
TypeInfo type; |
|||
for (type = configuration.UserType.GetTypeInfo(); type != null; type = type.BaseType?.GetTypeInfo()) { |
|||
if (!type.IsGenericType) { |
|||
continue; |
|||
} |
|||
|
|||
var definition = type.GetGenericTypeDefinition(); |
|||
if (definition == null) { |
|||
continue; |
|||
} |
|||
|
|||
if (definition != typeof(IdentityUser<>)) { |
|||
continue; |
|||
} |
|||
|
|||
return type.AsType().GetGenericArguments().Single(); |
|||
} |
|||
|
|||
throw new InvalidOperationException( |
|||
"The type of the key identifier used by the user " + |
|||
$"entity '{configuration.UserType}' cannot be automatically inferred."); |
|||
} |
|||
|
|||
private static bool IsSubclassOf([NotNull] Type type, [NotNull] Type generic) { |
|||
while (type != null && type != typeof(object)) { |
|||
var current = type.GetTypeInfo().IsGenericType ? |
|||
type.GetGenericTypeDefinition() : |
|||
type; |
|||
|
|||
if (current == generic) { |
|||
return true; |
|||
} |
|||
|
|||
type = type.GetTypeInfo().BaseType; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
@ -1,78 +0,0 @@ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using OpenIddict.Models; |
|||
|
|||
namespace OpenIddict { |
|||
public class OpenIddictStore<TUser, TApplication, TContext, TKey> : IOpenIddictStore<TUser, TApplication> |
|||
where TUser : IdentityUser<TKey> |
|||
where TApplication : Application<TKey> |
|||
where TContext : DbContext |
|||
where TKey : IEquatable<TKey> { |
|||
public OpenIddictStore(TContext context) { |
|||
Context = context; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the database context associated with the current store.
|
|||
/// </summary>
|
|||
public virtual TContext Context { get; } |
|||
|
|||
public DbSet<TApplication> Applications { |
|||
get { return Context.Set<TApplication>(); } |
|||
} |
|||
|
|||
public virtual Task<TApplication> FindApplicationByIdAsync(string identifier, CancellationToken cancellationToken) { |
|||
var converter = TypeDescriptor.GetConverter(typeof(TKey)); |
|||
|
|||
// If the string key cannot be converted to TKey, return null
|
|||
// to indicate that the requested application doesn't exist.
|
|||
if (!converter.CanConvertFrom(typeof(string))) { |
|||
return Task.FromResult<TApplication>(null); |
|||
} |
|||
|
|||
var key = (TKey) converter.ConvertFromInvariantString(identifier); |
|||
|
|||
return Applications.SingleOrDefaultAsync(application => application.Id.Equals(key), cancellationToken); |
|||
} |
|||
|
|||
public virtual Task<TApplication> FindApplicationByLogoutRedirectUri(string url, CancellationToken cancellationToken) { |
|||
return Applications.SingleOrDefaultAsync(application => application.LogoutRedirectUri == url, cancellationToken); |
|||
} |
|||
|
|||
public virtual Task<string> GetApplicationTypeAsync(TApplication application, CancellationToken cancellationToken) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Task.FromResult(application.Type); |
|||
} |
|||
|
|||
public virtual Task<string> GetDisplayNameAsync(TApplication application, CancellationToken cancellationToken) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Task.FromResult(application.DisplayName); |
|||
} |
|||
|
|||
public virtual Task<string> GetRedirectUriAsync(TApplication application, CancellationToken cancellationToken) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Task.FromResult(application.RedirectUri); |
|||
} |
|||
|
|||
public virtual Task<string> GetHashedSecretAsync(TApplication application, CancellationToken cancellationToken) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Task.FromResult(application.Secret); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Represents an OpenIddict application.
|
|||
/// </summary>
|
|||
public class OpenIddictApplication : OpenIddictApplication<string> { |
|||
public OpenIddictApplication() { |
|||
// Generate a new string identifier.
|
|||
Id = Guid.NewGuid().ToString(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict application.
|
|||
/// </summary>
|
|||
public class OpenIddictApplication<TKey> where TKey : IEquatable<TKey> { |
|||
/// <summary>
|
|||
/// Gets or sets the display name
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string DisplayName { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the unique identifier
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual TKey Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the logout callback URL
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string LogoutRedirectUri { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the callback URL
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string RedirectUri { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the hashed secret
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string Secret { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the application type
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string Type { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Represents an OpenIddict authorization.
|
|||
/// </summary>
|
|||
public class OpenIddictAuthorization : OpenIddictAuthorization<OpenIddictToken> { } |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict authorization.
|
|||
/// </summary>
|
|||
public class OpenIddictAuthorization<TToken> : OpenIddictAuthorization<TToken, string> { |
|||
public OpenIddictAuthorization() { |
|||
// Generate a new string identifier.
|
|||
Id = Guid.NewGuid().ToString(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict authorization.
|
|||
/// </summary>
|
|||
public class OpenIddictAuthorization<TToken, TKey> where TKey : IEquatable<TKey> { |
|||
/// <summary>
|
|||
/// Gets or sets the unique identifier
|
|||
/// associated with the current authorization.
|
|||
/// </summary>
|
|||
public virtual TKey Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the space-delimited scopes
|
|||
/// associated with the current authorization.
|
|||
/// </summary>
|
|||
public virtual string Scope { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the list of tokens
|
|||
/// associated with the current authorization.
|
|||
/// </summary>
|
|||
public virtual IList<TToken> Tokens { get; } = new List<TToken>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the identifier of the user profile
|
|||
/// associated with the current authorization.
|
|||
/// </summary>
|
|||
public virtual TKey UserId { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Represents an OpenIddict scope.
|
|||
/// </summary>
|
|||
public class OpenIddictScope : OpenIddictScope<string> { } |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict scope.
|
|||
/// </summary>
|
|||
public class OpenIddictScope<TKey> where TKey : IEquatable<TKey> { |
|||
/// <summary>
|
|||
/// Gets or sets the public description
|
|||
/// associated with the current scope.
|
|||
/// </summary>
|
|||
public virtual string Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the unique identifier
|
|||
/// associated with the current scope.
|
|||
/// </summary>
|
|||
public virtual TKey Id { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Represents an OpenIddict token.
|
|||
/// </summary>
|
|||
public class OpenIddictToken : OpenIddictToken<string> { |
|||
public OpenIddictToken() { |
|||
// Generate a new string identifier.
|
|||
Id = Guid.NewGuid().ToString(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict token.
|
|||
/// </summary>
|
|||
public class OpenIddictToken<TKey> where TKey : IEquatable<TKey> { |
|||
/// <summary>
|
|||
/// Gets or sets the identifier of the authorization attached with the current token.
|
|||
/// This property may be null if the token was issued without
|
|||
/// requiring the user consent or is bound to a client application.
|
|||
/// </summary>
|
|||
public virtual TKey AuthorizationId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the unique identifier
|
|||
/// associated with the current token.
|
|||
/// </summary>
|
|||
public virtual TKey Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type of the current token.
|
|||
/// </summary>
|
|||
public virtual string Type { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the identifier of the user attached with the current token.
|
|||
/// This property is null if the token represents a client application.
|
|||
/// </summary>
|
|||
public virtual TKey UserId { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Represents an OpenIddict user.
|
|||
/// </summary>
|
|||
public class OpenIddictUser : OpenIddictUser<OpenIddictAuthorization, OpenIddictToken> { } |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict user.
|
|||
/// </summary>
|
|||
public class OpenIddictUser<TAuthorization, TToken> : OpenIddictUser<TAuthorization, TToken, string> { |
|||
public OpenIddictUser() { |
|||
// Generate a new string identifier.
|
|||
Id = Guid.NewGuid().ToString(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict user.
|
|||
/// </summary>
|
|||
public class OpenIddictUser<TAuthorization, TToken, TKey> : IdentityUser<TKey> where TKey : IEquatable<TKey> { |
|||
/// <summary>
|
|||
/// Gets the list of the authorizations associated with this user profile.
|
|||
/// </summary>
|
|||
public virtual IList<TAuthorization> Authorizations { get; } = new List<TAuthorization>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the list of the tokens associated with this user profile.
|
|||
/// </summary>
|
|||
public virtual IList<TToken> Tokens { get; } = new List<TToken>(); |
|||
} |
|||
} |
|||
@ -0,0 +1,152 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Represents an OpenIddict-powered Entity Framework context.
|
|||
/// </summary>
|
|||
public class OpenIddictContext : OpenIddictContext<OpenIddictUser> { |
|||
/// <summary>
|
|||
/// Initializes a new OpenIddict context without configuring the Entity Framework options.
|
|||
/// </summary>
|
|||
protected OpenIddictContext() { } |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new OpenIddict context.
|
|||
/// </summary>
|
|||
/// <param name="options">The options used to configure the Entity Framework context.</param>
|
|||
public OpenIddictContext(DbContextOptions options) : base(options) { } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict-powered Entity Framework context.
|
|||
/// </summary>
|
|||
/// <typeparam name="TUser">The type of the User entity.</typeparam>
|
|||
public class OpenIddictContext<TUser> : OpenIddictContext<TUser, OpenIddictApplication, |
|||
OpenIddictAuthorization, |
|||
OpenIddictScope, |
|||
OpenIddictToken, IdentityRole, string> |
|||
where TUser : OpenIddictUser { |
|||
/// <summary>
|
|||
/// Initializes a new OpenIddict context without configuring the Entity Framework options.
|
|||
/// </summary>
|
|||
protected OpenIddictContext() { } |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new OpenIddict context.
|
|||
/// </summary>
|
|||
/// <param name="options">The options used to configure the Entity Framework context.</param>
|
|||
public OpenIddictContext(DbContextOptions options) : base(options) { } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict-powered Entity Framework context.
|
|||
/// </summary>
|
|||
/// <typeparam name="TUser">The type of the User entity.</typeparam>
|
|||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
/// <typeparam name="TRole">The type of the Role entity.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the primary key used by the Identity/OpenIddict entities.</typeparam>
|
|||
public class OpenIddictContext<TUser, TApplication, TAuthorization, TScope, TToken, TRole, TKey> : IdentityDbContext<TUser, TRole, TKey> |
|||
where TUser : OpenIddictUser<TAuthorization, TToken, TKey> |
|||
where TApplication : OpenIddictApplication<TKey> |
|||
where TAuthorization : OpenIddictAuthorization<TToken, TKey> |
|||
where TScope : OpenIddictScope<TKey> |
|||
where TToken : OpenIddictToken<TKey> |
|||
where TRole : IdentityRole<TKey> |
|||
where TKey : IEquatable<TKey> { |
|||
/// <summary>
|
|||
/// Initializes a new OpenIddict context without configuring the Entity Framework options.
|
|||
/// </summary>
|
|||
protected OpenIddictContext() { } |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new OpenIddict context.
|
|||
/// </summary>
|
|||
/// <param name="options">The options used to configure the Entity Framework context.</param>
|
|||
public OpenIddictContext(DbContextOptions options) : base(options) { } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the database set containing the applications.
|
|||
/// </summary>
|
|||
public DbSet<TApplication> Applications { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the database set containing the authorizations.
|
|||
/// </summary>
|
|||
public DbSet<TAuthorization> Authorizations { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the database set containing the scopes.
|
|||
/// </summary>
|
|||
public DbSet<TScope> Scopes { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the database set containing the tokens.
|
|||
/// </summary>
|
|||
public DbSet<TToken> Tokens { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Registers the OpenIddict entities in the Entity Framework context.
|
|||
/// </summary>
|
|||
/// <param name="builder">The model builder used by Entity Framework.</param>
|
|||
protected override void OnModelCreating(ModelBuilder builder) { |
|||
base.OnModelCreating(builder); |
|||
|
|||
// Configure the TApplication entity.
|
|||
builder.Entity<TApplication>(entity => { |
|||
entity.HasKey(application => application.Id); |
|||
|
|||
entity.ToTable("OpenIddictApplications"); |
|||
}); |
|||
|
|||
// Configure the TAuthorization entity.
|
|||
builder.Entity<TAuthorization>(entity => { |
|||
entity.HasKey(authorization => authorization.Id); |
|||
|
|||
entity.HasMany(authorization => authorization.Tokens) |
|||
.WithOne() |
|||
.HasForeignKey(token => token.AuthorizationId) |
|||
.IsRequired(required: false); |
|||
|
|||
entity.ToTable("OpenIddictAuthorizations"); |
|||
}); |
|||
|
|||
// Configure the TScope entity.
|
|||
builder.Entity<TScope>(entity => { |
|||
entity.HasKey(scope => scope.Id); |
|||
|
|||
entity.ToTable("OpenIddictScopes"); |
|||
}); |
|||
|
|||
// Configure the TToken entity.
|
|||
builder.Entity<TToken>(entity => { |
|||
entity.HasKey(token => token.Id); |
|||
|
|||
entity.ToTable("OpenIddictTokens"); |
|||
}); |
|||
|
|||
// Configure the TUser entity.
|
|||
builder.Entity<TUser>(entity => { |
|||
entity.HasMany(user => user.Authorizations) |
|||
.WithOne() |
|||
.HasForeignKey(authorization => authorization.UserId) |
|||
.IsRequired(required: false); |
|||
|
|||
entity.HasMany(user => user.Tokens) |
|||
.WithOne() |
|||
.HasForeignKey(token => token.UserId) |
|||
.IsRequired(required: false); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.Extensions.DependencyInjection.Extensions; |
|||
using OpenIddict; |
|||
|
|||
namespace Microsoft.AspNetCore.Builder { |
|||
public static class OpenIddictExtensions { |
|||
/// <summary>
|
|||
/// Registers the Entity Framework stores.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public static OpenIddictBuilder AddEntityFramework<TContext>([NotNull] this OpenIddictBuilder builder) |
|||
where TContext : DbContext { |
|||
return builder.AddEntityFramework<TContext, string>(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers the Entity Framework stores.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
|
|||
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
|
|||
public static OpenIddictBuilder AddEntityFramework<TContext, TKey>([NotNull] this OpenIddictBuilder builder) |
|||
where TContext : DbContext |
|||
where TKey : IEquatable<TKey> { |
|||
if (builder == null) { |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
Debug.Assert(builder.ApplicationType != null && |
|||
builder.AuthorizationType != null && |
|||
builder.ScopeType != null && |
|||
builder.TokenType != null, "The entity types exposed by OpenIddictBuilder shouldn't be null."); |
|||
|
|||
// Register the application store in the DI container.
|
|||
builder.Services.TryAddScoped( |
|||
typeof(IOpenIddictApplicationStore<>).MakeGenericType(builder.ApplicationType), |
|||
typeof(OpenIddictApplicationStore<,,>).MakeGenericType( |
|||
/* TApplication: */ builder.ApplicationType, |
|||
/* TContext: */ typeof(TContext), |
|||
/* TKey: */ typeof(TKey))); |
|||
|
|||
// Register the authorization store in the DI container.
|
|||
builder.Services.TryAddScoped( |
|||
typeof(IOpenIddictAuthorizationStore<>).MakeGenericType(builder.AuthorizationType), |
|||
typeof(OpenIddictAuthorizationStore<,,,>).MakeGenericType( |
|||
/* TAuthorization: */ builder.AuthorizationType, |
|||
/* TToken: */ builder.TokenType, |
|||
/* TContext: */ typeof(TContext), |
|||
/* TKey: */ typeof(TKey))); |
|||
|
|||
// Register the scope store in the DI container.
|
|||
builder.Services.TryAddScoped( |
|||
typeof(IOpenIddictScopeStore<>).MakeGenericType(builder.ScopeType), |
|||
typeof(OpenIddictScopeStore<,,>).MakeGenericType( |
|||
/* TScope: */ builder.ScopeType, |
|||
/* TContext: */ typeof(TContext), |
|||
/* TKey: */ typeof(TKey))); |
|||
|
|||
// Register the token store in the DI container.
|
|||
builder.Services.TryAddScoped( |
|||
typeof(IOpenIddictTokenStore<>).MakeGenericType(builder.TokenType), |
|||
typeof(OpenIddictTokenStore<,,>).MakeGenericType( |
|||
/* TToken: */ builder.TokenType, |
|||
/* TContext: */ typeof(TContext), |
|||
/* TKey: */ typeof(TKey))); |
|||
|
|||
return builder; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,140 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.EntityFrameworkCore; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the applications stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|||
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public class OpenIddictApplicationStore<TApplication, TContext, TKey> : IOpenIddictApplicationStore<TApplication> |
|||
where TApplication : OpenIddictApplication<TKey> |
|||
where TContext : DbContext |
|||
where TKey : IEquatable<TKey> { |
|||
public OpenIddictApplicationStore(TContext context) { |
|||
Context = context; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the database context associated with the current store.
|
|||
/// </summary>
|
|||
protected virtual TContext Context { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the database set corresponding to the <typeparamref name="TApplication"/> entity.
|
|||
/// </summary>
|
|||
protected DbSet<TApplication> Applications => Context.Set<TApplication>(); |
|||
|
|||
/// <summary>
|
|||
/// Creates a new application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application to create.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual Task CreateAsync(TApplication application, CancellationToken cancellationToken) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
Context.Add(application); |
|||
|
|||
return Context.SaveChangesAsync(cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its unique identifier.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual Task<TApplication> FindByIdAsync(string identifier, CancellationToken cancellationToken) { |
|||
var converter = TypeDescriptor.GetConverter(typeof(TKey)); |
|||
|
|||
// If the string key cannot be converted to TKey, return null
|
|||
// to indicate that the requested application doesn't exist.
|
|||
if (!converter.CanConvertFrom(typeof(string))) { |
|||
return Task.FromResult<TApplication>(null); |
|||
} |
|||
|
|||
var key = (TKey) converter.ConvertFromInvariantString(identifier); |
|||
|
|||
return Applications.SingleOrDefaultAsync(application => application.Id.Equals(key), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its post_logout_redirect_uri.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual Task<TApplication> FindByLogoutRedirectUri(string url, CancellationToken cancellationToken) { |
|||
return Applications.SingleOrDefaultAsync(application => application.LogoutRedirectUri == url, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the client type associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The 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 Task<string> GetClientTypeAsync(TApplication application, CancellationToken cancellationToken) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Task.FromResult(application.Type); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the display name associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The 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 Task<string> GetDisplayNameAsync(TApplication application, CancellationToken cancellationToken) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Task.FromResult(application.DisplayName); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the callback address associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The 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 Task<string> GetRedirectUriAsync(TApplication application, CancellationToken cancellationToken) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Task.FromResult(application.RedirectUri); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the hashed secret associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The 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 Task<string> GetHashedSecretAsync(TApplication application, CancellationToken cancellationToken) { |
|||
if (application == null) { |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return Task.FromResult(application.Secret); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using Microsoft.EntityFrameworkCore; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the authorizations stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public class OpenIddictAuthorizationStore<TAuthorization, TToken, TContext, TKey> : IOpenIddictAuthorizationStore<TAuthorization> |
|||
where TAuthorization : OpenIddictAuthorization<TToken, TKey> |
|||
where TToken : OpenIddictToken<TKey> |
|||
where TContext : DbContext |
|||
where TKey : IEquatable<TKey> { |
|||
public OpenIddictAuthorizationStore(TContext context) { |
|||
Context = context; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the database context associated with the current store.
|
|||
/// </summary>
|
|||
protected virtual TContext Context { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the database set corresponding to the <typeparamref name="TAuthorization"/> entity.
|
|||
/// </summary>
|
|||
protected DbSet<TAuthorization> Authorizations => Context.Set<TAuthorization>(); |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using Microsoft.EntityFrameworkCore; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the scopes stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|||
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public class OpenIddictScopeStore<TScope, TContext, TKey> : IOpenIddictScopeStore<TScope> |
|||
where TScope : OpenIddictScope<TKey> |
|||
where TContext : DbContext |
|||
where TKey : IEquatable<TKey> { |
|||
public OpenIddictScopeStore(TContext context) { |
|||
Context = context; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the database context associated with the current store.
|
|||
/// </summary>
|
|||
protected virtual TContext Context { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the database set corresponding to the <typeparamref name="TScope"/> entity.
|
|||
/// </summary>
|
|||
protected DbSet<TScope> Authorizations => Context.Set<TScope>(); |
|||
} |
|||
} |
|||
@ -0,0 +1,97 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.EntityFrameworkCore; |
|||
|
|||
namespace OpenIddict { |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the tokens stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public class OpenIddictTokenStore<TToken, TContext, TKey> : IOpenIddictTokenStore<TToken> |
|||
where TToken : OpenIddictToken<TKey>, new() |
|||
where TContext : DbContext |
|||
where TKey : IEquatable<TKey> { |
|||
public OpenIddictTokenStore(TContext context) { |
|||
Context = context; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the database context associated with the current store.
|
|||
/// </summary>
|
|||
protected virtual TContext Context { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the database set corresponding to the <typeparamref name="TToken"/> entity.
|
|||
/// </summary>
|
|||
protected DbSet<TToken> Tokens => Context.Set<TToken>(); |
|||
|
|||
/// <summary>
|
|||
/// Creates a new token, defined by a unique identifier and a token type.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the token to create.</param>
|
|||
/// <param name="type">The token type.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual Task CreateAsync(string identifier, string type, CancellationToken cancellationToken) { |
|||
var converter = TypeDescriptor.GetConverter(typeof(TKey)); |
|||
|
|||
// Ensure that the key type is compatible with string keys.
|
|||
if (!converter.CanConvertFrom(typeof(string))) { |
|||
return Task.FromResult(0); |
|||
} |
|||
|
|||
var key = (TKey) converter.ConvertFromInvariantString(identifier); |
|||
|
|||
var token = new TToken { Id = key, Type = type }; |
|||
Tokens.Add(token); |
|||
|
|||
return Context.SaveChangesAsync(cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an token using its unique identifier.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
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
|
|||
// to indicate that the requested token doesn't exist.
|
|||
if (!converter.CanConvertFrom(typeof(string))) { |
|||
return Task.FromResult<TToken>(null); |
|||
} |
|||
|
|||
var key = (TKey) converter.ConvertFromInvariantString(identifier); |
|||
|
|||
return Tokens.SingleOrDefaultAsync(token => token.Id.Equals(key), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Revokes a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token to revoke.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual Task RevokeAsync(TToken token, CancellationToken cancellationToken) { |
|||
if (token == null) { |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
Context.Remove(token); |
|||
|
|||
return Context.SaveChangesAsync(cancellationToken); |
|||
} |
|||
} |
|||
} |
|||
@ -1,20 +0,0 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
|
|||
namespace OpenIddict.Models { |
|||
public class Application : Application<string> { } |
|||
|
|||
public class Application<TKey> where TKey : IEquatable<TKey> { |
|||
public TKey Id { get; set; } |
|||
public string DisplayName { get; set; } |
|||
public string RedirectUri { get; set; } |
|||
public string LogoutRedirectUri { get; set; } |
|||
public string Secret { get; set; } |
|||
public string Type { get; set; } |
|||
} |
|||
} |
|||
@ -1,18 +0,0 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>79ae02c3-2ab4-4495-bedd-685a714ea51c</ProjectGuid> |
|||
<RootNamespace>OpenIddict.Models</RootNamespace> |
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|||
</PropertyGroup> |
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
|||
</Project> |
|||
@ -1,49 +0,0 @@ |
|||
{ |
|||
"version": "1.0.0-alpha2-*", |
|||
|
|||
"description": "Contains the default models used by OpenIddict.", |
|||
"authors": [ "Kévin Chalet" ], |
|||
|
|||
"packOptions": { |
|||
"owners": [ "Kévin Chalet" ], |
|||
|
|||
"projectUrl": "https://github.com/openiddict/openiddict-core", |
|||
"iconUrl": "https://avatars3.githubusercontent.com/u/13908567?s=64", |
|||
"licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.html", |
|||
|
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git://github.com/openiddict/openiddict-core" |
|||
}, |
|||
|
|||
"tags": [ |
|||
"aspnetcore", |
|||
"authentication", |
|||
"jwt", |
|||
"openidconnect", |
|||
"openiddict", |
|||
"security" |
|||
] |
|||
}, |
|||
|
|||
"buildOptions": { |
|||
"warningsAsErrors": true, |
|||
"nowarn": [ "CS1591" ], |
|||
"xmlDoc": true |
|||
}, |
|||
|
|||
"frameworks": { |
|||
"net451": { }, |
|||
|
|||
"netstandard1.3": { |
|||
"dependencies": { |
|||
"System.Runtime": "4.1.0-rc2-24027" |
|||
}, |
|||
|
|||
"imports": [ |
|||
"dotnet5.4", |
|||
"portable-net451+win8" |
|||
] |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue