@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 +38 -0
- package/dist/native/octane-client-build.json +1 -1
- package/dist/web/octane-client-build.json +1 -1
- package/package.json +13 -13
- package/src/apple.macos.ts +60 -17
- package/src/apple.web.ts +7 -4
- package/src/google.web.ts +5 -1
- package/src/index.ts +5 -5
- package/src/index.web.ts +5 -5
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).
|
package/package.json
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octane-xplat/auth",
|
|
3
|
-
"version": "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
|
-
"
|
|
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
|
-
"
|
|
17
|
-
"
|
|
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": "
|
|
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.
|
|
63
|
+
"tsrx-typegen": "0.2.1",
|
|
64
64
|
"typescript": "5.9.3",
|
|
65
65
|
"vite": "8.3.0"
|
|
66
66
|
},
|
package/src/apple.macos.ts
CHANGED
|
@@ -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 (
|
|
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([
|
|
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++) {
|
|
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 =
|
|
80
|
-
|
|
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
|
|
91
|
-
|
|
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
|
|
95
|
-
H[
|
|
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
|
|
112
|
-
|
|
113
|
-
|
|
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(
|
|
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 =
|
|
51
|
-
.filter(Boolean)
|
|
52
|
-
|
|
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
|
-
: {
|
|
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: {
|
|
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'
|