o-auth-lib 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -0
- package/dist/authService.d.ts +30 -0
- package/dist/authService.d.ts.map +1 -0
- package/dist/authService.js +76 -0
- package/dist/authService.js.map +1 -0
- package/dist/authService.test.d.ts +2 -0
- package/dist/authService.test.d.ts.map +1 -0
- package/dist/authService.test.js +51 -0
- package/dist/authService.test.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/oauthService.d.ts +50 -0
- package/dist/oauthService.d.ts.map +1 -0
- package/dist/oauthService.js +202 -0
- package/dist/oauthService.js.map +1 -0
- package/dist/oauthService.test.d.ts +2 -0
- package/dist/oauthService.test.d.ts.map +1 -0
- package/dist/oauthService.test.js +26 -0
- package/dist/oauthService.test.js.map +1 -0
- package/dist/useAuth.d.ts +9 -0
- package/dist/useAuth.d.ts.map +1 -0
- package/dist/useAuth.js +29 -0
- package/dist/useAuth.js.map +1 -0
- package/dist/useOAuth.d.ts +2 -0
- package/dist/useOAuth.d.ts.map +1 -0
- package/dist/useOAuth.js +6 -0
- package/dist/useOAuth.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# o-auth-lib
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/o-auth-lib)
|
|
4
|
+
[](https://opensource.org/licenses/ISC)
|
|
5
|
+
|
|
6
|
+
A TypeScript authentication library for OAuth and normal login flows. The package is designed so consuming apps provide credentials and configuration at runtime, keeping the library reusable and secure.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install o-auth-lib react
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
yarn add o-auth-lib react
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add o-auth-lib react
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
> **Requires:** `react@17` or `react@18`
|
|
23
|
+
|
|
24
|
+
## Browser Support
|
|
25
|
+
|
|
26
|
+
- Modern browsers with support for:
|
|
27
|
+
- `crypto.getRandomValues()` (for PKCE)
|
|
28
|
+
- `crypto.subtle.digest()` (for SHA-256)
|
|
29
|
+
- `fetch` API
|
|
30
|
+
- `URLSearchParams`
|
|
31
|
+
|
|
32
|
+
Targets **ES2019** and above.
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
### OAuth login
|
|
37
|
+
|
|
38
|
+
`useAuth()` is the recommended hook for browser-based OAuth login flows.
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import { useAuth } from "o-auth-lib";
|
|
42
|
+
|
|
43
|
+
const oauthConfig = {
|
|
44
|
+
authType: "oauth" as const,
|
|
45
|
+
provider: "google" as const,
|
|
46
|
+
clientId: import.meta.env.VITE_GOOGLE_CLIENT_ID,
|
|
47
|
+
redirectUri: import.meta.env.VITE_APP_REDIRECT_URI,
|
|
48
|
+
scopes: ["openid", "profile", "email"],
|
|
49
|
+
usePKCE: true,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
function LoginButton() {
|
|
53
|
+
const { execute, loading, error, result } = useAuth(oauthConfig);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<button onClick={() => execute()} disabled={loading}>
|
|
57
|
+
{loading ? "Signing in..." : "Sign in with Google"}
|
|
58
|
+
{error && <div>{error}</div>}
|
|
59
|
+
{result && <div>Authenticated</div>}
|
|
60
|
+
</button>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
> `usePKCE` is enabled by default for OAuth code flows, so browser apps do not need to use `clientSecret` in the frontend.
|
|
66
|
+
|
|
67
|
+
### Generic authentication helper
|
|
68
|
+
|
|
69
|
+
For normal login flows, use `authenticate()` with a configurable auth endpoint.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { authenticate } from "o-auth-lib";
|
|
73
|
+
|
|
74
|
+
const normalConfig = {
|
|
75
|
+
authType: "normal" as const,
|
|
76
|
+
provider: "normal",
|
|
77
|
+
serviceName: "my-service",
|
|
78
|
+
authUrl: "https://api.example.com/auth/login",
|
|
79
|
+
email: "user@example.com",
|
|
80
|
+
password: "secret-password",
|
|
81
|
+
contentType: "application/json",
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
async function login() {
|
|
85
|
+
const result = await authenticate(normalConfig);
|
|
86
|
+
console.log(result.accessToken, result.data);
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Custom provider example
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import { authenticate } from "o-auth-lib";
|
|
94
|
+
|
|
95
|
+
const customOAuthConfig = {
|
|
96
|
+
authType: "oauth" as const,
|
|
97
|
+
provider: {
|
|
98
|
+
authorizeUrl: "https://custom.example.com/oauth/authorize",
|
|
99
|
+
tokenUrl: "https://custom.example.com/oauth/token",
|
|
100
|
+
responseType: "code",
|
|
101
|
+
scopeSeparator: " ",
|
|
102
|
+
},
|
|
103
|
+
clientId: import.meta.env.VITE_CUSTOM_CLIENT_ID,
|
|
104
|
+
redirectUri: import.meta.env.VITE_APP_REDIRECT_URI,
|
|
105
|
+
scopes: ["read", "write"],
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const result = await authenticate(customOAuthConfig);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Supported provider presets
|
|
112
|
+
|
|
113
|
+
- `google`
|
|
114
|
+
- `github`
|
|
115
|
+
- custom provider objects using `provider: { authorizeUrl, tokenUrl, ... }`
|
|
116
|
+
|
|
117
|
+
## API Reference
|
|
118
|
+
|
|
119
|
+
### `useAuth(config: AuthConfig): UseAuthResult`
|
|
120
|
+
|
|
121
|
+
React hook for authentication flows.
|
|
122
|
+
|
|
123
|
+
**Parameters:**
|
|
124
|
+
- `config` – OAuth or normal auth configuration
|
|
125
|
+
- `authType` – `"oauth"` or `"normal"`
|
|
126
|
+
- `provider` – Provider name or custom preset
|
|
127
|
+
|
|
128
|
+
**Returns:**
|
|
129
|
+
- `execute()` – Function to trigger authentication
|
|
130
|
+
- `loading` – Boolean indicating if auth is in progress
|
|
131
|
+
- `error` – Error message if authentication failed
|
|
132
|
+
- `result` – `AuthResult` containing access token and response data
|
|
133
|
+
|
|
134
|
+
### `authenticate(config: AuthConfig): Promise<AuthResult>`
|
|
135
|
+
|
|
136
|
+
Generic async function for OAuth or normal authentication.
|
|
137
|
+
|
|
138
|
+
**Returns:**
|
|
139
|
+
- `authType` – Type of authentication used
|
|
140
|
+
- `provider` – Provider name
|
|
141
|
+
- `accessToken` – Access/bearer token if available
|
|
142
|
+
- `refreshToken` – Refresh token if available
|
|
143
|
+
- `data` – Raw response from OAuth provider or auth endpoint
|
|
144
|
+
|
|
145
|
+
### PKCE Support
|
|
146
|
+
|
|
147
|
+
PKCE is enabled by default for OAuth authorization code flows. To disable:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
const config = {
|
|
151
|
+
authType: "oauth" as const,
|
|
152
|
+
provider: "google",
|
|
153
|
+
clientId: "...",
|
|
154
|
+
redirectUri: "...",
|
|
155
|
+
usePKCE: false, // Disable PKCE
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Important notes
|
|
160
|
+
|
|
161
|
+
- Do not store real credentials inside the published package.
|
|
162
|
+
- Pass `clientId` and other credentials from consuming apps, for example via environment variables.
|
|
163
|
+
- `clientSecret` should not be used in browser-only OAuth flows unless the application is a confidential client and the token exchange is performed on a trusted backend.
|
|
164
|
+
- The package publishes only `dist/` via `package.json` `files`, so local `.env` files are not included in the npm package.
|
|
165
|
+
- State validation is automatic and prevents CSRF attacks in OAuth flows.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { OAuthConfig } from "./oauthService";
|
|
2
|
+
export type NormalAuthConfig = {
|
|
3
|
+
authType: "normal";
|
|
4
|
+
provider: "normal" | string;
|
|
5
|
+
serviceName?: string;
|
|
6
|
+
authUrl: string;
|
|
7
|
+
method?: "POST" | "PUT" | "PATCH" | "DELETE";
|
|
8
|
+
contentType?: "application/json" | "application/x-www-form-urlencoded";
|
|
9
|
+
email?: string;
|
|
10
|
+
password?: string;
|
|
11
|
+
credentials?: Record<string, string | number | boolean>;
|
|
12
|
+
extraBody?: Record<string, unknown>;
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
};
|
|
15
|
+
export type OAuthAuthConfig = OAuthConfig & {
|
|
16
|
+
authType: "oauth";
|
|
17
|
+
};
|
|
18
|
+
export type AuthConfig = OAuthAuthConfig | NormalAuthConfig;
|
|
19
|
+
export type AuthResult = {
|
|
20
|
+
authType: "oauth" | "normal";
|
|
21
|
+
provider: string;
|
|
22
|
+
serviceName?: string;
|
|
23
|
+
accessToken?: string | number;
|
|
24
|
+
refreshToken?: string | number;
|
|
25
|
+
data: any;
|
|
26
|
+
};
|
|
27
|
+
export declare function authenticate(config: AuthConfig): Promise<AuthResult>;
|
|
28
|
+
export declare function authenticateOAuth(config: OAuthAuthConfig): Promise<AuthResult>;
|
|
29
|
+
export declare function authenticateNormal(config: NormalAuthConfig): Promise<AuthResult>;
|
|
30
|
+
//# sourceMappingURL=authService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authService.d.ts","sourceRoot":"","sources":["../src/authService.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC7C,WAAW,CAAC,EAAE,kBAAkB,GAAG,mCAAmC,CAAC;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAC1C,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,gBAAgB,CAAC;AAE5D,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,IAAI,EAAE,GAAG,CAAC;CACX,CAAC;AAEF,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAM1E;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAwBpF;AAsBD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CA8BtF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authenticate = authenticate;
|
|
4
|
+
exports.authenticateOAuth = authenticateOAuth;
|
|
5
|
+
exports.authenticateNormal = authenticateNormal;
|
|
6
|
+
const oauthService_1 = require("./oauthService");
|
|
7
|
+
async function authenticate(config) {
|
|
8
|
+
if (config.authType === "normal") {
|
|
9
|
+
return authenticateNormal(config);
|
|
10
|
+
}
|
|
11
|
+
return authenticateOAuth(config);
|
|
12
|
+
}
|
|
13
|
+
async function authenticateOAuth(config) {
|
|
14
|
+
const authRequest = await (0, oauthService_1.createOAuthRequest)(config);
|
|
15
|
+
const oauthResult = await (0, oauthService_1.openAuthPopup)(authRequest.authUrl, config.redirectUri);
|
|
16
|
+
if (authRequest.state && oauthResult.state !== authRequest.state) {
|
|
17
|
+
throw new Error("OAuth state mismatch detected.");
|
|
18
|
+
}
|
|
19
|
+
if (oauthResult.error) {
|
|
20
|
+
throw new Error(oauthResult.error);
|
|
21
|
+
}
|
|
22
|
+
const tokenResponse = oauthResult.code
|
|
23
|
+
? await (0, oauthService_1.fetchToken)(config, oauthResult.code, authRequest.codeVerifier)
|
|
24
|
+
: oauthResult;
|
|
25
|
+
return {
|
|
26
|
+
authType: "oauth",
|
|
27
|
+
provider: typeof config.provider === "string" ? config.provider : "custom",
|
|
28
|
+
serviceName: config.provider === "normal" ? "normal" : undefined,
|
|
29
|
+
accessToken: tokenResponse.access_token || tokenResponse.token || tokenResponse.accessToken,
|
|
30
|
+
refreshToken: tokenResponse.refresh_token || tokenResponse.refreshToken,
|
|
31
|
+
data: tokenResponse,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function buildNormalBody(config) {
|
|
35
|
+
const payload = {
|
|
36
|
+
...(config.credentials || {}),
|
|
37
|
+
...(config.email !== undefined ? { email: config.email } : {}),
|
|
38
|
+
...(config.password !== undefined ? { password: config.password } : {}),
|
|
39
|
+
...(config.extraBody || {}),
|
|
40
|
+
};
|
|
41
|
+
if ((config.contentType || "application/json") === "application/x-www-form-urlencoded") {
|
|
42
|
+
return new URLSearchParams(Object.entries(payload).reduce((result, [key, value]) => {
|
|
43
|
+
result[key] = String(value !== null && value !== void 0 ? value : "");
|
|
44
|
+
return result;
|
|
45
|
+
}, {})).toString();
|
|
46
|
+
}
|
|
47
|
+
return JSON.stringify(payload);
|
|
48
|
+
}
|
|
49
|
+
async function authenticateNormal(config) {
|
|
50
|
+
const method = config.method || "POST";
|
|
51
|
+
const contentType = config.contentType || "application/json";
|
|
52
|
+
const body = buildNormalBody(config);
|
|
53
|
+
const response = await fetch(config.authUrl, {
|
|
54
|
+
method,
|
|
55
|
+
headers: {
|
|
56
|
+
"Content-Type": contentType,
|
|
57
|
+
Accept: "application/json",
|
|
58
|
+
...config.headers,
|
|
59
|
+
},
|
|
60
|
+
body,
|
|
61
|
+
});
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
const text = await response.text();
|
|
64
|
+
throw new Error(`Normal auth request failed: ${response.status} ${response.statusText} - ${text}`);
|
|
65
|
+
}
|
|
66
|
+
const data = await response.json();
|
|
67
|
+
return {
|
|
68
|
+
authType: "normal",
|
|
69
|
+
provider: config.provider,
|
|
70
|
+
serviceName: config.serviceName,
|
|
71
|
+
accessToken: data.access_token || data.token || data.accessToken,
|
|
72
|
+
refreshToken: data.refresh_token || data.refreshToken,
|
|
73
|
+
data,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=authService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authService.js","sourceRoot":"","sources":["../src/authService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authService.test.d.ts","sourceRoot":"","sources":["../src/authService.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const authService_1 = require("./authService");
|
|
5
|
+
const originalFetch = global.fetch;
|
|
6
|
+
(0, vitest_1.afterEach)(() => {
|
|
7
|
+
vitest_1.vi.restoreAllMocks();
|
|
8
|
+
global.fetch = originalFetch;
|
|
9
|
+
});
|
|
10
|
+
(0, vitest_1.describe)("authService", () => {
|
|
11
|
+
(0, vitest_1.it)("sends JSON normal auth payload", async () => {
|
|
12
|
+
const fetchMock = vitest_1.vi.fn(() => Promise.resolve({
|
|
13
|
+
ok: true,
|
|
14
|
+
json: async () => ({ access_token: "abc123" }),
|
|
15
|
+
}));
|
|
16
|
+
global.fetch = fetchMock;
|
|
17
|
+
const result = await (0, authService_1.authenticate)({
|
|
18
|
+
authType: "normal",
|
|
19
|
+
provider: "normal",
|
|
20
|
+
authUrl: "https://example.com/login",
|
|
21
|
+
email: "user@example.com",
|
|
22
|
+
password: "secret",
|
|
23
|
+
contentType: "application/json",
|
|
24
|
+
});
|
|
25
|
+
(0, vitest_1.expect)(fetchMock).toHaveBeenCalled();
|
|
26
|
+
(0, vitest_1.expect)(result.accessToken).toBe("abc123");
|
|
27
|
+
});
|
|
28
|
+
(0, vitest_1.it)("sends form-urlencoded normal auth payload", async () => {
|
|
29
|
+
const fetchMock = vitest_1.vi.fn(() => Promise.resolve({
|
|
30
|
+
ok: true,
|
|
31
|
+
json: async () => ({ access_token: "abc123" }),
|
|
32
|
+
}));
|
|
33
|
+
global.fetch = fetchMock;
|
|
34
|
+
const result = await (0, authService_1.authenticate)({
|
|
35
|
+
authType: "normal",
|
|
36
|
+
provider: "normal",
|
|
37
|
+
authUrl: "https://example.com/login",
|
|
38
|
+
email: "user@example.com",
|
|
39
|
+
password: "secret",
|
|
40
|
+
contentType: "application/x-www-form-urlencoded",
|
|
41
|
+
});
|
|
42
|
+
(0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://example.com/login", vitest_1.expect.objectContaining({
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: vitest_1.expect.objectContaining({
|
|
45
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
46
|
+
}),
|
|
47
|
+
}));
|
|
48
|
+
(0, vitest_1.expect)(result.accessToken).toBe("abc123");
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=authService.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authService.test.js","sourceRoot":"","sources":["../src/authService.test.ts"],"names":[],"mappings":";;AAAA,mCAA6D;AAC7D,+CAA6C;AAE7C,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC;AAEnC,IAAA,kBAAS,EAAC,GAAG,EAAE;IACb,WAAE,CAAC,eAAe,EAAE,CAAC;IACrB,MAAM,CAAC,KAAK,GAAG,aAAa,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEH,IAAA,iBAAQ,EAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,IAAA,WAAE,EAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,SAAS,GAAG,WAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAC3B,OAAO,CAAC,OAAO,CAAC;YACd,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;SACxC,CAAC,CACV,CAAC;QAEF,MAAM,CAAC,KAAK,GAAG,SAAgB,CAAC;QAEhC,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAY,EAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE,2BAA2B;YACpC,KAAK,EAAE,kBAAkB;YACzB,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,kBAAkB;SAChC,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,SAAS,CAAC,CAAC,gBAAgB,EAAE,CAAC;QACrC,IAAA,eAAM,EAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,SAAS,GAAG,WAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAC3B,OAAO,CAAC,OAAO,CAAC;YACd,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;SACxC,CAAC,CACV,CAAC;QAEF,MAAM,CAAC,KAAK,GAAG,SAAgB,CAAC;QAEhC,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAY,EAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE,2BAA2B;YACpC,KAAK,EAAE,kBAAkB;YACzB,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,mCAAmC;SACjD,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,SAAS,CAAC,CAAC,oBAAoB,CACpC,2BAA2B,EAC3B,eAAM,CAAC,gBAAgB,CAAC;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,eAAM,CAAC,gBAAgB,CAAC;gBAC/B,cAAc,EAAE,mCAAmC;aACpD,CAAC;SACH,CAAC,CACH,CAAC;QACF,IAAA,eAAM,EAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./oauthService"), exports);
|
|
18
|
+
__exportStar(require("./authService"), exports);
|
|
19
|
+
__exportStar(require("./useAuth"), exports);
|
|
20
|
+
__exportStar(require("./useOAuth"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B;AAC/B,gDAA8B;AAC9B,4CAA0B;AAC1B,6CAA2B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export type OAuthProviderName = "google" | "github" | "normal";
|
|
2
|
+
export type OAuthProviderPreset = {
|
|
3
|
+
authorizeUrl: string;
|
|
4
|
+
tokenUrl: string;
|
|
5
|
+
scopeSeparator?: string;
|
|
6
|
+
responseType?: "code" | "token";
|
|
7
|
+
additionalAuthParams?: Record<string, string>;
|
|
8
|
+
defaultScopes?: string[];
|
|
9
|
+
};
|
|
10
|
+
export type OAuthConfig = {
|
|
11
|
+
provider: OAuthProviderName | OAuthProviderPreset;
|
|
12
|
+
clientId: string;
|
|
13
|
+
clientSecret?: string;
|
|
14
|
+
redirectUri: string;
|
|
15
|
+
scopes?: string[];
|
|
16
|
+
state?: string;
|
|
17
|
+
extraAuthParams?: Record<string, string>;
|
|
18
|
+
extraTokenParams?: Record<string, string>;
|
|
19
|
+
responseType?: "code" | "token";
|
|
20
|
+
grantType?: string;
|
|
21
|
+
usePKCE?: boolean;
|
|
22
|
+
pkceMethod?: "S256" | "plain";
|
|
23
|
+
codeVerifier?: string;
|
|
24
|
+
};
|
|
25
|
+
export type OAuthAuthResponse = {
|
|
26
|
+
code?: string;
|
|
27
|
+
access_token?: string;
|
|
28
|
+
token_type?: string;
|
|
29
|
+
expires_in?: number;
|
|
30
|
+
refresh_token?: string;
|
|
31
|
+
error?: string;
|
|
32
|
+
state?: string;
|
|
33
|
+
[key: string]: string | number | undefined;
|
|
34
|
+
};
|
|
35
|
+
export type OAuthRequest = {
|
|
36
|
+
authUrl: string;
|
|
37
|
+
codeVerifier?: string;
|
|
38
|
+
state?: string;
|
|
39
|
+
};
|
|
40
|
+
export declare function buildAuthUrl(config: OAuthConfig): string;
|
|
41
|
+
export declare function parseAuthResponse(url: string): OAuthAuthResponse;
|
|
42
|
+
export declare function createOAuthRequest(config: OAuthConfig): Promise<OAuthRequest>;
|
|
43
|
+
export declare function fetchToken(config: OAuthConfig, code: string, codeVerifier?: string): Promise<OAuthAuthResponse>;
|
|
44
|
+
export type PopupOptions = {
|
|
45
|
+
width?: number;
|
|
46
|
+
height?: number;
|
|
47
|
+
timeoutMs?: number;
|
|
48
|
+
};
|
|
49
|
+
export declare function openAuthPopup(authUrl: string, redirectUri: string, options?: PopupOptions): Promise<OAuthAuthResponse>;
|
|
50
|
+
//# sourceMappingURL=oauthService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthService.d.ts","sourceRoot":"","sources":["../src/oauthService.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/D,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,iBAAiB,GAAG,mBAAmB,CAAC;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAqEF,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAiBxD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAmBhE;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CA2BnF;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAsC5B;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,iBAAiB,CAAC,CAiD5B"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildAuthUrl = buildAuthUrl;
|
|
4
|
+
exports.parseAuthResponse = parseAuthResponse;
|
|
5
|
+
exports.createOAuthRequest = createOAuthRequest;
|
|
6
|
+
exports.fetchToken = fetchToken;
|
|
7
|
+
exports.openAuthPopup = openAuthPopup;
|
|
8
|
+
const providerPresets = {
|
|
9
|
+
google: {
|
|
10
|
+
authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
11
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
12
|
+
scopeSeparator: " ",
|
|
13
|
+
responseType: "code",
|
|
14
|
+
defaultScopes: ["openid", "profile", "email"],
|
|
15
|
+
},
|
|
16
|
+
github: {
|
|
17
|
+
authorizeUrl: "https://github.com/login/oauth/authorize",
|
|
18
|
+
tokenUrl: "https://github.com/login/oauth/access_token",
|
|
19
|
+
scopeSeparator: " ",
|
|
20
|
+
responseType: "code",
|
|
21
|
+
additionalAuthParams: {
|
|
22
|
+
allow_signup: "true",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
normal: {
|
|
26
|
+
authorizeUrl: "",
|
|
27
|
+
tokenUrl: "",
|
|
28
|
+
scopeSeparator: " ",
|
|
29
|
+
responseType: "code",
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
function normalizeProvider(config) {
|
|
33
|
+
if (typeof config.provider === "string") {
|
|
34
|
+
const preset = providerPresets[config.provider];
|
|
35
|
+
if (!preset) {
|
|
36
|
+
throw new Error(`OAuth provider preset "${config.provider}" is not defined.`);
|
|
37
|
+
}
|
|
38
|
+
return preset;
|
|
39
|
+
}
|
|
40
|
+
return config.provider;
|
|
41
|
+
}
|
|
42
|
+
function generateRandomString(length = 64) {
|
|
43
|
+
const array = new Uint8Array(length);
|
|
44
|
+
crypto.getRandomValues(array);
|
|
45
|
+
return Array.from(array)
|
|
46
|
+
.map((byte) => (byte % 36).toString(36))
|
|
47
|
+
.join("");
|
|
48
|
+
}
|
|
49
|
+
async function sha256(value) {
|
|
50
|
+
const encoder = new TextEncoder();
|
|
51
|
+
const data = encoder.encode(value);
|
|
52
|
+
return crypto.subtle.digest("SHA-256", data);
|
|
53
|
+
}
|
|
54
|
+
function base64UrlEncode(buffer) {
|
|
55
|
+
const bytes = new Uint8Array(buffer);
|
|
56
|
+
let binary = "";
|
|
57
|
+
bytes.forEach((byte) => {
|
|
58
|
+
binary += String.fromCharCode(byte);
|
|
59
|
+
});
|
|
60
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
61
|
+
}
|
|
62
|
+
async function createCodeChallenge(verifier, method = "S256") {
|
|
63
|
+
if (method === "plain") {
|
|
64
|
+
return verifier;
|
|
65
|
+
}
|
|
66
|
+
const digest = await sha256(verifier);
|
|
67
|
+
return base64UrlEncode(digest);
|
|
68
|
+
}
|
|
69
|
+
function buildAuthUrl(config) {
|
|
70
|
+
const provider = normalizeProvider(config);
|
|
71
|
+
if (!provider.authorizeUrl) {
|
|
72
|
+
throw new Error("The OAuth provider authorizeUrl is required.");
|
|
73
|
+
}
|
|
74
|
+
const params = new URLSearchParams({
|
|
75
|
+
response_type: config.responseType || provider.responseType || "code",
|
|
76
|
+
client_id: config.clientId,
|
|
77
|
+
redirect_uri: config.redirectUri,
|
|
78
|
+
scope: (config.scopes || provider.defaultScopes || []).join(provider.scopeSeparator || " "),
|
|
79
|
+
state: config.state || generateRandomString(16),
|
|
80
|
+
...provider.additionalAuthParams,
|
|
81
|
+
...config.extraAuthParams,
|
|
82
|
+
});
|
|
83
|
+
return `${provider.authorizeUrl}?${params.toString()}`;
|
|
84
|
+
}
|
|
85
|
+
function parseAuthResponse(url) {
|
|
86
|
+
const parsed = new URL(url, window.location.origin);
|
|
87
|
+
const searchParams = new URLSearchParams(parsed.search);
|
|
88
|
+
const hashParams = new URLSearchParams(parsed.hash.replace(/^#/, ""));
|
|
89
|
+
const combined = new URLSearchParams();
|
|
90
|
+
searchParams.forEach((value, key) => combined.append(key, value));
|
|
91
|
+
hashParams.forEach((value, key) => combined.append(key, value));
|
|
92
|
+
const result = {};
|
|
93
|
+
combined.forEach((value, key) => {
|
|
94
|
+
if (key === "expires_in") {
|
|
95
|
+
result.expires_in = Number(value);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
result[key] = value;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
async function createOAuthRequest(config) {
|
|
104
|
+
const provider = normalizeProvider(config);
|
|
105
|
+
if (!provider.authorizeUrl) {
|
|
106
|
+
throw new Error("The OAuth provider authorizeUrl is required.");
|
|
107
|
+
}
|
|
108
|
+
const state = config.state || generateRandomString(16);
|
|
109
|
+
const extraAuthParams = {
|
|
110
|
+
...provider.additionalAuthParams,
|
|
111
|
+
...config.extraAuthParams,
|
|
112
|
+
};
|
|
113
|
+
let codeVerifier;
|
|
114
|
+
if (config.usePKCE !== false && (config.responseType || provider.responseType || "code") === "code") {
|
|
115
|
+
codeVerifier = config.codeVerifier || generateRandomString(128);
|
|
116
|
+
const codeChallenge = await createCodeChallenge(codeVerifier, config.pkceMethod || "S256");
|
|
117
|
+
extraAuthParams.code_challenge = codeChallenge;
|
|
118
|
+
extraAuthParams.code_challenge_method = config.pkceMethod || "S256";
|
|
119
|
+
}
|
|
120
|
+
const authUrl = buildAuthUrl({
|
|
121
|
+
...config,
|
|
122
|
+
state,
|
|
123
|
+
extraAuthParams,
|
|
124
|
+
});
|
|
125
|
+
return { authUrl, codeVerifier, state };
|
|
126
|
+
}
|
|
127
|
+
async function fetchToken(config, code, codeVerifier) {
|
|
128
|
+
const provider = normalizeProvider(config);
|
|
129
|
+
if (!provider.tokenUrl) {
|
|
130
|
+
throw new Error("The OAuth provider tokenUrl is required to exchange the authorization code.");
|
|
131
|
+
}
|
|
132
|
+
const body = new URLSearchParams({
|
|
133
|
+
grant_type: config.grantType || "authorization_code",
|
|
134
|
+
code,
|
|
135
|
+
redirect_uri: config.redirectUri,
|
|
136
|
+
client_id: config.clientId,
|
|
137
|
+
...config.extraTokenParams,
|
|
138
|
+
});
|
|
139
|
+
if (codeVerifier) {
|
|
140
|
+
body.append("code_verifier", codeVerifier);
|
|
141
|
+
}
|
|
142
|
+
if (config.clientSecret) {
|
|
143
|
+
body.append("client_secret", config.clientSecret);
|
|
144
|
+
}
|
|
145
|
+
const response = await fetch(provider.tokenUrl, {
|
|
146
|
+
method: "POST",
|
|
147
|
+
headers: {
|
|
148
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
149
|
+
Accept: "application/json",
|
|
150
|
+
},
|
|
151
|
+
body: body.toString(),
|
|
152
|
+
});
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
const text = await response.text();
|
|
155
|
+
throw new Error(`Token request failed: ${response.status} ${response.statusText} - ${text}`);
|
|
156
|
+
}
|
|
157
|
+
const data = await response.json();
|
|
158
|
+
return data;
|
|
159
|
+
}
|
|
160
|
+
async function openAuthPopup(authUrl, redirectUri, options = {}) {
|
|
161
|
+
var _a;
|
|
162
|
+
const width = options.width || 500;
|
|
163
|
+
const height = options.height || 650;
|
|
164
|
+
const left = window.screenX + (window.innerWidth - width) / 2;
|
|
165
|
+
const top = window.screenY + (window.innerHeight - height) / 2;
|
|
166
|
+
const popup = window.open(authUrl, "oauth_popup", `width=${width},height=${height},left=${left},top=${top},resizable,scrollbars=yes`);
|
|
167
|
+
if (!popup) {
|
|
168
|
+
throw new Error("Unable to open OAuth popup window. Please allow popups for this site.");
|
|
169
|
+
}
|
|
170
|
+
const start = Date.now();
|
|
171
|
+
const timeoutMs = (_a = options.timeoutMs) !== null && _a !== void 0 ? _a : 120000;
|
|
172
|
+
return new Promise((resolve, reject) => {
|
|
173
|
+
const interval = window.setInterval(() => {
|
|
174
|
+
if (popup.closed) {
|
|
175
|
+
clearInterval(interval);
|
|
176
|
+
reject(new Error("OAuth popup was closed before authentication completed."));
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
const popupUrl = popup.location.href;
|
|
181
|
+
if (!popupUrl || popupUrl === "about:blank") {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (popupUrl.startsWith(redirectUri) || popup.location.search.includes("code") || popup.location.hash) {
|
|
185
|
+
const result = parseAuthResponse(popupUrl);
|
|
186
|
+
popup.close();
|
|
187
|
+
clearInterval(interval);
|
|
188
|
+
resolve(result);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
// Cross-origin access is expected until redirect back to our origin.
|
|
193
|
+
}
|
|
194
|
+
if (Date.now() - start > timeoutMs) {
|
|
195
|
+
clearInterval(interval);
|
|
196
|
+
popup.close();
|
|
197
|
+
reject(new Error("OAuth popup timeout exceeded."));
|
|
198
|
+
}
|
|
199
|
+
}, 500);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=oauthService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthService.js","sourceRoot":"","sources":["../src/oauthService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthService.test.d.ts","sourceRoot":"","sources":["../src/oauthService.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const oauthService_1 = require("./oauthService");
|
|
5
|
+
(0, vitest_1.describe)("oauthService", () => {
|
|
6
|
+
(0, vitest_1.it)("creates an OAuth request with PKCE and state", async () => {
|
|
7
|
+
const request = await (0, oauthService_1.createOAuthRequest)({
|
|
8
|
+
provider: "google",
|
|
9
|
+
clientId: "test-client",
|
|
10
|
+
redirectUri: "https://app.test/callback",
|
|
11
|
+
scopes: ["openid"],
|
|
12
|
+
usePKCE: true,
|
|
13
|
+
});
|
|
14
|
+
(0, vitest_1.expect)(request.authUrl).toContain("code_challenge=");
|
|
15
|
+
(0, vitest_1.expect)(request.authUrl).toContain("code_challenge_method=S256");
|
|
16
|
+
(0, vitest_1.expect)(request.authUrl).toContain("state=");
|
|
17
|
+
(0, vitest_1.expect)(request.codeVerifier).toBeDefined();
|
|
18
|
+
(0, vitest_1.expect)(request.state).toBeDefined();
|
|
19
|
+
});
|
|
20
|
+
(0, vitest_1.it)("parses an OAuth redirect response", () => {
|
|
21
|
+
const response = (0, oauthService_1.parseAuthResponse)("https://app.test/callback?code=abc123&state=xyz");
|
|
22
|
+
(0, vitest_1.expect)(response.code).toBe("abc123");
|
|
23
|
+
(0, vitest_1.expect)(response.state).toBe("xyz");
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=oauthService.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthService.test.js","sourceRoot":"","sources":["../src/oauthService.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,iDAAuE;AAEvE,IAAA,iBAAQ,EAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,IAAA,WAAE,EAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAkB,EAAC;YACvC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,aAAa;YACvB,WAAW,EAAE,2BAA2B;YACxC,MAAM,EAAE,CAAC,QAAQ,CAAC;YAClB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QACrD,IAAA,eAAM,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;QAChE,IAAA,eAAM,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAA,eAAM,EAAC,OAAO,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3C,IAAA,eAAM,EAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,QAAQ,GAAG,IAAA,gCAAiB,EAAC,iDAAiD,CAAC,CAAC;QACtF,IAAA,eAAM,EAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAA,eAAM,EAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AuthConfig, AuthResult } from "./authService";
|
|
2
|
+
export type UseAuthResult = {
|
|
3
|
+
execute: () => Promise<AuthResult>;
|
|
4
|
+
loading: boolean;
|
|
5
|
+
error?: string;
|
|
6
|
+
result?: AuthResult;
|
|
7
|
+
};
|
|
8
|
+
export declare function useAuth(config: AuthConfig): UseAuthResult;
|
|
9
|
+
//# sourceMappingURL=useAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../src/useAuth.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAErE,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAuBzD"}
|
package/dist/useAuth.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useAuth = useAuth;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const authService_1 = require("./authService");
|
|
6
|
+
function useAuth(config) {
|
|
7
|
+
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
8
|
+
const [error, setError] = (0, react_1.useState)();
|
|
9
|
+
const [result, setResult] = (0, react_1.useState)();
|
|
10
|
+
const execute = (0, react_1.useCallback)(async () => {
|
|
11
|
+
setLoading(true);
|
|
12
|
+
setError(undefined);
|
|
13
|
+
try {
|
|
14
|
+
const response = await (0, authService_1.authenticate)(config);
|
|
15
|
+
setResult(response);
|
|
16
|
+
return response;
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
20
|
+
setError(message);
|
|
21
|
+
throw err;
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
setLoading(false);
|
|
25
|
+
}
|
|
26
|
+
}, [config]);
|
|
27
|
+
return { execute, loading, error, result };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=useAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuth.js","sourceRoot":"","sources":["../src/useAuth.ts"],"names":[],"mappings":";;AAUA,0BAuBC;AAjCD,iCAA8C;AAC9C,+CAAqE;AASrE,SAAgB,OAAO,CAAC,MAAkB;IACxC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,GAAU,CAAC;IAC7C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,GAAc,CAAC;IAEnD,MAAM,OAAO,GAAG,IAAA,mBAAW,EAAC,KAAK,IAAI,EAAE;QACrC,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,SAAS,CAAC,CAAC;QAEpB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAA,0BAAY,EAAC,MAAM,CAAC,CAAC;YAC5C,SAAS,CAAC,QAAQ,CAAC,CAAC;YACpB,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,QAAQ,CAAC,OAAO,CAAC,CAAC;YAClB,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOAuth.d.ts","sourceRoot":"","sources":["../src/useOAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/useOAuth.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useOAuth = void 0;
|
|
4
|
+
var useAuth_1 = require("./useAuth");
|
|
5
|
+
Object.defineProperty(exports, "useOAuth", { enumerable: true, get: function () { return useAuth_1.useAuth; } });
|
|
6
|
+
//# sourceMappingURL=useOAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOAuth.js","sourceRoot":"","sources":["../src/useOAuth.ts"],"names":[],"mappings":";;;AAAA,qCAAgD;AAAvC,mGAAA,OAAO,OAAY"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "o-auth-lib",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A TypeScript-friendly authentication library for OAuth and custom login flows with PKCE support.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"prepare": "npm run build",
|
|
13
|
+
"test": "vitest run"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"oauth",
|
|
17
|
+
"react",
|
|
18
|
+
"typescript",
|
|
19
|
+
"authentication",
|
|
20
|
+
"pkce"
|
|
21
|
+
],
|
|
22
|
+
"author": "dataxis-labs",
|
|
23
|
+
"license": "ISC",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/Dataxis-UditSingh/o-auth-lib.git"
|
|
27
|
+
},
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/Dataxis-UditSingh/o-auth-lib/issues"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/Dataxis-UditSingh/o-auth-lib#readme",
|
|
32
|
+
"type": "commonjs",
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": "^17 || ^18"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^20.0.0",
|
|
38
|
+
"@types/react": "^18.0.0",
|
|
39
|
+
"jsdom": "^29.1.1",
|
|
40
|
+
"typescript": "^5.0.0",
|
|
41
|
+
"vitest": "^4.1.7"
|
|
42
|
+
}
|
|
43
|
+
}
|