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.
@@ -1,5 +1,4 @@
1
1
  export declare function useAutherr(): {
2
- user: import("../types/auth").AutherrUser | null;
3
2
  accessToken: string | null;
4
3
  isAuthenticated: boolean;
5
4
  login: () => void;
@@ -1,8 +1,7 @@
1
1
  import { useAutherrContext } from "../provider/AutherrProvider";
2
2
  export function useAutherr() {
3
- const { user, accessToken, isAuthenticated, login, signup, logout, getAccessToken, refreshSession, } = useAutherrContext();
3
+ const { accessToken, isAuthenticated, login, signup, logout, getAccessToken, refreshSession, } = useAutherrContext();
4
4
  return {
5
- user,
6
5
  accessToken,
7
6
  isAuthenticated,
8
7
  login,
@@ -1,7 +1,5 @@
1
1
  import React from "react";
2
- import { AutherrUser } from "../types/auth";
3
2
  interface AutherrContextValue {
4
- user: AutherrUser | null;
5
3
  accessToken: string | null;
6
4
  isAuthenticated: boolean;
7
5
  login: () => void;
@@ -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
- }), [user, accessToken, isAuthenticated]);
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": "1.0.1",
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
+ }
@@ -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);