Skip to content

Fix Backstage Auth – GitHub Authentication Not Working

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Fix Backstage Auth. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

You configure GitHub OAuth in Backstage, set up the OAuth App in GitHub, and restart the backend. You click Sign in with GitHub β€” the browser navigates to GitHub, you authorise, and then... nothing. The callback URL fails, or you see "Backend returned an error: Auth provider 'github' is not configured".

Wrong ❌

# app-config.yaml β€” auth section
auth:
  environment: development
  providers:
    github:
      development:
        clientId: ${AUTH_GITHUB_CLIENT_ID}
        clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}

You set the env vars:

```bash
export AUTH_GITHUB_CLIENT_ID=Ov23liabc123
export AUTH_GITHUB_CLIENT_SECRET=abc123def456

Start Backstage. Click **Sign in with GitHub**. Browser goes to GitHub, you authorise, then get:

Redirect URI: http://localhost:7007/api/auth/github/handler/frame
Error: Backend returned an error: Request failed with status 401

The GitHub OAuth App callback URL is set to `http://localhost:3000/auth/github` β€” which doesn't match Backstage's backend handler.

## Right βœ…

**GitHub OAuth App settings:**

Homepage URL: http://localhost:3000
Authorization callback URL: http://localhost:7007/api/auth/github/handler/frame

**Backstage config:**

```yaml
# app-config.yaml
auth:
  environment: development
  providers:
    github:
      development:
        clientId: ${AUTH_GITHUB_CLIENT_ID}
        clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
        signInPage: github
        callbackUrl: http://localhost:7007/api/auth/github/handler/frame

**Frontend config (`packages/app/src/App.tsx`):**

```<a href="/programming-languages/typescript/">TypeScript</a>
import { githubAuthApiRef } from '@backstage/core-plugin-api';
import { SignInPage } from '@backstage/core-components';

const App = () => (
  <AppProvider>
    <SignInPage
      provider={{
        id: 'github',
        title: 'GitHub',
        message: 'Sign in with GitHub',
        apiRef: githubAuthApiRef,
      }}
      onSignInSuccess={() => {}}
    />
    <AppRouter>
      ...
    </AppRouter>
  </AppProvider>
);

**Restart and sign in:**

1. Click **Sign in with GitHub**
2. Authorise on GitHub
3. Browser redirects to `http://localhost:7007/api/auth/github/handler/frame`
4. Backstage authenticates and redirects to the dashboard

βœ… Signed in as: octocat (GitHub)

## Root Cause

The GitHub OAuth callback URL must point to the **Backstage backend** (`localhost:7007`), not the frontend (`localhost:3000`). Backstage's auth flow exchanges the code with GitHub at the backend endpoint, issues a token, and redirects to the frontend.

## Prevention

- Set the callback URL in GitHub to `http://<backend-base-url>/api/auth/github/handler/frame`.
- Use the `auth.environment` value that matches your config section (e.g. `development`, `production`).
- Test with `curl` the backend health endpoint before testing auth.
- Add `session` scope to the GitHub OAuth app if you need user info.


## Common Mistakes with auth github

1. **Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks**
2. **Using `return` to exit a function early instead of wrapping a pure value in the monad**
3. **Mixing let bindings with <- bindings in do notation, producing type errors**

These mistakes appear frequently in real-world BACKSTAGE code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

## Practice Exercise

**Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.**

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

## FAQ

<details style="margin-bottom:12px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden"><summary style="cursor:pointer;padding:14px 18px;font-weight:600;font-size:1.05rem;background:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1e293b">**Q: Multiple auth providers show up β€” how to show only GitHub?**</summary><div style="padding:14px 18px;color:#475569;line-height:1.7;background:#fff"><p>A: In <code>SignInPage</code> <code>provider</code> prop, specify the array of provider configs. Set <code>signInPage: github</code> to auto‑redirect.</p>
</div></details><details style="margin-bottom:12px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden"><summary style="cursor:pointer;padding:14px 18px;font-weight:600;font-size:1.05rem;background:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1e293b">**Q: Can I use GitHub Enterprise?**</summary><div style="padding:14px 18px;color:#475569;line-height:1.7;background:#fff"><p>A: Yes β€” set <code>enterpriseInstanceUrl</code> in the provider config and use the GitHub Enterprise base URL.</p>
</div></details><details style="margin-bottom:12px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden"><summary style="cursor:pointer;padding:14px 18px;font-weight:600;font-size:1.05rem;background:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1e293b">**Q: Why does auth fail with "access_denied"?**</summary><div style="padding:14px 18px;color:#475569;line-height:1.7;background:#fff"><p>A: The user declined the OAuth consent. This is expected if they click &quot;Cancel&quot; instead of &quot;Authorise&quot;.</p>
</div></details><details style="margin-bottom:12px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden"><summary style="cursor:pointer;padding:14px 18px;font-weight:600;font-size:1.05rem;background:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1e293b">**Q: How do I debug auth failures?**</summary><div style="padding:14px 18px;color:#475569;line-height:1.7;background:#fff"><p>A: Enable debug logging: set <code>LOG_LEVEL=debug</code> and check the backend log for OAuth token exchange details.</p>
</div></details>

---

*Authentication is covered in the [DodaTech Backstage Security course](https://dodatech.com/courses/backstage).*

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro