Skip to content

Commit cd139f3

Browse files
committed
feat: oauth access tokens
1 parent 05a290a commit cd139f3

File tree

3 files changed

+74
-4
lines changed

3 files changed

+74
-4
lines changed

src/auth.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { AuthOptions, StrategyOptionsWithDefaults } from "./types";
22
import { getAppAuthentication } from "./get-app-authentication";
33
import { getInstallationAuthentication } from "./get-installation-authentication";
4+
import { getOAuthAuthentication } from "./get-oauth-authentication";
45

56
export async function auth(
67
state: StrategyOptionsWithDefaults,
@@ -10,5 +11,9 @@ export async function auth(
1011
return getAppAuthentication(state.id, state.privateKey);
1112
}
1213

13-
return getInstallationAuthentication(state, options);
14+
if (options.type === "installation") {
15+
return getInstallationAuthentication(state, options);
16+
}
17+
18+
return getOAuthAuthentication(state, options);
1419
}

src/get-oauth-authentication.ts

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import {
2+
Request,
3+
OAuthOptions,
4+
StrategyOptionsWithDefaults,
5+
OAuthAccesTokenAuthentication
6+
} from "./types";
7+
8+
export async function getOAuthAuthentication(
9+
state: StrategyOptionsWithDefaults,
10+
options: OAuthOptions,
11+
customRequest?: Request
12+
): Promise<OAuthAccesTokenAuthentication> {
13+
const request = customRequest || state.request;
14+
15+
// The "/login/oauth/access_token" is not part of the REST API hosted on api.github.com,
16+
// instead it’s using the github.com domain.
17+
const route = /^https:\/\/(api\.)?github\.com$/.test(
18+
state.request.endpoint.DEFAULTS.baseUrl
19+
)
20+
? "POST https://github.com/login/oauth/access_token"
21+
: `POST ${state.request.endpoint.DEFAULTS.baseUrl.replace(
22+
"/api/v3",
23+
"/login/oauth/access_token"
24+
)}`;
25+
26+
const parameters = {
27+
headers: {
28+
accept: `application/json`
29+
},
30+
client_id: state.clientId,
31+
client_secret: state.clientSecret,
32+
code: options.code,
33+
state: options.state,
34+
redirect_uri: options.redirectUrl
35+
};
36+
37+
const {
38+
data: { access_token: token, scope }
39+
} = await request(route, parameters);
40+
41+
return {
42+
type: "token",
43+
tokenType: "oauth",
44+
token,
45+
scopes: scope.split(/,\s*/).filter(Boolean)
46+
};
47+
}

src/types.ts

+21-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface AppAuth {
1919
export type APP_TYPE = "app";
2020
export type TOKEN_TYPE = "token";
2121
export type INSTALLATION_TOKEN_TYPE = "installation";
22+
export type OAUTH_TOKEN_TYPE = "oauth";
2223
export type REPOSITORY_SELECTION = "all" | "selected";
2324
export type JWT = string;
2425
export type ACCESS_TOKEN = string;
@@ -47,14 +48,24 @@ export type InstallationAccessTokenAuthentication = InstallationAccessTokenData
4748
tokenType: INSTALLATION_TOKEN_TYPE;
4849
};
4950

51+
export type OAuthAccesTokenAuthentication = {
52+
type: TOKEN_TYPE;
53+
tokenType: OAUTH_TOKEN_TYPE;
54+
token: ACCESS_TOKEN;
55+
scopes: string[];
56+
};
57+
5058
export type Authentication =
5159
| AppAuthentication
52-
| InstallationAccessTokenAuthentication;
60+
| InstallationAccessTokenAuthentication
61+
| OAuthAccesTokenAuthentication;
5362

5463
export type StrategyOptions = {
5564
id: number;
5665
privateKey: string;
5766
installationId?: number;
67+
clientId?: string;
68+
clientSecret?: string;
5869
request?: typeof request;
5970
cache?: Cache;
6071
};
@@ -75,10 +86,17 @@ export type InstallationAuthOptions = {
7586
refresh?: boolean;
7687
};
7788

78-
export type AuthOptions = InstallationAuthOptions & {
79-
type: "app" | "installation";
89+
export type OAuthOptions = {
90+
code?: string;
91+
redirectUrl?: string;
92+
state?: string;
8093
};
8194

95+
export type AuthOptions = InstallationAuthOptions &
96+
OAuthOptions & {
97+
type: "app" | "installation" | "oauth";
98+
};
99+
82100
export type WithInstallationId = {
83101
installationId: number;
84102
};

0 commit comments

Comments
 (0)