autherr 1.0.1 → 2.0.1
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/dist/hooks/useAutherr.d.ts +0 -1
- package/dist/hooks/useAutherr.js +1 -2
- package/dist/provider/AutherrProvider.d.ts +0 -2
- package/dist/provider/AutherrProvider.js +1 -5
- package/package.json +2 -1
- package/src/crypto/createClientAssertion.ts +29 -0
- package/src/crypto/pemUtils.ts +16 -0
- package/src/hooks/useAutherr.ts +0 -2
- package/src/provider/AutherrProvider.tsx +31 -2
package/dist/hooks/useAutherr.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { useAutherrContext } from "../provider/AutherrProvider";
|
|
2
2
|
export function useAutherr() {
|
|
3
|
-
const {
|
|
3
|
+
const { accessToken, isAuthenticated, login, signup, logout, getAccessToken, refreshSession, } = useAutherrContext();
|
|
4
4
|
return {
|
|
5
|
-
user,
|
|
6
5
|
accessToken,
|
|
7
6
|
isAuthenticated,
|
|
8
7
|
login,
|
|
@@ -4,7 +4,6 @@ import { fetchSession } from "../api/session";
|
|
|
4
4
|
import { logoutSession } from "../api/logout";
|
|
5
5
|
const AutherrContext = createContext(null);
|
|
6
6
|
export function AutherrProvider({ children, clientId, baseUrl, }) {
|
|
7
|
-
const [user, setUser] = useState(null);
|
|
8
7
|
const [accessToken, setAccessToken] = useState(null);
|
|
9
8
|
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
10
9
|
const refreshSession = async () => {
|
|
@@ -14,7 +13,6 @@ export function AutherrProvider({ children, clientId, baseUrl, }) {
|
|
|
14
13
|
setIsAuthenticated(true);
|
|
15
14
|
}
|
|
16
15
|
else {
|
|
17
|
-
setUser(null);
|
|
18
16
|
setAccessToken(null);
|
|
19
17
|
setIsAuthenticated(false);
|
|
20
18
|
}
|
|
@@ -43,14 +41,12 @@ export function AutherrProvider({ children, clientId, baseUrl, }) {
|
|
|
43
41
|
await logoutSession(baseUrl, clientId);
|
|
44
42
|
}
|
|
45
43
|
finally {
|
|
46
|
-
setUser(null);
|
|
47
44
|
setAccessToken(null);
|
|
48
45
|
setIsAuthenticated(false);
|
|
49
46
|
window.location.href = window.location.origin;
|
|
50
47
|
}
|
|
51
48
|
};
|
|
52
49
|
const value = useMemo(() => ({
|
|
53
|
-
user,
|
|
54
50
|
accessToken,
|
|
55
51
|
isAuthenticated,
|
|
56
52
|
login,
|
|
@@ -58,7 +54,7 @@ export function AutherrProvider({ children, clientId, baseUrl, }) {
|
|
|
58
54
|
logout,
|
|
59
55
|
refreshSession,
|
|
60
56
|
getAccessToken: () => accessToken,
|
|
61
|
-
}), [
|
|
57
|
+
}), [accessToken, isAuthenticated]);
|
|
62
58
|
return (_jsx(AutherrContext.Provider, { value: value, children: children }));
|
|
63
59
|
}
|
|
64
60
|
export function useAutherrContext() {
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autherr",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"dest": "dist",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "tsc -p tsconfig.json"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
+
"jose": "^6.1.3",
|
|
10
11
|
"react": "^19.2.3"
|
|
11
12
|
},
|
|
12
13
|
"devDependencies": {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/crypto/createClientAssertion.ts
|
|
2
|
+
import { SignJWT } from "jose";
|
|
3
|
+
import { pemToArrayBuffer } from "./pemUtils";
|
|
4
|
+
|
|
5
|
+
export async function createClientAssertion(
|
|
6
|
+
clientId: string,
|
|
7
|
+
privateKeyPem: string
|
|
8
|
+
): Promise<string> {
|
|
9
|
+
const key = await crypto.subtle.importKey(
|
|
10
|
+
"pkcs8",
|
|
11
|
+
pemToArrayBuffer(privateKeyPem),
|
|
12
|
+
{
|
|
13
|
+
name: "RSASSA-PKCS1-v1_5",
|
|
14
|
+
hash: "SHA-256",
|
|
15
|
+
},
|
|
16
|
+
false,
|
|
17
|
+
["sign"]
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const now = Math.floor(Date.now() / 1000);
|
|
21
|
+
|
|
22
|
+
return await new SignJWT({ clientId })
|
|
23
|
+
.setProtectedHeader({ alg: "RS256", typ: "JWT" })
|
|
24
|
+
.setIssuedAt(now)
|
|
25
|
+
.setExpirationTime(now + 120) // ⏱ 2 minutes
|
|
26
|
+
.setAudience("autherr")
|
|
27
|
+
.setIssuer(clientId)
|
|
28
|
+
.sign(key);
|
|
29
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/crypto/pemUtils.ts
|
|
2
|
+
export function pemToArrayBuffer(pem: string): ArrayBuffer {
|
|
3
|
+
const b64 = pem
|
|
4
|
+
.replace(/-----BEGIN [^-]+-----/, "")
|
|
5
|
+
.replace(/-----END [^-]+-----/, "")
|
|
6
|
+
.replace(/\s+/g, "");
|
|
7
|
+
|
|
8
|
+
const binary = atob(b64);
|
|
9
|
+
const bytes = new Uint8Array(binary.length);
|
|
10
|
+
|
|
11
|
+
for (let i = 0; i < binary.length; i++) {
|
|
12
|
+
bytes[i] = binary.charCodeAt(i);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return bytes.buffer;
|
|
16
|
+
}
|
package/src/hooks/useAutherr.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { useAutherrContext } from "../provider/AutherrProvider";
|
|
|
2
2
|
|
|
3
3
|
export function useAutherr() {
|
|
4
4
|
const {
|
|
5
|
-
user,
|
|
6
5
|
accessToken,
|
|
7
6
|
isAuthenticated,
|
|
8
7
|
login,
|
|
@@ -13,7 +12,6 @@ export function useAutherr() {
|
|
|
13
12
|
} = useAutherrContext();
|
|
14
13
|
|
|
15
14
|
return {
|
|
16
|
-
user,
|
|
17
15
|
accessToken,
|
|
18
16
|
isAuthenticated,
|
|
19
17
|
login,
|
|
@@ -8,6 +8,7 @@ import React, {
|
|
|
8
8
|
import { fetchSession } from "../api/session";
|
|
9
9
|
import { logoutSession } from "../api/logout";
|
|
10
10
|
import { AutherrUser } from "../types/auth";
|
|
11
|
+
import { createClientAssertion } from "../crypto/createClientAssertion";
|
|
11
12
|
|
|
12
13
|
interface AutherrContextValue {
|
|
13
14
|
accessToken: string | null;
|
|
@@ -19,6 +20,15 @@ interface AutherrContextValue {
|
|
|
19
20
|
refreshSession: () => Promise<void>;
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
function setClientAssertionCookie(token: string) {
|
|
24
|
+
document.cookie =
|
|
25
|
+
`autherr_client_assertion=${token};` +
|
|
26
|
+
`Path=/;` +
|
|
27
|
+
`Secure;` +
|
|
28
|
+
`SameSite=None`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
22
32
|
|
|
23
33
|
const AutherrContext = createContext<AutherrContextValue | null>(null);
|
|
24
34
|
|
|
@@ -26,12 +36,14 @@ interface AutherrProviderProps {
|
|
|
26
36
|
children: React.ReactNode;
|
|
27
37
|
clientId: string;
|
|
28
38
|
baseUrl: string; // e.g. https://autherr.com
|
|
39
|
+
clientPrivateKey: string;
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
export function AutherrProvider({
|
|
32
43
|
children,
|
|
33
44
|
clientId,
|
|
34
45
|
baseUrl,
|
|
46
|
+
clientPrivateKey,
|
|
35
47
|
}: AutherrProviderProps) {
|
|
36
48
|
|
|
37
49
|
const [accessToken, setAccessToken] = useState<string | null>(null);
|
|
@@ -54,8 +66,16 @@ export function AutherrProvider({
|
|
|
54
66
|
refreshSession();
|
|
55
67
|
}, [baseUrl, clientId]);
|
|
56
68
|
|
|
57
|
-
const login = () => {
|
|
69
|
+
const login = async () => {
|
|
58
70
|
const state = crypto.randomUUID();
|
|
71
|
+
|
|
72
|
+
const assertion = await createClientAssertion(
|
|
73
|
+
clientId,
|
|
74
|
+
clientPrivateKey
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
setClientAssertionCookie(assertion);
|
|
78
|
+
|
|
59
79
|
window.location.href =
|
|
60
80
|
`${baseUrl}/auth/login` +
|
|
61
81
|
`?client_id=${clientId}` +
|
|
@@ -63,8 +83,16 @@ export function AutherrProvider({
|
|
|
63
83
|
`&state=${state}`;
|
|
64
84
|
};
|
|
65
85
|
|
|
66
|
-
const signup = () => {
|
|
86
|
+
const signup = async () => {
|
|
67
87
|
const state = crypto.randomUUID();
|
|
88
|
+
|
|
89
|
+
const assertion = await createClientAssertion(
|
|
90
|
+
clientId,
|
|
91
|
+
clientPrivateKey
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
setClientAssertionCookie(assertion);
|
|
95
|
+
|
|
68
96
|
window.location.href =
|
|
69
97
|
`${baseUrl}/auth/signup` +
|
|
70
98
|
`?client_id=${clientId}` +
|
|
@@ -72,6 +100,7 @@ export function AutherrProvider({
|
|
|
72
100
|
`&state=${state}`;
|
|
73
101
|
};
|
|
74
102
|
|
|
103
|
+
|
|
75
104
|
const logout = async () => {
|
|
76
105
|
try {
|
|
77
106
|
await logoutSession(baseUrl, clientId);
|