/* * 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 System.Security.Claims; using System.Threading.Tasks; using AspNet.Security.OpenIdConnect.Extensions; using AspNet.Security.OpenIdConnect.Primitives; using AspNet.Security.OpenIdConnect.Server; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenIddict.Core; namespace OpenIddict { public partial class OpenIddictProvider : OpenIdConnectServerProvider where TApplication : class where TAuthorization : class where TScope : class where TToken : class { public override async Task SerializeAuthorizationCode([NotNull] SerializeAuthorizationCodeContext context) { var applications = context.HttpContext.RequestServices.GetRequiredService>(); var options = context.HttpContext.RequestServices.GetRequiredService>(); var tokens = context.HttpContext.RequestServices.GetRequiredService>(); Debug.Assert(!string.IsNullOrEmpty(context.Request.ClientId), "The client identifier shouldn't be null or empty."); if (!options.Value.DisableTokenRevocation) { // Resolve the subject from the authentication ticket. If it cannot be found, throw an exception. var subject = context.Ticket.Principal.GetClaim(OpenIdConnectConstants.Claims.Subject) ?? context.Ticket.Principal.GetClaim(ClaimTypes.NameIdentifier) ?? context.Ticket.Principal.GetClaim(ClaimTypes.Upn); if (string.IsNullOrEmpty(subject)) { throw new InvalidOperationException("The subject associated with the authentication ticket cannot be retrieved."); } // If a null value was returned by CreateAsync, return immediately. var token = await tokens.CreateAsync(OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, subject, context.HttpContext.RequestAborted); if (token == null) { return; } // Throw an exception if the token identifier can't be resolved. var identifier = await tokens.GetIdAsync(token, context.HttpContext.RequestAborted); if (string.IsNullOrEmpty(identifier)) { throw new InvalidOperationException("The unique key associated with an authorization code cannot be null or empty."); } // Attach the key returned by the underlying store // to the authorization code to override the default GUID // generated by the OpenID Connect server middleware. context.Ticket.SetTicketId(identifier); var application = await applications.FindByClientIdAsync(context.Request.ClientId, context.HttpContext.RequestAborted); if (application == null) { throw new InvalidOperationException("The client application cannot be retrieved from the database."); } await tokens.SetClientAsync(token, await applications.GetIdAsync(application, context.HttpContext.RequestAborted), context.HttpContext.RequestAborted); // If an authorization identifier was specified, bind it to the token. var authorization = context.Ticket.GetProperty(OpenIddictConstants.Properties.AuthorizationId); if (!string.IsNullOrEmpty(authorization)) { await tokens.SetAuthorizationAsync(token, authorization, context.HttpContext.RequestAborted); } } } public override async Task SerializeRefreshToken([NotNull] SerializeRefreshTokenContext context) { var applications = context.HttpContext.RequestServices.GetRequiredService>(); var options = context.HttpContext.RequestServices.GetRequiredService>(); var tokens = context.HttpContext.RequestServices.GetRequiredService>(); if (!options.Value.DisableTokenRevocation) { // Resolve the subject from the authentication ticket. If it cannot be found, throw an exception. var subject = context.Ticket.Principal.GetClaim(OpenIdConnectConstants.Claims.Subject) ?? context.Ticket.Principal.GetClaim(ClaimTypes.NameIdentifier) ?? context.Ticket.Principal.GetClaim(ClaimTypes.Upn); if (string.IsNullOrEmpty(subject)) { throw new InvalidOperationException("The subject associated with the authentication ticket cannot be retrieved."); } // If a null value was returned by CreateAsync, return immediately. var token = await tokens.CreateAsync(OpenIdConnectConstants.TokenTypeHints.RefreshToken, subject, context.HttpContext.RequestAborted); if (token == null) { return; } // Throw an exception if the token identifier can't be resolved. var identifier = await tokens.GetIdAsync(token, context.HttpContext.RequestAborted); if (string.IsNullOrEmpty(identifier)) { throw new InvalidOperationException("The unique key associated with a refresh token cannot be null or empty."); } // Attach the key returned by the underlying store // to the refresh token to override the default GUID // generated by the OpenID Connect server middleware. context.Ticket.SetTicketId(identifier); // If the client application is known, associate it with the token. if (!string.IsNullOrEmpty(context.Request.ClientId)) { var application = await applications.FindByClientIdAsync(context.Request.ClientId, context.HttpContext.RequestAborted); if (application == null) { throw new InvalidOperationException("The client application cannot be retrieved from the database."); } await tokens.SetClientAsync(token, await applications.GetIdAsync(application, context.HttpContext.RequestAborted), context.HttpContext.RequestAborted); } // If an authorization identifier was specified, bind it to the token. var authorization = context.Ticket.GetProperty(OpenIddictConstants.Properties.AuthorizationId); if (!string.IsNullOrEmpty(authorization)) { await tokens.SetAuthorizationAsync(token, authorization, context.HttpContext.RequestAborted); } } } } }