this repo has no description
1import {
2 type Key,
3 type JwtHeader,
4 type JwtPayload,
5 type SignedJwt,
6 type VerifyOptions,
7 type VerifyResult,
8} from "@atproto/oauth-client";
9import type { JWK } from "./ExpoAtprotoAuth.types";
10import { default as NativeModule } from "./ExpoAtprotoAuthModule";
11
12export function getRandomValues(byteLength: number): Uint8Array {
13 return NativeModule.getRandomValues(byteLength);
14}
15
16export function digest(data: Uint8Array, algorithim: string): Uint8Array {
17 return NativeModule.digest(data, algorithim);
18}
19
20export function isECKey(jwk: any): jwk is JWK {
21 return jwk?.kty === "EC" && jwk.crv && jwk.y;
22}
23
24export function createJwt(
25 header: string,
26 payload: string,
27 key: ReactNativeKey,
28): string {
29 if (!key.privateJwk || !isECKey(key.privateJwk)) {
30 throw new Error("Invalid key");
31 }
32 return NativeModule.createJwt(header, payload, key.privateJwk);
33}
34
35export function verifyJwt(
36 token: string,
37 jwk: JWK,
38 options: VerifyOptions,
39): VerifyResult {
40 return NativeModule.verifyJwt(token, jwk, options);
41}
42
43// @ts-expect-error
44export class ReactNativeKey implements Key {
45 #jwk: Readonly<JWK>;
46
47 constructor(jwk: Readonly<JWK>) {
48 this.#jwk = jwk;
49 if (!isECKey(jwk)) {
50 throw new Error("Invalid key type");
51 }
52 if (!jwk.use) {
53 throw new Error(`Missing "use" parameter value`);
54 }
55 }
56
57 get jwk(): Readonly<JWK> {
58 return this.#jwk;
59 }
60
61 get isPrivate() {
62 return this.jwk.d !== undefined;
63 }
64
65 get privateJwk(): JWK {
66 return this.jwk;
67 }
68
69 get publicJwk() {
70 if (this.isSymetric) return undefined;
71 const { d, ...publicKey } = this.jwk;
72 return publicKey as Readonly<JWK & { d?: never }>;
73 }
74
75 get use() {
76 return this.jwk.use as NonNullable<"sig" | "enc" | undefined>;
77 }
78
79 get alg() {
80 return this.jwk.alg;
81 }
82
83 get kid() {
84 return this.jwk.kid;
85 }
86
87 get crv() {
88 return this.jwk.crv;
89 }
90
91 get algorithms() {
92 return [this.jwk.alg];
93 }
94
95 get bareJwk() {
96 return {
97 kty: this.jwk.kty,
98 crv: this.jwk.crv,
99 x: this.jwk.x,
100 y: this.jwk.y,
101 };
102 }
103
104 get isSymetric() {
105 return (
106 this.jwk.kty === "oct" && "k" in this.jwk && this.jwk.k !== undefined
107 );
108 }
109
110 async createJwt(header: JwtHeader, payload: JwtPayload): Promise<SignedJwt> {
111 return createJwt(
112 JSON.stringify(header),
113 JSON.stringify(payload),
114 this,
115 ) as "${string}.${string}.${string}";
116 }
117
118 async verifyJwt<C extends string = never>(
119 token: SignedJwt,
120 options?: VerifyOptions<C>,
121 ): Promise<VerifyResult<C>> {
122 return verifyJwt(
123 token,
124 this.jwk,
125 (options ?? {}) as VerifyOptions,
126 ) as VerifyResult<C>;
127 }
128}
129
130export function generateJwk(algoritihim: string): ReactNativeKey {
131 const privJwk = NativeModule.generatePrivateJwk(algoritihim);
132 return new ReactNativeKey(privJwk);
133}