Test GitLab OAuth login locally
Sign in with GitLab on localhost by registering a stable HTTPS Redirect URI from a Horizon tunnel, with Auth.js in Next.js.
Test "Sign in with GitLab" on your laptop, with a Redirect URI GitLab can reach.
Before you begin
- Node.js 18 or later
- A Horizon account and the CLI (see Getting started)
- A reserved subdomain for
-s. Reserve one on the Subdomains page. - A GitLab account
- A Next.js App Router app with Auth.js set up. The Auth.js guide covers
AUTH_SECRETand the route handler.
Start a tunnel
Use -s with a subdomain you reserved. Without it, the subdomain is random and changes every run, so the redirect URI you register would point at a dead URL after a restart. Reserved subdomains are a paid feature, see Pricing.
hrzn tunnel http://localhost:3000 -s my-appHORIZON: Tunnel connected
URL https://my-app.hrzn.run (reserved)
Forwarding http://localhost:3000
Request log https://hrzn.run/dashboard/tunnels/my-appKeep this terminal open.
Register the application in GitLab
- In the upper-right corner of GitLab, select your avatar, then Edit profile.
- In the left sidebar, select Access, then Applications.
- Add a new application. Set Name to something you recognize, such as
my-app local. - Set Redirect URI to
https://my-app.hrzn.run/api/auth/callback/gitlab. - Under OAuth 2 Scopes, select
read_user. Auth.js needs it to save the user's email address on sign up. - Save the application. GitLab shows the Application ID and a Secret. Copy both.
GitLab says you can use a non-SSL URL but should use an SSL one. A tunnel URL is already HTTPS.
Configure Auth.js
Auth.js reads the GitLab credentials from AUTH_GITLAB_ID and AUTH_GITLAB_SECRET. AUTH_TRUST_HOST=true makes Auth.js trust X-Forwarded-Host, so it builds the callback from the public host. Horizon sets Host to localhost:3000.
AUTH_SECRET=replace-with-the-generated-secret
AUTH_TRUST_HOST=true
AUTH_GITLAB_ID=replace-with-the-application-id
AUTH_GITLAB_SECRET=replace-with-the-secretimport NextAuth from "next-auth";
import GitLab from "next-auth/providers/gitlab";
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [GitLab],
});import { handlers } from "@/auth";
export const { GET, POST } = handlers;For a self-managed GitLab, pass its address: GitLab({ baseUrl: "https://gitlab.example.com" }).
Add a sign-in button, then start the app on port 3000.
import { signIn } from "@/auth";
export default function Home() {
return (
<form
action={async () => {
"use server";
await signIn("gitlab");
}}
>
<button type="submit">Sign in with GitLab</button>
</form>
);
}npm run devSign in
Open https://my-app.hrzn.run. On the first visit, select Continue to site on the Before you continue page. Then select Sign in with GitLab.
Check it works
GitLab shows its authorization screen. After you approve, your browser lands back on https://my-app.hrzn.run.
Your Horizon terminal prints a line for the callback:
GET 302 /api/auth/callback/gitlabTroubleshooting
GitLab rejects the redirect URI
GitLab requires the redirect_uri in the authorization request to match the one in the token request. It also expects it to match the application's Redirect URI.
- Check that Redirect URI is exactly
https://my-app.hrzn.run/api/auth/callback/gitlab. - Check that
AUTH_TRUST_HOST=trueis set and that you restartednpm run dev. Without it, Auth.js can build alocalhostcallback. - Check that the subdomain matches the one you pass to
-s.
The user has no email address
Select the read_user scope in the GitLab application. Auth.js documents it as the scope that saves the email on sign up.
The URL changed after a restart
You started the tunnel without -s, so Horizon gave you a new random subdomain. Restart with -s my-app and the Redirect URI stays valid. -s needs a subdomain you reserved, see Pricing.
Nothing reaches your app
- Check that the Horizon terminal is still running. If its last line is
Connection lost. Reconnecting…, wait forReconnected. - Check that the app listens on port 3000, the port in your tunnel command.
Next steps
- Read GitLab's OAuth 2.0 identity provider docs.
- Read the general page, Test OAuth redirect URLs locally.