4141using GSF . Reflection ;
4242using GSF . Security ;
4343using Microsoft . Owin ;
44- using Microsoft . Owin . Security ;
45- using Microsoft . Owin . Security . Infrastructure ;
4644
4745#pragma warning disable SG0015 // Validated - no hard-coded password present
4846
@@ -51,7 +49,7 @@ namespace GSF.Web.Security
5149 /// <summary>
5250 /// Handles authentication using the configured <see cref="ISecurityProvider"/> implementation in the Owin pipeline.
5351 /// </summary>
54- public class AuthenticationHandler : AuthenticationHandler < AuthenticationOptions >
52+ public class AuthenticationHandler
5553 {
5654 #region [ Members ]
5755
@@ -67,11 +65,31 @@ innerException is AggregateException aggEx ?
6765 string . Join ( "; " , aggEx . Flatten ( ) . InnerExceptions . Select ( inex => inex . Message ) ) :
6866 innerException . Message ;
6967 }
70-
68+
7169 #endregion
72-
70+
71+ #region [ Constructors ]
72+
73+ /// <summary>
74+ /// Creates a new instance of the <see cref="AuthenticationHandler"/> class.
75+ /// </summary>
76+ /// <param name="context">Context of the request to be authenticated</param>
77+ /// <param name="options">Configuration options for the authentication handler</param>
78+ public AuthenticationHandler ( IOwinContext context , AuthenticationOptions options )
79+ {
80+ Request = context . Request ;
81+ Response = context . Response ;
82+ Options = options ;
83+ }
84+
85+ #endregion
86+
7387 #region [ Properties ]
7488
89+ private IOwinRequest Request { get ; }
90+ private IOwinResponse Response { get ; }
91+ private AuthenticationOptions Options { get ; }
92+
7593 // Reads the authorization header value from the request
7694 private AuthenticationHeaderValue AuthorizationHeader
7795 {
@@ -104,6 +122,8 @@ private IPrincipal AnonymousPrincipal
104122 private string AuthTestPath =>
105123 Options . GetFullAuthTestPath ( "" ) ;
106124
125+ private bool Faulted { get ; set ; }
126+
107127 private string FaultReason { get ; set ; }
108128
109129 #endregion
@@ -112,10 +132,9 @@ private IPrincipal AnonymousPrincipal
112132
113133 /// <summary>
114134 /// The core authentication logic which must be provided by the handler. Will be invoked at most
115- /// once per request. Do not call directly, call the wrapping Authenticate method instead.
135+ /// once per request.
116136 /// </summary>
117- /// <returns>The ticket data provided by the authentication logic</returns>
118- protected override Task < AuthenticationTicket > AuthenticateCoreAsync ( )
137+ public void Authenticate ( )
119138 {
120139 try
121140 {
@@ -125,7 +144,7 @@ protected override Task<AuthenticationTicket> AuthenticateCoreAsync()
125144
126145 // No authentication required for anonymous resources
127146 if ( Options . IsAnonymousResource ( Request . Path . Value ) )
128- return Task . FromResult < AuthenticationTicket > ( null ) ;
147+ return ;
129148
130149 NameValueCollection queryParameters = System . Web . HttpUtility . ParseQueryString ( Request . QueryString . Value ) ;
131150
@@ -140,8 +159,7 @@ protected override Task<AuthenticationTicket> AuthenticateCoreAsync()
140159 IIdentity logoutIdentity = new GenericIdentity ( sessionID . ToString ( ) ) ;
141160 string [ ] logoutRoles = { "logout" } ;
142161 Request . User = new GenericPrincipal ( logoutIdentity , logoutRoles ) ;
143-
144- return Task . FromResult < AuthenticationTicket > ( null ) ;
162+ return ;
145163 }
146164
147165 AuthenticationHeaderValue authorization = AuthorizationHeader ;
@@ -214,32 +232,27 @@ Request.User is null ||
214232 else
215233 FaultReason = $ "Authentication Pipeline Exception: { ex . Message } ";
216234
217- Log . Publish ( MessageLevel . Warning , nameof ( AuthenticateCoreAsync ) , FaultReason , exception : ex ) ;
235+ Log . Publish ( MessageLevel . Warning , nameof ( Authenticate ) , FaultReason , exception : ex ) ;
218236 }
219-
220- return Task . FromResult < AuthenticationTicket > ( null ) ;
221237 }
222238
223239 /// <summary>
224- /// Called once by common code after initialization. If an authentication middle-ware
225- /// responds directly to specifically known paths it must override this virtual,
226- /// compare the request path to it's known paths, provide any response information
227- /// as appropriate, and true to stop further processing.
240+ /// Called once by common code after authentication to respond directly to specifically known paths.
228241 /// </summary>
229242 /// <returns>
230- /// Returning false will cause the common code to call the next middle-ware in line.
231- /// Returning true will cause the common code to begin the async completion journey
243+ /// Returning true will cause the common code to call the next middle-ware in line.
244+ /// Returning false will cause the common code to begin the async completion journey
232245 /// without calling the rest of the middle-ware pipeline.
233246 /// </returns>
234- public override async Task < bool > InvokeAsync ( )
247+ public async Task < bool > AuthorizeAsync ( )
235248 {
236249 if ( Faulted )
237250 {
238251 // Handle faulted authentication attempts to expose fault reason to client
239252 using TextWriter writer = new StreamWriter ( Response . Body , Encoding . UTF8 , 4096 , true ) ;
240253 await writer . WriteAsync ( FaultReason ) ;
241254 Response . StatusCode = ( int ) HttpStatusCode . InternalServerError ;
242- return ! HostingEnvironment . IsHosted ;
255+ return HostingEnvironment . IsHosted ;
243256 }
244257
245258 // Use Cases:
@@ -277,20 +290,20 @@ public override async Task<bool> InvokeAsync()
277290 cookieOptions . Path = Options . GetFullAuthTestPath ( pathBase ) ;
278291 Response . Cookies . Delete ( Options . AuthenticationToken , cookieOptions ) ;
279292
280- return true ; // Abort pipeline
293+ return false ; // Abort pipeline
281294 }
282295
283296 // If the user is properly Authenticated but a redirect is requested send that redirect
284297 if ( securityPrincipal ? . Identity . IsAuthenticated == true && securityPrincipal . Identity . Provider . IsRedirectRequested )
285298 {
286299 Response . Redirect ( securityPrincipal . Identity . Provider . RequestedRedirect ?? "/" ) ;
287- return true ;
300+ return false ; // Abort pipeline
288301 }
289302
290303 // If request is for an anonymous resource or user is properly authenticated, allow
291304 // request to propagate through the Owin pipeline
292305 if ( Options . IsAnonymousResource ( urlPath ) || securityPrincipal ? . Identity . IsAuthenticated == true )
293- return false ; // Let pipeline continue
306+ return true ; // Let pipeline continue
294307
295308 // Abort pipeline with appropriate response
296309 if ( Options . IsAuthFailureRedirectResource ( urlPath ) && ! IsAjaxCall ( ) && ! isAuthTest )
@@ -347,7 +360,7 @@ public override async Task<bool> InvokeAsync()
347360 string failureReason = SecurityPrincipal . GetFailureReasonPhrase ( securityPrincipal , AuthorizationHeader ? . Scheme , true ) ;
348361 Log . Publish ( MessageLevel . Info , "AuthenticationFailure" , $ "Failed to authenticate { currentIdentity } for { Request . Path } : { failureReason } ") ;
349362
350- return true ; // Abort pipeline
363+ return false ; // Abort pipeline
351364 }
352365
353366 private bool UserHasLogoutRole ( IPrincipal user )
0 commit comments