protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string header = Request.Headers[HeaderNames.Authorization];

            if (string.IsNullOrEmpty(header))
            {
                return(AuthenticateResult.Failed("Authentication failed because the bearer token " +
                                                 "was missing from the 'Authorization' header."));
            }

            // Ensure that the authorization header contains the mandatory "Bearer" scheme.
            // See https://tools.ietf.org/html/rfc6750#section-2.1
            if (!header.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
            {
                return(AuthenticateResult.Failed("Authentication failed because an invalid scheme " +
                                                 "was used in the 'Authorization' header."));
            }

            var token = header.Substring("Bearer ".Length);

            if (string.IsNullOrWhiteSpace(token))
            {
                return(AuthenticateResult.Failed("Authentication failed because the bearer token " +
                                                 "was missing from the 'Authorization' header."));
            }

            // Try to unprotect the token and return an error
            // if the ticket can't be decrypted or validated.
            var ticket = Options.TicketFormat.Unprotect(token);

            if (ticket == null)
            {
                return(AuthenticateResult.Failed("Authentication failed because the access token was invalid."));
            }

            // Ensure that the access token was issued
            // to be used with this resource server.
            if (!await ValidateAudienceAsync(ticket))
            {
                return(AuthenticateResult.Failed("Authentication failed because the access token " +
                                                 "was not valid for this resource server."));
            }

            // Ensure that the authentication ticket is still valid.
            if (ticket.Properties.ExpiresUtc.HasValue &&
                ticket.Properties.ExpiresUtc.Value < Options.SystemClock.UtcNow)
            {
                return(AuthenticateResult.Failed("Authentication failed because the access token was expired."));
            }

            return(AuthenticateResult.Success(ticket));
        }
Beispiel #2
0
        protected override async Task <AuthenticateResult> HandleRemoteAuthenticateAsync()
        {
            AuthenticationProperties properties = null;
            var query = Request.Query;
            var protectedRequestToken = Request.Cookies[StateCookie];

            var requestToken = DeveloperAuthOptions.StateDataFormat.Unprotect(protectedRequestToken);

            if (requestToken == null)
            {
                return(AuthenticateResult.Failed("Invalid state cookie."));
            }

            properties = requestToken.Properties;

            // REVIEW: see which of these are really errors

            var cookieOptions = new CookieOptions
            {
                HttpOnly = true,
                Secure   = Request.IsHttps
            };

            Response.Cookies.Delete(StateCookie, cookieOptions);

            var accessToken = new AccessToken()
            {
                CallBackUri       = requestToken.CallBackUri,
                CallbackConfirmed = requestToken.CallbackConfirmed,
                Properties        = requestToken.Properties,
                ScreenName        = Request.Form["_email"],
                UserId            = Request.Form["_userId"]
            };

            var identity = new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.NameIdentifier, accessToken.UserId, ClaimValueTypes.String, Options.ClaimsIssuer),
                new Claim(ClaimTypes.Name, accessToken.ScreenName, ClaimValueTypes.String, Options.ClaimsIssuer),
            },
                                              Options.ClaimsIssuer);

            if (Options.SaveTokensAsClaims)
            {
                identity.AddClaim(new Claim("access_token", accessToken.Token, ClaimValueTypes.String, Options.ClaimsIssuer));
            }

            return(AuthenticateResult.Success(await CreateTicketAsync(identity, properties, accessToken)));
        }
Beispiel #3
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            var header = Request.Headers["Authorization"].ToString();

            if (string.IsNullOrEmpty(header) || !header.StartsWith("Bearer "))
            {
                return(null);
            }

            var user      = header.Substring(7);
            var principal = PrincipalFactory.Get(user);

            if (principal == null)
            {
                return(AuthenticateResult.Failed("No such user"));
            }

            var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), Options.AuthenticationScheme);

            return(AuthenticateResult.Success(ticket));
        }
Beispiel #4
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            var ticket = await EnsureCookieTicket();

            if (ticket == null)
            {
                return(AuthenticateResult.Failed("No ticket."));
            }

            var context = new CookieValidatePrincipalContext(Context, ticket, Options);
            await Options.Events.ValidatePrincipal(context);

            if (context.Principal == null)
            {
                return(AuthenticateResult.Failed("No principal."));
            }

            if (context.ShouldRenew)
            {
                _shouldRenew = true;
            }

            return(AuthenticateResult.Success(new AuthenticationTicket(context.Principal, context.Properties, Options.AuthenticationScheme)));
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            var ticket = await EnsureCookieTicket();

            if (ticket == null)
            {
                return(AuthenticateResult.Failed("No ticket."));
            }

            var context = new CookieValidatePrincipalContext(Context, ticket, Options);
            await Options.Events.ValidatePrincipal(context);

            if (context.Principal == null)
            {
                return(AuthenticateResult.Failed("No principal."));
            }

            if (context.ShouldRenew)
            {
                _shouldRenew = true;
            }

            var tenantResolver = tenantResolverFactory.GetResolver();

            return(AuthenticateResult.Success(
                       new AuthenticationTicket(context.Principal,
                                                context.Properties,
                                                tenantResolver.ResolveAuthScheme(Options.AuthenticationScheme)
                                                )
                       ));

            //AuthenticationTicket ticket = null;
            //try
            //{
            //    ticket = await EnsureCookieTicket();
            //    if (ticket == null)
            //    {
            //        return null;
            //    }

            //    var context = new CookieValidatePrincipalContext(Context, ticket, Options); // this might ned change
            //    await Options.Events.ValidatePrincipal(context);

            //    if (context.Principal == null)
            //    {
            //        return null;
            //    }

            //    if (context.ShouldRenew)
            //    {
            //        _shouldRenew = true;
            //    }

            //    //return new AuthenticationTicket(context.Principal, context.Properties, Options.AuthenticationScheme);
            //    var tenantResolver = tenantResolverFactory.GetResolver();
            //    return new AuthenticationTicket(context.Principal, context.Properties, tenantResolver.ResolveAuthScheme(Options.AuthenticationScheme));
            //}
            //catch (Exception exception)
            //{
            //    var exceptionContext = new CookieExceptionContext(Context, Options,
            //        CookieExceptionContext.ExceptionLocation.Authenticate, exception, ticket);

            //    await Options.Events.Exception(exceptionContext);

            //    if (exceptionContext.Rethrow)
            //    {
            //        throw;
            //    }
            //    return exceptionContext.Ticket;
            //}
        }
Beispiel #6
0
        // I think this was renamed as HandleRemoteCallbackAsync
        // since we were not modifying this code jus commented it out to
        // let the base class handle it, may need to override it though needs testing
        //public async Task<bool> InvokeReturnPathAsync()
        //{
        //    log.LogDebug("InvokeReturnPathAsync called");

        //    var ticket = await HandleAuthenticateOnceAsync();
        //    if (ticket == null)
        //    {
        //        Logger.LogWarning("Invalid return state, unable to redirect.");
        //        Response.StatusCode = 500;
        //        return true;
        //    }

        //    var context = new SigningInContext(Context, ticket)
        //    {
        //        SignInScheme = Options.SignInScheme,
        //        RedirectUri = ticket.Properties.RedirectUri,
        //    };
        //    ticket.Properties.RedirectUri = null;

        //    await Options.Events.SigningIn(context);

        //    if (context.SignInScheme != null && context.Principal != null)
        //    {
        //        await Context.Authentication.SignInAsync(context.SignInScheme, context.Principal, context.Properties);
        //    }

        //    if (!context.IsRequestCompleted && context.RedirectUri != null)
        //    {
        //        if (context.Principal == null)
        //        {
        //            // add a redirect hint that sign-in failed in some way
        //            context.RedirectUri = QueryHelpers.AddQueryString(context.RedirectUri, "error", "access_denied");
        //        }
        //        Response.Redirect(context.RedirectUri);
        //        context.RequestCompleted();
        //    }

        //    return context.IsRequestCompleted;
        //}

        protected override async Task <AuthenticateResult> HandleRemoteAuthenticateAsync()
        {
            log.LogDebug("HandleAuthenticateAsync called");

            AuthenticationProperties properties = null;

            try
            {
                var query = Request.Query;

                // TODO: Is this a standard error returned by servers?
                var value = query["error"];
                if (!string.IsNullOrEmpty(value))
                {
                    Logger.LogVerbose("Remote server returned an error: " + Request.QueryString);
                    // TODO: Fail request rather than passing through?
                    return(null);
                }

                var code  = query["code"];
                var state = query["state"];

                properties = Options.StateDataFormat.Unprotect(state);
                if (properties == null)
                {
                    return(null);
                }

                // OAuth2 10.12 CSRF
                bool valid = await ValidateCorrelationId(properties);

                if (!valid)
                {
                    //return new AuthenticationTicket(properties, Options.AuthenticationScheme);
                    return(AuthenticateResult.Failed("Correlation failed."));
                }

                if (string.IsNullOrEmpty(code))
                {
                    // Null if the remote server returns an error.
                    //return new AuthenticationTicket(properties, Options.AuthenticationScheme);
                    return(AuthenticateResult.Failed("Code was not found."));
                }

                var tokens = await ExchangeCodeAsync(code, BuildRedirectUri(Options.CallbackPath));

                // must be after rc1
                //if (tokens.Error != null)
                //{
                //    return AuthenticateResult.Failed(tokens.Error);
                //}


                if (string.IsNullOrEmpty(tokens.AccessToken))
                {
                    Logger.LogWarning("Access token was not found");
                    //return new AuthenticationTicket(properties, Options.AuthenticationScheme);
                    return(AuthenticateResult.Failed("Failed to retrieve access token."));
                }

                var identity = new ClaimsIdentity(Options.ClaimsIssuer);

                if (Options.SaveTokensAsClaims)
                {
                    identity.AddClaim(new Claim("access_token", tokens.AccessToken,
                                                ClaimValueTypes.String, Options.ClaimsIssuer));

                    if (!string.IsNullOrEmpty(tokens.RefreshToken))
                    {
                        identity.AddClaim(new Claim("refresh_token", tokens.RefreshToken,
                                                    ClaimValueTypes.String, Options.ClaimsIssuer));
                    }

                    if (!string.IsNullOrEmpty(tokens.TokenType))
                    {
                        identity.AddClaim(new Claim("token_type", tokens.TokenType,
                                                    ClaimValueTypes.String, Options.ClaimsIssuer));
                    }

                    if (!string.IsNullOrEmpty(tokens.ExpiresIn))
                    {
                        identity.AddClaim(new Claim("expires_in", tokens.ExpiresIn,
                                                    ClaimValueTypes.String, Options.ClaimsIssuer));
                    }
                }

                //return await CreateTicketAsync(identity, properties, tokens);
                return(AuthenticateResult.Success(await CreateTicketAsync(identity, properties, tokens)));
            }
            catch (Exception ex)
            {
                Logger.LogError("Authentication failed", ex);
                //return new AuthenticationTicket(properties, Options.AuthenticationScheme);
                return(AuthenticateResult.Failed("Authentication failed, exception logged."));
            }
        }
        protected override async Task <AuthenticateResult> HandleRemoteAuthenticateAsync()
        {
            AuthenticationProperties properties = null;
            var query = Request.Query;
            var protectedRequestToken = Request.Cookies[StateCookie];

            var requestToken = Options.StateDataFormat.Unprotect(protectedRequestToken);

            if (requestToken == null)
            {
                return(AuthenticateResult.Failed("Invalid state cookie."));
            }

            properties = requestToken.Properties;

            // REVIEW: see which of these are really errors

            var returnedToken = query["oauth_token"];

            if (StringValues.IsNullOrEmpty(returnedToken))
            {
                return(AuthenticateResult.Failed("Missing oauth_token"));
            }

            if (!string.Equals(returnedToken, requestToken.Token, StringComparison.Ordinal))
            {
                return(AuthenticateResult.Failed("Unmatched token"));
            }

            var oauthVerifier = query["oauth_verifier"];

            if (StringValues.IsNullOrEmpty(oauthVerifier))
            {
                return(AuthenticateResult.Failed("Missing or blank oauth_verifier"));
            }

            var cookieOptions = new CookieOptions
            {
                HttpOnly = true,
                Secure   = Request.IsHttps
            };

            Response.Cookies.Delete(StateCookie, cookieOptions);

            var accessToken = await ObtainAccessTokenAsync(Options.ConsumerKey, Options.ConsumerSecret, requestToken, oauthVerifier);

            var identity = new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.NameIdentifier, accessToken.UserId, ClaimValueTypes.String, Options.ClaimsIssuer),
                new Claim(ClaimTypes.Name, accessToken.ScreenName, ClaimValueTypes.String, Options.ClaimsIssuer),
                new Claim("urn:twitter:userid", accessToken.UserId, ClaimValueTypes.String, Options.ClaimsIssuer),
                new Claim("urn:twitter:screenname", accessToken.ScreenName, ClaimValueTypes.String, Options.ClaimsIssuer)
            },
                                              Options.ClaimsIssuer);

            if (Options.SaveTokensAsClaims)
            {
                identity.AddClaim(new Claim("access_token", accessToken.Token, ClaimValueTypes.String, Options.ClaimsIssuer));
            }

            return(AuthenticateResult.Success(await CreateTicketAsync(identity, properties, accessToken)));
        }
Beispiel #8
0
 #pragma warning disable 1998
 protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
 {
     return(AuthenticateResult.Failed(new Exception("unknow operate")));
 }
Beispiel #9
0
        //public async Task<bool> InvokeReturnPathAsync()
        //{
        //    var model = await HandleAuthenticateOnceAsync();
        //    if (model == null)
        //    {
        //        Logger.LogWarning("Invalid return state, unable to redirect.");
        //        Response.StatusCode = 500;
        //        return true;
        //    }

        //    var context = new SigningInContext(Context, model)
        //    {
        //        SignInScheme = Options.SignInScheme,
        //        RedirectUri = model.Properties.RedirectUri
        //    };
        //    model.Properties.RedirectUri = null;

        //    await Options.Events.SigningIn(context);

        //    if (context.SignInScheme != null && context.Principal != null)
        //    {
        //        await Context.Authentication.SignInAsync(context.SignInScheme, context.Principal, context.Properties);
        //    }

        //    if (!context.IsRequestCompleted && context.RedirectUri != null)
        //    {
        //        if (context.Principal == null)
        //        {
        //            // add a redirect hint that sign-in failed in some way
        //            context.RedirectUri = QueryHelpers.AddQueryString(context.RedirectUri, "error", "access_denied");
        //        }
        //        Response.Redirect(context.RedirectUri);
        //        context.RequestCompleted();
        //    }

        //    return context.IsRequestCompleted;
        //}

        protected override async Task <AuthenticateResult> HandleRemoteAuthenticateAsync()
        {
            AuthenticationProperties properties = null;

            try
            {
                var currentSite = await GetSite();

                var tenantOptions = new MultiTenantTwitterOptionsResolver(
                    Options,
                    currentSite,
                    multiTenantOptions);

                var query = Request.Query;
                var protectedRequestToken = Request.Cookies[tenantOptions.ResolveStateCookieName(StateCookie)];

                var requestToken = Options.StateDataFormat.Unprotect(protectedRequestToken);

                if (requestToken == null)
                {
                    Logger.LogWarning("Invalid state");
                    return(AuthenticateResult.Failed("Invalid state cookie."));
                }

                properties = requestToken.Properties;

                var returnedToken = query["oauth_token"];
                //if (StringValues.IsNullOrEmpty(returnedToken))
                if (string.IsNullOrEmpty(returnedToken))
                {
                    Logger.LogWarning("Missing oauth_token");
                    //return new AuthenticationTicket(properties, Options.AuthenticationScheme);
                    return(AuthenticateResult.Failed("Missing oauth_token"));
                }

                if (!string.Equals(returnedToken, requestToken.Token, StringComparison.Ordinal))
                {
                    Logger.LogWarning("Unmatched token");
                    //return new AuthenticationTicket(properties, Options.AuthenticationScheme);
                    return(AuthenticateResult.Failed("Unmatched token"));
                }

                var oauthVerifier = query["oauth_verifier"];
                //if (StringValues.IsNullOrEmpty(oauthVerifier))
                if (string.IsNullOrEmpty(oauthVerifier))
                {
                    Logger.LogWarning("Missing or blank oauth_verifier");
                    //return new AuthenticationTicket(properties, Options.AuthenticationScheme);
                    return(AuthenticateResult.Failed("Missing or blank oauth_verifier"));
                }

                var cookieOptions = new CookieOptions
                {
                    HttpOnly = true,
                    Secure   = Request.IsHttps
                };

                Response.Cookies.Delete(tenantOptions.ResolveStateCookieName(StateCookie), cookieOptions);



                //var accessToken = await ObtainAccessTokenAsync(
                //    Options.ConsumerKey,
                //    Options.ConsumerSecret,
                //    requestToken,
                //    oauthVerifier);

                var accessToken = await ObtainAccessTokenAsync(
                    tenantOptions.ConsumerKey,
                    tenantOptions.ConsumerSecret,
                    requestToken,
                    oauthVerifier);

                var identity = new ClaimsIdentity(new[]
                {
                    new Claim(ClaimTypes.NameIdentifier, accessToken.UserId, ClaimValueTypes.String, Options.ClaimsIssuer),
                    new Claim(ClaimTypes.Name, accessToken.ScreenName, ClaimValueTypes.String, Options.ClaimsIssuer),
                    new Claim("urn:twitter:userid", accessToken.UserId, ClaimValueTypes.String, Options.ClaimsIssuer),
                    new Claim("urn:twitter:screenname", accessToken.ScreenName, ClaimValueTypes.String, Options.ClaimsIssuer)
                },
                                                  Options.ClaimsIssuer);

                if (Options.SaveTokensAsClaims)
                {
                    identity.AddClaim(new Claim("access_token", accessToken.Token, ClaimValueTypes.String, Options.ClaimsIssuer));
                }

                //return await CreateTicketAsync(identity, properties, accessToken);
                return(AuthenticateResult.Success(await CreateTicketAsync(identity, properties, accessToken)));
            }
            catch (Exception ex)
            {
                Logger.LogError("Authentication failed", ex);
                //return new AuthenticationTicket(properties, Options.AuthenticationScheme);
                return(AuthenticateResult.Failed("Authentication failed, exception logged"));
            }
        }
 protected override Task <AuthenticateResult> HandleAuthenticateAsync()
 {
     return(Task.FromResult(AuthenticateResult.Failed("No token found.")));
 }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            //if accessed from a different URL - ignore
            if (!Request.Path.Equals(Options.CallbackPath))
            {
                Context.Items[RedirectToEndpointKey] = true;
                Response.StatusCode = 302;
                return(AuthenticateResult.Failed("Redirecting to authentication route /windowsauthentication/ntlm"));
            }

            //check if the request has an NTLM header
            var authorizationHeader = Request.Headers["Authorization"];

            byte[] token   = null;
            var    hasNtlm = authorizationHeader.Any(h => h.StartsWith("NTLM "));

            if (!hasNtlm)
            {
                // This code runs under following conditions:
                // - authentication failed (in either step: IsClientResponseValid() or TryAcquireServerChallenge())
                // - there's no token in the headers
                //
                // This means we've got to set the WWW-Authenticate header and return a 401
                // 401 tells the browser that the request is unauthenticated and the WWW-Authenticate
                // header tells the browser to try again with NTLM
                Response.Headers.Add("WWW-Authenticate", new[] { "NTLM" });
                Response.StatusCode             = 401;
                Context.Items[RespondNoNtlmKey] = true;

                //We're creating a unique guid to identify the client between the
                //Type 2 and Type 3 handshake
                var requestUniqueId = Guid.NewGuid();
                Response.Cookies.Append(NtlmAuthUniqueIdCookieKey, requestUniqueId.ToString());

                return(AuthenticateResult.Failed("No NTLM header, returning WWW-Authenticate NTLM."));
            }

            if (!string.IsNullOrEmpty(authorizationHeader) && hasNtlm)
            {
                var header = authorizationHeader.First(h => h.StartsWith("NTLM "));
                token = Convert.FromBase64String(header.Substring(5));
            }

            var            responseUniqueId = Request.Cookies[NtlmAuthUniqueIdCookieKey];
            HandshakeState state            = null;

            //see if the response is from a known client handshake
            if (!string.IsNullOrWhiteSpace(responseUniqueId))
            {
                this.Options.LoginStateCache.TryGet(responseUniqueId, out state);
            }

            if (state == null)
            {
                state = new HandshakeState();
            }

            // First eight bytes are header containing NTLMSSP\0 signature
            // Next byte contains type of the message recieved.
            // No Token - it's the initial request. Add a authenticate header
            // Message Type 1 — is initial client's response to server's 401 Unauthorized error.
            // Message Type 2 — is the server's response to it. Contains random 8 bytes challenge.
            // Message Type 3 — is encrypted password hashes from client ready to server validation.
            if (token != null && token[8] == 1)
            {
                // Message of type 1 was received
                if (state.TryAcquireServerChallenge(ref token))
                {
                    // send the type 2 message
                    var authorization = Convert.ToBase64String(token);
                    Response.Headers.Add("WWW-Authenticate", new[] { string.Concat("NTLM ", authorization) });
                    Response.StatusCode = 401;

                    Options.LoginStateCache.Add(responseUniqueId, state);
                    Context.Items[RespondType2Key] = true;

                    return(AuthenticateResult.Failed("Received NTLM Type 1, sending Type 2 with status 401."));
                }
            }
            else if (token != null && token[8] == 3)
            {
                // message of type 3 was received, we validate it
                if (state.IsClientResponseValid(token))
                {
                    // Authorization successful
                    var properties = state.AuthenticationProperties;

                    if (Options.Filter == null || Options.Filter.Invoke(state.WindowsIdentity, Request))
                    {
                        // we need to create a new identity using the sign in type that
                        // the cookie authentication is listening for
                        var identity = new ClaimsIdentity(Options.Cookies.ApplicationCookie.AuthenticationScheme);

                        //Add WindowsIdentity claims to the Identity object
                        var newClaims = new[]
                        {
                            new Claim(ClaimTypes.AuthenticationMethod,
                                      ActiveDirectoryOptions.DefaultAuthenticationScheme),
                        };

                        identity.AddClaims(state.WindowsIdentity.Claims);

                        // We don't need that state anymore
                        Options.LoginStateCache.TryRemove(responseUniqueId);

                        // create the authentication ticket
                        var principal = new ClaimsPrincipal(identity);
                        var ticket    = new AuthenticationTicket
                                            (principal, properties,
                                            Options.Cookies.ApplicationCookie.AuthenticationScheme);

                        //handle the sign in method of the auth middleware
                        await Context.Authentication.SignInAsync
                            (Options.Cookies.ApplicationCookie.AuthenticationScheme,
                            principal, properties);

                        Context.Items[AuthenticatedKey] = true;

                        //throw the succeded event
                        await Options.Events.AuthenticationSucceeded(new Events.AuthenticationSucceededContext(Context, Options)
                        {
                            AuthenticationTicket = ticket //pass the ticket
                        });

                        return(AuthenticateResult.Success(ticket));
                    }
                }
            }

            await Options.Events.AuthenticationFailed(new Events.AuthenticationFailedContext(Context, Options));

            return(AuthenticateResult.Failed("Unauthorized"));
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            try
            {
                string requestToken  = null;
                string authorization = Request.Headers["Authorization"];
                if (!string.IsNullOrEmpty(authorization))
                {
                    if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
                    {
                        requestToken = authorization.Substring("Bearer ".Length).Trim();
                    }
                }

                // Give application opportunity to find from a different location, adjust, or reject token
                var requestTokenContext = new OAuthRequestTokenContext(Context, requestToken);
                await Options.Provider.RequestToken(requestTokenContext);

                // If no token found, no further work possible
                if (string.IsNullOrEmpty(requestTokenContext.Token))
                {
                    Logger.LogWarning("access token is empty");
                    return(AuthenticateResult.Failed(new Exception("access token is empty")));
                }

                // Call provider to process the token into data
                var tokenReceiveContext = new AuthenticationTokenReceiveContext(
                    Context,
                    Options.AccessTokenFormat,
                    requestTokenContext.Token);

                await Options.AccessTokenProvider.ReceiveAsync(tokenReceiveContext);

                if (tokenReceiveContext.Ticket == null)
                {
                    tokenReceiveContext.DeserializeTicket(tokenReceiveContext.Token);
                }

                AuthenticationTicket ticket = tokenReceiveContext.Ticket;
                if (ticket == null)
                {
                    Logger.LogWarning("invalid bearer token received");
                    return(AuthenticateResult.Failed(new Exception("invalid bearer token received")));
                }

                // Validate expiration time if present
                DateTimeOffset currentUtc = Options.SystemClock.UtcNow;

                if (ticket.Properties.ExpiresUtc.HasValue &&
                    ticket.Properties.ExpiresUtc.Value < currentUtc)
                {
                    Logger.LogWarning("expired bearer token received");
                    return(AuthenticateResult.Failed(new Exception("expired bearer token received")));
                }

                // Give application final opportunity to override results
                var context = new OAuthValidateIdentityContext(Context, Options, ticket);
                if (ticket != null &&
                    ticket.Principal != null &&
                    ticket.Principal.Identity.IsAuthenticated)
                {
                    // bearer token with identity starts validated
                    context.Validated();
                }
                if (Options.Provider != null)
                {
                    await Options.Provider.ValidateIdentity(context);
                }
                if (!context.IsValidated)
                {
                    return(AuthenticateResult.Failed(context.Error));
                }

                // resulting identity values go back to caller
                return(AuthenticateResult.Success(context.Ticket));
            }
            catch (Exception ex)
            {
                Logger.LogError("Authentication failed", ex);
                return(AuthenticateResult.Failed(ex.Message));;
            }
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            Uri redirectUrl;

            //Set the default error message when no SP Auth is attempted
            AuthenticateResult result = AuthenticateResult.Failed("Could not handle SharePoint authentication.");

            var authenticationProperties = new AuthenticationProperties()
            {
                ExpiresUtc   = DateTimeOffset.UtcNow.AddDays(10),
                IsPersistent = false,
                AllowRefresh = false
            };

            // Sets up the SharePoint configuration based on the middleware options.
            var spContextProvider = SharePointContextProvider.GetInstance(
                SharePointConfiguration.GetFromSharePointAuthenticationOptions(Options));

            switch (SharePointContextProvider.CheckRedirectionStatus(Context, out redirectUrl))
            {
            case RedirectionStatus.Ok:
                _redirectionStatus = RedirectionStatus.Ok;

                // Gets the current SharePoint context
                var spContext = SharePointContextProvider.Current.GetSharePointContext(Context);

                // Gets the SharePoint context CacheKey. The CacheKey would be assigned as issuer for new claim.
                // It is also used to validate identity that is authenticated.
                //Currently, we don't support High Trust
                var userCacheKey = ((SharePointAcsContext)spContext).CacheKey;

                // Checks if we already have an authenticated principal
                ClaimsPrincipal principal;
                if (Context.User.Identities.Any(identity =>
                                                identity.IsAuthenticated && identity.HasClaim(x => x.Issuer == GetType().Assembly.GetName().Name)))
                {
                    principal = Context.User;
                }
                else
                {
                    //build a claims identity and principal
                    var identity = new ClaimsIdentity(this.Options.AuthenticationScheme);

                    // Adds claims with the SharePoint context CacheKey as issuer to the Identity object.
                    var claims = new[]
                    {
                        new Claim(ClaimTypes.Authentication, userCacheKey, "SPCacheKey", GetType().Assembly.GetName().Name),
                    };

                    identity.AddClaims(claims);

                    principal = new ClaimsPrincipal(identity);

                    // Handles the sign in method of the SP auth middleware
                    await Context.Authentication.SignInAsync
                        (this.Options.AuthenticationScheme, principal, authenticationProperties);

                    //sign in the cookie middleware so it issues a cookie
                    if (!string.IsNullOrWhiteSpace(this.Options.CookieAuthenticationScheme))
                    {
                        SignInAccepted = true;
                        await Context.Authentication.SignInAsync
                            (this.Options.CookieAuthenticationScheme, principal, authenticationProperties);
                    }
                }

                // Creates the authentication ticket.
                var ticket = new AuthenticationTicket(principal, authenticationProperties, this.Options.AuthenticationScheme);
                result = AuthenticateResult.Success(ticket);

                //Throw auth ticket success event
                await Options.Events.AuthenticationSucceeded(
                    new Events.AuthenticationSucceededContext(Context, Options)
                {
                    AuthenticationTicket = ticket,    //pass the ticket
                    SharePointContext    = spContext  //append the sp context
                });

                //Log success
                LoggingExtensions.TokenValidationSucceeded(this.Logger);

                break;

            case RedirectionStatus.ShouldRedirect:
                _redirectionStatus = RedirectionStatus.ShouldRedirect;

                Response.StatusCode = 301;
                result = AuthenticateResult.Failed("ShouldRedirect");

                // Signs out so new signin to be performed on redirect back from SharePoint
                await Context.Authentication.SignOutAsync(this.Options.AuthenticationScheme);

                // Redirect to get new context token
                Context.Response.Redirect(redirectUrl.AbsoluteUri);
                break;

            case RedirectionStatus.CanNotRedirect:
                _redirectionStatus = RedirectionStatus.CanNotRedirect;

                //There's a potential issue here if this is not the only auth middleware
                //setting the response to 401 might not be safe for the other middlewares
                Response.StatusCode = 401;
                result = AuthenticateResult.Failed("CanNotRedirect");

                //Log that we cannot redirect
                LoggingExtensions.CannotRedirect(this.Logger);

                //Throw failed event
                await Options.Events.AuthenticationFailed(new Events.AuthenticationFailedContext(Context, Options));

                break;
            }

            return(result);
        }
        /// <summary>
        /// Searches the 'Authorization' header for a 'Bearer' token. If the 'Bearer' token is found, it is validated using <see cref="TokenValidationParameters"/> set in the options.
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string token = null;

            try
            {
                // Give application opportunity to find from a different location, adjust, or reject token
                var receivingTokenContext = new ReceivingTokenContext(Context, Options);

                // event can set the token
                await Options.Events.ReceivingToken(receivingTokenContext);

                if (receivingTokenContext.HandledResponse)
                {
                    return(AuthenticateResult.Success(receivingTokenContext.AuthenticationTicket));
                }

                if (receivingTokenContext.Skipped)
                {
                    return(AuthenticateResult.Success(ticket: null));
                }

                // If application retrieved token from somewhere else, use that.
                token = receivingTokenContext.Token;

                if (string.IsNullOrEmpty(token))
                {
                    string authorization = Request.Headers["Authorization"];

                    // If no authorization header found, nothing to process further
                    if (string.IsNullOrEmpty(authorization))
                    {
                        return(AuthenticateResult.Failed("No authorization header."));
                    }

                    if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
                    {
                        token = authorization.Substring("Bearer ".Length).Trim();
                    }

                    // If no token found, no further work possible
                    if (string.IsNullOrEmpty(token))
                    {
                        return(AuthenticateResult.Failed("No bearer token."));
                    }
                }

                // notify user token was received
                var receivedTokenContext = new ReceivedTokenContext(Context, Options)
                {
                    Token = token,
                };

                await Options.Events.ReceivedToken(receivedTokenContext);

                if (receivedTokenContext.HandledResponse)
                {
                    return(AuthenticateResult.Success(receivedTokenContext.AuthenticationTicket));
                }

                if (receivedTokenContext.Skipped)
                {
                    return(AuthenticateResult.Success(ticket: null));
                }

                if (_configuration == null && Options.ConfigurationManager != null)
                {
                    _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
                }

                var validationParameters = Options.TokenValidationParameters.Clone();
                if (_configuration != null)
                {
                    if (validationParameters.ValidIssuer == null && !string.IsNullOrEmpty(_configuration.Issuer))
                    {
                        validationParameters.ValidIssuer = _configuration.Issuer;
                    }
                    else
                    {
                        var issuers = new[] { _configuration.Issuer };
                        validationParameters.ValidIssuers = (validationParameters.ValidIssuers == null ? issuers : validationParameters.ValidIssuers.Concat(issuers));
                    }

                    validationParameters.IssuerSigningKeys = (validationParameters.IssuerSigningKeys == null ? _configuration.SigningKeys : validationParameters.IssuerSigningKeys.Concat(_configuration.SigningKeys));
                }

                SecurityToken validatedToken;
                foreach (var validator in Options.SecurityTokenValidators)
                {
                    if (validator.CanReadToken(token))
                    {
                        var principal             = validator.ValidateToken(token, validationParameters, out validatedToken);
                        var ticket                = new AuthenticationTicket(principal, new AuthenticationProperties(), Options.AuthenticationScheme);
                        var validatedTokenContext = new ValidatedTokenContext(Context, Options)
                        {
                            AuthenticationTicket = ticket
                        };

                        await Options.Events.ValidatedToken(validatedTokenContext);

                        if (validatedTokenContext.HandledResponse)
                        {
                            return(AuthenticateResult.Success(validatedTokenContext.AuthenticationTicket));
                        }

                        if (validatedTokenContext.Skipped)
                        {
                            return(AuthenticateResult.Success(ticket: null));
                        }

                        return(AuthenticateResult.Success(ticket));
                    }
                }

                // REVIEW: this maybe return an error instead?
                throw new InvalidOperationException("No SecurityTokenValidator available for token: " + token ?? "null");
            }
            catch (Exception ex)
            {
                Logger.LogError("Exception occurred while processing message", ex);

                // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the event.
                if (Options.RefreshOnIssuerKeyNotFound && ex.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException)))
                {
                    Options.ConfigurationManager.RequestRefresh();
                }

                var authenticationFailedContext = new AuthenticationFailedContext(Context, Options)
                {
                    Exception = ex
                };

                await Options.Events.AuthenticationFailed(authenticationFailedContext);

                if (authenticationFailedContext.HandledResponse)
                {
                    return(AuthenticateResult.Success(authenticationFailedContext.AuthenticationTicket));
                }
                if (authenticationFailedContext.Skipped)
                {
                    return(AuthenticateResult.Success(ticket: null));
                }

                throw;
            }
        }
Beispiel #15
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            try
            {
                var feat = Context.Features.OfType <HttpRequestFeature>();

                var headers = Request.Headers[RequestHeader];
                if (headers.Count <= 0)
                {
                    return(AuthenticateResult.Failed("No authorization header."));
                }

                var header = headers.Where(h => h.StartsWith(RequestHeaderPrefix)).FirstOrDefault();
                if (header == null)
                {
                    return(AuthenticateResult.Failed("Not basic authentication header."));
                }

                var encoded = header.Substring(RequestHeaderPrefix.Length);
                var decoded = default(string);
                try
                {
                    decoded = Encoding.UTF8.GetString(Convert.FromBase64String(encoded));
                }
                catch (Exception)
                {
                    return(AuthenticateResult.Failed("Invalid basic authentication header encoding."));
                }

                var index = decoded.IndexOf(':');
                if (index == -1)
                {
                    return(AuthenticateResult.Failed("Invalid basic authentication header format."));
                }

                var username = decoded.Substring(0, index);
                var password = decoded.Substring(index + 1);

                var signInContext = new BasicSignInContext(Context, Options, username, password);
                await Options.Events.SignIn(signInContext);

                if (signInContext.HandledResponse)
                {
                    if (signInContext.AuthenticationTicket != null)
                    {
                        return(AuthenticateResult.Success(signInContext.AuthenticationTicket));
                    }
                    else
                    {
                        return(AuthenticateResult.Failed("Invalid basic authentication credentials."));
                    }
                }

                if (signInContext.Skipped)
                {
                    return(AuthenticateResult.Success(null));
                }

                var credentials = Options.Credentials.Where(c => c.Username == username && c.Password == password).FirstOrDefault();
                if (credentials == null)
                {
                    return(AuthenticateResult.Failed("Invalid basic authentication credentials."));
                }

                var claims = credentials.Claims.Select(c => new Claim(c.Type, c.Value)).ToList();
                if (!claims.Any(c => c.Type == ClaimTypes.Name))
                {
                    claims.Add(new Claim(ClaimTypes.Name, username));
                }

                var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, Options.AuthenticationScheme));

                var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), Options.AuthenticationScheme);

                return(AuthenticateResult.Success(ticket));
            }
            catch (Exception ex)
            {
                var exceptionContext = new BasicExceptionContext(Context, Options, ex);

                await Options.Events.Exception(exceptionContext);

                if (exceptionContext.HandledResponse)
                {
                    return(AuthenticateResult.Success(exceptionContext.AuthenticationTicket));
                }

                if (exceptionContext.Skipped)
                {
                    return(AuthenticateResult.Success(null));
                }

                throw;
            }
        }
Beispiel #16
0
        protected override async Task <AuthenticateResult> HandleRemoteAuthenticateAsync()
        {
            AuthenticationProperties properties = null;
            var query = Request.Query;

            var error = query["error"];

            if (!StringValues.IsNullOrEmpty(error))
            {
                return(AuthenticateResult.Failed(error));
            }

            var code  = query["code"];
            var state = query["state"];

            properties = Options.StateDataFormat.Unprotect(state);
            if (properties == null)
            {
                return(AuthenticateResult.Failed("The oauth state was missing or invalid."));
            }

            // OAuth2 10.12 CSRF
            if (!ValidateCorrelationId(properties))
            {
                return(AuthenticateResult.Failed("Correlation failed."));
            }

            if (StringValues.IsNullOrEmpty(code))
            {
                return(AuthenticateResult.Failed("Code was not found."));
            }

            var tokens = await ExchangeCodeAsync(code, BuildRedirectUri(Options.CallbackPath));

            if (string.IsNullOrEmpty(tokens.AccessToken))
            {
                return(AuthenticateResult.Failed("Access token was not found."));
            }

            var identity = new ClaimsIdentity(Options.ClaimsIssuer);

            if (Options.SaveTokensAsClaims)
            {
                identity.AddClaim(new Claim("access_token", tokens.AccessToken,
                                            ClaimValueTypes.String, Options.ClaimsIssuer));

                if (!string.IsNullOrEmpty(tokens.RefreshToken))
                {
                    identity.AddClaim(new Claim("refresh_token", tokens.RefreshToken,
                                                ClaimValueTypes.String, Options.ClaimsIssuer));
                }

                if (!string.IsNullOrEmpty(tokens.TokenType))
                {
                    identity.AddClaim(new Claim("token_type", tokens.TokenType,
                                                ClaimValueTypes.String, Options.ClaimsIssuer));
                }

                if (!string.IsNullOrEmpty(tokens.ExpiresIn))
                {
                    identity.AddClaim(new Claim("expires_in", tokens.ExpiresIn,
                                                ClaimValueTypes.String, Options.ClaimsIssuer));
                }
            }

            return(AuthenticateResult.Success(await CreateTicketAsync(identity, properties, tokens)));
        }