Spring remember-me with custom authentication provider - java

I want to implement remember me services for my application. The main problem I am facing is I am using a custom authentication provider . which uses a third party application for authentication. I dont have direct access to their DB.
I checked this Link and It tells implementation of UserDetailService is Mandatory for userauthenticxation service. Unfortunately in my case I cant do this.
I checked this Link as well and it says you may also implement a customRememberMeServices . But I am not sure how this is done. It just passes a request and a response which doesn't have the credentials.
With the limited understanding I have; spring stores userName and password in the token
base64(username + ":" + expirationTime + ":" +
md5Hex(username + ":" + expirationTime + ":" password + ":" + key))
username: As identifiable to the UserDetailsService
password: That matches the one in the retrieved UserDetails
expirationTime: The date and time when the remember-me token expires,
expressed in milliseconds
key: A private key to prevent modification of the remember-me token
Is there a way I can retrieve password from this token ? if not how else I can achieve the same ?

No. The token is a one-way hash. The whole point is that the password is used to create the token and it can later be verified using the same data when the user connects again. If you can't read the password from the database then you can't use this method directly. You could create a fake random password for each user and store it in a database which you do have access to, and implement a UserDetailsService which loads that instead.
Alternatively, you can use the alternative "persistent token" implementation, which stores the actual token in the database, rather than rebuilding it from unique user data.

Related

Get access token using Spring Security with a specific use-case

Is this use-case supported for Spring Security 5, or something else, where we don't have to reinvent the wheel? Thoughts on how to (re)implement this better?
Details are as follows. 3rd party vendor supplied endpoints. We pull info from upstream source then forward to the downstream vendor. Only 2 APIs are required:
Request Access Token
Save Info
Both are actually being called via a gateway. We've been given specifics:
(A)
The token request requires Basic Auth (standard header - usual base64 encoded). Gateway User and Gateway Password are provided.
Credentials for request token are provided to us:
Grant Type = password
Consumer Id
Consumer Secret
Account User
Account Password
It responds with an access token and few other details we don't really care about and of zero value to our use-case.
There is no expires_in info in the response. But I've tested it multiple times to know it does expire. Not sure how long right now, I could do more tests to determine that.
(B)
The save request requires a different custom header for the same Gateway User / Password, then a Bearer Authorization header in the call to the Save Info API.
Right now, all implementations for above are using RestTemplate. Working fine already. But a token is requested for each save which is costly. Before writing any caching, or some other logic to wait XY minutes before another token request is made, I would appreciate any other options which may already be possibly handled via Spring-specific libraries or further advise on how to handle this scenario.
Apologies if this is not the right place to ask this, or it has already been asked before. Been searching for a similar use-case but can't seem to find one.
Thanks.
Try any one of the option
You can use OAuth2ClientContext which stores your access token.
final OAuth2RestTemplate restTemplate=new OAuth2RestTemplate(resourceDetails, clientContext);
You can create session & store your token & user details inside it.
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user, null,null);
SecurityContextHolder.getContext().setAuthentication(authToken);
from option 1 Or option 2 you can then fetch existing token for each request at your Filter e.g. PRE_AUTH_FILTER
Then check if token expired - if yes request new token Or call refresh token
Check Oauth2 expires_in in below :-
https://www.rfc-editor.org/rfc/rfc6749?

JWT gets decoded easily on its site

I am working with JWT api , i have generated a token using:
public void addAuthentication(HttpServletResponse response, String name) {
// We generate a token now.
String JWT = Jwts.builder()
.setSubject(name)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
response.addHeader(headerString, tokenPrefix + " " + JWT);
}
abd secret token prefix being string , however it does generate token, but when i copy it into
https://jwt.io/#debugger
It does undecode it and reveal all informations stored inside it , did i do something wrong or its as it should be? This does not seem secure at all.
Thanks for answers
This is secure at all. Don't worry about it. Just store your key in a secure way.
The remarkable point is decoded information can not be changed or token can not be generated without the key.
Avoid storing essential information in token like credit card number or password etc. I'm sure that you are not using the JWT for this purpose.
If you want to hide the payload, the JWT specification allows use encryption (see Json Web Encryption-JWE at RFC). If auth0 does not support it, you have a lot of libraries listed in jwt.io
Check this topics
Is JWT that secure?
Why are JWT's secure?
It's secure in the sense it tells you who the user is and what claims they have. You can verify that the user's identity and claims are valid by checking the JWTs signature.
Also, see this: https://stackoverflow.com/a/38459231/2115684
If you want to hide the payload, the JWT specification allows use encryption (see Json Web Encryption-JWE at RFC). If auth0 does not support it, you have a lot of libraries listed in jwt.io

How to hide password and username from url

if (jsonresponse == 'SESSION_ALREADY_LOGGED_IN' || jsonresponse == 'USER_ALREADY_LOGGED_IN'){
window.location.replace("${pageContext.request.contextPath}/TrialUser.jsp?rsUsername=" +
getURLParameter("rsUsername") + "&rsPassword" + getURLParameter("rsPassword") + "&rsUse=" +
getURLParameter("rsUse") +"&HOOK_URL=" + getURLParameter("HOOK_URL"));
}
Simple is to Encrypt it and send it in the "Authentication" in the Request header, you can use a simple http base with username/password in Base64, or make it more complicated using Bearer and JWT (JSON Web Token) with a token, hash and at least 256-bit.
If you are considering using MD5 then you should know it was cracked in 1991 and is not secure in over 25 years.
Why are you sending the username and password on get request, it should be on post request always.
In case if you have to do it at least encrypt your password or user details through javascript before sending it
window.location.href = "index.php?Id=" + encrypt(5)+ "&No=" +encrypt( 5);
I strongly recement don't do it
It seems like the overall architecture design should change regarding the log in functionality. Might be a good idea to rethink how you'd like to implement the process.
Also, why sending username/password as GET parameters? GET-requests is also usually logged in various webservers/application servers, which poses a security risk. Uses POST for this whilst performing login sequences.
If GET should be used, look into other solutions regarding identification possibilities.

Check The Client's Authenticated Status (web-services)

everybody.
Say, I have a web server and a client, which connects to it for the first time. The authentication mechanism is:
1) parse the client's UsernameToken element and retrieve its username, password and
nonce.
2) evaluate a hash: SHA2 (username + password + nonce)
3) check if a Data Base contains such a hash.
Let's assume that there is such a hash. The question is, how to know that the client is already authenticated, when it connects the second time?
Searching the DB is rather expensive, so I can't do it at every connect.
Saving the clients hash in memory will increase the performance, but how long should it present in such a registry and it seem to be a huge security hole.
Session parameter? But how can it be implemented in the web-services context?

How does Remember Me work in Spring Security?

I'm curious how does Remember Me work and how does it work in Spring Security?
I understand that server sends long-lived cookies to the client. And then client sends cookie back and server can recognize the client because there's something like hash-map on the server with relations cookie --> session.
I don't understand how does the server [server-side application] recognize a client by cookie after server [Tomcat] has been restarted.
How and where does Spring Security save cookie-session map before server shutdown? Is it server-specific (i.e. something different is happened in Tomcat, Jetty etc)?
P.S. one more related problem with Spring Security and redeployment: even if I don't tick RememberMe and log in, I'm still recognized after redeployment for about 3 mins. Is it fixable?
The Spring Security docs discuss how this actually works.
This approach uses hashing to achieve a useful remember-me strategy. In essence a cookie is sent to the browser upon successful interactive authentication, with the cookie being composed as follows:
base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key))
...
As such the remember-me token is valid only for the period specified, and provided that the username, password and key does not change. Notably, this has a potential security issue in that a captured remember-me token will be usable from any user agent until such time as the token expires. This is the same issue as with digest authentication.
Basically the cookie contains the username, password, expiration time and a key (which you specify), all of which are hashed together. When your browser sends the contents of this cookie to the server, Spring Security:
Retrieves the password from the backend for the given username
Computes the md5Hex() of the username/password/etc from the database and compares it to the value in the cookie
If they match - you are logged in! If not a match, then you've supplied a forged cookie or one of the username/password/key has changed.
The underlying assumption here is that the hash function - the md5Hex() part above - provides a way to easily encode some piece of data in one direction yet is incredibly hard and unpractical to reverse (to recover the password from the md5Hex text).
Dont' confuse session cookies with Remember Me cookies.
Session cookie is sent by the server (e.g. Tomcat) and used to associate incoming request with the session.
Remember Me cookie is sent by Spring Security to authenticate the client in the different sessions (e.g. after expiration of the original session or after the server restart).
To authenticate a user by Remember Me cookie Spring Security provides 2 strategies:
TokenBasedRememberMeServices - used by default, less secure - cookie contains a hash of the password and other data
PersistentTokenBasedRememberMeServices - more secure, requires database access - cookie containt an unique identifier stored in the database

Categories

Resources