Esempio n. 1
0
 protected override void Seed(AuthenticationDb db)
 {
     //  This method will be called after migrating to the latest version.
     Db.Operations repo = new Db.Operations(db);
     repo.InitializeClients();
     repo.InitializeRoles();
 }
Esempio n. 2
0
        public async Task <IHttpActionResult> ObtainLocalAccessToken(string provider, string externalAccessToken)
        {
            if (string.IsNullOrWhiteSpace(provider) || string.IsNullOrWhiteSpace(externalAccessToken))
            {
                return(BadRequest("Provider or external access token is not sent"));
            }

            var verifiedAccessToken = await VerifyExternalAccessToken(provider, externalAccessToken);

            if (verifiedAccessToken == null)
            {
                return(BadRequest("Invalid Provider or External Access Token"));
            }

            IdentityUser user = null;

            using (Db.Operations ops = new Db.Operations())
            {
                user = await ops.FindAsync(new UserLoginInfo(provider, verifiedAccessToken.user_id));
            }

            bool hasRegistered = user != null;

            if (!hasRegistered)
            {
                return(BadRequest("External user is not registered"));
            }

            //generate access token response
            var accessTokenResponse = GenerateLocalAccessTokenResponse(user.UserName);

            return(Ok(accessTokenResponse));
        }
Esempio n. 3
0
        public async Task <IHttpActionResult> PasswordReset(PasswordResetModel pwd)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            IdentityUser idUser = null;

            using (Db.Operations ops = new Db.Operations())
            {
                idUser = await ops.FindUserByEmail(pwd.Email);

                if (idUser != null)
                {
                    IdentityResult result = await ops.ResetPasswordAsync(idUser.Id, pwd.Token, pwd.Password);

                    if (!result.Succeeded)
                    {
                        if (result.Errors != null && result.Errors.Count() > 0)
                        {
                            return(Redirect(pwd.FailUrl + "?error=" + GetErrorString(result)));
                        }
                    }
                    else
                    {
                        return(Redirect(pwd.SuccessUrl));
                    }
                }
            }

            return(Ok());
        }
Esempio n. 4
0
 public async Task <IHttpActionResult> Test()
 {
     using (Db.Operations db = new Db.Operations())
     {
         Client client = db.FindClient("mainApp");
         return(Ok("Client found. Allowed origin: " + client.AllowedOrigin));
     }
 }
Esempio n. 5
0
        public async static void SetupClientsAndRoles()
        {
            using (Db.Operations repo = new Db.Operations())
            {
                await repo.InitializeClients();

                await repo.InitializeRoles();
            }
        }
Esempio n. 6
0
        public async Task <IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var verifiedAccessToken = await VerifyExternalAccessToken(model.Provider, model.ExternalAccessToken);

            if (verifiedAccessToken == null)
            {
                return(BadRequest("Invalid Provider or External Access Token"));
            }

            using (Db.Operations ops = new Db.Operations())
            {
                IdentityUser user = await ops.FindAsync(new UserLoginInfo(model.Provider, verifiedAccessToken.user_id));

                bool hasRegistered = user != null;

                if (hasRegistered)
                {
                    return(BadRequest("External user is already registered"));
                }

                user = new IdentityUser()
                {
                    UserName = model.UserName
                };                                                          // TODO: We will need other fields in the User object

                IdentityResult result = await ops.CreateAsync(user);

                if (!result.Succeeded)
                {
                    return(GetErrorResult(result));
                }

                var info = new ExternalLoginInfo()
                {
                    DefaultUserName = model.UserName,
                    Login           = new UserLoginInfo(model.Provider, verifiedAccessToken.user_id)
                };

                result = await ops.AddLoginAsync(user.Id, info.Login);

                if (!result.Succeeded)
                {
                    return(GetErrorResult(result));
                }
            }

            //generate access token response
            var accessTokenResponse = GenerateLocalAccessTokenResponse(model.UserName);

            return(Ok(accessTokenResponse));
        }
Esempio n. 7
0
        public async Task <IHttpActionResult> GetExternalLogin(string provider, string error = null)
        {
            string redirectUri = string.Empty;

            if (error != null)
            {
                return(BadRequest(Uri.EscapeDataString(error)));
            }

            if (!User.Identity.IsAuthenticated)
            {
                return(new ChallengeResult(provider, this));
            }

            var redirectUriValidationResult = ValidateClientAndRedirectUri(this.Request, ref redirectUri);

            if (!string.IsNullOrWhiteSpace(redirectUriValidationResult))
            {
                return(BadRequest(redirectUriValidationResult));
            }

            ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

            if (externalLogin == null)
            {
                return(InternalServerError());
            }

            if (externalLogin.LoginProvider != provider)
            {
                Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
                return(new ChallengeResult(provider, this));
            }

            IdentityUser user = null;

            using (Db.Operations ops = new Db.Operations())
            {
                user = await ops.FindAsync(new UserLoginInfo(externalLogin.LoginProvider, externalLogin.ProviderKey));
            }

            bool hasRegistered = user != null;

            redirectUri = string.Format("{0}#external_access_token={1}&provider={2}&haslocalaccount={3}&external_user_name={4}",
                                        redirectUri,
                                        externalLogin.ExternalAccessToken,
                                        externalLogin.LoginProvider,
                                        hasRegistered.ToString(),
                                        externalLogin.UserName);

            return(Redirect(redirectUri));
        }
Esempio n. 8
0
        public async Task <IHttpActionResult> Register(AspNetUser userModel)
        {
            if (userModel == null)
            {
                return(BadRequest("User data is empty - cannot register user"));
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }
            else if (Settings.UseEmailAsUsername && String.IsNullOrWhiteSpace(userModel.Email))
            {
                return(BadRequest("Email must be provided"));
            }
            else if (!Settings.UseEmailAsUsername && String.IsNullOrWhiteSpace(userModel.UserName))
            {
                return(BadRequest("Username must be provided"));
            }

            IHttpActionResult errorResult = null;

            using (Db.Operations ops = new Db.Operations())
            {
                IdentityUser idUser = new IdentityUser()
                {
                    UserName             = Settings.UseEmailAsUsername ? userModel.Email : userModel.UserName,
                    Email                = userModel.Email,
                    EmailConfirmed       = false,
                    PhoneNumber          = userModel.PhoneNumber,
                    PhoneNumberConfirmed = false,
                    TwoFactorEnabled     = false
                };
                IdentityResult result = await ops.RegisterUser(idUser, userModel.Password);

                errorResult = GetErrorResult(result);
                if (errorResult != null)
                {
                    return(errorResult);
                }
                else
                {
                    userModel.IdentityUserId = idUser.Id;
                }
            }

            return(Ok());
        }
Esempio n. 9
0
        /// <summary>
        /// GrantResourceOwnerCredentials is used to validate provided username and password when the grant_type is set to password
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            var allowedOrigin = context.OwinContext.Get <string>("as:clientAllowedOrigin");

            if (allowedOrigin == null)
            {
                allowedOrigin = "*";
            }

            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

            ClaimsIdentity identity = null;

            using (Db.Operations _repo = new Db.Operations())
            {
                IdentityUser user = await _repo.FindUser(context.UserName, context.Password);

                if (user == null)
                {
                    context.SetError("invalid_grant", "The user name or password is incorrect.");
                    return;
                }

                IList <string> roles = await _repo.UserRoles(user.Id);

                identity = new ClaimsIdentity(context.Options.AuthenticationType);
                identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
                foreach (string role in roles)
                {
                    identity.AddClaim(new Claim(ClaimTypes.Role, role));
                }
                //identity.AddClaim(new Claim("sub", context.UserName));
            }

            var props = new AuthenticationProperties(new Dictionary <string, string>
            {
                {
                    "as:client_id", (context.ClientId == null) ? string.Empty : context.ClientId
                },
                {
                    "userName", context.UserName
                }
            });

            var ticket = new AuthenticationTicket(identity, props);

            context.Validated(ticket);
        }
Esempio n. 10
0
        private string ValidateClientAndRedirectUri(HttpRequestMessage request, ref string redirectUriOutput)
        {
            Uri redirectUri;

            var redirectUriString = GetQueryString(Request, "redirect_uri");

            if (string.IsNullOrWhiteSpace(redirectUriString))
            {
                return("redirect_uri is required");
            }

            bool validUri = Uri.TryCreate(redirectUriString, UriKind.Absolute, out redirectUri);

            if (!validUri)
            {
                return("redirect_uri is invalid");
            }

            var clientId = GetQueryString(Request, "client_id");

            if (string.IsNullOrWhiteSpace(clientId))
            {
                return("client_Id is required");
            }

            Client client = null;

            using (Db.Operations ops = new Db.Operations())
            {
                client = ops.FindClient(clientId);
            }

            if (client == null)
            {
                return(string.Format("Client_id '{0}' is not registered in the system.", clientId));
            }

            if (!string.Equals(client.AllowedOrigin, redirectUri.GetLeftPart(UriPartial.Authority), StringComparison.OrdinalIgnoreCase))
            {
                return(string.Format("The given URL is not allowed by Client_id '{0}' configuration.", clientId));
            }

            redirectUriOutput = redirectUri.AbsoluteUri;

            return(string.Empty);
        }
Esempio n. 11
0
        public static async Task <AspNetUser> GetCurrentUser()
        {
            AspNetUser user = new AspNetUser();

            // Populate inherited AspNetUser fields
            IdentityUser idUser = null;

            using (Db.Operations _repo = new Db.Operations())
            {
                idUser = await _repo.GetCurrentUser();
            }
            if (idUser != null)
            {
                user.IdentityUser = idUser;
            }

            return(user);
        }
        public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
        {
            var allowedOrigin = context.OwinContext.Get <string>("as:clientAllowedOrigin");

            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

            string hashedTokenId = Helper.GetHash(context.Token);

            using (Db.Operations _repo = new Db.Operations())
            {
                var refreshToken = await _repo.FindRefreshToken(hashedTokenId);

                if (refreshToken != null)
                {
                    //Get protectedTicket from refreshToken class
                    context.DeserializeTicket(refreshToken.ProtectedTicket);
                    var result = await _repo.RemoveRefreshToken(hashedTokenId);
                }
            }
        }
        public async Task CreateAsync(AuthenticationTokenCreateContext context)
        {
            var clientid = context.Ticket.Properties.Dictionary["as:client_id"];

            if (string.IsNullOrEmpty(clientid))
            {
                return;
            }

            var refreshTokenId = Guid.NewGuid().ToString("n");

            using (Db.Operations _repo = new Db.Operations())
            {
                var refreshTokenLifeTime = context.OwinContext.Get <string>("as:clientRefreshTokenLifeTime");

                var token = new RefreshToken()
                {
                    Id         = Helper.GetHash(refreshTokenId),
                    ClientId   = clientid,
                    Subject    = context.Ticket.Identity.Name,
                    IssuedUtc  = DateTime.UtcNow,
                    ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime))
                };

                context.Ticket.Properties.IssuedUtc  = token.IssuedUtc;
                context.Ticket.Properties.ExpiresUtc = token.ExpiresUtc;

                token.ProtectedTicket = context.SerializeTicket();

                var result = await _repo.AddRefreshToken(token);

                if (result)
                {
                    context.SetToken(refreshTokenId);
                }
            }
        }
Esempio n. 14
0
        public async Task <IHttpActionResult> PasswordResetRequest(string email)
        {
            IdentityUser idUser = null;

            using (Db.Operations ops = new Db.Operations())
            {
                idUser = await ops.FindUserByEmail(email);

                if (idUser != null)
                {
                    try
                    {
                        // For the Password Reset Token to work:
                        // Go to the Application Pool for the web site in IIS
                        // Advanced Settings > Process Model > Load User Profile = True
                        string resetToken = await ops.GetPasswordResetToken(idUser.Id);

                        if (Settings.EmailClient != null && Settings.PasswordReset != null)
                        {
                            EmailMessage mailMessage = Settings.PasswordReset;
                            mailMessage.To = new EmailAddress(email);
                            mailMessage.PlainTextContent = mailMessage.PlainTextContent.Replace("{EmailAddress}", email).Replace("{Token}", HttpUtility.UrlEncode(resetToken));
                            mailMessage.HtmlContent      = mailMessage.HtmlContent.Replace("{EmailAddress}", email).Replace("{Token}", HttpUtility.UrlEncode(resetToken));
                            await Settings.EmailClient.SendAsync(mailMessage);
                        }

                        return(Ok());
                    }
                    catch (Exception ex)
                    {
                        return(BadRequest(string.Format("Password reset details could not be sent to {0}. Internal error: {1}", email, ex.Message)));
                    }
                }
            }

            return(Ok());
        }
 public RefreshTokensController()
 {
     _repo = new Db.Operations();
 }
Esempio n. 16
0
        /// <summary>
        /// The route of this method is defined by Settings.TokenEndpointPath endpoint, e.g. /token
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            // Called to validate that the origin of the request is a registered "client_id", and that the correct credentials for that
            // client are present on the request. If the web application accepts Basic authentication credentials,
            // context.TryGetBasicCredentials(out clientId, out clientSecret) may be called to acquire those values if present in the request header.
            // If the web application accepts "client_id" and "client_secret" as form encoded POST parameters,
            // context.TryGetFormCredentials(out clientId, out clientSecret) may be called to acquire those values if present in the request body.
            // If context.Validated is not called the request will not proceed further.

            string clientId     = string.Empty;
            string clientSecret = string.Empty;

            #region Load ClientId and ClientSecret from the request

            bool BodyAuthentication   = false;
            bool HeaderAuthentication = false;

            BodyAuthentication = context.TryGetFormCredentials(out clientId, out clientSecret);
            if (!BodyAuthentication)
            {
                HeaderAuthentication = context.TryGetBasicCredentials(out clientId, out clientSecret);
                if (!HeaderAuthentication)
                {
                    AuthRequest authRequest = context.GetAuthRequest();
                    if (authRequest != null)
                    {
                        clientId     = authRequest.client_id;
                        clientSecret = authRequest.client_secret;
                    }
                }
            }

            if (string.IsNullOrWhiteSpace(clientId))
            {
                // Remove the comments from the below lines if you want to force sending clientId/secrects
                // once access token is obtained
                context.Rejected();
                context.SetError("invalid_clientId", "ClientId should be sent.");
                return(Task.FromResult <object>(null));
            }

            #endregion

            Client client = null;

            #region Validate Client from the database

            using (Db.Operations _repo = new Db.Operations())
            {
                client = _repo.FindClient(clientId);
            }

            if (client == null)
            {
                context.SetError("invalid_clientId", string.Format("Client '{0}' is not registered in the system.", clientId));
                return(Task.FromResult <object>(null));
            }

            if (client.ApplicationType == Models.ApplicationTypes.NativeConfidential)
            {
                if (string.IsNullOrWhiteSpace(clientSecret))
                {
                    context.SetError("invalid_clientId", "Client secret should be sent.");
                    return(Task.FromResult <object>(null));
                }
                else
                {
                    if (client.Secret != Helper.GetHash(clientSecret))
                    {
                        context.SetError("invalid_clientId", "Client secret is invalid.");
                        return(Task.FromResult <object>(null));
                    }
                }
            }

            if (!client.Active)
            {
                context.SetError("invalid_clientId", "Client is inactive.");
                return(Task.FromResult <object>(null));
            }

            #endregion

            context.OwinContext.Set <string>("as:clientAllowedOrigin", client.AllowedOrigin);
            context.OwinContext.Set <string>("as:clientRefreshTokenLifeTime", client.RefreshTokenLifeTime.ToString());

            context.Validated(clientId);  // This sets context.ClientId parameter
            return(Task.FromResult <object>(null));
        }