You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
7.3 KiB
138 lines
7.3 KiB
/*
|
|
* 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<TApplication, TAuthorization, TScope, TToken> : 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<OpenIddictApplicationManager<TApplication>>();
|
|
var options = context.HttpContext.RequestServices.GetRequiredService<IOptions<OpenIddictOptions>>();
|
|
var tokens = context.HttpContext.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
|
|
|
|
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<OpenIddictApplicationManager<TApplication>>();
|
|
var options = context.HttpContext.RequestServices.GetRequiredService<IOptions<OpenIddictOptions>>();
|
|
var tokens = context.HttpContext.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|