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 // eslint-disable-next-line @typescript-eslint/no-unused-vars
72 const { d, ...publicKey } = this.jwk
73 return publicKey as Readonly<JWK & { d?: never }>
74 }
75
76 get use() {
77 return this.jwk.use as NonNullable<'sig' | 'enc' | undefined>
78 }
79
80 get alg() {
81 return this.jwk.alg
82 }
83
84 get kid() {
85 return this.jwk.kid
86 }
87
88 get crv() {
89 return this.jwk.crv
90 }
91
92 get algorithms() {
93 return [this.jwk.alg]
94 }
95
96 get bareJwk() {
97 return {
98 kty: this.jwk.kty,
99 crv: this.jwk.crv,
100 x: this.jwk.x,
101 y: this.jwk.y,
102 }
103 }
104
105 get isSymetric() {
106 return this.jwk.kty === 'oct' && 'k' in this.jwk && this.jwk.k !== undefined
107 }
108
109 async createJwt(header: JwtHeader, payload: JwtPayload): Promise<SignedJwt> {
110 return createJwt(
111 JSON.stringify(header),
112 JSON.stringify(payload),
113 this
114 ) as '${string}.${string}.${string}'
115 }
116
117 async verifyJwt<C extends string = never>(
118 token: SignedJwt,
119 options?: VerifyOptions<C>
120 ): Promise<VerifyResult<C>> {
121 return verifyJwt(
122 token,
123 this.jwk,
124 (options ?? {}) as VerifyOptions
125 ) as VerifyResult<C>
126 }
127}
128
129export function generateJwk(algoritihim: string): ReactNativeKey {
130 const privJwk = NativeModule.generatePrivateJwk(algoritihim)
131 return new ReactNativeKey(privJwk)
132}