/// <summary> /// The core authentication logic which must be provided by the handler. Will be invoked at most /// once per request. Do not call directly, call the wrapping Authenticate method instead. /// </summary> /// <returns>The ticket data provided by the authentication logic</returns> protected override Task <AuthenticationTicket> AuthenticateCoreAsync() { return(Task.Run(() => { SecurityPrincipal securityPrincipal; // Track original principal Request.Environment["OriginalPrincipal"] = Request.User; Request.Environment["AuthenticationOptions"] = Options.Readonly; // No authentication required for anonymous resources if (Options.IsAnonymousResource(Request.Path.Value)) { return null; } // Attempt to read the session ID from the HTTP cookies Guid sessionID = SessionHandler.GetSessionIDFromCookie(Request, Options.SessionToken); AuthenticationHeaderValue authorization = AuthorizationHeader; // Attempt to retrieve the user's credentials that were cached to the user's session if (TryGetPrincipal(sessionID, out securityPrincipal)) { bool useCachedCredentials = (object)Request.User == null || Request.User.Identity.Name.Equals(securityPrincipal.Identity.Name, StringComparison.OrdinalIgnoreCase) || authorization?.Scheme != "Basic"; if (!useCachedCredentials) { // Explicit login attempts as a different user // cause credentials to be flushed from the session ClearAuthorizationCache(sessionID); securityPrincipal = null; } } if ((object)authorization == null && (object)securityPrincipal == null) { // Attempt to authenticate using cached credentials associated with the authentication token cookie string authenticationToken = SessionHandler.GetAuthenticationTokenFromCookie(Request, Options.AuthenticationToken); securityPrincipal = AuthenticateCachedCredentials(authenticationToken); // If authentication using cached credentials fails, // fall back on the other authentication methods if (securityPrincipal?.Identity.IsAuthenticated != true) { securityPrincipal = null; } // Attempt to cache the security principal to the session if (sessionID != Guid.Empty && securityPrincipal?.Identity.IsAuthenticated == true) { CachePrincipal(sessionID, securityPrincipal); } } if ((object)securityPrincipal == null) { // Pick the appropriate authentication logic based // on the authorization type in the HTTP headers if (authorization?.Scheme == "Basic") { securityPrincipal = AuthenticateBasic(authorization.Parameter); } else { securityPrincipal = AuthenticatePassthrough(); } // Attempt to cache the security principal to the session if (sessionID != Guid.Empty && securityPrincipal?.Identity.IsAuthenticated == true) { CachePrincipal(sessionID, securityPrincipal); } } // Set the principal of the IOwinRequest so that it // can be propagated through the Owin pipeline Request.User = securityPrincipal ?? AnonymousPrincipal; return (AuthenticationTicket)null; })); }
/// <summary> /// The core authentication logic which must be provided by the handler. Will be invoked at most /// once per request. Do not call directly, call the wrapping Authenticate method instead. /// </summary> /// <returns>The ticket data provided by the authentication logic</returns> protected override Task <AuthenticationTicket> AuthenticateCoreAsync() { // Track original principal Request.Environment["OriginalPrincipal"] = Request.User; Request.Environment["AuthenticationOptions"] = Options.Readonly; // No authentication required for anonymous resources if (Options.IsAnonymousResource(Request.Path.Value)) { return(Task.FromResult <AuthenticationTicket>(null)); } NameValueCollection queryParameters = System.Web.HttpUtility.ParseQueryString(Request.QueryString.Value); bool useAlternateSecurityProvider = Options.IsAlternateSecurityProviderResource(Request.Path.Value); useAlternateSecurityProvider = useAlternateSecurityProvider || (Options.AuthTestPage == Request.Path.Value && Request.QueryString.HasValue && queryParameters.AllKeys.Contains("useAlternate")); // Attempt to read the session ID from the HTTP cookies Guid sessionID = SessionHandler.GetSessionIDFromCookie(Request, Options.SessionToken); if (Request.Uri.LocalPath == Options.LogoutPage) { IIdentity logoutIdentity = new GenericIdentity(sessionID.ToString()); string[] logoutRoles = { "logout" }; Request.User = new GenericPrincipal(logoutIdentity, logoutRoles); return(Task.FromResult <AuthenticationTicket>(null)); } AuthenticationHeaderValue authorization = AuthorizationHeader; // Attempt to retrieve the user's credentials that were cached to the user's session if (TryGetPrincipal(sessionID, useAlternateSecurityProvider, out SecurityPrincipal securityPrincipal)) { bool useCachedCredentials = Request.User is null || Request.User.Identity.Name.Equals(securityPrincipal.Identity.Name, StringComparison.OrdinalIgnoreCase) || authorization?.Scheme != "Basic"; if (!useCachedCredentials) { // Explicit login attempts as a different user // cause credentials to be flushed from the session ClearAuthorizationCache(sessionID); securityPrincipal = null; } } if (authorization is null && securityPrincipal is null) { // Attempt to authenticate using cached credentials associated with the authentication token cookie string authenticationToken = SessionHandler.GetAuthenticationTokenFromCookie(Request, Options.AuthenticationToken); securityPrincipal = AuthenticateCachedCredentials(authenticationToken, useAlternateSecurityProvider); // If authentication using cached credentials fails, // fall back on the other authentication methods if (securityPrincipal?.Identity.IsAuthenticated != true) { securityPrincipal = null; } // Attempt to cache the security principal to the session if (sessionID != Guid.Empty && securityPrincipal?.Identity.IsAuthenticated == true) { CachePrincipal(sessionID, securityPrincipal, useAlternateSecurityProvider); } } if (securityPrincipal is null) { // Pick the appropriate authentication logic based // on the authorization type in the HTTP headers // or in the URI Parameters if it is using OIDC. if (authorization?.Scheme == "Basic") { securityPrincipal = AuthenticateBasic(authorization.Parameter, useAlternateSecurityProvider); } // If the resources contains a code make an Attempt to Authorize via OIDC Auth server else if (Request.QueryString.HasValue && queryParameters.AllKeys.Contains("code")) { securityPrincipal = AuthenticateCode(useAlternateSecurityProvider); } else { securityPrincipal = AuthenticatePassthrough(useAlternateSecurityProvider); } // Attempt to cache the security principal to the session if (sessionID != Guid.Empty && securityPrincipal?.Identity.IsAuthenticated == true) { CachePrincipal(sessionID, securityPrincipal, useAlternateSecurityProvider); } } // Set the principal of the IOwinRequest so that it // can be propagated through the Owin pipeline Request.User = securityPrincipal ?? AnonymousPrincipal; return(Task.FromResult <AuthenticationTicket>(null)); }