Campus One

Quickstart

Connect your app to Campus One and sign in a test user in a few minutes

This is the fastest path from zero to seamless sign-in. It uses OpenID Connect — the live SSO protocol — and a library that auto-configures from our discovery URL, so you write very little code.

[!IMPORTANT] Don't build a login page. Campus One is the login experience. Your app should never render its own email/password, signup, or password-reset screens — instead it redirects unauthenticated visitors straight to Campus One, and because the student already has a Campus One session, they come back signed in without typing anything. See Seamless single sign-on below.

[!TIP] Already know OIDC? You only need three things: the discovery URL https://auth.campusone.com.ng/api/auth/.well-known/openid-configuration, your Client ID, and your Client Secret. Point any OIDC library at them and you're done. The rest of this page walks through it.

Before you start

You need a developer account. An admin invites you (you'll get a link to set your password), then you sign in to the developer dashboard at https://app.campusone.com.ng/developer/apps. See Application Management for the full dashboard tour.

Register your app

In the developer dashboard, click Connect new app and complete the wizard:

  • Protocol: OIDC
  • Redirect URL: where Campus One sends users back after login — e.g. http://localhost:3000/api/auth/callback/campus-one for local development. You can add production URLs later.
  • Scopes: start with profile and email; add academic, notifications, events, or roles if you need them (see Permissions).

[!NOTE] Apps work immediately in Pending status — you do not need admin approval to start testing OIDC sign-in, consent, and token issuance.

Copy your credentials

Open your app → Sign-in tab and copy:

CAMPUS_ONE_CLIENT_ID="…"        # shown at the top of the tab
CAMPUS_ONE_CLIENT_SECRET="…"    # click "Reveal" — shown once; rotate if lost

Keep the secret server-side. Never ship it in a client bundle or commit it.

Wire up an OIDC client

Point your framework's OIDC support at the discovery URL. Two common setups:

// Auth.js / NextAuth — app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth";

export const { handlers, auth } = NextAuth({
  providers: [
    {
      id: "campus-one",
      name: "Campus One",
      type: "oidc",
      issuer: "https://auth.campusone.com.ng",
      wellKnown:
        "https://auth.campusone.com.ng/api/auth/.well-known/openid-configuration",
      clientId: process.env.CAMPUS_ONE_CLIENT_ID,
      clientSecret: process.env.CAMPUS_ONE_CLIENT_SECRET,
      authorization: { params: { scope: "openid profile email academic" } },
    },
  ],
});
// Better Auth (consumer side)
import { betterAuth } from "better-auth";
import { genericOAuth } from "better-auth/plugins/generic-oauth";

export const auth = betterAuth({
  plugins: [
    genericOAuth({
      config: [
        {
          providerId: "campus-one",
          discoveryUrl:
            "https://auth.campusone.com.ng/api/auth/.well-known/openid-configuration",
          clientId: process.env.CAMPUS_ONE_CLIENT_ID!,
          clientSecret: process.env.CAMPUS_ONE_CLIENT_SECRET!,
          scopes: ["openid", "profile", "email", "academic"],
          pkce: true, // required
        },
      ],
    }),
  ],
});

PKCE is required on all clients. Mainstream libraries handle it automatically; if you're rolling your own flow, follow the OIDC guide.

Auto-redirect unauthenticated users (no login page)

Instead of a login screen, guard your protected routes: when there's no local session, immediately start the OIDC redirect. The student is bounced to Campus One and — if they already have a Campus One session — straight back to your app, signed in, with nothing to type.

// Example: middleware / route guard (pseudo-code, framework-agnostic)
export function middleware(request) {
  const session = getLocalSession(request);
  if (!session) {
    // No app-side login UI — kick off the OIDC flow right here.
    return redirectToCampusOne(request.url); // -> /api/auth/signin/campus-one
  }
}

For the rare signed-out entry point (e.g. a public marketing page with a "Go to dashboard" action), a single redirect link is all you need — never a form:

<a href="/api/auth/signin/campus-one">Continue with Campus One</a>

After login your app receives an ID token containing the user's identity — sub, email, name, role, and (with the academic scope) student_id, level, faculty_id, department_id. Use the top-level role claim for authorization without an extra request. Full claim list: OIDC claims.

Seamless single sign-on (no login page)

The whole point of Campus One is that students sign in once. When they open your connected app, they shouldn't see a login form or re-enter credentials — they should just be in. Here's how to get that:

  • Don't build auth UI. No login, signup, or password-reset pages. Your app's only job is to redirect unauthenticated visitors to Campus One (the previous step) and read the returned identity.
  • An existing Campus One session means automatic login. Campus One keeps a session for the signed-in student; when your app redirects to the authorize endpoint, Campus One sees that session and sends the student straight back with an authorization code — no credential prompt. (Apps served on a *.campusone.com.ng subdomain even share the session cookie directly.)
  • Skip the consent screen for trusted apps. First-party/internal apps can be marked Trusted app in the developer dashboard so returning students aren't shown the scope-consent dialog at all. Otherwise, consent is shown once and then remembered until your scopes change.
  • Want zero redirect flash? Use prompt=none. Add prompt=none to the authorize request to attempt a fully silent sign-in. If the student has a Campus One session you get a code back invisibly; if not, Campus One returns error=login_required — catch that and fall back to a normal redirect. See Automatic & silent sign-in.

The result: a student who is logged into Campus One lands in your app already authenticated, every time.

Signing out

Logout is ecosystem-wide: redirecting a user to the end-session endpoint clears their entire Campus One session. Since your app has no login screen of its own, enable a Sign-out redirect in your app settings (Sign-In → Sign-out redirect → Return to Campus One directory), then point your "Log out" action at the end-session endpoint — Campus One handles the rest:

window.location.href =
  "https://auth.campusone.com.ng/api/auth/oauth2/endsession" +
  `?id_token_hint=${idToken}&client_id=${CAMPUS_ONE_CLIENT_ID}`;

No post_logout_redirect_uri needed. Full details (including the custom-URL option) are in Single logout.

Testing your integration

You can fully exercise the integration locally before you have a production campusone.com.ng subdomain.

  • Pending apps are live. Authorization, the consent screen, and token issuance all work while your app is in Pending status — no approval needed.
  • Register a separate staging app. Keep one app for local/staging (with localhost and preview redirect URLs) and a second for production. That gives you independent test keys you can rotate freely. See Multi-app strategy.
  • Localhost just works. Over http://localhost, the auth server relaxes secure-cookie and cross-subdomain rules automatically, so sessions hold without browser cookie warnings. Register the exact callback your framework uses, e.g. http://localhost:3000/api/auth/callback/campus-one.
  • Use test users. Sign in with any seeded student, staff, developer, or admin account on the staging deployment to verify role-based behaviour. (Ask your Campus One admin for test credentials — they aren't published here.)
  • Verify the token. Always validate the ID token signature against the JWKS and check iss, aud, and exp.

Next steps

On this page