Skip to content

Commit 1b15d0e

Browse files
authored
Reuse failed auth results in AuthN (#43269)
1 parent 6d90a04 commit 1b15d0e

15 files changed

+93
-28
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.AspNetCore.Authentication.Certificate;
5+
6+
internal static class AuthenticateResults
7+
{
8+
internal static AuthenticateResult NoSelfSigned = AuthenticateResult.Fail("Options do not allow self signed certificates.");
9+
internal static AuthenticateResult NoChainedCertificates = AuthenticateResult.Fail("Options do not allow chained certificates.");
10+
internal static AuthenticateResult InvalidClientCertificate = AuthenticateResult.Fail("Client certificate failed validation.");
11+
}

src/Security/Authentication/Certificate/src/CertificateAuthenticationHandler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ private async Task<AuthenticateResult> ValidateCertificateAsync(X509Certificate2
126126
!Options.AllowedCertificateTypes.HasFlag(CertificateTypes.SelfSigned))
127127
{
128128
Logger.CertificateRejected("Self signed", clientCertificate.Subject);
129-
return AuthenticateResult.Fail("Options do not allow self signed certificates.");
129+
return AuthenticateResults.NoSelfSigned;
130130
}
131131

132132
// If we have a chained cert, and they're not allowed, exit early and not bother with
@@ -135,7 +135,7 @@ private async Task<AuthenticateResult> ValidateCertificateAsync(X509Certificate2
135135
!Options.AllowedCertificateTypes.HasFlag(CertificateTypes.Chained))
136136
{
137137
Logger.CertificateRejected("Chained", clientCertificate.Subject);
138-
return AuthenticateResult.Fail("Options do not allow chained certificates.");
138+
return AuthenticateResults.NoChainedCertificates;
139139
}
140140

141141
var chainPolicy = BuildChainPolicy(clientCertificate, isCertificateSelfSigned);
@@ -153,7 +153,7 @@ private async Task<AuthenticateResult> ValidateCertificateAsync(X509Certificate2
153153
chainErrors.Add($"{validationFailure.Status} {validationFailure.StatusInformation}");
154154
}
155155
Logger.CertificateFailedValidation(clientCertificate.Subject, chainErrors);
156-
return AuthenticateResult.Fail("Client certificate failed validation.");
156+
return AuthenticateResults.InvalidClientCertificate;
157157
}
158158

159159
var certificateValidatedContext = new CertificateValidatedContext(Context, Scheme, Options)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.AspNetCore.Authentication.Cookies;
5+
6+
internal static class AuthenticateResults
7+
{
8+
internal static AuthenticateResult FailedUnprotectingTicket = AuthenticateResult.Fail("Unprotect ticket failed");
9+
internal static AuthenticateResult MissingSessionId = AuthenticateResult.Fail("SessionId missing");
10+
internal static AuthenticateResult MissingIdentityInSession = AuthenticateResult.Fail("Identity missing in session store");
11+
internal static AuthenticateResult ExpiredTicket = AuthenticateResult.Fail("Ticket expired");
12+
internal static AuthenticateResult NoPrincipal = AuthenticateResult.Fail("No principal.");
13+
}

src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,21 +147,21 @@ private async Task<AuthenticateResult> ReadCookieTicket()
147147
var ticket = Options.TicketDataFormat.Unprotect(cookie, GetTlsTokenBinding());
148148
if (ticket == null)
149149
{
150-
return AuthenticateResult.Fail("Unprotect ticket failed");
150+
return AuthenticateResults.FailedUnprotectingTicket;
151151
}
152152

153153
if (Options.SessionStore != null)
154154
{
155155
var claim = ticket.Principal.Claims.FirstOrDefault(c => c.Type.Equals(SessionIdClaim));
156156
if (claim == null)
157157
{
158-
return AuthenticateResult.Fail("SessionId missing");
158+
return AuthenticateResults.MissingSessionId;
159159
}
160160
// Only store _sessionKey if it matches an existing session. Otherwise we'll create a new one.
161161
ticket = await Options.SessionStore.RetrieveAsync(claim.Value, Context, Context.RequestAborted);
162162
if (ticket == null)
163163
{
164-
return AuthenticateResult.Fail("Identity missing in session store");
164+
return AuthenticateResults.MissingIdentityInSession;
165165
}
166166
_sessionKey = claim.Value;
167167
}
@@ -178,7 +178,7 @@ private async Task<AuthenticateResult> ReadCookieTicket()
178178
// Clear out the session key if its expired, so renew doesn't try to use it
179179
_sessionKey = null;
180180
}
181-
return AuthenticateResult.Fail("Ticket expired");
181+
return AuthenticateResults.ExpiredTicket;
182182
}
183183

184184
// Finally we have a valid ticket
@@ -204,7 +204,7 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
204204

205205
if (context.Principal == null)
206206
{
207-
return AuthenticateResult.Fail("No principal.");
207+
return AuthenticateResults.NoPrincipal;
208208
}
209209

210210
if (context.ShouldRenew)

src/Security/Authentication/Core/src/HandleRequestResult.cs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ namespace Microsoft.AspNetCore.Authentication;
88
/// </summary>
99
public class HandleRequestResult : AuthenticateResult
1010
{
11+
private static readonly HandleRequestResult _noResult = new() { None = true };
12+
private static readonly HandleRequestResult _skippedResult = new() { Skipped = true };
13+
private static readonly HandleRequestResult _handledResult = new() { Handled = true };
14+
1115
/// <summary>
1216
/// Indicates that stage of authentication was directly handled by
1317
/// user intervention and no further processing should be attempted.
@@ -77,26 +81,17 @@ public class HandleRequestResult : AuthenticateResult
7781
/// The caller is responsible for generating the full response.
7882
/// </summary>
7983
/// <returns>The result.</returns>
80-
public static HandleRequestResult Handle()
81-
{
82-
return new HandleRequestResult() { Handled = true };
83-
}
84+
public static HandleRequestResult Handle() => _handledResult;
8485

8586
/// <summary>
8687
/// Discontinue processing the request in the current handler.
8788
/// </summary>
8889
/// <returns>The result.</returns>
89-
public static HandleRequestResult SkipHandler()
90-
{
91-
return new HandleRequestResult() { Skipped = true };
92-
}
90+
public static HandleRequestResult SkipHandler() => _skippedResult;
9391

9492
/// <summary>
9593
/// Indicates that there were no results produced during authentication.
9694
/// </summary>
9795
/// <returns>The result.</returns>
98-
public static new HandleRequestResult NoResult()
99-
{
100-
return new HandleRequestResult() { None = true };
101-
}
96+
public static new HandleRequestResult NoResult() => _noResult;
10297
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.AspNetCore.Authentication.JwtBearer;
5+
6+
internal static class AuthenticateResults
7+
{
8+
internal static AuthenticateResult ValidatorNotFound = AuthenticateResult.Fail("No SecurityTokenValidator available for token.");
9+
}

src/Security/Authentication/JwtBearer/src/JwtBearerHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
178178
return AuthenticateResult.Fail(authenticationFailedContext.Exception);
179179
}
180180

181-
return AuthenticateResult.Fail("No SecurityTokenValidator available for token.");
181+
return AuthenticateResults.ValidatorNotFound;
182182
}
183183
catch (Exception ex)
184184
{
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.AspNetCore.Authentication.OAuth;
5+
6+
internal static class HandleRequestResults
7+
{
8+
internal static HandleRequestResult InvalidState = HandleRequestResult.Fail("The oauth state was missing or invalid.");
9+
}

src/Security/Authentication/OAuth/src/OAuthHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync
6161

6262
if (properties == null)
6363
{
64-
return HandleRequestResult.Fail("The oauth state was missing or invalid.");
64+
return HandleRequestResults.InvalidState;
6565
}
6666

6767
// OAuth2 10.12 CSRF
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect;
5+
6+
internal static class HandleRequestResults
7+
{
8+
internal static HandleRequestResult UnexpectedParams = HandleRequestResult.Fail("An OpenID Connect response cannot contain an identity token or an access token when using response_mode=query");
9+
internal static HandleRequestResult NoMessage = HandleRequestResult.Fail("No message.");
10+
}

0 commit comments

Comments
 (0)