Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the ASP.NET Core/OWIN integrations to allow returning authentication tickets with a null or empty principal #1912

Merged
merged 1 commit into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,14 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()

else if (context.IsRejected)
{
// Note: the missing_token error is special-cased to indicate to ASP.NET Core
// that no authentication result could be produced due to the lack of token.
// This also helps reducing the logging noise when no token is specified.
if (string.Equals(context.Error, Errors.MissingToken, StringComparison.Ordinal))
{
return AuthenticateResult.NoResult();
}

var properties = new AuthenticationProperties(new Dictionary<string, string?>
{
[Properties.Error] = context.Error,
Expand All @@ -147,11 +155,6 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()

else
{
if (context.MergedPrincipal is not ClaimsPrincipal principal)
{
return AuthenticateResult.NoResult();
}

// Restore or create a new authentication properties collection and populate it.
var properties = CreateProperties(context.StateTokenPrincipal);
properties.ExpiresUtc = context.StateTokenPrincipal?.GetExpirationDate();
Expand Down Expand Up @@ -314,7 +317,8 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
properties.SetParameter(Properties.UserinfoTokenPrincipal, context.UserinfoTokenPrincipal);
}

return AuthenticateResult.Success(new AuthenticationTicket(principal, properties,
return AuthenticateResult.Success(new AuthenticationTicket(
context.MergedPrincipal ?? new ClaimsPrincipal(new ClaimsIdentity()), properties,
OpenIddictClientAspNetCoreDefaults.AuthenticationScheme));

static AuthenticationProperties CreateProperties(ClaimsPrincipal? principal)
Expand Down
9 changes: 2 additions & 7 deletions src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,6 @@ public override async Task<bool> InvokeAsync()

else
{
if (context.MergedPrincipal is not ClaimsPrincipal principal)
{
return null;
}

// Restore or create a new authentication properties collection and populate it.
var properties = CreateProperties(context.StateTokenPrincipal);
properties.ExpiresUtc = context.StateTokenPrincipal?.GetExpirationDate();
Expand Down Expand Up @@ -240,7 +235,7 @@ public override async Task<bool> InvokeAsync()
properties.Dictionary[Tokens.UserinfoToken] = context.UserinfoToken;
}

return new AuthenticationTicket((ClaimsIdentity) principal.Identity, properties);
return new AuthenticationTicket(context.MergedPrincipal?.Identity as ClaimsIdentity, properties);

static AuthenticationProperties CreateProperties(ClaimsPrincipal? principal)
{
Expand Down Expand Up @@ -270,7 +265,7 @@ static AuthenticationProperties CreateProperties(ClaimsPrincipal? principal)
/// <inheritdoc/>
protected override async Task TeardownCoreAsync()
{
// Note: OWIN authentication handlers cannot reliabily write to the response stream
// Note: OWIN authentication handlers cannot reliably write to the response stream
// from ApplyResponseGrantAsync() or ApplyResponseChallengeAsync() because these methods
// are susceptible to be invoked from AuthenticationHandler.OnSendingHeaderCallback(),
// where calling Write() or WriteAsync() on the response stream may result in a deadlock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,10 @@ OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType(
_ => null
};

if (principal is null)
{
return AuthenticateResult.NoResult();
}

// Restore or create a new authentication properties collection and populate it.
var properties = CreateProperties(principal);
properties.ExpiresUtc = principal.GetExpirationDate();
properties.IssuedUtc = principal.GetCreationDate();
properties.ExpiresUtc = principal?.GetExpirationDate();
properties.IssuedUtc = principal?.GetCreationDate();

List<AuthenticationToken>? tokens = null;

Expand Down Expand Up @@ -311,7 +306,8 @@ OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType(
properties.StoreTokens(tokens);
}

return AuthenticateResult.Success(new AuthenticationTicket(principal, properties,
return AuthenticateResult.Success(new AuthenticationTicket(
principal ?? new ClaimsPrincipal(new ClaimsIdentity()), properties,
OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
}

Expand Down
13 changes: 4 additions & 9 deletions src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,10 @@ OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType(
_ => null
};

if (principal is null)
{
return null;
}

// Restore or create a new authentication properties collection and populate it.
var properties = CreateProperties(principal);
properties.ExpiresUtc = principal.GetExpirationDate();
properties.IssuedUtc = principal.GetCreationDate();
properties.ExpiresUtc = principal?.GetExpirationDate();
properties.IssuedUtc = principal?.GetCreationDate();

// Attach the tokens to allow any OWIN component (e.g a controller)
// to retrieve them (e.g to make an API request to another application).
Expand Down Expand Up @@ -240,7 +235,7 @@ OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType(
properties.Dictionary[Tokens.UserCode] = context.UserCode;
}

return new AuthenticationTicket((ClaimsIdentity) principal.Identity, properties);
return new AuthenticationTicket(principal?.Identity as ClaimsIdentity, properties);
}

static AuthenticationProperties CreateProperties(ClaimsPrincipal? principal)
Expand Down Expand Up @@ -270,7 +265,7 @@ static AuthenticationProperties CreateProperties(ClaimsPrincipal? principal)
/// <inheritdoc/>
protected override async Task TeardownCoreAsync()
{
// Note: OWIN authentication handlers cannot reliabily write to the response stream
// Note: OWIN authentication handlers cannot reliably write to the response stream
// from ApplyResponseGrantAsync() or ApplyResponseChallengeAsync() because these methods
// are susceptible to be invoked from AuthenticationHandler.OnSendingHeaderCallback(),
// where calling Write() or WriteAsync() on the response stream may result in a deadlock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

using System.ComponentModel;
using System.Security.Claims;
using System.Text.Encodings.Web;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
Expand Down Expand Up @@ -162,15 +163,10 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
_ => null
};

if (principal is null)
{
return AuthenticateResult.NoResult();
}

var properties = new AuthenticationProperties
{
ExpiresUtc = principal.GetExpirationDate(),
IssuedUtc = principal.GetCreationDate()
ExpiresUtc = principal?.GetExpirationDate(),
IssuedUtc = principal?.GetCreationDate()
};

List<AuthenticationToken>? tokens = null;
Expand Down Expand Up @@ -198,7 +194,8 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
properties.StoreTokens(tokens);
}

return AuthenticateResult.Success(new AuthenticationTicket(principal, properties,
return AuthenticateResult.Success(new AuthenticationTicket(
principal ?? new ClaimsPrincipal(new ClaimsIdentity()), properties,
OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,10 @@ public override async Task<bool> InvokeAsync()
_ => null
};

if (principal is null)
{
return null;
}

var properties = new AuthenticationProperties
{
ExpiresUtc = principal.GetExpirationDate(),
IssuedUtc = principal.GetCreationDate()
ExpiresUtc = principal?.GetExpirationDate(),
IssuedUtc = principal?.GetCreationDate()
};

// Attach the tokens to allow any OWIN/Katana component (e.g a controller)
Expand All @@ -189,14 +184,14 @@ public override async Task<bool> InvokeAsync()
properties.Dictionary[TokenTypeHints.AccessToken] = context.AccessToken;
}

return new AuthenticationTicket((ClaimsIdentity) principal.Identity, properties);
return new AuthenticationTicket(principal?.Identity as ClaimsIdentity, properties);
}
}

/// <inheritdoc/>
protected override async Task TeardownCoreAsync()
{
// Note: OWIN authentication handlers cannot reliabily write to the response stream
// Note: OWIN authentication handlers cannot reliably write to the response stream
// from ApplyResponseGrantAsync() or ApplyResponseChallengeAsync() because these methods
// are susceptible to be invoked from AuthenticationHandler.OnSendingHeaderCallback(),
// where calling Write() or WriteAsync() on the response stream may result in a deadlock
Expand Down