Authentication Patterns

Understanding different authentication types: form-based, SSO/SAML, OAuth, certificates, and MFA

Before implementing the MCP server, understand the authentication patterns encountered in academic research. This chapter covers five fundamental patterns and how to recognize them.

Pattern 1: Form-Based Authentication

The simplest and most common pattern: username and password submitted via HTML form.

Technical Flow

Browser loads login page

Navigate to the authentication endpoint and render the login form.

User enters credentials

Fill username and password fields in the HTML form.

Form submits to authentication endpoint

POST request sends credentials to server for validation.

Server validates credentials

Backend checks username and password against user database.

Server sets session cookies

Authenticated session tokens stored in browser cookies.

Browser redirects to authenticated area

User gains access to protected resources.

Automation Strategy

// Playwright automation example
await page.goto('https://university.edu/login');
await page.fill('input[name="username"]', username);
await page.fill('input[name="password"]', password);
await page.click('button[type="submit"]');
await page.waitForNavigation();
// Session cookies now stored in browser context

Common Variations

Challenge: Hidden form field with anti-forgery token.

Solution: Extract token from page and include in submission.

// Extract CSRF token
const csrfToken = await page.getAttribute(
  'input[name="csrf_token"]',
  'value'
);

// Submit with token
await page.fill('input[name="username"]', username);
await page.fill('input[name="password"]', password);
await page.click('button[type="submit"]');

Challenge: Credentials sent via AJAX instead of form POST.

Solution: Wait for network request completion.

// Wait for AJAX request
await Promise.all([
  page.waitForResponse(resp =>
    resp.url().includes('/api/login') && resp.status() === 200
  ),
  page.click('button#login')
]);

Challenge: Username on page 1, password on page 2.

Solution: Handle sequential navigation.

// Step 1: Username
await page.fill('input[name="username"]', username);
await page.click('button:has-text("Next")');
await page.waitForLoadState('networkidle');

// Step 2: Password
await page.fill('input[name="password"]', password);
await page.click('button:has-text("Sign In")');

Challenge: Checkbox may extend session lifetime.

Solution: Enable for longer session persistence.

// Enable "Remember Me"
await page.check('input[name="remember"]');
await page.click('button[type="submit"]');
// Session cookies persist beyond browser close

Detection Tips: Look for <form> elements with action pointing to login endpoints, input fields with type="password", and POST requests containing credentials in the Network tab.

Pattern 2: SSO/SAML Flows

Academic institutions commonly use SAML-based SSO for federated authentication.

Technical Flow

The SAML authentication flow involves multiple redirects between Service Provider (SP) and Identity Provider (IdP):

User visits Service Provider

Access platform like ScienceDirect requiring institutional login.

SP redirects to Identity Provider

Redirect includes SAML request for authentication.

User authenticates at IdP

Log in using university credentials.

IdP generates SAML assertion

Creates signed XML document proving identity.

IdP redirects back to SP

SAML response contains authentication assertion.

SP validates assertion

Verifies signature and creates authenticated session.

Automation Strategy

// Handle SAML redirect flow
await page.goto('https://www.sciencedirect.com/');
await page.click('a:has-text("Institutional Login")');

// Wait for redirect to IdP
await page.waitForURL(/university\.edu\/idp/);

// Authenticate at IdP
await page.fill('#username', username);
await page.fill('#password', password);
await page.click('button[name="submit"]');

// Wait for SAML redirect back to SP
await page.waitForURL(/sciencedirect\.com/);
// Now authenticated

SAML Characteristics

Key indicators of SAML-based authentication:

  • Multiple redirects (SP → IdP → SP)
  • URLs containing SAMLRequest or SAMLResponse parameters
  • IdP URL typically contains /idp/ or /sso/
  • Long base64-encoded XML payloads in URLs

Debugging SAML

Use browser DevTools Network tab to trace redirects:

// Monitor all redirects
page.on('response', response => {
  if (response.status() >= 300 && response.status() < 400) {
    console.log(`Redirect: ${response.url()}`);
    console.log(`Location: ${response.headers()['location']}`);
  }
});

Install SAML-tracer browser extension to decode SAML messages:

Features:

  • Decodes base64-encoded SAML requests/responses
  • Shows XML assertion content
  • Displays signature verification status
  • Timestamps each redirect step

Look for SAMLResponse form fields in POST requests:

// Intercept SAML response
await page.route('**/*', async (route, request) => {
  const postData = request.postData();
  if (postData?.includes('SAMLResponse')) {
    console.log('SAML Response detected');
    // Decode base64 to inspect XML
  }
  await route.continue();
});

Check for assertion validation errors in SP logs:

Common errors:

  • Signature verification failed
  • Assertion expired
  • Invalid recipient URL
  • Missing required attributes

Pattern 3: OAuth 2.0 / OpenID Connect

Modern platforms increasingly use OAuth 2.0 and OIDC for authentication.

Technical Flow (Authorization Code Flow)

User clicks "Login with University"

Initiates OAuth authorization flow.

Redirects to OAuth authorization endpoint

Application requests specific scopes (permissions).

User authenticates and consents

Login at provider and approve requested permissions.

Redirects back with authorization code

Temporary code included in callback URL.

App exchanges code for access token

Backend exchanges code for JWT access token.

App uses access token for API requests

Token included in Authorization header for authenticated requests.

Automation Strategy

// OAuth flow automation
const authUrl = 'https://provider.com/oauth/authorize?' +
  'client_id=xyz&redirect_uri=https://app.com/callback&' +
  'response_type=code&scope=openid profile';

await page.goto(authUrl);

// Handle IdP login page
await page.fill('#email', email);
await page.fill('#password', password);
await page.click('#submit');

// Wait for consent page (may be skipped if previously granted)
if (await page.isVisible('button:has-text("Allow")')) {
  await page.click('button:has-text("Allow")');
}

// Wait for redirect to callback URL
await page.waitForURL(/app\.com\/callback/);

// Extract authorization code from URL
const url = new URL(page.url());
const code = url.searchParams.get('code');

// Exchange code for token (app handles this)

OAuth Characteristics

Key indicators of OAuth-based authentication:

  • Query parameters like client_id, redirect_uri, code
  • Consent screens showing requested permissions
  • Tokens typically JWT format (base64-encoded JSON)
  • Refresh tokens allow long-lived access

Token Management

Security Best Practices: Store access tokens securely, implement refresh logic before expiration, handle token revocation gracefully, and never expose tokens in logs or URLs.

// Token refresh pattern
async function getValidToken() {
  if (isTokenExpired(accessToken)) {
    // Refresh token before expiration
    const response = await fetch('https://provider.com/oauth/token', {
      method: 'POST',
      body: JSON.stringify({
        grant_type: 'refresh_token',
        refresh_token: refreshToken,
        client_id: clientId,
        client_secret: clientSecret
      })
    });

    const data = await response.json();
    accessToken = data.access_token;
    refreshToken = data.refresh_token;
  }

  return accessToken;
}

Pattern 4: Certificate-Based Authentication

Some institutional resources use client certificates for authentication.

Technical Flow

Server requests client certificate

During TLS handshake, server asks for client certificate.

Browser presents certificate

Retrieves certificate from user's certificate store.

Server validates certificate

Checks certificate against trusted Certificate Authorities.

Connection established with mTLS

Mutual TLS provides two-way authentication.

Automation Strategy

// Launch browser with client certificate
const context = await browser.newContext({
  clientCertificates: [{
    origin: 'https://secure-library.edu',
    certPath: '/path/to/client-cert.pem',
    keyPath: '/path/to/client-key.pem',
  }]
});

const page = await context.newPage();
await page.goto('https://secure-library.edu');
// Certificate automatically presented

Certificate Characteristics

Key indicators of certificate-based authentication:

  • Browser shows certificate selection dialog
  • URLs often use https:// with specific domain requirements
  • No traditional username/password form
  • Certificate errors if cert invalid or not trusted

Security Considerations: Private keys must be kept secure. Certificates have expiration dates (monitor and renew). Revoked certificates must be removed. Never share private keys.

Pattern 5: Multi-Factor Authentication (MFA)

MFA adds a second verification factor beyond passwords.

Common MFA Types

SMS/Email Codes

One-time codes sent to registered contact method.

Authenticator Apps

TOTP codes from Google Authenticator, Authy, etc.

Push Notifications

Approve login from mobile app notification.

Hardware Tokens

Physical devices like YubiKey.

Biometrics

Fingerprint or face recognition.

Automation Strategies

Best for automation: TOTP codes can be generated programmatically.

import speakeasy from 'speakeasy';

// Generate TOTP code from stored secret
const token = speakeasy.totp({
  secret: process.env.TOTP_SECRET,
  encoding: 'base32'
});

// Enter code in MFA form
await page.fill('input[name="code"]', token);
await page.click('button[type="submit"]');

Human-in-the-loop required: Wait for user approval.

// Trigger MFA prompt
await page.click('button:has-text("Send Push")');

// Wait for user to approve on device
console.log('Approve the push notification on your device...');
await page.waitForNavigation({ timeout: 60000 });

Interactive input: Prompt user to enter received code.

// Trigger SMS
await page.click('button:has-text("Send SMS")');

// Prompt user to enter code
const readline = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});

const code = await new Promise(resolve => {
  readline.question('Enter SMS code: ', resolve);
});

await page.fill('input[name="sms_code"]', code);
await page.click('button[type="submit"]');
readline.close();

MFA Best Practices

Recommended Approach: Prefer TOTP over SMS (more secure and automatable). Store TOTP secrets in secure credential store. Implement "Remember This Device" when available. Have fallback for MFA failures. Log MFA events for security audit.

Pattern Recognition in the Wild

When encountering a new authentication system, follow this systematic approach:

Open DevTools Network Tab

Watch for authentication requests and responses.

Identify Redirects

Trace the authentication flow through redirect chain.

Check for Known Patterns

Look for indicators of SAML, OAuth, form POST, or certificates.

Inspect Cookies

Note which cookies are set after successful authentication.

Test Session Persistence

Close and reopen browser with cookies to verify session lifetime.

Document the Flow

Create step-by-step manual procedure for reference.

Tools for Analysis

Browser DevTools (Network, Application tabs)

  • Monitor all HTTP requests and responses
  • Inspect cookies, localStorage, sessionStorage
  • View redirect chains
  • Examine request/response headers

SAML-tracer extension

  • Decodes SAML messages
  • Shows XML assertion content
  • Displays signature verification
  • Tracks redirect flow

Fiddler or Charles Proxy

  • Intercept and inspect HTTPS traffic
  • Modify requests on-the-fly
  • Replay authentication flows
  • Export HAR files for analysis

curl with --cookie-jar flag

# Save cookies from login
curl -c cookies.txt -X POST https://university.edu/login \
  -d "username=user&password=pass"

# Use cookies for authenticated request
curl -b cookies.txt https://university.edu/protected

Playwright trace viewer

// Record trace
await context.tracing.start({ screenshots: true, snapshots: true });
// Perform authentication
await context.tracing.stop({ path: 'trace.zip' });

View trace: npx playwright show-trace trace.zip


Next Chapter: MCP Server Implementation - Build the authentication bypass server using these patterns.