Blog | G5 Cyber Security

Secure Invitation Links: Client-Side Generation

TL;DR

No, you can’t create truly secure invitation links client-side only. While you can generate a random token on the client and use it in a URL, this isn’t secure enough for sensitive applications. The server *must* be involved to verify uniqueness, prevent guessing, and associate the link with a user or resource.

Why Client-Side Alone Isn’t Secure

Generating a random string (like a UUID) in JavaScript is easy, but it doesn’t guarantee security. Here’s why:

How to Create Secure Invitation Links (Server-Side Required)

Here’s a step-by-step guide on how to generate secure invitation links, emphasizing the server’s role:

  1. Generate a Unique Token Server-Side: Use a cryptographically secure random number generator on your server.
from flask import Flask, jsonify
import secrets

app = Flask(__name__)

@app.route('/generate-token')
def generate_token():
  token = secrets.token_urlsafe(32) # Generates a 32-character random URL-safe token
  # Store the token in your database associated with the user/resource.
  return jsonify({'token': token})
  • Store the Token: Save the generated token in your database, linked to the relevant user or resource. Include an expiry date for security.
  • Create the Invitation Link: Construct the invitation link using the token.
    • Example: https://yourdomain.com/invite?token=generated_token
  • Verify the Token on Access (Server-Side): When a user clicks the link, your server *must* verify the following:
    • Token Existence: Check if the token exists in the database.
    • Token Validity: Ensure the token hasn’t expired.
    • Token Usage: Prevent reuse of the same token (mark it as used).
  • Redirection/Activation: If the token is valid, redirect the user to the appropriate activation page or grant access.
    • Example (Node.js with Express):
    const express = require('express');
    const app = express();
    
    app.get('/invite', async (req, res) => {
      const token = req.query.token;
      // Check database for token...
      if (isValidToken(token)) {
        res.redirect('/activation?token=' + token);
      } else {
        res.status(400).send('Invalid or expired invitation link.');
      }
    });
    
  • Client-Side Role (Limited)

    The client-side can be used for:

    Important Considerations

    Exit mobile version