@octane-xplat/auth 0.8.0 → 0.9.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 ADDED
@@ -0,0 +1,38 @@
1
+ # `@octane-xplat/auth`
2
+
3
+ Sign in with Apple and Google Sign-In for Octane xplat apps — the native
4
+ SDKs (`@nativescript/apple-sign-in`, `@nativescript/google-signin`) on
5
+ iOS/Android, the providers' web SDKs (Apple JS / Google Identity Services)
6
+ in the browser, and AuthenticationServices through the ObjC bridge plus a
7
+ Google flow on the macOS AppKit host. One `AuthUser`/`AuthCredential`
8
+ contract everywhere.
9
+
10
+ ```sh
11
+ pnpm add @octane-xplat/auth
12
+ ```
13
+
14
+ ```tsx
15
+ import { appleAuth, googleAuth, AppleSignInButton } from '@octane-xplat/auth'
16
+
17
+ appleAuth.configure({ clientId: 'com.example.app.web' }) // web-only fields
18
+
19
+ const result = await appleAuth.signIn({ scopes: ['email', 'name'] })
20
+ if (result.status === 'success') {
21
+ const { idToken, user } = result.credential // hand idToken to your backend
22
+ }
23
+ ```
24
+
25
+ Each provider object reports `supported` — Apple is `false` on Android —
26
+ and exposes `configure`, `signIn`, and provider extras
27
+ (`appleAuth.getCredentialState`, `googleAuth.signOut`). `SignInResult`
28
+ distinguishes `success` / `cancelled` / `error`; a dismissed sheet is
29
+ `cancelled`, not a throw. The sign-in buttons are platform-authentic
30
+ components, so render them from platform-suffixed files or accept each
31
+ target's native styling.
32
+
33
+ Web needs registered client IDs; iOS needs the `applesignin` entitlement
34
+ and Google's `GoogleService-Info.plist`/reversed-client-id URL scheme;
35
+ Android needs `google-services.json` and a `serverClientId` for
36
+ `serverAuthCode`. Guide: [Using device
37
+ features](../../docs/platform-services.md). Exercised by
38
+ [`AuthDemo`](../demos/src/AuthDemo.tsrx).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "buildId": "b22aa5b8-e210-4f27-babd-a9c30bb0a8dd",
3
+ "buildId": "2924c745-ebe0-4012-9aea-c8c26eeb7458",
4
4
  "mode": "production",
5
5
  "capabilities": {
6
6
  "independentHydration": false
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "buildId": "321142a6-1005-48c0-850a-256122cdddf2",
3
+ "buildId": "dc0dd9f6-f1fb-4b15-a5c3-95ddbe1709aa",
4
4
  "mode": "production",
5
5
  "capabilities": {
6
6
  "independentHydration": false
package/package.json CHANGED
@@ -1,26 +1,26 @@
1
1
  {
2
2
  "name": "@octane-xplat/auth",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Sign in with Apple + Google Sign-In for Octane xplat — native SDKs on iOS/Android, platform web SDKs in the browser",
5
5
  "keywords": [
6
- "octane",
7
- "xplat",
8
- "cross-platform",
9
- "auth",
10
- "sign-in",
6
+ "android",
11
7
  "apple",
8
+ "auth",
9
+ "cross-platform",
12
10
  "google",
13
- "oauth",
14
- "nativescript",
15
11
  "ios",
16
- "android",
17
- "web"
12
+ "nativescript",
13
+ "oauth",
14
+ "octane",
15
+ "sign-in",
16
+ "web",
17
+ "xplat"
18
18
  ],
19
- "license": "MIT",
20
19
  "homepage": "https://github.com/octane-xplat/octane-xplat/tree/main/packages/auth",
20
+ "license": "MIT",
21
21
  "repository": {
22
22
  "type": "git",
23
- "url": "git+https://github.com/octane-xplat/octane-xplat.git",
23
+ "url": "https://github.com/octane-xplat/octane-xplat",
24
24
  "directory": "packages/auth"
25
25
  },
26
26
  "files": [
@@ -60,7 +60,7 @@
60
60
  "@octanejs/vite-plugin": "0.1.61",
61
61
  "@tsrx/typescript-plugin": "0.4.11",
62
62
  "octane": "0.6.3",
63
- "tsrx-typegen": "0.2.0",
63
+ "tsrx-typegen": "0.2.1",
64
64
  "typescript": "5.9.3",
65
65
  "vite": "8.3.0"
66
66
  },
@@ -40,7 +40,10 @@ const SCOPE_MAP: Record<string, () => any> = {
40
40
 
41
41
  function isCancel(error: unknown): boolean {
42
42
  // ASAuthorizationError.canceled = 1001 (NSError.code).
43
- return (error as any)?.code === 1001 || /cancel/i.test(String((error as any)?.localizedDescription ?? error))
43
+ return (
44
+ (error as any)?.code === 1001 ||
45
+ /cancel/i.test(String((error as any)?.localizedDescription ?? error))
46
+ )
44
47
  }
45
48
 
46
49
  function utf8Bytes(input: string): Uint8Array {
@@ -63,7 +66,10 @@ function sha256Hex(input: string): string {
63
66
  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
64
67
  ])
65
68
 
66
- const H = new Uint32Array([0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19])
69
+ const H = new Uint32Array([
70
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
71
+ ])
72
+
67
73
  const bytes = utf8Bytes(input)
68
74
  const bitLen = bytes.length * 8
69
75
  const padded = new Uint8Array((bytes.length + 9 + 63) & ~63)
@@ -74,25 +80,48 @@ function sha256Hex(input: string): string {
74
80
  dv.setUint32(padded.length - 4, bitLen >>> 0)
75
81
  const w = new Uint32Array(64)
76
82
  for (let block = 0; block < padded.length; block += 64) {
77
- for (let t = 0; t < 16; t++) {w[t] = dv.getUint32(block + t * 4)}
83
+ for (let t = 0; t < 16; t++) {
84
+ w[t] = dv.getUint32(block + t * 4)
85
+ }
86
+
78
87
  for (let t = 16; t < 64; t++) {
79
- const s0 = (w[t - 15] >>> 7 | w[t - 15] << 25) ^ (w[t - 15] >>> 18 | w[t - 15] << 14) ^ (w[t - 15] >>> 3)
80
- const s1 = (w[t - 2] >>> 17 | w[t - 2] << 15) ^ (w[t - 2] >>> 19 | w[t - 2] << 13) ^ (w[t - 2] >>> 10)
88
+ const s0 =
89
+ ((w[t - 15] >>> 7) | (w[t - 15] << 25)) ^
90
+ ((w[t - 15] >>> 18) | (w[t - 15] << 14)) ^
91
+ (w[t - 15] >>> 3)
92
+
93
+ const s1 =
94
+ ((w[t - 2] >>> 17) | (w[t - 2] << 15)) ^
95
+ ((w[t - 2] >>> 19) | (w[t - 2] << 13)) ^
96
+ (w[t - 2] >>> 10)
97
+
81
98
  w[t] = (w[t - 16] + s0 + w[t - 7] + s1) >>> 0
82
99
  }
83
100
 
84
101
  let [a, b, c, d, e, f, g, h] = H
85
102
  for (let t = 0; t < 64; t++) {
86
- const S1 = (e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7)
103
+ const S1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7))
87
104
  const t1 = (h + S1 + ((e & f) ^ (~e & g)) + K[t] + w[t]) >>> 0
88
- const S0 = (a >>> 2 | a << 30) ^ (a >>> 13 | a << 19) ^ (a >>> 22 | a << 10)
105
+ const S0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10))
89
106
  const t2 = (S0 + ((a & b) ^ (a & c) ^ (b & c))) >>> 0
90
- h = g; g = f; f = e; e = (d + t1) >>> 0
91
- d = c; c = b; b = a; a = (t1 + t2) >>> 0
107
+ h = g
108
+ g = f
109
+ f = e
110
+ e = (d + t1) >>> 0
111
+ d = c
112
+ c = b
113
+ b = a
114
+ a = (t1 + t2) >>> 0
92
115
  }
93
116
 
94
- H[0] = (H[0] + a) >>> 0; H[1] = (H[1] + b) >>> 0; H[2] = (H[2] + c) >>> 0; H[3] = (H[3] + d) >>> 0
95
- H[4] = (H[4] + e) >>> 0; H[5] = (H[5] + f) >>> 0; H[6] = (H[6] + g) >>> 0; H[7] = (H[7] + h) >>> 0
117
+ H[0] = (H[0] + a) >>> 0
118
+ H[1] = (H[1] + b) >>> 0
119
+ H[2] = (H[2] + c) >>> 0
120
+ H[3] = (H[3] + d) >>> 0
121
+ H[4] = (H[4] + e) >>> 0
122
+ H[5] = (H[5] + f) >>> 0
123
+ H[6] = (H[6] + g) >>> 0
124
+ H[7] = (H[7] + h) >>> 0
96
125
  }
97
126
 
98
127
  return [...H].map((x) => x.toString(16).padStart(8, '0')).join('')
@@ -102,15 +131,21 @@ function toCredential(credential: any): AuthCredential {
102
131
  const tokenData = credential.valueForKey('identityToken')
103
132
  const codeData = credential.valueForKey('authorizationCode')
104
133
  const fullName = credential.fullName
105
- const name =
106
- [fullName?.givenName, fullName?.familyName].filter(Boolean).join(' ') || undefined
134
+ const name = [fullName?.givenName, fullName?.familyName].filter(Boolean).join(' ') || undefined
107
135
 
108
136
  return {
109
137
  provider: 'apple',
110
138
  idToken: tokenData ? String(NSString.alloc().initWithDataEncoding(tokenData, 4)) : undefined,
111
- authorizationCode: codeData ? String(NSString.alloc().initWithDataEncoding(codeData, 4)) : undefined,
112
- scopes: (credential.authorizedScopes ? Array.from(credential.authorizedScopes as any) : []).map((s: any) =>
113
- s === ASAuthorizationScopeEmail ? 'email' : s === ASAuthorizationScopeFullName ? 'name' : String(s),
139
+ authorizationCode: codeData
140
+ ? String(NSString.alloc().initWithDataEncoding(codeData, 4))
141
+ : undefined,
142
+ scopes: (credential.authorizedScopes ? Array.from(credential.authorizedScopes as any) : []).map(
143
+ (s: any) =>
144
+ s === ASAuthorizationScopeEmail
145
+ ? 'email'
146
+ : s === ASAuthorizationScopeFullName
147
+ ? 'name'
148
+ : String(s),
114
149
  ),
115
150
  user: {
116
151
  id: String(credential.user ?? ''),
@@ -269,7 +304,15 @@ export const appleAuth: AppleAuth = {
269
304
  return
270
305
  }
271
306
 
272
- resolve(state === 1 ? 'authorized' : state === 0 ? 'revoked' : state === 3 ? 'transferred' : 'notFound')
307
+ resolve(
308
+ state === 1
309
+ ? 'authorized'
310
+ : state === 0
311
+ ? 'revoked'
312
+ : state === 3
313
+ ? 'transferred'
314
+ : 'notFound',
315
+ )
273
316
  },
274
317
  )
275
318
  })
package/src/apple.web.ts CHANGED
@@ -47,9 +47,9 @@ function decodeJwt(token: string): Record<string, any> {
47
47
  function toCredential(response: any): AuthCredential {
48
48
  const auth = response?.authorization ?? {}
49
49
  const claims = auth.id_token ? decodeJwt(auth.id_token) : {}
50
- const name = [response?.user?.name?.firstName, response?.user?.name?.lastName]
51
- .filter(Boolean)
52
- .join(' ') || undefined
50
+ const name =
51
+ [response?.user?.name?.firstName, response?.user?.name?.lastName].filter(Boolean).join(' ') ||
52
+ undefined
53
53
 
54
54
  return {
55
55
  provider: 'apple',
@@ -101,7 +101,10 @@ export const appleAuth: AppleAuth = {
101
101
  } catch (error) {
102
102
  return isCancel(error)
103
103
  ? { status: 'cancelled' }
104
- : { status: 'error', message: String((error as any)?.message ?? (error as any)?.error ?? error) }
104
+ : {
105
+ status: 'error',
106
+ message: String((error as any)?.message ?? (error as any)?.error ?? error),
107
+ }
105
108
  }
106
109
  },
107
110
  async getCredentialState(): Promise<AppleCredentialState> {
package/src/google.web.ts CHANGED
@@ -78,7 +78,11 @@ function initialize(google: any) {
78
78
  /** Internal — the button leaf renders the official GIS button into `host`. */
79
79
  export async function renderGoogleButton(
80
80
  host: HTMLElement,
81
- options: { theme?: 'dark' | 'light' | 'auto'; variant?: 'standard' | 'wide' | 'icon'; width?: number },
81
+ options: {
82
+ theme?: 'dark' | 'light' | 'auto'
83
+ variant?: 'standard' | 'wide' | 'icon'
84
+ width?: number
85
+ },
82
86
  onResult: (result: SignInResult) => void,
83
87
  ): Promise<void> {
84
88
  if (!config.clientId) {
package/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  // Platform barrels — explicit .tsrx leaf imports (moduleSuffixes don't
2
2
  // reach .tsrx; same convention as @octane-xplat/ui index.*.ts).
3
- export { appleAuth } from './apple';
4
- export { googleAuth } from './google';
5
- export { AppleSignInButton } from './AppleSignInButton.tsrx';
6
- export { GoogleSignInButton } from './GoogleSignInButton.tsrx';
3
+ export { appleAuth } from './apple'
4
+ export { googleAuth } from './google'
5
+ export { AppleSignInButton } from './AppleSignInButton.tsrx'
6
+ export { GoogleSignInButton } from './GoogleSignInButton.tsrx'
7
7
  export type {
8
8
  AppleAuth,
9
9
  AppleAuthConfig,
@@ -18,4 +18,4 @@ export type {
18
18
  GoogleSignInButtonProps,
19
19
  GoogleSignInOptions,
20
20
  SignInResult,
21
- } from './types';
21
+ } from './types'
package/src/index.web.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  // Platform barrels — explicit .tsrx leaf imports (moduleSuffixes don't
2
2
  // reach .tsrx; same convention as @octane-xplat/ui index.*.ts).
3
- export { appleAuth } from './apple.web';
4
- export { googleAuth } from './google.web';
5
- export { AppleSignInButton } from './AppleSignInButton.web.tsrx';
6
- export { GoogleSignInButton } from './GoogleSignInButton.web.tsrx';
3
+ export { appleAuth } from './apple.web'
4
+ export { googleAuth } from './google.web'
5
+ export { AppleSignInButton } from './AppleSignInButton.web.tsrx'
6
+ export { GoogleSignInButton } from './GoogleSignInButton.web.tsrx'
7
7
  export type {
8
8
  AppleAuth,
9
9
  AppleAuthConfig,
@@ -18,4 +18,4 @@ export type {
18
18
  GoogleSignInButtonProps,
19
19
  GoogleSignInOptions,
20
20
  SignInResult,
21
- } from './types';
21
+ } from './types'