I am building a web app which runs react on the front end and Java/Spring on the back end.
I am using a RESTful API to communicate with my client (client will communicate with an external API too).
I am facing a problem. When a user registers, I want to send an email verification code. My question is about practice.
Is it ok to send an email with a verification code, store the code in the database and then check if the code is correct?
Or is it better to create some static bean which would hold the code for a while and then check if it's correct?
I am not sure which is better in terms of back-end logic.
I appreciate all help.
It's a very common practice to store this in the DB. Just make sure to cleanup the expired tokens once in a while (maybe on timer, maybe when inserting new ones).
You can also store the tokens in an in-memory cache (EhCahe comes to mind) and set the expiration time accordingly, but this way you lose the cache if the application shuts down. Yes, you can make the cache persistent, but why not go the DB route then?
With that said, think about not storing the token anywhere and instead send the link with the email as an URL parameter and a salted hash as an additional parameter. Once the link is clicked, you can check if the hash matches and if it does, the email parameter wasn't tempered with, so you can mark it as validated. Maybe not Pentagon-level secure, but probably enough for email validation and makes everything easier.
In pseudo-code:
public String hash(String email) {
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(email.getBytes(StandardCharsets.UTF_8)));
digester.update("RanDOmComplCatEdSalt647826583745".getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(digester.digest());
}
String email = "dude#example.com";
sendEmailWithLink("/verify?email=" + email + "&hash=" + hash(email));
On the way in, you just do the exact same thing to calculate and check if the hash matched:
String email = httpRequest.getParameter("email");
String receivedHash = httpRequest.getParameter("hash");
if (hash(email).equals(receivedHash)) {
//the user didn't do anything funny, mark email as valid
}
Or, taking this idea further but with more security, you can generate something like a JWT that contains the email and is properly encrypted.
Related
I am obtaining a kerberos ticket with the following code:
String client = "com.sun.security.jgss.krb5.initiate";
LoginContext lc = new LoginContext(client, new CallbackHandler() {
#Override
public void handle(Callback[] arg0) throws IOException, UnsupportedCallbackException {
System.out.println("CB: " + arg0);
}
});
lc.login();
System.out.println("SUBJ: " + lc.getSubject());
This code works fine, I get a subject that shows my user ID. The problem I'm having is now I need to know whether the user belongs to a certain group in AD. Is there a way to do this from here?
I've seen code to get user groups using LDAP but it requires logging in with a user/password, I need to do it the SSO way.
You cannot actually do this with the kind of ticket you get at login. The problem is that the Windows PAC (which contains the group membership information) is in the encrypted part of the ticket. Only the domain controller knows how to decrypt that initial ticket.
It is possible to do with a service ticket.
So, you could set up a keytab, use jgss to authenticate to yourself and then decrypt the ticket, find the PAC, decode the PAC and then process the SIDs. I wasn't able to find code for most of that in Java, although it is available in C. Take a look at this for how to decrypt the ticket.
Now, at this point you're talking about writing or finding an NDR decoder, reading all the specs about how the PAC and sids are put together, or porting the C code to Java.
My recommendation would be to take a different approach.
Instead, use Kerberos to sign into LDAP. Find an LDAP library that supports Java SASL and you should be able to use a Kerberos ticket to log in.
If your application wants to know the groups the user belongs to in order to populate menus and stuff like that, you can just log in as the user.
However, if you're going to decide what access the user has, don't log in as the user to gain access to LDAP. The problem is that with Kerberos, an attacker can cooperate with the user to impersonate the entire infrastructure to your application unless you confirm that your ticket comes from the infrastructure.
That is, because the user knows their password, and because that's the only secret your application knows about, the user can cooperate with someone to pretend to be the LDAP server and claim to have any access they want.
Instead, your application should have its own account to use when accessing LDAP. If you do that, you can just look up the group list.
I do realize this is all kind of complex.
I have this registration page which works fine ,but for the email field I need to make sure that the email is correct and valid
1 : Correct
2 : Valid
for the correct email add i am using java script validation for maintaining
abc#def.com
well that is working fine
but my question is , Is there any web service or java API to make sure whether the mail ID actually is existing and registered
Like my mail id is : hussainABCD#gmail.com
this is actually a existing ID
but i may try hussain5555#gmail.com,hussain1111#gmail.com,hussain8888#gmail.com,
these will pass the java script validation but are not existing in reality
do we have any way to make sure that the mail id exists ??
The only way to check if an email address actually exists is to send an email to it and let the user respond on that.
For example:
a confirmation code that needs to be filled in your website
a link, going to your website, that needs to be visited
And still it is uncertain whether the email is existing afterwards, as it is easy to simply create a temporary email to pass the validation and delete it afterwards.
Instead of validating email addresses you can use the Google API to let your users sign in using their account. It is also possible to use OpenID on a similar way.
This probably isn't possible using existing services and/or API's, since it could be quite a security risk. Use an email with a validation link if you want to be sure the address exists. Or OpenID, as mentioned by BalusC.
I am Using Google App Engine for Java and I want to be able to share session data between subdomains:
www.myapp.com
user1.myapp.com
user2.myapp.com
The reason I need this is that I need to be able to detect if the user was logged in on www.myapp.com when trying to access user1.myapp.com. I want to do this to give them admin abilities on their own subdomains as well as allow them to seamlessly switch between subdomains without having to login again.
I am willing to share all cookie data between the subdomains and this is possible using Tomcat as seen here: Share session data between 2 subdomains
Is this possible with App Engine in Java?
Update 1
I got a good tip that I could share information using a cookie with the domain set to ".myapp.com". This allows me to set something like the "current_user" to "4" and have access to that on all subdomains. Then my server code can be responsible for checking cookies if the user does not have an active session.
This still doesn't allow me to get access to the original session (which seems like it might not be possible).
My concern now is security. Should I allow a user to be authenticated purely on the fact that the cookie ("current_user" == user_id)? This seems very un-secure and I certainly hope I'm missing something.
Shared cookie is most optimal way for your case. But you cannot use it to share a session on appengine. Except the case when you have a 3rd party service to store sessions, like Redis deployed to Cloud Instances.
You also need to add some authentication to your cookie. In cryptography there is a special thing called Message Authentication Code (MAC), or most usually HMAC.
Basically you need to store user id + hash of this id and a secret key (known to both servers, but not to the user). So each time you could check if user have provided valid id, like:
String cookie = "6168165_4aee8fb290d94bf4ba382dc01873b5a6";
String[] pair = cookie.split('_');
assert pair.length == 2
String id = pair[0];
String sign = pair[1];
assert DigestUtils.md5Hex(id + "_mysecretkey").equals(sign);
Take a look also at TokenBasedRememberMeServices from Spring Security, you can use it as an example.
There is way to detect whether an email id is well-formed or not. Example abcqs#def.com is a well-formed email address, but this may or may not be valid email account.
Case 1 May be the domain doesnot exist (e.g. def.com here).
Case 2 If the domain is valid then may be the id doesnot exist
for the domain (eg abcqs username doesnot exist for def domain).
If it is not valid then if we sent mail, we will get some delivery failure mail, maybe in some hours after sending the email.
I want to implement a similar concept. I want to verify if an email id belongs to a valid account, which will find out whether the account exists or not.
How to achieve it?
I think a better approach is to send an email and verify it the user activates the account.
The user fills in his email
You create a link to be acessed by the user, passing some parameter to him. Example: http://your.domain.com/activate?account=984239048302948203482390
You save the email and all info in your database, with a flag (a field) indicating that it hasn't being activated yet, and the code you sent him
When he clicks the link, you'll receive that parameter in your site, in some program you have wrote. So you'll know that the parameter 984239048302948203482390 has been used
You verify if that code exists in your database and activate the account.
And them he's verified.
You can check your database, every x days, and remove all the old entries, like one that weren't validated more than one week ago.
Unfortunately, you cannot know if it's valid until you actually send the message, as it's the remote server that decides whether or not the address is valid. All your local computer knows how to do is route the message to the appropriate domain for processing.
You could check to see if the domain name resolves if you wanted, but you still wont know if the exact email address exists.
As Nick posted, you can't really know for sure until you send it. However, you CAN check against MX records for the given domain name programmatically: http://stefanp.eu/blog/2009/09/dns-lookup-mx-records-java/ . This solves your case-1
Validating emails has been discussed many, many times on SO. In short there is NO WAY to know whether an email address/inbox actually exists. Some servers may helpfully bounce an email addressed to a non-existent inbox, but many/most will not.
Additionally regex validating of an email format is also pretty much a lost cause. It is is trade off between maximising coverage and minimising false positives. Plus of course there are genuine addresses that do not adhere to the various RFCs. So my advice is to do a simple sanity check: check for the existence of the "#" character.
If you want to validate a sign-up, include a link in the email that contains the user id and some random auth code. The user clicks this to authenticate his account. If he's given a bogus address he wont get the email, and his account will not be validated.
When you want to veryfy an email address, create a unique number and store it in a database against the email address. Then send an email to the address with a link back to your website. The link should have the unique number as a parameter. The email should say something like;
Click here to verify your email address.
Once your website receives a hit on the link with the given unique number, you know that the email address is real.
(Voted up several of the other answers - agree that user email verification is probably best - but wanted to also contribute this simplistic version of DNS validation that Henri described. The link he posted requires another library, but you can do at least basic checks without it.)
Here's the basic domain check:
public boolean isValidDomain(String domainName)
{
try
{
InetAddress.getByName(domainName);
return true;
}
catch (UnknownHostException e)
{
return false;
}
}
And here's the basic DNS MX record check:
public boolean isValidEmailDomain(String domainName)
{
try
{
DirContext ictx = new InitialDirContext();
Attributes attrs = ictx.getAttributes("dns://" + dnsServer + "/" + domainName,
new String[] { "MX" });
Attribute attr = attrs.get("MX");
return (attr != null);
}
catch (NamingException e)
{
return false;
}
}
Where dnsServer does not have to be used in some environments, but will have to be in others. You may need to experiment there.
(All classes referenced are in java.net or javax.naming.)
My application is a Eclipse Rich Client and I would like to add authentication and authorization features to. My Users and roles are stored in a database and my application also has a web based admin console which lets me manage users and roles. I am leveraging Spring security on this admin console.
So here's my requirement:
I would like my thick client to provide users with a login dialog box. The authentication would need to be performed on the server side (it could be a webservice) and the roles have to flow in to the thick client. I would also like to manage sessions on the server side, somehow.
I really can't think of any easy way to doing this. I know that if I were to use Spring Rich Client, it would integrate pretty well with Spring Security on the server side.
But, that is not an option for me at this point.
Please share your thoughts on how to acheive this. Appreciate your help.
Since you're leaning toward web services (it sounds like you are) I'd think about taking the user information from your rich client (I assume user ID and password), using WS-Security to send the encrypted info to a web service, and having the web service do the auth stuff. Also I'd think about the web service returning any info that you want to go back to the rich client about the user (first/last name, etc).
I developed a similar application recently using the Challenge-Response-authentication. Basically you have three methods in your webservice or on your server
getChallenge(username) : challenge
getSession(username, response) : key
getData(username, action?) : data
getChallenge returns a value (some random value or a timestamp for instance) that the client hashes with his/hers password and sends back to getSession. The server stores the username and the challenge in a map for instance.
In getSession the server calculates the same hash and compares against the response from the client. If correct, a session key is generated, stored, and sent to the client encrypted with the users password. Now every call to getData could encrypt the data with the session key, and since the client is already validated in getSession, s/he doesn't have to "login" again.
The good thing about this is that the password is never sent in plain text, and if someone is listening, since the password is hashed with a random value, the call to getSession will be hard to fake (by replaying a call for instance). Since the key from getSession is sent encrypted with the users password, a perpetrator would have to know the password to decipher it. And last, you only have to validate a user once, since the call to getData would encipher the data with the users session key and then wouldn't have to "care" anymore.
I've a similar requirement I think. In our case:
user provides username and password at login
check this against a USER table (password not in plain text btw)
if valid, we want a session to last, say, 20 minutes; we don't want to check username and password every time the thick client does a retrieve-data or store-data (we could do that, and in fact it wouldn't be the end of the world, but it's an extra DB op that's unnecessary)
In our case we have many privileges to consider, not just a boolean "has or has not got access". What I am thinking of doing is generating a globally unique session token/key (e.g. a java.util.UUID) that the thick client retains in a local ThickClientSession object of some sort.
Every time the thick client initiates an operation, e.g. calls getLatestDataFromServer(), this session key gets passed to the server.
The app server (e.g. a Java webapp running under Tomcat) is essentially stateless, except for the record of this session key. If I log in at 10am, then the app server records the session key as being valid until 10:20am. If I request data at 10:05am, the session key validity extends to 10:25am. The various privilege levels accompanying the session are held in state as well. This could be done via a simple Map collection keyed on the UUID.
As to how to make these calls: I recommend Spring HTTP Invoker. It's great. You don't need a full blown Spring Rich Client infrastructure, it can be very readily integrated into any Java client technology; I'm using Swing to do so for example. This can be combined with SSL for security purposes.
Anyway that's roughly how I plan to tackle it. Hope this is of some use!
Perhaps this will help you out:
http://prajapatinilesh.wordpress.com/2009/01/14/manually-set-php-session-timeout-php-session/
Notice especially this (for forcing garbage collection):
ini_set(’session.gc_maxlifetime’,30);
ini_set(’session.gc_probability’,1);
ini_set(’session.gc_divisor’,1);
There is also another variable called session.cookie_lifetime which you may have to alter as well.
IIRC, there are at least 2, possibly more, variables that you have to set. I can't remember for the life of me what they were, but I do remember there was more than 1.