Skip to content

Authentication

The Northwestern Laravel Starter provides a flexible, multi-method authentication system designed to handle both Northwestern users (via NetID/SSO) and external collaborators (via passwordless verification codes or Access Tokens).

NetID Single Sign-On

Northwestern SSO (Entra ID or Online Passport)

Primary authentication method for Northwestern users via NetID.

  • Entra ID (OAuth2) or Online Passport (cookie-based)
  • Multi-factor authentication support
  • Automatic user provisioning
  • Session-based authentication

Passwordless Verification Codes

Email OTP Authentication

Email-based passwordless authentication for external users.

  • No password management
  • Time-limited verification codes
  • Rate limiting protection
  • Invite-only access

Access Tokens

Bearer Token Authentication

Long-lived tokens for programmatic API access.

  • Multiple tokens per user
  • IP allowlisting
  • Token expiration

Northwestern users authenticate via single sign-on using their NetID credentials. The starter supports two SSO providers — Microsoft Entra ID (OAuth2) and Online Passport (agentless WebSSO via ForgeRock) — and auto-detects which one to use based on your configured credentials. See the WebSSO / Entra ID documentation for provider-specific details.

  1. User visits protected route

    User attempts to access a route requiring authentication

  2. Redirect to SSO

    Application redirects to Northwestern’s authentication service

  3. User authenticates

    User enters NetID and password (+ MFA if enabled)

  4. Callback with token

    SSO provider redirects back with authentication token

  5. User provisioning

    Application creates/updates user record from Directory Search data

  6. Session established

    User is logged in and session cookie is set

When a Northwestern user logs in for the first time, the application:

  1. Validates NetID from SSO response
  2. Queries Directory Search API for user demographics
  3. Creates user record with demographic data:
    • Full name
    • Email address
    • Department
    • Affiliations (student, faculty, staff, etc.)
    • etc.

Subsequent logins update the user’s demographic data to keep it synchronized.


External users (non-Northwestern) can access the application via time-limited verification codes sent to their email.

  1. Admin creates local user

    Administrator creates a local user account in the Filament panel

  2. Verification code sent

    Admin triggers a code email or user requests one themselves

  3. User receives email

    Email contains a time-limited verification code (valid for 10 minutes by default)

  4. User enters code

    Code authenticates the user and establishes a session

  5. Code expires

    Code becomes invalid after use or expiration

.env
# Enable/disable local authentication
LOCAL_AUTH_ENABLED=true
# Rate limit for login code requests per email (per hour)
LOCAL_AUTH_RATE_LIMIT_PER_HOUR=10
# Rate limit for login code requests per IP (per hour)
LOCAL_AUTH_RATE_LIMIT_PER_IP_PER_HOUR=20
# Where to redirect after successful login
LOCAL_AUTH_REDIRECT_AFTER_LOGIN=/
# Use a fixed, predictable verification code instead of random codes
LOCAL_AUTH_USE_FIXED_CODE=false
  1. Navigate to Users
  2. Click ActionsCreate Local User
  3. Enter user details (name, email, etc.)
  4. Create the user

Time-Limited Codes

Codes automatically expire after configured duration (default: 10 minutes)

Single-Use Codes

Each code can only be used once, preventing replay attacks

Rate Limiting

Limits login code requests to prevent abuse and enumeration attacks

Timing Attack Protection

Consistent response times prevent user enumeration via timing analysis


API users authenticate using long-lived Bearer tokens for programmatic access.

  1. Admin creates API user

    Administrator creates an API user and generates first token

  2. Token delivered once

    Plain-text token shown only at creation (never retrievable again)

  3. Client stores token

    Client securely stores token for API requests

  4. Token in requests

    Client includes token in Authorization: Bearer header

  5. Middleware validates

    AuthenticatesAccessTokens middleware validates token and IP allowlist

  6. Request logged

    API request logged with metrics and analytics

See the API Documentation for complete Access Token management details.


Every login creates a UserLoginRecord with a segment — a classification of the user at that moment. Segments are used by the login analytics dashboard (charts, stats, filters) and are captured at login time so historical metrics remain accurate even if user roles change later.

SegmentClassificationColor
Super AdminUser has the ManageAll permissionDanger (red)
External UserUser authenticates via local/passwordless authWarning (amber)
OtherEveryone else (default)Gray

All charts, filters, exports, and stats dynamically pull from the UserSegment. Adding a new case automatically appears everywhere.

  1. Add a case to the enum

    app/Domains/User/Enums/UserSegment.php
    case SuperAdmin = 'super-admin';
    case ExternalUser = 'external-user';
    case Faculty = 'faculty'; // New segment
    case Other = 'other';

    Add a color and icon for the new case in getColor() and getIcon(). The label is auto-generated from the value (e.g., 'faculty'"Faculty").

  2. Add classification logic

    In DetermineUserSegment, add a check above the default case:

    app/Domains/User/Actions/DetermineUserSegment.php
    return match (true) {
    $this->isSuperAdmin($user) => UserSegment::SuperAdmin,
    $this->isExternalUser($user) => UserSegment::ExternalUser,
    $this->isFaculty($user) => UserSegment::Faculty,
    default => UserSegment::Other,
    };

    Cases are evaluated top-to-bottom — order matters when a user could match multiple segments.


Authentication endpoints use layered rate limiters to prevent brute force attacks and abuse. Limits are applied per IP and per identifier (email or challenge ID) to balance security with usability.

VariableDefaultDescription
RATE_LIMIT_AUTH_LOGIN_CODE_REQUEST_PER_MINUTE5Code request attempts per minute (per IP)
RATE_LIMIT_AUTH_LOGIN_CODE_REQUEST_PER_EMAIL_PER_MINUTE3Code request attempts per minute (per email)
RATE_LIMIT_AUTH_LOGIN_CODE_VERIFY_PER_MINUTE10Code verification attempts per minute (per IP)
RATE_LIMIT_AUTH_LOGIN_CODE_VERIFY_PER_CHALLENGE_PER_MINUTE5Code verification attempts per minute (per challenge)
VariableDefaultDescription
RATE_LIMIT_AUTH_IMPERSONATE_PER_MINUTE10Impersonation actions per minute

All rate limiters are defined in config/rate-limiting.php.

For information on roles, permissions, and policies after a user is authenticated, see the Authorization documentation.