diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index cd7b1e8bc5..232e543094 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -28,6 +28,7 @@ - \ No newline at end of file + diff --git a/ios/smartwallet.xcodeproj/project.pbxproj b/ios/smartwallet.xcodeproj/project.pbxproj index 97a11fe818..9070861441 100644 --- a/ios/smartwallet.xcodeproj/project.pbxproj +++ b/ios/smartwallet.xcodeproj/project.pbxproj @@ -1678,6 +1678,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.jolocom.wallet; PRODUCT_NAME = smartwallet; PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -1712,6 +1713,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.jolocom.wallet; PRODUCT_NAME = smartwallet; PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; diff --git a/src/NavigatorContainer.tsx b/src/NavigatorContainer.tsx index 2011943374..3edce0ee65 100644 --- a/src/NavigatorContainer.tsx +++ b/src/NavigatorContainer.tsx @@ -5,7 +5,7 @@ import { NavigationEventCallback, } from 'react-navigation' import { connect } from 'react-redux' -import { BackHandler, Linking, Platform, StatusBar } from 'react-native' +import { BackHandler, Linking, StatusBar } from 'react-native' import { AnyAction } from 'redux' import { Routes } from 'src/routes' import { RootState } from 'src/reducers/' @@ -46,26 +46,16 @@ export class NavigatorContainer extends React.Component { } UNSAFE_componentWillMount() { + Linking.getInitialURL().then((url: string) => { + if (!url) { + this.props.checkIfAccountExists() + } else { + this.props.handleDeepLink(url) + } + }) + + Linking.addEventListener('url', this.handleOpenURL) BackHandler.addEventListener('hardwareBackPress', this.navigateBack) - if (Platform.OS === 'android') { - Linking.getInitialURL().then((url: string) => { - if (!url) { - this.props.checkIfAccountExists() - } else { - this.props.handleDeepLink(url) - } - }) - } else { - Linking.addEventListener('url', this.handleOpenURL) - // TODO: test with deep linking on ios - Linking.getInitialURL().then((url: string) => { - if (!url) { - this.props.checkIfAccountExists() - } else { - this.props.handleDeepLink(url) - } - }) - } } componentWillUnmount() { @@ -75,17 +65,16 @@ export class NavigatorContainer extends React.Component { private navigateBack = () => { // return false if app exit is desired + const { navigation } = this.props if ( - this.props.navigation.index === 0 && - this.props.navigation.routes.length === 1 && - this.props.navigation.routes[0].index === 0 + navigation.index === 0 && + navigation.routes.length === 1 && + navigation.routes[0].index === 0 ) { return false } - console.log(this.props.navigation) - this.props.goBack() - return true + return this.props.goBack() } //When handleOpenURL is called, we pass the event url to the navigate method. diff --git a/src/actions/navigation/index.ts b/src/actions/navigation/index.ts index b43fcdfc34..7694890a31 100644 --- a/src/actions/navigation/index.ts +++ b/src/actions/navigation/index.ts @@ -7,7 +7,7 @@ import { ssoActions } from 'src/actions/' import { setDid, toggleLoading } from '../account' import { BackendMiddleware } from 'src/backendMiddleware' import { instantiateIdentityWallet } from 'src/lib/util' -import { setDeepLinkLoading } from '../sso' +import { setDeepLinkLoading, toggleDeepLinkFlag } from '../sso' export const navigate = (options: NavigationNavigateActionPayload) => NavigationActions.navigate(options) @@ -41,6 +41,7 @@ export const handleDeepLink = (url: string) => async ( routeName === 'authenticate' ) { dispatch(setDeepLinkLoading(true)) + dispatch(toggleDeepLinkFlag(true)) const personas = await backendMiddleware.storageLib.get.persona() if (!personas.length) { diff --git a/src/actions/sso/authenticationRequest.ts b/src/actions/sso/authenticationRequest.ts index c9586d576e..1527914f1e 100644 --- a/src/actions/sso/authenticationRequest.ts +++ b/src/actions/sso/authenticationRequest.ts @@ -6,7 +6,7 @@ import { showErrorScreen } from 'src/actions/generic' import { Authentication } from 'jolocom-lib/js/interactionTokens/authentication' import { StateAuthenticationRequestSummary } from 'src/reducers/sso' import { routeList } from 'src/routeList' -import { cancelSSO } from '.' +import { cancelSSO, clearInteractionRequest } from '.' import { Linking } from 'react-native' import { JolocomLib } from 'jolocom-lib' @@ -52,6 +52,8 @@ export const sendAuthenticationResponse = () => async ( backendMiddleware: BackendMiddleware, ) => { const { identityWallet } = backendMiddleware + const { isDeepLinkInteraction } = getState().sso + const { callbackURL, requestJWT, @@ -69,19 +71,20 @@ export const sendAuthenticationResponse = () => async ( decodedAuthRequest, ) - if (callbackURL.includes('http')) { - await fetch(callbackURL, { + if (isDeepLinkInteraction) { + return Linking.openURL(`${callbackURL}/${response.encode()}`).then(() => + dispatch(cancelSSO()), + ) + } else { + return fetch(callbackURL, { method: 'POST', body: JSON.stringify({ token: response.encode() }), headers: { 'Content-Type': 'application/json' }, - }) - } else { - const url = callbackURL + response.encode() - Linking.openURL(url) + }).then(() => dispatch(cancelSSO())) } - dispatch(cancelSSO()) } catch (err) { console.log(err) + dispatch(clearInteractionRequest()) dispatch(showErrorScreen(new Error('Sending payment response failed.'))) } } diff --git a/src/actions/sso/index.ts b/src/actions/sso/index.ts index 2aa00bf815..e25b42a5ba 100644 --- a/src/actions/sso/index.ts +++ b/src/actions/sso/index.ts @@ -286,7 +286,10 @@ export const sendCredentialResponse = ( backendMiddleware: BackendMiddleware, ) => { const { storageLib, keyChainLib, encryptionLib, registry } = backendMiddleware - const { activeCredentialRequest } = getState().sso + const { + activeCredentialRequest: { callbackURL, requestJWT }, + isDeepLinkInteraction, + } = getState().sso try { const password = await keyChainLib.getPassword() @@ -313,32 +316,30 @@ export const sendCredentialResponse = ( const jsonCredentials = credentials.map(cred => cred.toJSON()) - const request = JolocomLib.parse.interactionToken.fromJWT( - activeCredentialRequest.requestJWT, - ) - const credentialResponse = await wallet.create.interactionTokens.response.share( + const request = JolocomLib.parse.interactionToken.fromJWT(requestJWT) + const response = await wallet.create.interactionTokens.response.share( { - callbackURL: activeCredentialRequest.callbackURL, + callbackURL, suppliedCredentials: jsonCredentials, }, password, request, ) - if (activeCredentialRequest.callbackURL.includes('http')) { - await fetch(activeCredentialRequest.callbackURL, { + if (isDeepLinkInteraction) { + return Linking.openURL(`${callbackURL}/${response.encode()}`).then(() => + dispatch(cancelSSO()), + ) + } else { + return fetch(callbackURL, { method: 'POST', - body: JSON.stringify({ token: credentialResponse.encode() }), + body: JSON.stringify({ token: response.encode() }), headers: { 'Content-Type': 'application/json' }, - }) - } else { - const url = - activeCredentialRequest.callbackURL + credentialResponse.encode() - Linking.openURL(url) + }).then(() => dispatch(cancelSSO())) } - dispatch(cancelSSO()) } catch (error) { // TODO: better error message + dispatch(clearInteractionRequest()) console.log(error) dispatch(accountActions.toggleLoading(false)) dispatch( @@ -359,3 +360,8 @@ export const cancelReceiving = () => (dispatch: Dispatch) => { dispatch(resetSelected()) dispatch(navigationActions.navigatorReset({ routeName: routeList.Home })) } + +export const toggleDeepLinkFlag = (value: boolean) => ({ + type: 'SET_DEEP_LINK_FLAG', + value, +}) diff --git a/src/actions/sso/paymentRequest.ts b/src/actions/sso/paymentRequest.ts index f446845be3..a62d736d63 100644 --- a/src/actions/sso/paymentRequest.ts +++ b/src/actions/sso/paymentRequest.ts @@ -8,7 +8,7 @@ import { StatePaymentRequestSummary } from 'src/reducers/sso' import { showErrorScreen } from 'src/actions/generic' import { JolocomLib } from 'jolocom-lib' import { Linking } from 'react-native' -import { cancelSSO } from 'src/actions/sso' +import { cancelSSO, clearInteractionRequest } from 'src/actions/sso' import { JolocomRegistry } from 'jolocom-lib/js/registries/jolocomRegistry' export const setPaymentRequest = (request: StatePaymentRequestSummary) => ({ @@ -62,6 +62,7 @@ export const sendPaymentResponse = () => async ( const { identityWallet } = backendMiddleware const { activePaymentRequest: { callbackURL, paymentRequest }, + isDeepLinkInteraction, } = getState().sso // add loading screen here try { @@ -79,19 +80,20 @@ export const sendPaymentResponse = () => async ( decodedPaymentRequest, ) - if (callbackURL.includes('http')) { - await fetch(callbackURL, { + if (isDeepLinkInteraction) { + return Linking.openURL(`${callbackURL}/${response.encode()}`).then(() => + dispatch(cancelSSO()), + ) + } else { + return fetch(callbackURL, { method: 'POST', body: JSON.stringify({ token: response.encode() }), headers: { 'Content-Type': 'application/json' }, - }) - } else { - const url = callbackURL + response.encode() - Linking.openURL(url) + }).then(() => dispatch(cancelSSO())) } - dispatch(cancelSSO()) } catch (err) { console.log(err) + dispatch(clearInteractionRequest()) dispatch(showErrorScreen(new Error('Sending payment response failed.'))) } } diff --git a/src/reducers/sso/index.ts b/src/reducers/sso/index.ts index eb594baae7..80b9d948f1 100644 --- a/src/reducers/sso/index.ts +++ b/src/reducers/sso/index.ts @@ -43,6 +43,7 @@ export interface SsoState { activePaymentRequest: StatePaymentRequestSummary activeAuthenticationRequest: StateAuthenticationRequestSummary deepLinkLoading: boolean + isDeepLinkInteraction: boolean } const initialState: SsoState = { @@ -62,6 +63,7 @@ const initialState: SsoState = { description: '', paymentRequest: '', }, + isDeepLinkInteraction: false, // add blank authentication request, which is did, public profile? activeAuthenticationRequest: { requester: '', @@ -81,6 +83,8 @@ export const ssoReducer = ( return { ...state, activeCredentialRequest: action.value } case 'SET_PAYMENT_REQUEST': return { ...state, activePaymentRequest: action.value } + case 'SET_DEEP_LINK_FLAG': + return { ...state, isDeepLinkInteraction: action.value } case 'SET_AUTHENTICATION_REQUEST': return { ...state, activeAuthenticationRequest: action.value } case 'SET_DEEP_LINK_LOADING': diff --git a/tests/actions/navigation/__snapshots__/index.test.ts.snap b/tests/actions/navigation/__snapshots__/index.test.ts.snap index 374780b8ce..74e0feb395 100644 --- a/tests/actions/navigation/__snapshots__/index.test.ts.snap +++ b/tests/actions/navigation/__snapshots__/index.test.ts.snap @@ -10,6 +10,10 @@ Array [ "type": "SET_DEEP_LINK_LOADING", "value": true, }, + Object { + "type": "SET_DEEP_LINK_FLAG", + "value": true, + }, Object { "type": "DID_SET", "value": "did:jolo:mock", diff --git a/tests/actions/registration/index.test.ts b/tests/actions/registration/index.test.ts index a3b239ae78..3f6514e885 100644 --- a/tests/actions/registration/index.test.ts +++ b/tests/actions/registration/index.test.ts @@ -3,7 +3,9 @@ import configureStore from 'redux-mock-store' import thunk from 'redux-thunk' import data from './data/mockRegistrationData' import { JolocomLib } from 'jolocom-lib' +import { getJestConfig } from 'ts-jest/dist/test-utils' import * as util from 'src/lib/util' + const MockDate = require('mockdate') describe('Registration action creators', () => { diff --git a/tests/reducers/sso/__snapshots__/index.test.ts.snap b/tests/reducers/sso/__snapshots__/index.test.ts.snap index c55ecf0ee0..5a1c6ec96b 100644 --- a/tests/reducers/sso/__snapshots__/index.test.ts.snap +++ b/tests/reducers/sso/__snapshots__/index.test.ts.snap @@ -20,6 +20,7 @@ Object { }, }, "deepLinkLoading": false, + "isDeepLinkInteraction": false, } `; @@ -55,6 +56,7 @@ Object { }, }, "deepLinkLoading": false, + "isDeepLinkInteraction": false, } `; @@ -83,5 +85,6 @@ Object { }, }, "deepLinkLoading": false, + "isDeepLinkInteraction": false, } `;