Repository: privacyidea/privacyidea

Issue:
Email Token validation check api don't return valid_until  
When we use the Email token /validation/check api, the result of challenge has not the valid_until attribute.

Email Token response
```
{
    "jsonrpc": "2.0",
    "signature": "23925829983283939...",
    "detail": {
        "multi_challenge": [
            {
                "attributes": {
                    "state": null
                },
                "serial": "be9d623b-a7af-4eb1-8ebd-a74abef839ab",
                "transaction_id": "00100808267047909883"
            }
        ],
        "threadid": 139862418716416,
        "attributes": {
            "state": null
        },
        "message": "Enter the OTP from the Email:",
        "serial": "be9d623b-a7af-4eb1-8ebd-a74abef839ab",
        "transaction_id": "00100808267047909883"
    },
    "versionnumber": "2.21.4",
    "version": "privacyIDEA 2.21.4",
    "result": {
        "status": true,
        "value": false
    },
    "time": 1519308563.715886,
    "id": 1
}
```
SMS Token response
```
{
    "jsonrpc": "2.0",
    "signature": "200341928065452...",
    "detail": {
        "multi_challenge": [
            {
                "attributes": {
                    "valid_until": "2018-02-22 11:26:29.188675",
                    "state": null
                },
                "serial": "dc96fff3-14ee-487c-9278-3f7a687bd99d",
                "transaction_id": "07693633112437876699"
            }
        ],
        "threadid": 139862418716416,
        "attributes": {
            "valid_until": "2018-02-22 11:26:29.188675",
            "state": null
        },
        "message": "Enter the OTP from the SMS:",
        "serial": "dc96fff3-14ee-487c-9278-3f7a687bd99d",
        "transaction_id": "07693633112437876699"
    },
    "versionnumber": "2.21.4",
    "version": "privacyIDEA 2.21.4",
    "result": {
        "status": true,
        "value": false
    },
    "time": 1519308989.307912,
    "id": 1
}
```
Is this a bug or is the behavior expected?

Thank you.



Discussion:
Good question. I do not know anyone who acutally uses this return value...
This is the validity date of the challenge.
Here in the SMS:
https://github.com/privacyidea/privacyidea/blob/master/privacyidea/lib/tokens/smstoken.py#L301

This would be the place in the Email where to modify the ``return_message``:
https://github.com/privacyidea/privacyidea/blob/master/privacyidea/lib/tokens/emailtoken.py#L264
The ``validity`` is however available.
https://github.com/privacyidea/privacyidea/blob/master/privacyidea/lib/tokens/emailtoken.py#L241

Just to clarify, both tokens behave as expected, that the challange is valid for a certain time.
Only difference is, that the SMS token passes this information to the calling client.
But acutally no calling client I know uses this information ;-)



I use this information, I need to inform the user the otp time validity, I created a patch to print this attribute on the email token too.

emailtoken.py

```
@log_with(log)
 def create_challenge(self, transactionid=None, options=None):
...
   expiry_date = datetime.datetime.now() + \
                                    datetime.timedelta(seconds=validity)
   attributes['valid_until'] = "{0!s}".format(expiry_date)
   return success, return_message, transactionid, attributes
```

Do you think is important to put it on the privacyidea?

Thank you



Perfect. If you need this I am happy to receive your pull request. 

After all, you spotted this inconsitancy, you fixed it, so I am happy to have you add the code and get the credits! 

Resolving patch:
diff --git a/privacyidea/lib/tokens/emailtoken.py b/privacyidea/lib/tokens/emailtoken.py
--- a/privacyidea/lib/tokens/emailtoken.py
+++ b/privacyidea/lib/tokens/emailtoken.py
@@ -62,6 +62,7 @@
 
 import logging
 import traceback
+import datetime
 from privacyidea.lib.tokens.smstoken import HotpTokenClass
 from privacyidea.lib.config import get_from_config
 from privacyidea.api.lib.utils import getParam
@@ -225,6 +226,7 @@ def create_challenge(self, transactionid=None, options=None):
         options = options or {}
         return_message = "Enter the OTP from the Email:"
         attributes = {'state': transactionid}
+        validity = int(get_from_config("email.validtime", 120))
 
         if self.is_active() is True:
             counter = self.get_otp_count()
@@ -238,7 +240,6 @@ def create_challenge(self, transactionid=None, options=None):
                 subject_template, _ = self._get_email_text_or_subject(options,
                                                                    EMAILACTION.EMAILSUBJECT,
                                                                    "Your OTP")
-                validity = int(get_from_config("email.validtime", 120))
 
                 # Create the challenge in the database
                 db_challenge = Challenge(self.token.serial,
@@ -261,6 +262,10 @@ def create_challenge(self, transactionid=None, options=None):
                 log.debug(u"{0!s}".format(traceback.format_exc(e)))
                 return_message = info
 
+        expiry_date = datetime.datetime.now() + \
+                                    datetime.timedelta(seconds=validity)
+        attributes['valid_until'] = "{0!s}".format(expiry_date)
+
         return success, return_message, transactionid, attributes
 
     @log_with(log)


Test patch: