4D Blog

Home Product Generate, share and use web sessions One-Time Passcodes (OTP)

Generate, share and use web sessions One-Time Passcodes (OTP)

June 16, 2025

Product

Today, web applications have become integral to our lives, offering convenient features that save time and simplify everyday tasks. As an example, creating accounts on various platforms is one the most frequent user action on web sites.

They expect this kind of process to be quick and accessible—whether at home, commuting, or relaxing on the beach.

Behind this simplicity lies a more complex reality. These operations often require integration with third-party systems, such as email verification services. This introduces challenges related to security, user experience continuity, and protecting against man-in-the-middle attacks.

For developers, ensuring a smooth experience means managing interactions between external systems and the 4D web session. This involves maintaining the user’s context—retrieving data, privileges, and the exact step of their journey to complete the process.

Sounds complicated? It doesn’t have to be! Discover how to build robust web applications that securely and efficiently communicate with third-party systems with 4D 20 R9.

HDI_Session_Token

Before going into details, watch this video. It will help you running the attached HDI.

Often, on web applications, the user experience requires several steps like:

When handling warehouse inventories of products:

  • make a selection of products
  • send the selection to an external registering system
  • get back on the products list in the app

or

When creating an account on a website:

  • enter the email + password to create the account
  • validate the email by clicking on a link received in an email to finalize the account creation

     

    Those steps require going back and forth with third-party systems. Thus, a 4D web session must be uniquely identified on the server to be retrieved later.

     

    THE createOTP() FUNCTION ON THE SESSION OBJECT

    The identifier of a 4D web session is the session cookie (“4DSID_AppName“). Exchanging this cookie value on the network between a 4D web application and a third-party system is a clumsy security breach.

    To avoid that, in any web process, a One-Time-Passcode (OTP) can be generated thanks to the new createOTP() function available on the Session object.

    This OTP is linked to this session and allows retrieval in a received request, which is not given the session cookie.

    This OTP can be used once only and can be associated with a lifespan.

    example

    var $token : Text
    
    $token:=Session.createOTP()

    How do I retrieve a web session thanks to the OTP?

    The web session can be retrieved in two ways.

     

    the $4DSID parameter in a URL

    The web session will be automatically retrieved if the received request contains in the $4DSID parameter a valid OTP corresponding to the session.

    example

    In this example, a user account is created in the Users dataclass with the create() function.

    An $info object is received with the email + password. A new user is created, and some information is stored in the session, especially the current step of the user account creation process (Waiting for validation email) and the user ID.

    An OTP corresponding to the current session is generated. Finally, an URL is returned with this OTP given in the $4DSID parameter.

    // In the Users dataclass
    Function create($info : Object) : Text
    	
    var $user : cs.UsersEntity
    var $status : Object
    var $token : Text
    	
    //A new entity of the Users dataclass is created
    $user:=This.new()
    $user.fromObject($info)
    $status:=$user.save()
    	
    Use (Session.storage)
    	Session.storage.status:=New shared object("step"; "Waiting for validation email"; "email"; $user.email; "ID"; $user.ID)
    End use 
    	
    $token:=Session.createOTP()
    	
    return "https://my4DApp/validateEmail?$4DSID="+$token

    Afterward, the user is sent this URL as a link in an email. The URL prefix /validateEmail is handled by the HTTP request handlers (HTTPHandlers.json file).

    [
      {
        "class": "RequestHandler",
        "method": "validateEmail",
        "regexPattern": "/validateEmail",
        "verbs": "get"
      }
    ]

    Here is the validateEmail() function of the RequestHandler singleton.

    Function validateEmail() : 4D.OutgoingMessage
    	
    var $result:=4D.OutgoingMessage.new()
    var $user : cs.UsersEntity
    var $status : Object
    	
    If (Session.storage.status.step="Waiting for validation email")
    		
    	$user:=ds.Users.get(Session.storage.status.ID)
    	$user.validated:=True
    	$status:=$user.save()
    		
    	$result.setBody("Congratulations <br>"\
    	+"Your email "+Session.storage.status.email+" has been validated")
    	$result.setHeader("Content-Type"; "text/html")
    		
    	Use (Session.storage.status)
    		Session.storage.status.step:="Email validated"
    	End use 
    Else 
            // Retrieving the session with the OTP failed
    	$result.setBody("Validation failed")
    End if 
    	
    return $result

    Because the $4DSID parameter contains a valid OTP corresponding to the original session, the Session object refers to the session that created the OTP

    Here is the result in a browser:

    THE restore() FUNCTION ON THE SESSION OBJECT

    Usually, a callback mechanism is applied when a third-party system is involved. The principle is:

    • send a request to the third-party system and pass a callback URL 
    • after processing the request, the third-party system calls the callback URL

     

    Sometimes, third-party systems do not allow callback URLs to contain custom parameters like $4DSID.

    However, they allow client information (e.g. a state) to be sent, and the third-party system returns this information to the caller. This is a way to be called back with a 4D web session OTP.

    Check the documentation of the third-party system API to find the parameter name in question. The example below will use the state parameter.

    A restore() function is available on the Session object and allows the retrieval of the session corresponding to a given OTP.

    In the example below, the OTP is put in the reserved state parameter instead of being added in the URL as a $4DSID parameter.

    example

    On a 4D web application, a warehouse employee selects products to make an inventory and sends them to an external system for registring. Here is the sendProducts() function called:

    exposed Function sendProducts($chosenProducts : cs.ProductsSelection) : Text
    	
    var $token; $callBackURL; $callExternalAppURL; $result : Text
    var $request : Object
    	
    //The chosen products are put in the session
    Use (Session.storage)
    	Session.storage.info:=New shared object("inventoryStatus"; "Calling registring app")
    	Session.storage.chosenProducts:=$chosenProducts
    End use 
    	
    // $token is C318C81651F84F238EE72C14B46A45C3 (example)
    $token:=Session.createOTP()
    	
    //Build the callback URL - Put the OTP in the state parameter
    $callBackURL:="https://my4DApp/callBack?state="+$token
    	
    // Call the external registring system - Put the callback URL in the redirect parameter
    $callExternalAppURL:="https://acme.com/callRegistringApp?redirect="+$callBackURL
    $requestObj:={method: HTTP POST method}
    $request:=4D.HTTPRequest.new($callExternalAppURL; $requestObj).wait()
    	
    // The external registring system made the call back. This call back retrieved and updated the Session
    // So now the inventoryStatus attribute is up to date
    If (Position("Products registered"; Session.storage.info.inventoryStatus)#0)
    	$result:=Session.storage.info.inventoryStatus
    Else 
    	$result:="Registering failed"
    End if 
    	
    return $result

    The chosen products are put in the session, and an OTP is generated.

    The third-party system is called. The redirect parameter indicates the callback URL. This URL contains the state parameter, which is the session OTP.

    In the example above, the third-party system URL is:

    https://acme.com/callRegistringApp?redirect=https://my4DApp/callBack?state=C318C81651F84F238EE72C14B46A45C3

    The URL prefix /callBack is handled by the HTTP request handlers (HTTPHandlers.json file) in the 4D web app.

    [
      {
        "class": "RequestHandler",
        "method": "handleCallBack",
        "regexPattern": "/callBack",
        "verbs": "post"
      }
    ]

    Here is the handleCallback() function of the RequestHandler singleton:

    Function handleCallBack($request : 4D.IncomingMessage)
    	
    //Get the state parameter in the URL
    $otp:=$request.urlQuery.state
    	
    //Restore the session thanks to the OTP
    $restore:=Session.restore($otp)
    	
    //Restoring the session is successful
    If ($restore=True)
    	//Get the body of the request (information sent by the third party system) - It contains "Products registered"
    	$text:=$request.getText()
    		
    	//Update the session with the registring result
    	If ($text#Null)
    		Use (Session.storage.info)
    			Session.storage.info.inventoryStatus:=$text
    			If (Session.storage.chosenProducts#Null)
    				Session.storage.info.inventoryStatus+=" total price: "+String(Session.storage.chosenProducts.sum("price"))
    			End if 
    		End use 
    	End if 
    End if 

    About the 4D Client licence consuming

    Only the original session (which generates the OTP) consumes a 4D Client licence. Restoring a session (for example with a validation email link) does not consume any additional 4D Client licence.

    Download the attached HDI to run those examples live and check the documentation to learn more.

    Discuss

    Tags 20 R9, 21, HTTP, http server, http session, otp, restore session, Web, Web session

    Latest related posts

    • May 20, 2025

      Automatic Refresh of OEM Build Licenses

    • May 16, 2025

      New class to handle incoming TCP connections

    • April 29, 2025

      Discover your AI-powered writing assistant in 4D Write Pro

    Avatar
    Marie-Sophie Landrieu-Yvert
    - Product Owner - Marie-Sophie Landrieu-Yvert joined the 4D Product team as a Product Owner in 2017. In this role, she is responsible for writing user stories and translating them into functional specifications. She also ensures that the delivered feature implementation meets the customer's needs. Marie-Sophie graduated from the engineering school ESIGELEC and began her career as an engineer at IBM in 1995. She took part in various projects (maintenance and development projects) and worked as a COBOL developer. She then moved on to work as a UML designer and Java developer. More recently, her main responsibilities included analyzing and writing functional requirements, and coordinating business and development teams.
    • Deutsch
    • Français
    • English
    • Português
    • Čeština
    • Español
    • Italiano
    • 日本語

    Categories

    Browse categories

    • 4D View Pro
    • 4D Write Pro
    • 4D for Mobile
    • Email
    • Development Mode
    • 4D Language
    • ORDA
    • User Interface / GUI
    • Qodly Studio
    • Server
    • Maintenance
    • Deployment
    • 4D Tutorials
    • Generic
    • 4D Summit sessions and other online videos

    Tags

    4D-Analyzer 4D for Android 4D for iOS 4D NetKit 4D Qodly Pro 4D View Pro 4D Write Pro 20 R8 20 R9 Administration Authentication Build application CI/CD Class Client/Server Code editor Collections Compatibility settings Formula Listbox Logs Mail Microsoft 365 Network Objects ORDA PDF Pictures Preemptive Programming Qodly Studio REST Scalability Security Session Source control Speed Spreadsheet Tutorial UI User Experience v20 vscode Web Word processor

    Tags

    4D-Analyzer 4D for Android 4D for iOS 4D NetKit 4D Qodly Pro 4D View Pro 4D Write Pro 20 R8 20 R9 Administration Authentication Build application CI/CD Class Client/Server Code editor Collections Compatibility settings Formula Listbox Logs Mail Microsoft 365 Network Objects ORDA PDF Pictures Preemptive Programming Qodly Studio REST Scalability Security Session Source control Speed Spreadsheet Tutorial UI User Experience v20 vscode Web Word processor
    Subscribe to 4D Newsletter

    © 2025 4D SAS - All rights reserved
    Terms & Conditions | Legal Notices | Data Policy | Cookie Policy | Contact us | Write for us


    Subscribe to 4D Newsletter

    * Your privacy is very important to us. Please click here to view our Policy

    Contact us

    Got a question, suggestion or just want to get in touch with the 4D bloggers? Drop us a line!

    * Your privacy is very important to us. Please click here to view our Policy