/// <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 (s_authorizationCache.TryGetValue(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 s_authorizationCache.TryRemove(sessionID, out securityPrincipal); 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) { s_authorizationCache[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) { s_authorizationCache[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; })); }