|
@@ -0,0 +1,145 @@
|
|
|
+package id.co.hanoman.ngdemo;
|
|
|
+
|
|
|
+import java.security.MessageDigest;
|
|
|
+import java.security.NoSuchAlgorithmException;
|
|
|
+import java.util.UUID;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.security.core.context.SecurityContextHolder;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import com.senomas.boot.security.LoginRequest;
|
|
|
+import com.senomas.boot.security.LoginUser;
|
|
|
+import com.senomas.boot.security.RefreshTokenRequest;
|
|
|
+import com.senomas.boot.security.TokenAuthentication;
|
|
|
+import com.senomas.boot.security.domain.AuthToken;
|
|
|
+import com.senomas.boot.security.domain.SecurityUser;
|
|
|
+import com.senomas.boot.security.rs.AuthenticationException;
|
|
|
+import com.senomas.boot.security.rs.InvalidRefreshTokenException;
|
|
|
+import com.senomas.boot.security.rs.InvalidSaltException;
|
|
|
+import com.senomas.boot.security.rs.InvalidUserPasswordException;
|
|
|
+import com.senomas.boot.security.service.AuthenticationService;
|
|
|
+import com.senomas.boot.security.service.TokenService;
|
|
|
+import com.senomas.common.RateLimiterService;
|
|
|
+import com.senomas.common.U;
|
|
|
+import com.senomas.common.rs.InvalidTimestampException;
|
|
|
+
|
|
|
+import id.co.hanoman.ngdemo.domain.AppUser;
|
|
|
+import id.co.hanoman.ngdemo.domain.AppUserRepository;
|
|
|
+
|
|
|
+@Component
|
|
|
+public class AuthenticationServiceImpl implements AuthenticationService {
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(AuthenticationServiceImpl.class);
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected AppUserRepository userRepo;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected RateLimiterService rateLimiterService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected TokenService tokenService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AuthToken login(HttpServletRequest request, LoginRequest login) {
|
|
|
+ if (Math.abs(System.currentTimeMillis() - login.getTimestamp().getTime()) > 300000) {
|
|
|
+ log.info("TIMESTAMP " + System.currentTimeMillis() + " "
|
|
|
+ + (System.currentTimeMillis() - login.getTimestamp().getTime()));
|
|
|
+ throw new InvalidTimestampException();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!rateLimiterService.acquire("/ip/auth", request.getRemoteAddr())) {
|
|
|
+ throw new AuthenticationException("Too many request");
|
|
|
+ }
|
|
|
+ if (!rateLimiterService.acquire("/auth", login.getLogin())) {
|
|
|
+ throw new AuthenticationException("Too many request");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (login.getSalt() == null)
|
|
|
+ throw new InvalidSaltException(login.getTimestamp().getTime(), generateSalt(request, login),
|
|
|
+ "Invalid salt");
|
|
|
+ String salt = generateSalt(request, login);
|
|
|
+ if (!salt.equals(login.getSalt()))
|
|
|
+ throw new InvalidSaltException(login.getTimestamp().getTime(), generateSalt(request, login),
|
|
|
+ "Invalid salt");
|
|
|
+
|
|
|
+ AppUser user = userRepo.findOne(login.getLogin());
|
|
|
+
|
|
|
+ if (user == null) {
|
|
|
+ log.info("INVALID LOGIN [" + login.getLogin() + "]");
|
|
|
+ throw new InvalidUserPasswordException();
|
|
|
+ }
|
|
|
+
|
|
|
+ String securePasscode = U.digest(user.getPasscode(), "|", login.getSalt());
|
|
|
+
|
|
|
+ if (!securePasscode.equals(login.getSecurePasscode())) {
|
|
|
+ log.info("INVALID TOKEN ["+user.getPasscode()+"] [" + securePasscode + "] [" + login.getSecurePasscode() + "]");
|
|
|
+ throw new InvalidUserPasswordException();
|
|
|
+ }
|
|
|
+
|
|
|
+ LoginUser loginUser = tokenService.create(user);
|
|
|
+ log.info("LOGIN-USER "+U.dump(loginUser));
|
|
|
+ String token = loginUser.getToken();
|
|
|
+
|
|
|
+ String refreshToken = UUID.randomUUID().toString();
|
|
|
+ user.setLoginToken(refreshToken);
|
|
|
+ userRepo.save(user);
|
|
|
+
|
|
|
+ return new AuthToken(token, refreshToken, user);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected String generateSalt(HttpServletRequest request, LoginRequest login) {
|
|
|
+ try {
|
|
|
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
|
|
|
+ md.update(U.getBytes(login.getLogin()));
|
|
|
+ md.update(U.getBytes(request.getRemoteAddr()));
|
|
|
+ md.update(U.getBytes(login.getTimestamp().getTime()));
|
|
|
+ return U.encode64(md.digest());
|
|
|
+ } catch (NoSuchAlgorithmException e) {
|
|
|
+ throw new RuntimeException(e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public SecurityUser getUser() {
|
|
|
+ AppUser user = (AppUser) ((TokenAuthentication) SecurityContextHolder.getContext().getAuthentication()).getUser();
|
|
|
+ return user;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AuthToken refresh(HttpServletRequest request, RefreshTokenRequest refreshToken) {
|
|
|
+ if (Math.abs(System.currentTimeMillis() - refreshToken.getTimestamp().getTime()) > 300000) {
|
|
|
+ log.info("TIMESTAMP " + System.currentTimeMillis() + " "
|
|
|
+ + (System.currentTimeMillis() - refreshToken.getTimestamp().getTime()));
|
|
|
+ throw new InvalidTimestampException();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!rateLimiterService.acquire("/ip/auth", request.getRemoteAddr())) {
|
|
|
+ throw new AuthenticationException("Too many request");
|
|
|
+ }
|
|
|
+ if (!rateLimiterService.acquire("/auth", refreshToken.getLogin())) {
|
|
|
+ throw new AuthenticationException("Too many request");
|
|
|
+ }
|
|
|
+
|
|
|
+ AppUser user = userRepo.findOne(refreshToken.getLogin());
|
|
|
+
|
|
|
+ if (user == null) {
|
|
|
+ log.info("INVALID LOGIN [" + refreshToken.getLogin() + "]");
|
|
|
+ throw new InvalidRefreshTokenException("Invalid login");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!U.digest(String.valueOf(refreshToken.getTimestamp().getTime()), "|", user.getLogin(), "|", user.getLoginToken()).equals(refreshToken.getRefreshTokenHash())) {
|
|
|
+ log.info("INVALID REFRESH-TOKEN " + U.dump(refreshToken));
|
|
|
+ throw new InvalidRefreshTokenException("Invalid refresh-token");
|
|
|
+ }
|
|
|
+
|
|
|
+ LoginUser loginUser = tokenService.create(user);
|
|
|
+
|
|
|
+ return new AuthToken(loginUser.getToken(), null, user);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|