Skip to main content

Overview

One-time links provide maximum security for sensitive file sharing by becoming permanently inaccessible after a single use. This feature is ideal for sharing confidential documents, temporary passwords, or any content that should only be accessed once. One-time links use a two-flag system to track usage:
  1. Create access link with oneTimeUse: true
  2. First access succeeds and sets used: true
  3. All subsequent access attempts are denied
  4. Link remains in database but becomes permanently inaccessible
The used flag is set after successful access, not during the check. This ensures the first access is always granted.

Data Model

One-time use is controlled by two boolean fields in the Access model (see models/access.go:15-16):
OneTimeUse bool `gorm:"default:false"` // Flag indicating if the link is one-time use
Used       bool `gorm:"default:false"` // Flag indicating if the link has been used
  • OneTimeUse - Enables single-use behavior when set to true
  • Used - Tracks whether the link has been accessed; set to true after first use
1

Prepare your file

Ensure the file you want to share is uploaded and you have its file ID.
2

Enable one-time use

Set oneTimeUse: true in your access creation request.
3

Configure additional restrictions

Optionally add IP restrictions, expiration, or other security measures.
4

Create and share

Generate the link and share it with your intended recipient.

API Examples

curl -X POST https://your-defdrive-instance.com/files/42/access \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Confidential Document",
    "public": true,
    "oneTimeUse": true
  }'

Success Response

{
  "message": "Access created successfully",
  "access": {
    "ID": 19,
    "CreatedAt": "2026-03-04T10:30:00Z",
    "UpdatedAt": "2026-03-04T10:30:00Z",
    "DeletedAt": null,
    "Name": "Confidential Document",
    "Link": "e6f5a1d2b4c789023defbc45678901ab",
    "Subnets": [],
    "IPs": [],
    "Expires": "",
    "Public": true,
    "OneTimeUse": true,
    "Used": false,
    "TTL": 0,
    "EnableTTL": false,
    "FileID": 42
  },
  "link": "https://your-defdrive-instance.com/e6f5a1d2b4c789023defbc45678901ab"
}
Notice OneTimeUse: true and Used: false - the link is ready for its single use.

Validation Logic

One-time use is validated in two stages during the access middleware (see middleware/access_restrictions.go:52-55 and 73-80):

Stage 1: Pre-Access Check

func checkOneTimeUse(access models.Access, c *gin.Context) bool {
    if access.OneTimeUse && access.Used {
        c.JSON(http.StatusForbidden, gin.H{"error": "Access link has already been used"})
        c.Abort()
        return false
    }
    return true
}
Process:
  1. Check if OneTimeUse is true AND Used is true
  2. If both true, deny access (link already used)
  3. If Used is false, allow access to proceed

Stage 2: Post-Access Marking

if access.OneTimeUse {
    access.Used = true
    db.Save(&access)
}
Process:
  1. After all checks pass and access is granted
  2. If OneTimeUse is true, set Used to true
  3. Save the updated access record to database
  4. All future attempts will fail the pre-access check
The used flag is set immediately after the first successful access check, even before the file download completes. If the download is interrupted, the link is still marked as used.

Lifecycle Example

Let’s trace a one-time link through its complete lifecycle:
1

Initial Creation

{
  "OneTimeUse": true,
  "Used": false
}
Link is created and ready for its single use.
2

First Access Attempt

User clicks the link for the first time.Pre-access check:
  • OneTimeUse: true
  • Used: false
  • Check passes, access granted
Post-access:
{
  "OneTimeUse": true,
  "Used": true
}
Flag is immediately set to Used: true.
3

Second Access Attempt

Same or different user tries to access the link.Pre-access check:
  • OneTimeUse: true
  • Used: true
  • Check fails, access denied
Error:
{
  "error": "Access link has already been used"
}
4

All Future Attempts

{
  "OneTimeUse": true,
  "Used": true
}
Link remains permanently disabled. All attempts fail.

Error Response

When attempting to access a used one-time link:
{
  "error": "Access link has already been used"
}
HTTP Status: 403 Forbidden This error is permanent - once a one-time link is used, it cannot be reset through normal access.
To restore access, you must update the access record through the API (see “Resetting Used Links” below), or create a new access link.
You can check if a one-time link has been used:
curl -X GET https://your-defdrive-instance.com/access/19 \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN"
Response (unused):
{
  "access": {
    "ID": 19,
    "Name": "Confidential Document",
    "Link": "e6f5a1d2b4c789023defbc45678901ab",
    "OneTimeUse": true,
    "Used": false,
    "Public": true,
    "FileID": 42
  }
}
Response (used):
{
  "access": {
    "ID": 19,
    "Name": "Confidential Document",
    "Link": "e6f5a1d2b4c789023defbc45678901ab",
    "OneTimeUse": true,
    "Used": true,
    "Public": true,
    "FileID": 42
  }
}
The Used: true field indicates the link has been accessed. If you need to restore a used one-time link (e.g., first access failed to download), you can reset the used flag:
curl -X PUT https://your-defdrive-instance.com/access/19 \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Confidential Document",
    "public": true,
    "oneTimeUse": true
  }'
Updating an access record through the API does not automatically reset the used flag. The flag persists unless the access record is deleted and recreated.
To fully reset, delete and create a new access:
curl -X DELETE https://your-defdrive-instance.com/access/19 \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN"

Combining with Other Restrictions

One-time links can be layered with other access controls for enhanced security:

One-Time + Expiration

{
  "oneTimeUse": true,
  "expires": "2026-03-05T23:59:59Z"
}
Behavior:
  • Link expires after first use, OR
  • Link expires on date (whichever comes first)
This ensures the link can’t remain unused indefinitely. If recipient doesn’t access within the timeframe, the link becomes inaccessible.

One-Time + IP Restrictions

{
  "oneTimeUse": true,
  "ips": ["203.0.113.45"],
  "subnets": ["192.168.1.0/24"]
}
Behavior:
  • Access only from allowed IPs/subnets, AND
  • Only once from any of those addresses
{
  "oneTimeUse": true,
  "enableTTL": true,
  "ttl": 5
}
Combining oneTimeUse with TTL is redundant. The oneTimeUse flag will cause the link to fail after first use, making the TTL setting irrelevant. Choose one or the other.

One-Time vs TTL

Both limit access, but work differently:
FeatureOne-Time UseTTL
Uses allowed1Configurable (any integer)
ConfigurationoneTimeUse: trueenableTTL: true + ttl: N
Trackingused boolean flagInteger counter
Reset behaviorCannot be reset (must delete)Can be increased
When markedAfter first accessDecrements during access
Best forMaximum security, sensitive filesMulti-use limits, trial access
Implementation Difference:
// One-Time Use: Check then mark
if access.OneTimeUse && access.Used {
    // Deny
}
// ... grant access ...
access.Used = true

// TTL: Decrement then check
if access.EnableTTL && access.TTL > 0 {
    access.TTL--
    if access.TTL == 0 {
        // Deny
    }
}

Use Cases

Password Sharing

Share temporary credentials securely:
{
  "name": "Admin Password",
  "oneTimeUse": true,
  "expires": "2026-03-04T15:00:00Z",
  "ips": ["203.0.113.45"]
}
Recipient can view password once, from specific IP, within 5 hours. Share contracts or NDAs for review:
{
  "name": "NDA for Review",
  "oneTimeUse": true,
  "expires": "2026-03-11T23:59:59Z"
}
Client can access document once within one week.

Secure File Transfers

Exchange sensitive files with partners:
{
  "name": "Q4 Financial Report",
  "oneTimeUse": true,
  "subnets": ["198.51.100.0/24"]
}
Partner can download once from their corporate network.

Audit Logs

Provide one-time access to audit reports:
{
  "name": "Security Audit 2026-Q1",
  "oneTimeUse": true,
  "expires": "2026-03-08T23:59:59Z"
}
Auditor can access report once before deadline.

Access Restrictions Order

The middleware checks restrictions in a specific order (see middleware/access_restrictions.go:44-50):
  1. Subnet Restriction - Verify client IP in allowed subnets
  2. IP Restriction - Verify client IP in allowed IPs
  3. One-Time Use - Check if link already used
  4. TTL - Decrement and check TTL counter
  5. Expiration - Verify current time before expiration
All checks must pass for access to be granted.
if !checkSubnetRestriction(access, c) ||
    !checkIPRestriction(access, c) ||
    !checkOneTimeUse(access, c) ||
    !checkTTL(access, db, c) ||
    !checkExpiration(access, c) {
    return
}

if access.OneTimeUse {
    access.Used = true
    db.Save(&access)
}
If any check fails, subsequent checks are not performed and access is immediately denied.

Best Practices

  1. Use for Sensitive Content - Reserve one-time links for truly confidential information
  2. Add Expiration Dates - Combine with time limits to prevent indefinite unused links
  3. Layer IP Restrictions - Add IP/subnet filters for maximum security
  4. Test Before Sharing - Verify the link works, but remember it will be consumed
  5. Monitor Usage - Check used flag to confirm recipient accessed the file
  6. Create New for Retries - If first access fails, delete and recreate the link
  7. Avoid TTL Combination - Don’t combine with TTL; use one or the other
  8. Document Purpose - Use descriptive names to track why one-time was needed

Security Considerations

Important Security Notes:
  • Once a link is used, the used flag is set immediately, even if download is interrupted
  • If the first access fails (network error, etc.), the link is still marked as used
  • The link hash remains in the database permanently; only the used flag changes
  • Anyone with the link can use it first; there’s no recipient verification
For maximum security, combine one-time links with:
  • IP restrictions - Ensure only specific IP can access
  • Expiration - Limit the window of opportunity
  • Out-of-band communication - Share link via secure channel

Troubleshooting

Possible causes:
  • Link preview bot/crawler accessed the link
  • Accidental click during testing
  • Malicious actor intercepted the link
Solution: Delete and recreate the access link with additional restrictions.

Need to allow second access

One-time links are permanent by design. Solution: Create a new one-time link or a TTL link with ttl: 2.

Monitoring who accessed

DefDrive doesn’t log access timestamps or IPs in the access record. Solution: Check server logs or implement custom logging middleware.

Next Steps

Build docs developers (and LLMs) love