Skip to content

Commit 0c9fa43

Browse files
committed
Add GitHub OAuth2 adapter for AdminForth
1 parent 392569d commit 0c9fa43

4 files changed

Lines changed: 118 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
custom/node_modules
3+
dist

index.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import type { OAuth2Adapter } from "adminforth";
2+
3+
export class AdminForthAdapterGithubOauth2 implements OAuth2Adapter {
4+
private clientID: string;
5+
private clientSecret: string;
6+
private redirectUri: string;
7+
8+
constructor(options: {
9+
clientID: string;
10+
clientSecret: string;
11+
redirectUri: string;
12+
}) {
13+
this.clientID = options.clientID;
14+
this.clientSecret = options.clientSecret;
15+
this.redirectUri = options.redirectUri;
16+
}
17+
18+
getAuthUrl(): string {
19+
const params = new URLSearchParams({
20+
client_id: this.clientID,
21+
redirect_uri: this.redirectUri,
22+
scope: 'user:email read:user',
23+
allow_signup: 'true',
24+
provider: this.constructor.name
25+
});
26+
const url = `https://github.com/login/oauth/authorize?${params.toString()}`;
27+
return url;
28+
}
29+
30+
async getTokenFromCode(code: string): Promise<{ email: string; name?: string; picture?: string }> {
31+
console.log('Getting token from code:', code);
32+
33+
// Exchange code for token
34+
const tokenResponse = await fetch('https://github.com/login/oauth/access_token', {
35+
method: 'POST',
36+
headers: {
37+
'Accept': 'application/json',
38+
'Content-Type': 'application/json'
39+
},
40+
body: JSON.stringify({
41+
code,
42+
client_id: this.clientID,
43+
client_secret: this.clientSecret,
44+
redirect_uri: this.redirectUri,
45+
}),
46+
});
47+
48+
const tokenData = await tokenResponse.json();
49+
50+
if (tokenData.error) {
51+
console.error('Token error:', tokenData);
52+
throw new Error(tokenData.error_description || tokenData.error);
53+
}
54+
55+
// Get user info using access token
56+
const userResponse = await fetch('https://api.github.com/user', {
57+
headers: {
58+
'Authorization': `Bearer ${tokenData.access_token}`,
59+
'Accept': 'application/vnd.github.v3+json'
60+
},
61+
});
62+
63+
const userData = await userResponse.json();
64+
65+
if (userData.error) {
66+
throw new Error(userData.error_description || userData.error);
67+
}
68+
69+
// If email is not public, fetch email separately
70+
if (!userData.email) {
71+
const emailResponse = await fetch('https://api.github.com/user/emails', {
72+
headers: {
73+
'Authorization': `Bearer ${tokenData.access_token}`,
74+
'Accept': 'application/vnd.github.v3+json'
75+
},
76+
});
77+
78+
const emails = await emailResponse.json();
79+
const primaryEmail = emails.find(email => email.primary);
80+
userData.email = primaryEmail?.email;
81+
}
82+
83+
return {
84+
email: userData.email,
85+
};
86+
}
87+
getIcon(): string {
88+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 98"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg>`;
89+
}
90+
}

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "adminforth-google-oauth-adapter",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"scripts": {
6+
"test": "echo \"Error: no test specified\" && exit 1"
7+
},
8+
"keywords": [],
9+
"author": "",
10+
"license": "ISC",
11+
"description": ""
12+
}

0 commit comments

Comments
 (0)