feat(auth): implement Gitea authentication provider with NextAuth integration
This commit is contained in:
parent
12e37e908f
commit
b04613784a
@ -11,8 +11,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"gitea-js": "^1.22.0",
|
||||||
"lucide-react": "^0.468.0",
|
"lucide-react": "^0.468.0",
|
||||||
"next": "15.0.4",
|
"next": "15.0.4",
|
||||||
|
"next-auth": "^5.0.0-beta.25",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"tailwind-merge": "^2.5.5",
|
"tailwind-merge": "^2.5.5",
|
||||||
|
3
src/app/api/auth/[...nextauth]/route.ts
Normal file
3
src/app/api/auth/[...nextauth]/route.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { handlers } from "@/auth";
|
||||||
|
|
||||||
|
export const { GET, POST } = handlers;
|
15
src/auth.ts
Normal file
15
src/auth.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import NextAuth from "next-auth";
|
||||||
|
import Gitea from "@/lib/providers/gitea";
|
||||||
|
|
||||||
|
export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||||
|
providers: [
|
||||||
|
Gitea({
|
||||||
|
clientId: process.env.AUTH_GITEA_ID,
|
||||||
|
clientSecret: process.env.AUTH_GITEA_SECRET,
|
||||||
|
enterprise: {
|
||||||
|
baseUrl: process.env.AUTH_GITEA_URL,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
secret: process.env.AUTH_SECRET,
|
||||||
|
});
|
72
src/lib/providers/gitea.ts
Normal file
72
src/lib/providers/gitea.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { Email as GiteaEmail, User } from "gitea-js";
|
||||||
|
import { OAuthConfig, OAuthUserConfig } from "next-auth/providers";
|
||||||
|
|
||||||
|
export interface GiteaProfile extends User {
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Gitea(
|
||||||
|
config: OAuthUserConfig<GiteaProfile> & {
|
||||||
|
enterprise?: {
|
||||||
|
baseUrl?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
): OAuthConfig<GiteaProfile> {
|
||||||
|
const baseUrl = config?.enterprise?.baseUrl ?? "https://gitea.com";
|
||||||
|
const apiBaseUrl = config?.enterprise?.baseUrl
|
||||||
|
? `${config?.enterprise?.baseUrl}/api/v1`
|
||||||
|
: "https://gitea.com/api/v1";
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: "gitea",
|
||||||
|
name: "Gitea",
|
||||||
|
type: "oauth",
|
||||||
|
authorization: {
|
||||||
|
url: `${baseUrl}/login/oauth/authorize`,
|
||||||
|
params: { scope: "read:user user:email" },
|
||||||
|
},
|
||||||
|
token: `${baseUrl}/login/oauth/access_token`,
|
||||||
|
userinfo: {
|
||||||
|
url: `${apiBaseUrl}/user`,
|
||||||
|
async request({
|
||||||
|
tokens,
|
||||||
|
provider,
|
||||||
|
}: {
|
||||||
|
tokens: { access_token: string };
|
||||||
|
provider: OAuthConfig<GiteaProfile>;
|
||||||
|
}) {
|
||||||
|
const profile = await fetch(provider.userinfo?.url as URL, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${tokens.access_token}`,
|
||||||
|
"User-Agent": "authjs",
|
||||||
|
},
|
||||||
|
}).then(async (res) => await res.json());
|
||||||
|
|
||||||
|
if (!profile.email) {
|
||||||
|
const res = await fetch(`${apiBaseUrl}/user/emails`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${tokens.access_token}`,
|
||||||
|
"User-Agent": "authjs",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
const emails: GiteaEmail[] = await res.json();
|
||||||
|
profile.email = (emails.find((e) => e.primary) ?? emails[0]).email;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return profile;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
profile(profile) {
|
||||||
|
return {
|
||||||
|
id: profile.id?.toString(),
|
||||||
|
name: profile.username ?? profile.login,
|
||||||
|
email: profile.email,
|
||||||
|
image: profile.avatar_url,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
options: config,
|
||||||
|
};
|
||||||
|
}
|
1
src/middleware.ts
Normal file
1
src/middleware.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { auth as middleware } from "@/auth";
|
Loading…
Reference in New Issue
Block a user