Skip to content

Commit c7d982e

Browse files
Chris Bobbechrisbobbe
authored andcommitted
iOS deps: Add expo-apple-authentication at latest.
Following their instructions for a "bare" app (as opposed to "managed" by Expo) [1], which include the addition of the "Sign in with Apple" entitlement, which we did through the Xcode UI as instructed. We don't have to worry about excluding this package from being linked on Android, it seems; its `unimodule.json` specifies `"platforms": ["ios"]`. Empirically (when running Jest), there seems to be uncompiled JavaScript in this package, so add an entry in `transformModulesWhitelist`. Also mock the module, as we then get errors about things being undefined. [1]: https://github.com/expo/expo/tree/1c5eb9818/packages/expo-apple-authentication
1 parent 6e0d3bf commit c7d982e

File tree

8 files changed

+364
-0
lines changed

8 files changed

+364
-0
lines changed

docs/howto/libdefs.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,43 @@ Flow and FlowTyped about not being able to import third-party types
152152
into one's own libdefs that haven't been resolved. [9]
153153

154154
[9]: https://github.com/zulip/zulip-mobile/issues/3458#issuecomment-639859987
155+
156+
## Expo packages (made available through Unimodules)
157+
158+
We're starting to see a pattern developing with these, e.g.:
159+
160+
- `expo-apple-authentication`
161+
- `expo-screen-orientation`
162+
163+
Namely:
164+
165+
1. See what `node_modules/expo-name-of-package/build/index.d.ts`
166+
depends on; it's probably at least `'./NameOfPackage'` and
167+
`'./NameOfPackage.types'`.
168+
169+
Assuming so, make a `declare module expo-name-of-package` block and
170+
have it do what that `index.d.ts` does, maybe
171+
172+
```javascript
173+
declare module 'expo-name-of-package' {
174+
declare export * from 'expo-name-of-package/build/NameOfPackage'
175+
declare export * from 'expo-name-of-package/build/NameOfPackage.types'
176+
}
177+
```
178+
179+
2. Run `node_modules/expo-name-of-package/build/NameOfPackage.d.ts`
180+
through Flowgen and paste the output into a
181+
`declare module 'expo-name-of-package/build/NameOfPackage'`
182+
block.
183+
2. Run `node_modules/expo-name-of-package/build/PackageName.types'`
184+
through Flowgen and paste the output into a
185+
`declare module 'expo-screen-orientation/build/ScreenOrientation.types'`
186+
block.
187+
3. Make any necessary syntactic fixes based on error messages (in
188+
particular, replacing `export` with `declare export` everywhere may
189+
be necessary) or adjustments to imports. You may only import from
190+
something that's been declared in that same file, with
191+
`declare export` [1] [2].
192+
193+
[1]: https://github.com/flow-typed/flow-typed/blob/master/CONTRIBUTING.md#dont-import-types-from-other-libdefs
194+
[2]: See discussion around https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/libdef.3A.20react-native-webview/near/896713.
Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
// Assembled with help from Flowgen v1.10.0.
2+
//
3+
// The modules 'expo-apple-authentication/build/AppleAuthentication',
4+
// 'expo-apple-authentication/build/AppleAuthenticationButton', and
5+
// 'expo-apple-authentication/build/AppleAuthentication.types' are the
6+
// result of passing those files in node_modules through Flowgen and
7+
// doing some minor syntactic tweaks.
8+
9+
declare module 'expo-apple-authentication/build/AppleAuthentication' {
10+
import type {
11+
AppleAuthenticationSignInOptions,
12+
AppleAuthenticationRefreshOptions,
13+
AppleAuthenticationSignOutOptions,
14+
AppleAuthenticationCredential,
15+
AppleAuthenticationRevokeListener,
16+
} from 'expo-apple-authentication/build/AppleAuthentication.types';
17+
import typeof { AppleAuthenticationCredentialState } from 'expo-apple-authentication/build/AppleAuthentication.types';
18+
19+
declare type Subscription = {
20+
remove: () => void,
21+
};
22+
23+
declare export function isAvailableAsync(): Promise<boolean>;
24+
declare export function signInAsync(
25+
options?: AppleAuthenticationSignInOptions,
26+
): Promise<AppleAuthenticationCredential>;
27+
declare export function refreshAsync(
28+
options: AppleAuthenticationRefreshOptions,
29+
): Promise<AppleAuthenticationCredential>;
30+
declare export function signOutAsync(
31+
options: AppleAuthenticationSignOutOptions,
32+
): Promise<AppleAuthenticationCredential>;
33+
declare export function getCredentialStateAsync(
34+
user: string,
35+
): Promise<AppleAuthenticationCredentialState>;
36+
declare export function addRevokeListener(
37+
listener: AppleAuthenticationRevokeListener,
38+
): Subscription;
39+
}
40+
41+
declare module 'expo-apple-authentication/build/AppleAuthentication.types' {
42+
declare export type AppleAuthenticationButtonProps = {
43+
onPress: () => void,
44+
buttonType: $Values<typeof AppleAuthenticationButtonType>,
45+
buttonStyle: $Values<typeof AppleAuthenticationButtonStyle>,
46+
cornerRadius?: number,
47+
style?: mixed,
48+
...
49+
};
50+
/**
51+
* The options you can supply when making a call to `AppleAuthentication.signInAsync()`. None of
52+
* these options are required.
53+
* @see [Apple
54+
* Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationopenidrequest)
55+
* for more details.
56+
*/
57+
declare export type AppleAuthenticationSignInOptions = {
58+
/**
59+
* The scope of personal information to which your app is requesting access. The user can choose
60+
* to deny your app access to any scope at the time of logging in.
61+
* @defaults `[]` (no scopes).
62+
*/
63+
requestedScopes?: $Values<typeof AppleAuthenticationScope>[],
64+
65+
/**
66+
* Data that's returned to you unmodified in the corresponding credential after a successful
67+
* authentication. Used to verify that the response was from the request you made. Can be used to
68+
* avoid replay attacks.
69+
*/
70+
state?: string,
71+
72+
/**
73+
* Data that is used to verify the uniqueness of a response and prevent replay attacks.
74+
*/
75+
nonce?: string,
76+
...
77+
};
78+
/**
79+
* The options you can supply when making a call to `AppleAuthentication.refreshAsync()`. You must
80+
* include the ID string of the user whose credentials you'd like to refresh.
81+
* @see [Apple
82+
* Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationopenidrequest)
83+
* for more details.
84+
*/
85+
declare export type AppleAuthenticationRefreshOptions = {
86+
user: string,
87+
88+
/**
89+
* The scope of personal information to which your app is requesting access. The user can choose
90+
* to deny your app access to any scope at the time of refreshing.
91+
* @defaults `[]` (no scopes).
92+
*/
93+
requestedScopes?: $Values<typeof AppleAuthenticationScope>[],
94+
95+
/**
96+
* Data that's returned to you unmodified in the corresponding credential after a successful
97+
* authentication. Used to verify that the response was from the request you made. Can be used to
98+
* avoid replay attacks.
99+
*/
100+
state?: string,
101+
...
102+
};
103+
/**
104+
* The options you can supply when making a call to `AppleAuthentication.signOutAsync()`. You must
105+
* include the ID string of the user to sign out.
106+
* @see [Apple
107+
* Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationopenidrequest)
108+
* for more details.
109+
*/
110+
declare export type AppleAuthenticationSignOutOptions = {
111+
user: string,
112+
113+
/**
114+
* Data that's returned to you unmodified in the corresponding credential after a successful
115+
* authentication. Used to verify that the response was from the request you made. Can be used to
116+
* avoid replay attacks.
117+
*/
118+
state?: string,
119+
...
120+
};
121+
/**
122+
* The user credentials returned from a successful call to `AppleAuthentication.signInAsync()`,
123+
* `AppleAuthentication.refreshAsync()`, or `AppleAuthentication.signOutAsync()`.
124+
* @see [Apple
125+
* Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationappleidcredential)
126+
* for more details.
127+
*/
128+
declare export type AppleAuthenticationCredential = {
129+
/**
130+
* An identifier associated with the authenticated user. You can use this to check if the user is
131+
* still authenticated later. This is stable and can be shared across apps released under the same
132+
* development team. The same user will have a different identifier for apps released by other
133+
* developers.
134+
*/
135+
user: string,
136+
137+
/**
138+
* An arbitrary string that your app provided as `state` in the request that generated the
139+
* credential. Used to verify that the response was from the request you made. Can be used to
140+
* avoid replay attacks.
141+
*/
142+
state: string | null,
143+
144+
/**
145+
* The user's name. May be `null` or contain `null` values if you didn't request the `FULL_NAME`
146+
* scope, if the user denied access, or if this is not the first time the user has signed into
147+
* your app.
148+
*/
149+
fullName: AppleAuthenticationFullName | null,
150+
151+
/**
152+
* The user's email address. Might not be present if you didn't request the `EMAIL` scope. May
153+
* also be null if this is not the first time the user has signed into your app. If the user chose
154+
* to withhold their email address, this field will instead contain an obscured email address with
155+
* an Apple domain.
156+
*/
157+
email: string | null,
158+
159+
/**
160+
* A value that indicates whether the user appears to the system to be a real person.
161+
*/
162+
realUserStatus: $Values<typeof AppleAuthenticationUserDetectionStatus>,
163+
164+
/**
165+
* A JSON Web Token (JWT) that securely communicates information about the user to your app.
166+
*/
167+
identityToken: string | null,
168+
169+
/**
170+
* A short-lived session token used by your app for proof of authorization when interacting with
171+
* the app's server counterpart. Unlike `user`, this is ephemeral and will change each session.
172+
*/
173+
authorizationCode: string | null,
174+
...
175+
};
176+
/**
177+
* An object representing the tokenized portions of the user's full name.
178+
*/
179+
declare export type AppleAuthenticationFullName = {
180+
namePrefix: string | null,
181+
givenName: string | null,
182+
middleName: string | null,
183+
familyName: string | null,
184+
nameSuffix: string | null,
185+
nickname: string | null,
186+
...
187+
};
188+
declare export type AppleAuthenticationRevokeListener = () => void;
189+
/**
190+
* Scopes you can request when calling `AppleAuthentication.signInAsync()` or
191+
* `AppleAuthentication.refreshAsync()`.
192+
* @note Note that it is possible that you will not be granted all of the scopes which you request.
193+
* You will still need to handle null values for any fields you request.
194+
* @see [Apple
195+
* Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationscope)
196+
* for more details.
197+
*/
198+
199+
declare export var AppleAuthenticationScope: {|
200+
+FULL_NAME: 0, // 0
201+
+EMAIL: 1, // 1
202+
|};
203+
204+
declare export var AppleAuthenticationOperation: {|
205+
+IMPLICIT: 0, // 0
206+
+LOGIN: 1, // 1
207+
+REFRESH: 2, // 2
208+
+LOGOUT: 3, // 3
209+
|};
210+
211+
/**
212+
* The state of the credential when checked with `AppleAuthentication.getCredentialStateAsync()`.
213+
* @see [Apple
214+
* Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationappleidprovidercredentialstate)
215+
* for more details.
216+
*/
217+
218+
declare export var AppleAuthenticationCredentialState: {|
219+
+REVOKED: 0, // 0
220+
+AUTHORIZED: 1, // 1
221+
+NOT_FOUND: 2, // 2
222+
+TRANSFERRED: 3, // 3
223+
|};
224+
225+
/**
226+
* A value that indicates whether the user appears to be a real person. You get this in the
227+
* realUserStatus property of a `Credential` object. It can be used as one metric to help prevent
228+
* fraud.
229+
* @see [Apple
230+
* Documentation](https://developer.apple.com/documentation/authenticationservices/asuserdetectionstatus)
231+
* for more details.
232+
*/
233+
234+
declare export var AppleAuthenticationUserDetectionStatus: {|
235+
+UNSUPPORTED: 0, // 0
236+
+UNKNOWN: 1, // 1
237+
+LIKELY_REAL: 2, // 2
238+
|};
239+
240+
/**
241+
* Controls the predefined text shown on the authentication button.
242+
*/
243+
244+
declare export var AppleAuthenticationButtonType: {|
245+
+SIGN_IN: 0, // 0
246+
+CONTINUE: 1, // 1
247+
|};
248+
249+
/**
250+
* Controls the predefined style of the authenticating button.
251+
*/
252+
253+
declare export var AppleAuthenticationButtonStyle: {|
254+
+WHITE: 0, // 0
255+
+WHITE_OUTLINE: 1, // 1
256+
+BLACK: 2, // 2
257+
|};
258+
}
259+
260+
declare module 'expo-apple-authentication/build/AppleAuthenticationButton' {
261+
import type { StatelessFunctionalComponent } from 'react';
262+
/* eslint-disable-next-line */
263+
import type { AppleAuthenticationButtonProps } from 'expo-apple-authentication/build/AppleAuthentication.types';
264+
265+
/**
266+
* This component displays the proprietary "Sign In with Apple" / "Continue with Apple" button on
267+
* your screen. The App Store Guidelines require you to use this component to start the sign in
268+
* process instead of a custom button. You can customize the design of the button using the
269+
* properties. You should start the sign in process when the `onPress` property is called.
270+
*
271+
* You should only attempt to render this if `AppleAuthentication.isAvailableAsync()` resolves to
272+
* true. This component will render nothing if it is not available and you will get a warning if
273+
* `__DEV__ === true`.
274+
*
275+
* The properties of this component extend from `View`; however, you should not attempt to set
276+
* `backgroundColor` or `borderRadius` with the `style` property. This will not work and is against
277+
* the App Store Guidelines. Instead, you should use the `buttonStyle` property to choose one of the
278+
* predefined color styles and the `cornerRadius` property to change the border radius of the
279+
* button.
280+
* @see [Apple
281+
* Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationappleidbutton)
282+
* for more details.
283+
*/
284+
declare type AppleAuthenticationButton = StatelessFunctionalComponent<AppleAuthenticationButtonProps>;
285+
declare export default AppleAuthenticationButton;
286+
}
287+
288+
/*
289+
* Flowtype definitions for AppleAuthenticationButton
290+
* Generated by Flowgen from a Typescript Definition
291+
* Flowgen v1.10.0
292+
*/
293+
declare module 'expo-apple-authentication' {
294+
declare export * from 'expo-apple-authentication/build/AppleAuthentication'
295+
declare export * from 'expo-apple-authentication/build/AppleAuthentication.types'
296+
declare export {
297+
default as AppleAuthenticationButton,
298+
} from 'expo-apple-authentication/build/AppleAuthenticationButton';
299+
}

ios/Podfile.lock

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
PODS:
22
- boost-for-react-native (1.63.0)
33
- DoubleConversion (1.1.6)
4+
- EXAppleAuthentication (2.1.1):
5+
- UMCore
46
- EXApplication (2.1.1):
57
- UMCore
68
- EXAppLoaderProvider (7.0.0)
@@ -154,6 +156,7 @@ PODS:
154156

155157
DEPENDENCIES:
156158
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
159+
- EXAppleAuthentication (from `../node_modules/expo-apple-authentication/ios`)
157160
- EXApplication (from `../node_modules/expo-application/ios`)
158161
- EXAppLoaderProvider (from `../node_modules/expo-app-loader-provider/ios`)
159162
- EXConstants (from `../node_modules/expo-constants/ios`)
@@ -218,6 +221,9 @@ SPEC REPOS:
218221
EXTERNAL SOURCES:
219222
DoubleConversion:
220223
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
224+
EXAppleAuthentication:
225+
:path: !ruby/object:Pathname
226+
path: "../node_modules/expo-apple-authentication/ios"
221227
EXApplication:
222228
:path: !ruby/object:Pathname
223229
path: "../node_modules/expo-application/ios"
@@ -348,6 +354,7 @@ EXTERNAL SOURCES:
348354
SPEC CHECKSUMS:
349355
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
350356
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
357+
EXAppleAuthentication: 046c76335343eaa97f6ed8d35a9cf493a2c4d351
351358
EXApplication: 7cf81de6fafccff42f5d1caa5c24a159db6b9437
352359
EXAppLoaderProvider: 5d348813a9cf09b03bbe5b8b55437bc1bfbddbd1
353360
EXConstants: 857aa7b1c84e2878f8402d712061860bca16a697

ios/ZulipMobile/ZulipMobile.entitlements

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,9 @@
44
<dict>
55
<key>aps-environment</key>
66
<string>development</string>
7+
<key>com.apple.developer.applesignin</key>
8+
<array>
9+
<string>Default</string>
10+
</array>
711
</dict>
812
</plist>

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//
44
// These will be used as regexp fragments.
55
const transformModulesWhitelist = [
6+
'expo-apple-authentication',
67
'react-native',
78
// @rnc/async-storage itself is precompiled, but its mock-helper is not
89
'@react-native-community/async-storage',

0 commit comments

Comments
 (0)