Skip to main content

Magic Links

ConsentKeys uses passwordless authentication via magic links instead of traditional passwords. This approach provides better security and user experience.

A magic link is a secure, time-limited URL sent to a user's email that allows them to authenticate without entering a password. When clicked, it automatically logs the user in.

Example magic link:

https://pseudoidc.consentkeys.com/verify-email?token=eyJhbGciOiJIUzI1NiIs...

Security Benefits

  1. No Password Reuse: Users can't reuse weak passwords across sites
  2. No Password Breaches: No passwords to steal or leak
  3. Phishing Resistant: Links are single-use and time-limited
  4. Email Verification: Proves email ownership automatically

User Experience Benefits

  1. No Password to Remember: Reduces friction for users
  2. Faster Login: One click instead of typing credentials
  3. No Password Reset Flow: Eliminates "forgot password" frustration
  4. Cross-Device Friendly: Easy to authenticate on any device

How It Works

Token Security

Magic link tokens are designed with multiple security layers:

Token Generation

// Pseudocode - internal ConsentKeys implementation
const token = {
email: 'user@example.com',
clientId: 'ck_...',
redirectUri: 'https://...',
state: '...',
nonce: '...',
exp: Date.now() + (15 * 60 * 1000), // 15 minutes
iat: Date.now(),
jti: generateUniqueId(), // Prevents reuse
};

const signedToken = jwt.sign(token, SECRET_KEY);

Token Properties

  • Single-use: Each token can only be used once
  • Time-limited: Expires after 15 minutes
  • Cryptographically signed: Cannot be tampered with
  • Email-bound: Tied to a specific email address
  • Client-bound: Tied to your specific application

Token Validation

When a user clicks the magic link, ConsentKeys validates:

  1. ✅ Token signature is valid
  2. ✅ Token has not expired
  3. ✅ Token has not been used before
  4. ✅ Email matches the token
  5. ✅ Client ID matches the token

If any check fails, the token is rejected.

Implementation

When a user enters their email:

POST /request-magic-link
Content-Type: application/json

{
"email": "user@example.com",
"client_id": "ck_your_client_id",
"redirect_uri": "https://yourapp.com/callback",
"scope": "openid profile email",
"state": "csrf_protection_token",
"nonce": "replay_protection_token"
}

Response:

{
"message": "Magic link sent successfully",
"email": "user@example.com"
}

Email Content

The user receives an email like this:

Subject: Sign in to YourApp

Hello,

Click the button below to sign in to YourApp:

[Sign In to YourApp]

Or copy and paste this link:
https://pseudoidc.consentkeys.com/verify-email?token=...

This link will expire in 15 minutes.

If you didn't request this, you can safely ignore this email.

Verification Process

When the user clicks the link:

GET /verify-email?token=eyJhbGciOiJIUzI1NiIs...

Success Flow:

  1. Token validated → User redirected to consent screen
  2. User approves → Redirect to your app with auth code
  3. Your app exchanges code for tokens

Error Flow:

{
"error": "invalid_token",
"error_description": "The magic link has expired or is invalid."
}

User Experience Patterns

First-Time User

1. User enters email
2. Sees "Check your email" message
3. Opens email client
4. Clicks magic link
5. Sees consent screen
6. Clicks "Allow"
7. Redirected to your app (logged in)

Returning User (Same Device)

1. User enters email
2. Sees account chooser (recognizes device)
3. Clicks their account
4. Redirected to your app (logged in)
(No email needed - session exists!)

Returning User (New Device)

1. User enters email
2. Sees "Check your email" message
3. Clicks magic link
4. Consent screen skipped (already approved)
5. Redirected to your app (logged in)

Rate Limiting

To prevent abuse, magic link requests are rate-limited:

  • 20 requests per hour per email address
  • 100 requests per hour per IP address

Exceeding limits returns:

{
"error": "too_many_requests",
"error_description": "Too many magic link requests. Please try again later."
}

Customization

Email Templates

You can customize the magic link email through the Developer Portal:

  • Brand logo: Display your app's logo
  • Brand colors: Match your app's theme
  • Custom text: Add additional context
  • Sender name: Display your app name

Default expiration is 15 minutes. Contact support to adjust this for your use case.

Troubleshooting

Cause: User waited more than 15 minutes to click the link

Solution: Request a new magic link

Cause: Token was already consumed (clicked twice)

Solution: Request a new magic link

"Email not received"

Possible causes:

  1. Email in spam folder
  2. Incorrect email address
  3. Rate limit exceeded

Solutions:

  1. Check spam folder
  2. Verify email address spelling
  3. Wait before requesting again

"Invalid token"

Possible causes:

  1. Token was tampered with
  2. Email client modified the URL
  3. Token signature invalid

Solution: Request a new magic link

Best Practices

1. Show Clear Instructions

function LoginSuccess() {
return (
<div>
<h2>Check your email</h2>
<p>
We sent a magic link to <strong>{email}</strong>
</p>
<p>Click the link in the email to sign in.</p>
<p>
Didn't receive it? Check your spam folder or{' '}
<button onClick={resendMagicLink}>request a new link</button>
</p>
</div>
);
}

2. Handle Expired Tokens Gracefully

function TokenExpired() {
return (
<div>
<h2>Link Expired</h2>
<p>This magic link has expired for security reasons.</p>
<button onClick={() => window.location.href = '/login'}>
Request a new link
</button>
</div>
);
}

3. Support Deep Linking

Preserve the user's intended destination:

// Before redirecting to login
sessionStorage.setItem('return_to', window.location.pathname);

// After authentication
const returnTo = sessionStorage.getItem('return_to') || '/dashboard';
window.location.href = returnTo;

4. Mobile App Considerations

For mobile apps, use deep links to return to the app:

redirect_uri=myapp://auth/callback

Security Considerations

Email Account Security

Since authentication is email-based, email account security is critical:

  1. Encourage 2FA: Remind users to enable 2FA on their email
  2. Detect Suspicious Activity: Monitor for unusual login patterns
  3. Session Management: Implement appropriate session timeouts

Magic links in emails are vulnerable to:

  1. Email forwarding: Users might forward the email
  2. Email backups: Links might be stored in backups
  3. Email client previews: Some clients preview links

Mitigations:

  • Short expiration times (15 minutes)
  • Single-use tokens
  • IP address validation (optional)

Next Steps