Password encryption/decryption Spring security - spring-security

I am encrypting the security in my web page with MD5 and Im using the following code.
public static String stringToMD5(String password)
{
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(password.getBytes(),0, password.length());
String hashedPass = new BigInteger(1,messageDigest.digest()).toString(16);
if (hashedPass.length() < 32) {
hashedPass = "0" + hashedPass;
}
return hashedPass;
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return password;
}
But because a custom way to log in I had to developed a custom AbstractAuthenticationProcessingFilter and now I have to decrypt that MD5.
So the question is how to decrypt the produced by that function.
Thanks in advance.

MD5 is a one-way algorithm. This is not a one-to-one mapping. There is no way to decrypt its output.
When working with stored MD5 encrypted passwords, you must authenticate users by encrypting their input and comparing the result to the stored encrypted password.

Related

soapUI - Oauth2 and Basic Authentication to retrieve token

I need to develop a SoapUi test using to oauth2, the authorization API requires Basic Authentication.
I tried to use the [username]:[password]#url approch, but the password contains a special character # that gets changed to %40, I also changed the Enconding but no luck.
I added the header in the class EnabledWebViewBasedBrowserComponent
public void navigate(final String url, String errorPage) {
if (SoapUI.isBrowserDisabled()) {
return;
}
setErrorPage(errorPage);
this.url = url;
Platform.runLater(new Runnable() {
public void run() {
getWebEngine().setUserAgent("\nAuthorization: Basic bWNb25lhbGRzlk1jRDuGxklWg==");
getWebEngine().load(url);
}
});
}

How to decrypt password in MVC5?

I am using MVC5, i know that if a user forgets his password, then MVC provides the feature of forgot password and reset password.
My client server is disconnected from internet or mailing, it is behind the firewalls, so i cannot use forgot password, as it might generate a link to reset password, but cannot mail it to the user to facilitate the password reset.
Please suggest if there is any way to decrypt the password(to let user know if he forgets his password) like how it was available in asp.net membership by simply using the GetPassword method of the membership classes.
Thank you
As far I know there is no easy way to do this in MVC5, because Identity (next gen of Membership) is using hash of password rather then encrypted password.
Password is hashed and stored in db as a hash - generally it's one-way operation (it's mean that there is no easy way to get password form hash).
Little bit more about what is hashing and salting you can read here:
How to securely store passwords and beat the hackers
How does hashing work?
This step to Ecrypt and decrypt password in asp.net mvc5.
create class name Hashing, paste this code
private static string GetRandomSalt()
{
return BCrypt.Net.BCrypt.GenerateSalt(12);
}
public static string HashPassword(string password)
{
return BCrypt.Net.BCrypt.HashPassword(password, GetRandomSalt());
}
public static bool ValidatePassword(string password, string correctHash)
{
return BCrypt.Net.BCrypt.Verify(password, correctHash);
}
Create controller login you past this code
using WebBcryptMVC.Models; //
using WebBcryptMVC.Util; // call folder name of Hashing class
namespace WebBcryptMVC.Controllers
{
public class LoginController : Controller
{
private DBLoginEntities db = new DBLoginEntities();
public ActionResult frmLogin()
{
return View("frmLogin", new tblLogin());
}
[HttpPost]
public ActionResult frmLogin(tblLogin account)
{
var currentAccount = db.tblLogins.First(a => a.UserName.Equals(account.UserName));
if ((currentAccount != null))
{
if (Hashing.ValidatePassword(account.Password, currentAccount.Password))
{
Session.Add("UserName", account.UserName);
//return View("~/Views/Home/frmHome.cshtml");
return RedirectToAction("frmHome", "Home");
}
else
{
ViewBag.error = "Invalid";
return View("frmLogin");
}
}
else
{
ViewBag.error = "Invalid";
return View("frmLogin");
}
}

Login with UsernamePasswordAuthenticationToken and PasswordEncoder

I did not encode my password until now and therefore the code at bottom worked fine.
Now the password is encoded with PasswordEncoder at signup, therefore the hashed password is in database - as it should be.
My question now would be how to do it now with UsernamePasswordAuthenticationToken. If I pass i the encoded password the login failes? Is there another class where I can put in the encoded password?
final UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(usernameOrEmailAddress, password);
Here is my login methode:
#RequestMapping(value = "/login", method = { RequestMethod.POST }, consumes = "application/json;charset=utf-8")
public UserTransferObject login(final #RequestBody LoginData loginData) throws BusinessException {
final String usernameOrEmailAddress = loginData.getUsername();
final String password = loginData.getPassword();
// passwordEncoded does not work here
final UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(usernameOrEmailAddress, password);
try {
final Authentication authentication = this.authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (Exception e) {
final String message = messageByLocaleService.getMessage("login.error"); // key declared in frontend project
throw new BusinessException(message, "400", e.getCause());
}
final UserDetails userDetails = this.userDetailsService.loadUserByUsername(usernameOrEmailAddress);
Here I get the problem, die AuthenticationManager can not authenticate when I user encoded password - I get a BadCredentialsException exception:
final Authentication authentication = this.authenticationManager.authenticate(token);
[EDIT]
I recognized that I have another problem. In method login username and plain password came in and then I calculate the hash and salt with PasswordEncoder. Than authenticationManager.authenticate loads user from database but in database the user have another hashed password because the salt was different at creation time
Actually my approach to solve this would be to disable the salt but then the security is wearer. I would be thankful for any hint solving this.

Getting same hashed value while using BCryptPasswordEncoder

I am using spring security using BCryptPasswordEncoder. Now for change password what I need to do is to compare Existing Password provided by user with DB value.
But since salt is generated dynamically by BCryptPasswordEncoder, every time I get different hashed value from below method and not necessarily it would match with my DB value.
public static String encodePassword(String password) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String hashedPassword = passwordEncoder.encode(password);
return hashedPassword;
}
What's the remedy for this problem? can I identify salt used for my DB field and use the same salt in above method ?
Use the matches method on the PasswordEncoder interface to check whether the password is valid, rather than encoding it again and comparing with the existing hash.
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String existingPassword = ... // Password entered by user
String dbPassword = ... // Load hashed DB password
if (passwordEncoder.matches(existingPassword, dbPassword)) {
// Encode new password and store it
} else {
// Report error
}
If you are using BCryptPasswordEncoder with your own properties (strength / random) together with Spring MVC, then you could declare your PasswordEncoder as a Bean. That way, it will be a singleton instance and you can reuse it.
Here comes an example (I don't know which configuration style you are using):
in your security configuration:
#Bean
public PasswordEncoder passwordEncoder() {
int strength = // your strength;
SecureRandom random = // your random
PasswordEncoder encoder = new BCryptPasswordEncoder(strength, random);
return encoder;
}
However, in your controller, you can compare passwords like this:
#Autowired
private PasswordEncoder passwordEncoder;
public boolean checkPassword(String password, String
return passwordEncoder.matches(password, hashedPassword);;
}

Authenticating users with auth token in query string with ASP.NET MVC

[This question relates to ASP.NET MVC4, and it is about best-practice approach - so please, don't suggest hacks.]
I want to authenticate users using an auth token sent in the request URL. It works similarly to a password reset token, except in this case it does not go to a reset page but instead grants access to some portion of the site. The idea is to send the URL with the auth token to a verified email address of the user. Users can click the link and perform some actions without typing their password.
Out-of-the-box, ASP.NET has the [Authorize] attribute and the SimpleMembershipProvider - these seem to work great, but they do some voodoo magic under the hood (like auto-generating database tables), so I don't know how to extend them to add this link-based auth token.
I don't expect an exact answer, but please do point me to the right direction.
Thanks!
Uf, broad question. But I will try at least to direct you to a right direction.
So first if suggest that you use Forms Authentication as a base, but you will have to customize using of it. And I presume that you do not want to use cookies for the authentication as this is native behaviour of the Forms Authentication.
The most important point you should consider to have it you custom query string token based authentication.
Create a login action and in this action you will authorize the user, if he have granted access you ask FormsAuthentication to create AuthCookie. For the further on you just take the httpCookie.Value as your auth token that you will carry in query string.
You need to implement the Application_BeginRequest in the Global.asax that will handle this query string tokens and translate it into the cookie. With this approach you can leverage all the ASP.NET Forms Authentication infrastructure.
This is quite high level picture w/o code. If you need more detail help I can also provide it to you.
You should just use a regular Action that accepts HttpGet.
Upon receiving the token, immediately invalid it so it can't be used again.
Also, only accept tokens that are within your pre-defined range of time period, like 24 or 72 hours.
Thank you Peter for idea.
If smb need to create JWT token authorization for old ASP.NET MVC5.I wrote small example. I don't serialize cookie to JWT. I create a JWT and after I am checking it in the BeginRequest. If everything is ok, I create a cookie and set it to the httpContext.Request. I used authentication mode="Forms" for application and it require cookies.
For create JWT token:
const string secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
[AllowAnonymous]
[HttpPost]
public ActionResult LoginJWT(LoginViewModel model)
{
ActionResult response = null;
if (ModelState.IsValid)
{
if (true) //todo: check user login&password
{
var payload = new Dictionary<string, object>
{
{ "iss", "subject" },
{ "sub", "api" },
{ "exp", DateTimeOffset.UtcNow.AddHours(2).ToUnixTimeSeconds()},
{ "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds()},
{ "jti", Guid.NewGuid() },
{ "uid", "64" } //custom field for identificate user
};
IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); // symmetric
IJsonSerializer serializer = new JsonNetSerializer();
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
var token = encoder.Encode(payload, secret);
response = Content(token);
}
else
{
response = new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest, "Login or password are not found");
}
}
else
{
response = new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest, "Errors in Model");
}
return response;
}
For check JWT token in Global.asax:
public override void Init()
{
this.BeginRequest += this.BeginRequestHandler;
base.Init();
}
private void BeginRequestHandler(object sender, EventArgs e)
{
var bearerToken = this.Context.Request.Headers["Authorization"];
if (bearerToken != null)
{
var token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
const string secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
int userId = 0;
try
{
IJsonSerializer serializer = new JsonNetSerializer();
var provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); // symmetric
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);
var json = decoder.DecodeToObject<IDictionary<string, string>>(token, secret, verify: true);
if (json.TryGetValue("uid", out var uid))
{
userId = Convert.ToInt32(uid);
}
}
catch (TokenExpiredException)
{
Console.WriteLine("Token has expired");
}
catch (SignatureVerificationException)
{
Console.WriteLine("Token has invalid signature");
}
if (userId != 0)
{
// check user by id, if found create cookie.
}
}
}
I used:
jwt-dotnet/jwt library 7.2.1

Resources