Back

GitHub App unable to create OAuth token

  • 0
  • Auth
  • Web
  • Cloud
hefler
13 Feb, 2025, 20:37

Does account.createOAuth2Token handle GitHub apps (this is not a GitHub OAuth app)? I'm using NextJS 15 and appwrite-node SDK and testing in local environment. So origin should be something like http://localhost:3000 In my login page I have a button Continue with GitHub where the user is redirected to this route:

TypeScript
import { NextRequest } from 'next/server';
import { adminClient } from '@/lib/server/appwrite';
import { OAuthProvider } from 'node-appwrite';

export async function GET(request: NextRequest) {
    try {
        const origin = process.env.NEXT_PUBLIC_APP_URL!;
        if (!origin) {
            throw new Error('NEXT_PUBLIC_APP_URL environment variable is required');
        }

        const { account } = await adminClient();
        
        const redirectUrl = await account.createOAuth2Token(
            OAuthProvider.Github,
            `${origin}/auth`,
            `${origin}/login?error=github_auth_cancelled`,
            ['repo', 'user', 'issues:write']
        );

        return Response.redirect(redirectUrl, 302);
    }
    catch (error) {
        console.error('GitHub auth error:', error);
        if (error instanceof Error) {
            console.error('Error details:', {
                message: error.message,
                name: error.name,
                stack: error.stack,
            });
        }
        return Response.redirect(`${origin}/login?error=github_auth_failed`, 302);
    }
}

This is the ERROR I get:

TypeScript
{"message":"There was an error processing your request. Please check the inputs and try again.","code":400,"type":"general_bad_request","version":"1.6.1"}

Would be nice to have some logs in the dashboard

TL;DR
Developers are having trouble with their GitHub App's OAuth token creation through an appwrite setup in a NextJS 15 environment using the appwrite-node SDK in a local environment. The issue occurs when trying to implement `account.createOAuth2Token` for GitHub apps (not GitHub OAuth apps) in the login page. An error message displays a general bad request with the code 400. They are attempting to set up authentication with GitHub through this process, but encounter this issue. Logs are requested in the dashboard for better insight. Solution: To solve this issue, developers need to ensure that the origin in the login page matches the expected value
hefler
13 Feb, 2025, 20:38

The success route looks like this:

TypeScript
import { adminClient } from '@/lib/server/appwrite';
import { cookieSave } from '@/lib/server/cookies';
import { redirect } from 'next/navigation';
import { NextRequest, NextResponse } from 'next/server';

export const GET = async (request: NextRequest) => {
    try {
        const { searchParams } = request.nextUrl;
        const userId = searchParams.get('userId');
        const secret = searchParams.get('secret');
        const { account } = await adminClient();

        if(!userId || !secret) {
            return redirect(`${process.env.NEXT_PUBLIC_APP_URL!}/signup`)
        }

        const session = await account.createSession(userId, secret);
        const cookieSaved = await cookieSave(session.secret);
        const tokenCookieSaved = await cookieSave(secret, `${process.env.NEXT_PUBLIC_COOKIE_SESSION_NAME!}_token`);
        const sessionCookie = cookieSaved.toString();
        const tokenCookie = tokenCookieSaved.toString();

        return new Response(
            `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${process.env.NEXT_PUBLIC_APP_URL}/app"></head></html>`,
            {
                headers: {
                    'Content-Type': 'text/html',
                    'Set-Cookie': `${sessionCookie}, ${tokenCookie}`,
                },
            }
        );
    } catch (error) {
        console.error('Auth error:', error);
        return NextResponse.redirect(`${process.env.NEXT_PUBLIC_APP_URL}/error`);
    }
};
hefler
13 Feb, 2025, 20:38

And this is my appwrite setup:

TypeScript
'use server';

import { Client, Account, Databases } from 'node-appwrite';
import { cookieGet } from './cookies';
import { cache } from 'react';

// For middleware only
export const createSessionClient = async () => {
    const client = new Client()
        .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
        .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!)

    const session = await cookieGet();
    if (!session?.value) {
        throw new Error('No session');
    }

    client.setSession(session.value);
    return new Account(client);
};

export const sessionClient = cache(async () => {
    const client = new Client()
        .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
        .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!)

    const session = await cookieGet();

    if (!session?.value) {
        throw new Error('No session');
    }

    client.setSession(session.value);
    return {
        get account() {
            return new Account(client);
        }
    };
});

export const adminClient = async () => {
    const client = new Client()
        .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
        .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!)
        .setKey(process.env.APPWRITE_API_KEY!);
      
    return {
        get databases() {
            return new Databases(client)
        },
        get account() {
            return new Account(client);
        },
    };
};

export const getLoggedInUser = async () => {
    try {
        const { account } = await sessionClient();
        return await account.get();
    }
    catch (error) {
        console.error(error);
        return null;
    }
};
Reply

Reply to this thread by joining our Discord

Reply on Discord

Need support?

Join our Discord

Get community support by joining our Discord server.

Join Discord

Get premium support

Join Appwrite Pro and get email support from our team.

Learn more