Skip to content

Commit

Permalink
Merge pull request #881 from mraible/auth0-logout
Browse files Browse the repository at this point in the history
Fix logout with Auth0
  • Loading branch information
Matt Raible authored Sep 1, 2022
2 parents 591b06b + 0875bee commit 9c732f9
Show file tree
Hide file tree
Showing 23 changed files with 312 additions and 225 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ concurrency:
jobs:
generate:
name: e2e-${{ matrix.app_type }}-${{ matrix.jhipster_version }}
runs-on: macos-11
runs-on: macos-12
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.pull_request.title, '[skip ci]') && !contains(github.event.pull_request.title, '[ci skip]') && !contains(github.event.ref_type, '[tag]')"
timeout-minutes: 90
strategy:
Expand Down
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
- [CLI Flags](docs/cli-flags.md)
- JHipster Integrations
- [OAuth 2.0 and OpenID Connect](docs/oauth2-oidc.md)
- [Websockets](docs/websockets.md)
- [WebSockets](docs/websockets.md)
- React Native Library Integrations
- [Expo](https://docs.expo.io/) - A framework and platform for universal React application
- [React Native Web](https://docs.expo.io/workflow/web/) - Run your React Native application in a browser, including PWA support
Expand All @@ -37,12 +37,11 @@
- Verify version with `node -v`
- [generator-jhipster-react-native](https://github.com/jhipster/generator-jhipster-react-native) installed
- Install with `npm install -g generator-jhipster-react-native`
- [expo-cli](https://docs.expo.io/get-started/installation/) installed
- Install with `npm install -g expo-cli`
- To run your app on an emulator instead of a device, follow the platform-specific instructions:
- [Android](https://docs.expo.io/workflow/android-studio-emulator/)
- [iOS](https://docs.expo.io/workflow/ios-simulator/)
- JHipster backend must use JWT or OAuth2 auth types.
- [eas-cli](https://docs.expo.dev/build/introduction/) installed with `npm install -g eas-cli`
- To run your app on an emulator instead of a device, follow the platform-specific instructions:
- [Android](https://docs.expo.dev/workflow/android-studio-emulator/)
- [iOS](https://docs.expo.dev/workflow/ios-simulator/)
- JHipster backend must use `jwt` or `oauth2` for its `authenticationType`

Create a directory for your app:

Expand Down
2 changes: 2 additions & 0 deletions docs/detox.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ To run the Detox tests:
npm run test:e2e
```

You will need to have [`jq`](https://stedolan.github.io/jq/download/) installed for this command to work.

To customize the build and test parameters (such as which device to test), modify the `.detoxrc.json` file found in the root of the project.

For more information on Detox configuration and writing tests, check the [official Detox documentation](https://github.com/wix/Detox/blob/master/docs/README.md).
10 changes: 8 additions & 2 deletions docs/oauth2-oidc.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Configure the redirect URIs for your app in your Identity Provider's authorized
- Use the value for `reactNativeAppName` in your `.yo-rc.json`
- Use your Expo username in place of `@your-expo-username` (run `expo whoami`)
- Used for [Expo's Auth Proxy](https://docs.expo.io/versions/latest/sdk/auth-session/#what--authexpoio--does-for-you)
- Some identity providers may require you to configure this value as a logout URL too

#### Web

Expand Down Expand Up @@ -42,8 +43,13 @@ Using the [Okta CLI](https://cli.okta.com/), run `okta apps create`

Copy the provided `clientId` to `app/config/app-config.js`, and set `nativeClientId` to the copied value. This is loaded in `login.sagas.js` during authentication.

You can now log in to Okta through React Native clients on iOS, Android, and Web.
> If you're using Auth0, you'll also need to change the `audience` in `app/modules/login/login.utils.ts`. For example:
>
> ```
> audience: 'https://dev-06bzs1cu.us.auth0.com/api/v2/',
> ```
You can now log in to Okta through React Native clients on iOS, Android, and Web.
#### Add Claims to Access Token
Expand All @@ -57,4 +63,4 @@ Expo's auth proxy does not currently work with logging out from the identity pro
- Change `useExpoAuthProxy` to `false` in `app-config.js`
- Configure your redirect URLs for logout in your identity provider
- Usually something like `exp://127.0.0.1:19000` and `exp://10.0.0.114:19000`, where `10.0.0.114` is your local IP
- A popup will appear on browser open, but will say "Expo wants to use identy-provider.com to sign in", but it will really be signing out.
- A popup will appear on browser open, but will say "Expo wants to use identity-provider.com to sign in", but it will really be signing out.
2 changes: 1 addition & 1 deletion docs/websockets.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Websockets
## WebSockets

A websockets example is present under "Chat" in the Drawer Menu. JHipster React Native uses the existing `/websocket/tracker` endpoint to connect. It sends and receives chat messages using the `/topic/chat` message mapping.

Expand Down
2 changes: 2 additions & 0 deletions generators/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const {
generateReactNativeApp,
appendFiles,
patchInFile,
patchBabel,
} = require('../../lib');

module.exports = class extends AppGenerator {
Expand Down Expand Up @@ -95,6 +96,7 @@ module.exports = class extends AppGenerator {
this.fs.writeJSON('app.json', appConfig);
},
appendFiles: appendFiles.bind(this),
patchBabel: patchBabel.bind(this),
replacePackageJsonVersionsInGeneratedApp() {
this.debug('Replacing Package.json Versions');
this.replacePackageJsonVersions('REPLACE_WITH_VERSION', path.join(__dirname, 'templates/package.json'));
Expand Down
2 changes: 1 addition & 1 deletion generators/app/templates/.detoxrc.json.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"binaryPath": "e2e/Exponent.app",
"type": "ios.simulator",
"device": {
"type": "iPhone 11"
"type": "iPhone 12"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Platform } from 'react-native';
import { DiscoveryDocument, makeRedirectUri } from 'expo-auth-session';
import * as AuthSession from 'expo-auth-session';
import { generateHexStringAsync, buildCodeAsync } from 'expo-auth-session/src/PKCE';
Expand Down Expand Up @@ -74,7 +75,8 @@ export async function doOauthPkceFlow(clientId: string, issuer: string): Promise
// set up the IDP url, prepare codeVerifier and state
const { authUrl, codeVerifier, state } = await getAuthParams(clientId, redirectUri, discovery);
// redirect to the IDP
const authResult = await AuthSession.startAsync({ authUrl, returnUrl: Linking.makeUrl('/') });
const returnUri = Platform.OS === 'android' && !AppConfig.useExpoAuthProxy ? redirectUri : Linking.createURL('/');
const authResult = await AuthSession.startAsync({ authUrl, returnUrl: returnUri });
// check the response for success/failure
const code = extractCodeOrThrow(authResult, state);
// exchange the received code for an access token
Expand All @@ -90,6 +92,10 @@ export async function logoutFromIdp(clientId: string, issuer: string, idToken: s
// set up redirect uri
const redirectUri = makeRedirectUri({ useProxy: AppConfig.useExpoAuthProxy });
await WebBrowser.openAuthSessionAsync(`${endSessionEndpoint}?id_token_hint=${idToken}&client_id=${clientId}&post_logout_redirect_uri=${redirectUri}`, redirectUri);
} else if (issuer.includes('auth0.com')) {
// Auth0 need special handling since end_session_endpoint is not in oidc-configuration
const redirectUri = makeRedirectUri({ useProxy: AppConfig.useExpoAuthProxy });
await WebBrowser.openAuthSessionAsync(`${issuer}/v2/logout?client_id=${clientId}&returnTo=${redirectUri}`, redirectUri);
}
}
}
2 changes: 1 addition & 1 deletion generators/app/templates/e2e/scripts/download-expo.sh.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if [ ! -d $APP_PATH ]; then
mkdir $APP_PATH

# query expo.io to find most recent ipaUrl
IPA_URL=`curl --silent --show-error https://expo.io/--/api/v2/versions | python -c 'import sys, json; print json.load(sys.stdin)["iosUrl"]'`
IPA_URL=$(curl --silent --show-error https://expo.io/--/api/v2/versions | jq -r ".iosUrl")

# download tar.gz
TMP_PATH=./exponent.tar.gz
Expand Down
36 changes: 18 additions & 18 deletions generators/app/templates/package.expo.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@
"description": "Dependencies managed by Expo - need a specific version",
"version": "0.0.1",
"dependencies": {
"@expo/vector-icons": "^12.0.0",
"@react-native-async-storage/async-storage": "~1.15.0",
"@react-native-community/datetimepicker": "3.5.2",
"@react-native-community/masked-view": "0.1.10",
"@react-native-picker/picker": "1.16.1",
"expo-auth-session": "~3.2.3",
"expo-constants": "~11.0.1",
"expo-linking": "~2.3.1",
"expo-splash-screen": "~0.11.2",
"expo-random": "~11.1.2",
"react-native-gesture-handler": "~1.10.2",
"react-native-web": "^0.14.13",
"expo-web-browser": "~9.1.0",
"react-native-reanimated": "~2.2.0",
"react-native-safe-area-context": "3.2.0",
"react-native-screens": "~3.4.0"
"@expo/vector-icons": "^13.0.0",
"@react-native-async-storage/async-storage": "~1.17.10",
"@react-native-community/datetimepicker": "6.2.0",
"@react-native-community/masked-view": "0.2.7",
"@react-native-picker/picker": "2.4.2",
"expo-auth-session": "~3.7.1",
"expo-constants": "~13.2.4",
"expo-linking": "~3.2.2",
"expo-splash-screen": "~0.16.2",
"expo-random": "~12.3.0",
"react-native-gesture-handler": "~2.5.0",
"react-native-web": "^0.18.9",
"expo-web-browser": "~11.0.0",
"react-native-reanimated": "~2.9.1",
"react-native-safe-area-context": "4.3.1",
"react-native-screens": "~3.15.0"
},
"devDependencies": {
"jest-expo": "^42.0.0",
"@expo/webpack-config": "^0.12.63"
"jest-expo": "^46.0.1",
"@expo/webpack-config": "^0.17.2"
}
}
11 changes: 6 additions & 5 deletions generators/app/templates/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"webstomp-client": "1.2.6",
"sockjs-client": "1.5.2",
"net": "1.0.2",
"@react-native-masked-view/masked-view": "0.2.6",
"@react-native-masked-view/masked-view": "0.2.7",
"@react-navigation/drawer": "5.12.5",
"@react-navigation/stack": "5.14.5",
"react-native-sectioned-multi-select": "0.8.1",
Expand All @@ -32,8 +32,8 @@
"yup": "0.32.11"
},
"devDependencies": {
"expo": "42",
"expo-cli": "4.13.0",
"expo": "46.0.20",
"create-expo-app": "1.1.1",
"@storybook/addons": "5.3.21",
"@storybook/react-native": "5.3.25",
"@storybook/theming": "5.3.21",
Expand All @@ -50,13 +50,14 @@
"jest-circus": "26.6.3",
"@react-native-community/eslint-config": "3.0.1",
"lint-staged": "12.1.2",
"detox": "18.18.1",
"detox": "19.11.0",
"@ruddell/detox-expo-helpers": "0.7.0",
"expo-detox-hook": "1.0.10",
"redux-devtools-extension": "2.13.9",
"mockery": "2.1.0",
"typescript": "4.5.3",
"typescript": "4.6.3",
"prettier": "2.5.1",
"react-test-renderer": "18.2.0",
"patch-package": "6.4.7",
"path-exists": "5.0.0",
"resolve": "1.20.0",
Expand Down
10 changes: 4 additions & 6 deletions generators/app/templates/package.json.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"publish": "expo publish",
"build:ios": "expo build:ios",
"build:android": "expo build:android",
"build:web": "expo build:web",
"build:web": "expo export:web",
<%_ if (!context.skipCommitHook) { _%>
"precommit": "lint-staged",
<%_ } _%>
Expand Down Expand Up @@ -96,6 +96,7 @@
<%_ } _%>
"redux-devtools-extension": "REPLACE_WITH_VERSION",
"mockery": "REPLACE_WITH_VERSION",
"react-test-renderer": "REPLACE_WITH_VERSION",
"prettier": "REPLACE_WITH_VERSION",
"patch-package": "REPLACE_WITH_VERSION",
"typescript": "REPLACE_WITH_VERSION",
Expand Down Expand Up @@ -130,11 +131,8 @@
"setupFiles": [
"./test/setup"
],
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
},
"transformIgnorePatterns": [
"node_modules/(?!(@react-native-community|react-native|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|@storybook))"
"node_modules/(?!(@react-native-community|@react-native|react-native|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|@storybook))"
],
"coveragePathIgnorePatterns": [
"app/shared/services/api.js",
Expand All @@ -145,7 +143,7 @@
"preset": "jest-expo"
},
"engines": {
"node": ">=12.x",
"node": ">=14.x",
"npm": ">=6.x"
}
}
2 changes: 0 additions & 2 deletions generators/app/templates/webpack.config.js.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ module.exports = async function (env, argv) {
const config = await createExpoWebpackConfigAsync(
{
...env,
// Passing true will enable the default Workbox + Expo SW configuration.
offline: false,
},
argv,
);
Expand Down
4 changes: 2 additions & 2 deletions generators/heroku/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ module.exports = class extends HerokuGenerator {
},
addHerokuDependencies() {
const packageJsonSource = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
packageJsonSource.dependencies['http-server'] = '0.12.3';
packageJsonSource.scripts['heroku-prebuild'] = 'npm install -g expo-cli http-server gzipper generator-jhipster-react-native';
packageJsonSource.dependencies['http-server'] = '14.1.1';
packageJsonSource.scripts['heroku-prebuild'] = 'npm install -g sharp-cli http-server gzipper generator-jhipster-react-native';
packageJsonSource.scripts['heroku-postbuild'] = 'npm run build:web && gzipper compress ./web-build --brotli';
this.fs.writeJSON('package.json', packageJsonSource);
},
Expand Down
6 changes: 3 additions & 3 deletions lib/generate-react-native-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ const chalk = require('chalk');
const fse = require('fs-extra');
const dependenciesPackageJson = require('../generators/app/templates/package.json');

const expoCliVersion = dependenciesPackageJson.devDependencies['expo-cli'];
const createExpoAppVersion = dependenciesPackageJson.devDependencies['create-expo-app'];
const expoSdkVersion = dependenciesPackageJson.devDependencies.expo;

function generateReactNativeApp() {
const name = this.context.reactNativeAppName;
this.info(chalk.green("Running 'npx expo-cli init', this will take some time..."));
this.info(chalk.green("Running 'npx create-expo-app', this will take some time..."));
try {
// remove the expected folder in case it already exists
fse.removeSync(`${process.cwd()}/${name}/`);

const generateCommand = `expo-cli@${expoCliVersion} init --npm -t expo-template-blank-typescript@sdk-${expoSdkVersion} --no-install --non-interactive ${name}`;
const generateCommand = `-y create-expo-app@${createExpoAppVersion} -t expo-template-blank-typescript@${expoSdkVersion} --no-install ${name}`;
this.debug(generateCommand);

// generate the expo app
Expand Down
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { createEarlyFiles } = require('./pre-write');
const { generateReactNativeApp } = require('./generate-react-native-app');
const { appendFiles } = require('./append-files');
const { getAppFolder } = require('./get-app-folder');
const { patchBabel } = require('./patch-babel');
const { patchNavigationForEntity } = require('./patch-navigation');
const { patchInFile } = require('./patch-in-file');
const { patchEntityApi } = require('./patch-entity-api');
Expand All @@ -19,6 +20,7 @@ module.exports = {
generateReactNativeApp,
appendFiles,
getAppFolder,
patchBabel,
patchInFile,
patchNavigationForEntity,
patchEntityApi,
Expand Down
2 changes: 1 addition & 1 deletion lib/merge-react-native-package-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function mergeReactNativePackageJson() {
utils.renderContent('package.json.ejs', _this, _this, {}, templatedPackageJsonAsString => {
this.debug(templatedPackageJsonAsString);
const mergedPackageJson = JSON.parse(templatedPackageJsonAsString);
// merge these sections, with a precedence to the our templated version
// merge these sections, with a precedence to our templated version
const keys = ['scripts', 'dependencies', 'devDependencies'];
// loop through the keys
keys.forEach(packageJsonSectionKey => {
Expand Down
11 changes: 11 additions & 0 deletions lib/patch-babel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function patchBabel() {
this.patchInFile('babel.config.js', {
after: 'presets',
insert: "plugins: ['react-native-reanimated/plugin'],",
ignoreIfContains: 'react-native-reanimated',
});
}

module.exports = {
patchBabel,
};
Loading

0 comments on commit 9c732f9

Please sign in to comment.