public async Task <IActionResult> Register([FromBody] PropyUser user)
        {
            await this.dbContext.CreateUser(user);

            return(new JsonResult(new
            {
                response = $"User with name {user.FirstName} was created"
            }));
        }
        public async Task <IActionResult> FacebookLogin([FromBody] FacebookToken tokenModel)
        {
            var account = await this.facebookService.GetAccountAsync(tokenModel.AccessToken);

            var bsonUser = await this.dbContext.GetUserByFacebookId(account.Id);

            PropyUser user;

            if (bsonUser.Count == 0)
            {
                user = new PropyUser()
                {
                    FacebookId = account.Id,
                    UserName   = account.Username,
                    FirstName  = account.FirstName,
                    LastName   = account.LastName,
                    Email      = account.Email
                };

                await this.dbContext.CreateUser(user);
            }
            else
            {
                user = new PropyUser()
                {
                    Id         = Guid.NewGuid().ToString(),
                    FacebookId = bsonUser[0]["facebookId"].ToString(),
                    UserName   = bsonUser[0]["UserName"].ToString(),
                    FirstName  = bsonUser[0]["firstName"].ToString(),
                    LastName   = bsonUser[0]["lastName"].ToString(),
                    Email      = bsonUser[0]["facebookId"].ToString(),
                };
            }

            var identity = new ClaimsIdentity(
                OpenIdConnectServerDefaults.AuthenticationScheme,
                OpenIdConnectConstants.Claims.Name,
                OpenIdConnectConstants.Claims.Role);

            identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                              user.Id,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.Name, user.UserName,
                              OpenIdConnectConstants.Destinations.AccessToken);

            var principal = new ClaimsPrincipal(identity);

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

            ticket.SetScopes(new[]
            {
                OpenIdConnectConstants.Scopes.OfflineAccess,
            });

            return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
        }
        public async Task <IActionResult> Exhange(OpenIdConnectRequest request)
        {
            if (request.IsPasswordGrantType())
            {
                //request.GrantType = "password";
                // Validate the user credentials.
                // Note: to mitigate brute force attacks, you SHOULD strongly consider
                // applying a key derivation function like PBKDF2 to slow down
                // the password validation process. You SHOULD also consider
                // using a time-constant comparer to prevent timing attacks.
                var bsonUser = await this.dbContext.GetUser(request.Username);

                var user = new PropyUser();
                if (bsonUser.Count == 0)
                {
                    user.Id            = Guid.NewGuid().ToString();
                    user.UserName      = "******";
                    user.PasswordHash  = "AnonPass";
                    user.SecurityStamp = Guid.NewGuid().ToString();
                }
                else
                {
                    user = new PropyUser()
                    {
                        Id            = bsonUser[0]["_id"].ToString(),
                        UserName      = bsonUser[0]["UserName"].ToString(),
                        PasswordHash  = bsonUser[0]["PasswordHash"].ToString(),
                        SecurityStamp = bsonUser[0]["SecurityStamp"].ToString()
                    };
                }

                // Check password hash
                var hasher             = new PasswordHasher <PropyUser>();
                var verificationResult = hasher.VerifyHashedPassword(user, user.PasswordHash, request.Password);
                //if (user.Username != "*****@*****.**" ||
                //    user.Password != "P@ssw0rd")
                //{
                //    return Forbid(OpenIdConnectServerDefaults.AuthenticationScheme);
                //}
                // Create a new ClaimsIdentity holding the user identity.
                var identity = new ClaimsIdentity(
                    OpenIdConnectServerDefaults.AuthenticationScheme,
                    OpenIdConnectConstants.Claims.Name,
                    OpenIdConnectConstants.Claims.Role);
                // Add a "sub" claim containing the user identifier, and attach
                // the "access_token" destination to allow OpenIddict to store it
                // in the access token, so it can be retrieved from your controllers.
                //identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                //    "71346D62-9BA5-4B6D-9ECA-755574D628D8",
                //    OpenIdConnectConstants.Destinations.AccessToken);
                //identity.AddClaim(OpenIdConnectConstants.Claims.Name, "Alice",
                //    OpenIdConnectConstants.Destinations.AccessToken);

                identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                                  user.Id,
                                  OpenIdConnectConstants.Destinations.AccessToken);
                identity.AddClaim(OpenIdConnectConstants.Claims.Name, user.UserName,
                                  OpenIdConnectConstants.Destinations.AccessToken);
                // ... add other claims, if necessary.
                var principal = new ClaimsPrincipal(identity);

                //var ticket = CreateTicket(request, principal);
                var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme);
                ticket.SetScopes(new[]
                {
                    OpenIdConnectConstants.Scopes.OpenId,
                    OpenIdConnectConstants.Scopes.Email,
                    OpenIdConnectConstants.Scopes.Profile,
                    OpenIdConnectConstants.Scopes.OfflineAccess,
                    //OpenIddictConstants.Scopes.Roles
                }.Intersect(request.GetScopes()));

                // Ask OpenIddict to generate a new token and return an OAuth2 token response.
                //return SignIn(principal, OpenIdConnectServerDefaults.AuthenticationScheme);
                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }
            else if (request.IsRefreshTokenGrantType())
            {
                var info = await this.HttpContext.AuthenticateAsync(OpenIdConnectServerDefaults.AuthenticationScheme);

                // Create a new ClaimsIdentity holding the user identity.
                var identity = new ClaimsIdentity(
                    OpenIdConnectServerDefaults.AuthenticationScheme,
                    OpenIdConnectConstants.Claims.Name,
                    OpenIdConnectConstants.Claims.Role);
                // Add a "sub" claim containing the user identifier, and attach
                // the "access_token" destination to allow OpenIddict to store it
                // in the access token, so it can be retrieved from your controllers.
                identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                                  "71346D62-9BA5-4B6D-9ECA-755574D628D8",
                                  OpenIdConnectConstants.Destinations.AccessToken);
                identity.AddClaim(OpenIdConnectConstants.Claims.Name, "Alice",
                                  OpenIdConnectConstants.Destinations.AccessToken);
                // ... add other claims, if necessary.
                var principal = new ClaimsPrincipal(identity);

                var ticket = new AuthenticationTicket(principal, info.Properties,
                                                      OpenIdConnectServerDefaults.AuthenticationScheme);

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }
            else if (request.GrantType == "urn:ietf:params:oauth:grant-type:facebook_access_token")
            {
                var account = await this.facebookService.GetAccountAsync(request.Assertion);

                var bsonUser = await this.dbContext.GetUserByFacebookId(account.Id);

                PropyUser user;
                if (bsonUser.Count == 0)
                {
                    user = new PropyUser()
                    {
                        Id         = request.Assertion,
                        FacebookId = account.Id,
                        UserName   = account.Username,
                        FirstName  = account.FirstName,
                        LastName   = account.LastName,
                        Email      = account.Email
                    };

                    await this.dbContext.CreateUser(user);
                }
                else
                {
                    user = new PropyUser()
                    {
                        Id         = request.Assertion,
                        FacebookId = bsonUser[0]["facebookId"].ToString(),
                        UserName   = bsonUser[0]["UserName"].ToString(),
                        FirstName  = bsonUser[0]["firstName"].ToString(),
                        LastName   = bsonUser[0]["lastName"].ToString(),
                        Email      = bsonUser[0]["facebookId"].ToString(),
                    };
                }

                var identity = new ClaimsIdentity(
                    OpenIdConnectServerDefaults.AuthenticationScheme,
                    OpenIdConnectConstants.Claims.Name,
                    OpenIdConnectConstants.Claims.Role);

                identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                                  user.Id,
                                  OpenIdConnectConstants.Destinations.AccessToken);
                identity.AddClaim(OpenIdConnectConstants.Claims.Name, user.UserName,
                                  OpenIdConnectConstants.Destinations.AccessToken);

                var principal = new ClaimsPrincipal(identity);

                var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme);
                ticket.SetScopes(new[]
                {
                    OpenIdConnectConstants.Scopes.OfflineAccess,
                });

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }
            else if (request.GrantType == "urn:ietf:params:oauth:grant-type:google_identity_token")
            {
                // Exchange recieved Authorization Code for an access token
                var tokenUrl = "https://www.googleapis.com/oauth2/v4/token";

                //var code = "4/1VeXJLNmmH2dIYR8FSeW3OaVlYpK7BtZwVAhqzLvErk";
                var code          = request.Assertion;
                var client_id     = "295998800597-kao41iolosp6kl304dedl3u2551bogie.apps.googleusercontent.com";
                var client_secret = "z4VDv49a9aGMtQQK4NM8dZnn";
                var grant_type    = "authorization_code";
                var redirect_uri  = "http://localhost:5000";

                var data = new Dictionary <string, string>
                {
                    { "code", code },
                    { "client_id", client_id },
                    { "client_secret", client_secret },
                    { "grant_type", grant_type },
                    { "redirect_uri", redirect_uri }
                };

                var httpClient   = new HttpClient();
                var requestToken = new HttpRequestMessage(HttpMethod.Post, tokenUrl)
                {
                    Content = new FormUrlEncodedContent(data)
                };
                var response = await httpClient.SendAsync(requestToken);

                var responseContent = await response.Content.ReadAsStringAsync();

                var responseContentDeserializrd = JsonConvert.DeserializeObject <ResponseData>(responseContent);
                var accessToken = responseContentDeserializrd.AccessToken;

                // Use the access token to request the user's info
                httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
                var userInfoUrl  = "https://www.googleapis.com/oauth2/v1/userinfo";
                var userResponse = await httpClient.GetAsync(userInfoUrl);

                var userResponseContent = await userResponse.Content.ReadAsStringAsync();

                var userInfo = JsonConvert.DeserializeObject <UserInfo>(userResponseContent);

                // Create user if one does not exist, and log him in
                var user     = new PropyUser();
                var bsonUser = await this.dbContext.GetUserByGoogleId(userInfo.Id);

                if (bsonUser.Count == 0)
                {
                    user.Id        = Guid.NewGuid().ToString();
                    user.Email     = userInfo.Email;
                    user.UserName  = userInfo.Name;
                    user.FirstName = userInfo.GivenName;
                    user.LastName  = userInfo.FamilyName;
                    user.GoogleId  = userInfo.Id;

                    await this.dbContext.CreateUser(user);
                }
                else
                {
                    user.Id        = Guid.NewGuid().ToString();
                    user.Email     = bsonUser[0]["email"].ToString();
                    user.UserName  = bsonUser[0]["UserName"].ToString();
                    user.FirstName = bsonUser[0]["firstName"].ToString();
                    user.LastName  = bsonUser[0]["lastName"].ToString();
                    user.GoogleId  = bsonUser[0]["googleId"].ToString();
                }

                // Create user's identity, a ticket and then sign him in
                var identity = new ClaimsIdentity(
                    OpenIdConnectServerDefaults.AuthenticationScheme,
                    OpenIdConnectConstants.Claims.Name,
                    OpenIdConnectConstants.Claims.Role);

                identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                                  user.Id,
                                  OpenIdConnectConstants.Destinations.AccessToken);
                identity.AddClaim(OpenIdConnectConstants.Claims.Name, user.UserName,
                                  OpenIdConnectConstants.Destinations.AccessToken);

                var principal = new ClaimsPrincipal(identity);

                var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme);
                ticket.SetScopes(new[]
                {
                    OpenIdConnectConstants.Scopes.OfflineAccess,
                });

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }

            return(BadRequest(new OpenIdConnectResponse
            {
                Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
                ErrorDescription = "The specified grant type is not supported."
            }));
        }