Loopwise Docs
Concepts

OAuth Overview

How OAuth 2.0 works in the Loopwise platform and why it matters for integrations.

Loopwise uses OAuth 2.0 to allow third-party applications to access school data on behalf of users. This page explains the key concepts.

Why OAuth?

OAuth lets users grant limited access to their Loopwise data without sharing their password. An integration (the "client") receives an access token with specific scopes that define exactly what it can do.

Benefits:

  • Security — users never share their credentials with third-party apps
  • Granular access — scopes limit what data an integration can access
  • Revocable — users or admins can revoke access at any time without changing passwords
  • Auditable — each integration has its own identity, making it easy to track who accessed what

Architecture

Each school operates as an independent OAuth provider. When you create an OAuth application in a school's admin panel, it is scoped exclusively to that school.

The token issued by School A can only access School A's data. There is no cross-school access.

Key concepts

Authorization server

Each school acts as its own OAuth authorization server. It authenticates users, presents the consent screen, issues authorization codes, and exchanges them for access tokens.

A school's OAuth endpoints are accessible at https://{school-domain} (e.g., https://demo.teachify.tw). Each school's frontend application proxies OAuth requests to the centralized OAuth backend at connect.loopwise.com.

Client application

The third-party integration that wants to access a school's data. Clients are identified by a client_id and optionally a client_secret (for confidential clients). Each client is registered within a specific school and can only access that school's resources.

Resource owner

The user (typically a school admin) who authorizes the client to access data. The authorization grants access to the school where the OAuth application was registered.

Access token

A short-lived credential (2 hours) that the client uses to make API requests. Tokens are scoped to the school where the OAuth application was created, along with a set of permissions.

Refresh token

A long-lived credential used to obtain new access tokens without requiring the user to re-authorize.

Supported flows

Loopwise supports the Authorization Code flow with PKCE (Proof Key for Code Exchange, RFC 7636). This is the recommended flow for all clients, including public clients (SPAs, native apps, CLI tools).

For a detailed walkthrough of the flow, see Authorization Code Flow.

School scoping

Each OAuth application belongs to exactly one school. When an admin creates an OAuth application in their school's settings, the application is permanently bound to that school:

  • The issued client_id only works with that school's authorization endpoint
  • All tokens carry the school's school_id and are validated against it
  • The token response includes school_id and school_subdomain for the client's reference

This design ensures strict tenant isolation — an OAuth application created for School A can never be used to access School B's data.

Proxy architecture

Each school runs its own frontend application on a custom domain (e.g., demo.teachify.tw). The frontend exposes standard OAuth endpoints (/oauth/authorize, /api/oauth/token, etc.) that proxy requests to the centralized OAuth backend at connect.loopwise.com. From the client's perspective, all OAuth interactions happen through the school's domain — the backend proxy is transparent.

MCP clients

Loopwise also supports Model Context Protocol (MCP) clients such as Claude Code and Cursor. These are platform-level integrations that use the same OAuth 2.0 protocol but work differently from school-scoped applications:

  • MCP clients are registered as system-default applications across the platform
  • During authorization, the user selects which school to grant access to
  • Each authorization produces a token scoped to the selected school

If you are building a standard integration for a specific school, you do not need to worry about MCP — simply register your application in the school's admin panel.

Audience model

Every OAuth application declares an audience — who is allowed to authenticate through it. Audience is enforced at authorization time.

AudienceWho can authenticateTypical apps
org_adminTenant operators (owner or manager role) of the contextual schoolClaude Code, Cursor, Windsurf, loopwise-cli; school-registered admin dashboards
memberAny role of the bound or contextual school (student, TA, owner, manager)School-registered member-facing apps (quiz, exam, bootcamp companion tools); future member MCP clients

Audience is orthogonal to two other dimensions you will notice in the admin UI:

  • Registration scope — whether the app is bound to a single school (visible only in that school's admin) or pre-registered by Loopwise for use across all schools (e.g., Claude Code).
  • Audience selection on the school admin UI is a planned follow-up; today, newly created school-registered apps default to member (any role can complete OAuth), preserving the long-standing behaviour of school-installed integrations. When the UI lands, admins will be able to narrow an app to org_admin explicitly.

How scopes are determined

Scope limits depend on how the app was registered:

  • Loopwise pre-registered apps (Claude Code, Cursor, etc.) — the platform applies an audience-based scope ceiling automatically. org_admin apps get resource scopes (courses:*, students:*, pages:*, etc.) but never admin:*. member apps get identity scopes (openid profile email); dedicated account:* scopes are upcoming as part of the Member Account API rollout.
  • School-registered apps — the admin chooses the app's scopes when creating the application. Audience still controls who can complete OAuth into the app, but the scope set comes from the admin's configuration (subject to platform validation).

Defense in depth

The audience gate runs before consent and before token issuance. It's complemented by:

  • Per-audience scope ceiling for Loopwise pre-registered apps — those apps cannot obtain a scope outside their audience's allowed set, even if their configured scope list ever drifts.
  • Resolver-level scope gates on the GraphQL API — regardless of how an app's scopes were configured, the API rejects data access that lacks the required scope.
  • Contextual school checkorg_admin authorization requires the user to administer the school selected during the authorize flow, not just "any" school they happen to administer.

Loopwise also runs a small number of platform-internal OAuth applications for its own operational tools. Some of those apps use a staff audience, but that audience is internal-only: it is not exposed via the school admin UI, cannot be self-registered, and is not part of the public integration surface described above.

IP allowlisting

For enhanced security, we recommend allowlisting the following IP address in your firewall or reverse proxy:

52.194.91.27

This is the IP address from which Loopwise makes outbound requests (webhooks, callbacks).

On this page