-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(auth): Add Expo support for phone auth (#6645)
* feat(auth) expo config plugin for phone auth * add expo config plugin dependency * build scripts * fix types * Update docs/auth/phone-auth.md Co-authored-by: Bartłomiej Klocek <[email protected]> * reformat * plugin file * plist dep * Update package.json * Add tests for auth expo config plugin * Add missing files previously ignored by .gitignore * build(deps): bump to new expo config plugins version Co-authored-by: Fernando Rojo <[email protected]> Co-authored-by: Bartłomiej Klocek <[email protected]> Co-authored-by: Mike Hardy <[email protected]>
- Loading branch information
1 parent
1f2385b
commit 97a4ea5
Showing
12 changed files
with
578 additions
and
361 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('./plugin/build'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
packages/auth/plugin/__tests__/__snapshots__/iosPlugin.test.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Config Plugin iOS Tests adds url types to the Info.plist 1`] = ` | ||
{ | ||
"CFBundleURLTypes": [ | ||
{ | ||
"CFBundleURLSchemes": [ | ||
"com.googleusercontent.apps.SomeRandomClientIdString", | ||
], | ||
}, | ||
], | ||
} | ||
`; |
6 changes: 6 additions & 0 deletions
6
packages/auth/plugin/__tests__/fixtures/TestGoogleService-Info.incomplete.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
</dict> | ||
</plist> |
38 changes: 38 additions & 0 deletions
38
packages/auth/plugin/__tests__/fixtures/TestGoogleService-Info.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>CLIENT_ID</key> | ||
<string>SomeRandomClientIdString.apps.googleusercontent.com</string> | ||
<key>REVERSED_CLIENT_ID</key> | ||
<string>com.googleusercontent.apps.SomeRandomClientIdString</string> | ||
<key>ANDROID_CLIENT_ID</key> | ||
<string>SomeRandomAndroidClientIdString.apps.googleusercontent.com</string> | ||
<key>API_KEY</key> | ||
<string>SomeRandomApiKeyString</string> | ||
<key>GCM_SENDER_ID</key> | ||
<string>SomeRandomGcmSenderIdNumber</string> | ||
<key>PLIST_VERSION</key> | ||
<string>1</string> | ||
<key>BUNDLE_ID</key> | ||
<string>com.example.app</string> | ||
<key>PROJECT_ID</key> | ||
<string>example</string> | ||
<key>STORAGE_BUCKET</key> | ||
<string>example.appspot.com</string> | ||
<key>IS_ADS_ENABLED</key> | ||
<false></false> | ||
<key>IS_ANALYTICS_ENABLED</key> | ||
<false></false> | ||
<key>IS_APPINVITE_ENABLED</key> | ||
<true></true> | ||
<key>IS_GCM_ENABLED</key> | ||
<true></true> | ||
<key>IS_SIGNIN_ENABLED</key> | ||
<true></true> | ||
<key>GOOGLE_APP_ID</key> | ||
<string>1234:1234:ios:1234</string> | ||
<key>DATABASE_URL</key> | ||
<string>https://example.firebaseio.com</string> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import path from 'path'; | ||
import { beforeEach, describe, expect, it, jest } from '@jest/globals'; | ||
import { setUrlTypesForCaptcha } from '../src/ios/urlTypes'; | ||
|
||
describe('Config Plugin iOS Tests', () => { | ||
beforeEach(function () { | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
it('throws if path to GoogleServer-Info.plist is not provided', async () => { | ||
expect(() => { | ||
setUrlTypesForCaptcha({ | ||
config: { | ||
name: 'TestName', | ||
slug: 'TestSlug', | ||
modRequest: { projectRoot: path.join(__dirname, 'fixtures') } as any, | ||
modResults: {}, | ||
modRawConfig: { name: 'TestName', slug: 'TestSlug' }, | ||
ios: {}, | ||
}, | ||
}); | ||
}).toThrow( | ||
`[@react-native-firebase/auth] Your app.json file is missing ios.googleServicesFile. Please add this field.`, | ||
); | ||
}); | ||
|
||
it('throws if GoogleServer-Info.plist cannot be read', async () => { | ||
const googleServiceFilePath = path.join(__dirname, 'fixtures', 'ThisFileDoesNotExist.plist'); | ||
expect(() => { | ||
setUrlTypesForCaptcha({ | ||
config: { | ||
name: 'TestName', | ||
slug: 'TestSlug', | ||
modRequest: { projectRoot: path.join(__dirname, 'fixtures') } as any, | ||
modResults: {}, | ||
modRawConfig: { name: 'TestName', slug: 'TestSlug' }, | ||
ios: { googleServicesFile: 'ThisFileDoesNotExist.plist' }, | ||
}, | ||
}); | ||
}).toThrow( | ||
`[@react-native-firebase/auth] GoogleService-Info.plist doesn't exist in ${googleServiceFilePath}. Place it there or configure the path in app.json`, | ||
); | ||
}); | ||
|
||
it('throws if GoogleServer-Info.plist has no reversed client id', async () => { | ||
expect(() => { | ||
setUrlTypesForCaptcha({ | ||
config: { | ||
name: 'TestName', | ||
slug: 'TestSlug', | ||
modRequest: { projectRoot: path.join(__dirname, 'fixtures') } as any, | ||
modResults: {}, | ||
modRawConfig: { name: 'TestName', slug: 'TestSlug' }, | ||
ios: { googleServicesFile: 'TestGoogleService-Info.incomplete.plist' }, | ||
}, | ||
}); | ||
}).toThrow( | ||
'[@react-native-firebase/auth] Failed to parse your GoogleService-Info.plist. Are you sure it is a valid Info.Plist file with a REVERSE_CLIENT_ID field?', | ||
); | ||
}); | ||
|
||
it('adds url types to the Info.plist', async () => { | ||
const result = setUrlTypesForCaptcha({ | ||
config: { | ||
name: 'TestName', | ||
slug: 'TestSlug', | ||
modRequest: { projectRoot: path.join(__dirname, 'fixtures') } as any, | ||
modResults: {}, | ||
modRawConfig: { name: 'TestName', slug: 'TestSlug' }, | ||
ios: { googleServicesFile: 'TestGoogleService-Info.plist' }, | ||
}, | ||
}); | ||
expect(result.modResults).toMatchSnapshot(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { ConfigPlugin, withPlugins, createRunOncePlugin } from '@expo/config-plugins'; | ||
|
||
import { withIosCaptchaUrlTypes } from './ios'; | ||
|
||
/** | ||
* A config plugin for configuring `@react-native-firebase/auth` | ||
*/ | ||
const withRnFirebaseAuth: ConfigPlugin = config => { | ||
return withPlugins(config, [ | ||
// iOS | ||
withIosCaptchaUrlTypes, | ||
]); | ||
}; | ||
|
||
const pak = require('@react-native-firebase/auth/package.json'); | ||
export default createRunOncePlugin(withRnFirebaseAuth, pak.name, pak.version); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { withIosCaptchaUrlTypes } from './urlTypes'; | ||
|
||
export { withIosCaptchaUrlTypes }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { | ||
ConfigPlugin, | ||
IOSConfig, | ||
withInfoPlist, | ||
ExportedConfigWithProps, | ||
} from '@expo/config-plugins'; | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
import plist from 'plist'; | ||
|
||
// does this for you: https://firebase.google.com/docs/auth/ios/phone-auth#enable-phone-number-sign-in-for-your-firebase-project | ||
export const withIosCaptchaUrlTypes: ConfigPlugin = config => { | ||
return withInfoPlist(config, config => { | ||
return setUrlTypesForCaptcha({ config }); | ||
}); | ||
}; | ||
|
||
function getReversedClientId(googleServiceFilePath: string): string { | ||
try { | ||
const googleServicePlist = fs.readFileSync(googleServiceFilePath, 'utf8'); | ||
|
||
const googleServiceJson = plist.parse(googleServicePlist) as { REVERSED_CLIENT_ID: string }; | ||
const REVERSED_CLIENT_ID = googleServiceJson.REVERSED_CLIENT_ID; | ||
|
||
if (!REVERSED_CLIENT_ID) { | ||
throw new TypeError('REVERSED_CLIENT_ID missing'); | ||
} | ||
|
||
return REVERSED_CLIENT_ID; | ||
} catch { | ||
throw new Error( | ||
'[@react-native-firebase/auth] Failed to parse your GoogleService-Info.plist. Are you sure it is a valid Info.Plist file with a REVERSE_CLIENT_ID field?', | ||
); | ||
} | ||
} | ||
|
||
// add phone auth support by configuring recaptcha | ||
// https://github.com/invertase/react-native-firebase/pull/6167 | ||
function addUriScheme( | ||
config: ExportedConfigWithProps<IOSConfig.InfoPlist>, | ||
reversedClientId: string, | ||
): ExportedConfigWithProps<IOSConfig.InfoPlist> { | ||
if (!config.modResults) { | ||
config.modResults = {}; | ||
} | ||
|
||
if (!config.modResults.CFBundleURLTypes) { | ||
config.modResults.CFBundleURLTypes = []; | ||
} | ||
|
||
const hasReverseClientId = config.modResults.CFBundleURLTypes?.some(urlType => | ||
urlType.CFBundleURLSchemes.includes(reversedClientId), | ||
); | ||
|
||
if (!hasReverseClientId) { | ||
config.modResults.CFBundleURLTypes.push({ | ||
CFBundleURLSchemes: [reversedClientId], | ||
}); | ||
} | ||
|
||
return config; | ||
} | ||
|
||
export function setUrlTypesForCaptcha({ | ||
config, | ||
}: { | ||
config: ExportedConfigWithProps<IOSConfig.InfoPlist>; | ||
}) { | ||
const googleServicesFileRelativePath = config.ios?.googleServicesFile; | ||
if (!googleServicesFileRelativePath) { | ||
throw new Error( | ||
`[@react-native-firebase/auth] Your app.json file is missing ios.googleServicesFile. Please add this field.`, | ||
); | ||
} | ||
const googleServiceFilePath = path.resolve( | ||
config.modRequest.projectRoot, | ||
googleServicesFileRelativePath, | ||
); | ||
|
||
if (!fs.existsSync(googleServiceFilePath)) { | ||
throw new Error( | ||
`[@react-native-firebase/auth] GoogleService-Info.plist doesn't exist in ${googleServiceFilePath}. Place it there or configure the path in app.json`, | ||
); | ||
} | ||
|
||
const reversedClientId = getReversedClientId(googleServiceFilePath); | ||
addUriScheme(config, reversedClientId); | ||
|
||
return config; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"extends": "@tsconfig/node12/tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "build", | ||
"rootDir": "src", | ||
"declaration": true | ||
}, | ||
"include": ["./src"] | ||
} |
Oops, something went wrong.
97a4ea5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
react-native-firebase – ./
react-native-firebase.vercel.app
react-native-firebase-git-main-invertase.vercel.app
react-native-firebase-invertase.vercel.app
rnfirebase.io