okta / okta-react-native

OIDC enablement for React Native applications
https://github.com/okta/okta-react-native
Other
58 stars 39 forks source link

Authentication with sessionToken rejects Promise (Android) #230

Open kennyho-ml opened 3 years ago

kennyho-ml commented 3 years ago

I'm submitting a:

Current behavior

I'm using the Js wrapper to login => get a sessionToken => use authenticate with session Token

      const response = await getAuthClient().signInWithCredentials({username, password})

      const {sessionToken } = response

      await authenticate({sessionToken})

On IOS, this works as expected as I see the network requests via Flipper that is calling the authn endpoints. Then after you call authenticate it calls authorize which sets the sid cookie.

❗ However on android, when you call authenticate it seems like it's rejecting a promise (which maybe why it doesn't call authorize

Here are the logs

Possible Unhandled Promise Rejection (id: 5):
TypeError: null is not an object (evaluating '_reactNative.NativeModules.OktaSdkBridge.authenticate')
_callee5$@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:110719:87
tryCatch@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24264:23
invoke@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24434:32
tryCatch@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24264:23
invoke@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24336:30
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24366:19
tryCallTwo@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:28950:9
doResolve@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:29114:25
Promise@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:28973:14
callInvokeWithMethodAndArg@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24365:33
enqueue@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24370:157
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24385:69
_callee5@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:110714:38
_callee2$
tryCatch@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24264:23
invoke@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24434:32
tryCatch@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24264:23
invoke@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24336:30
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:24346:21
tryCallOne@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:28941:16
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:29042:27
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:29633:26
_callTimer@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:29529:17
_callReactNativeMicrotasksPass@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:29568:17
callReactNativeMicrotasks@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:29778:44
__callReactNativeMicrotasks@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:3049:46
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:2827:45
__guard@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:3032:15
flushedQueue@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true:2826:21
flushedQueue@[native code]
invokeCallbackAndReturnFlushedQueue@[native code]

Expected behavior

Able to call authenticate on android and have the sid cookie set on the device. (just for reference... I'm using sid cookie to SSO into zendesk).

Minimal reproduction of the problem with instructions

Creating new react-native app and install new okta... via

{
  "name": "oktaandroidtest",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint ."
  },
  "dependencies": {
    "@okta/okta-react": "^6.2.0",
    "@okta/okta-react-native": "^2.1.1",
    "react": "17.0.2",
    "react-native": "0.66.0"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/runtime": "^7.12.5",
    "@react-native-community/eslint-config": "^2.0.0",
    "babel-jest": "^26.6.3",
    "eslint": "7.14.0",
    "jest": "^26.6.3",
    "metro-react-native-babel-preset": "^0.66.2",
    "react-test-renderer": "17.0.2"
  },
  "jest": {
    "preset": "react-native"
  }
}

Config taken from https://github.com/okta/okta-react-native#createconfig:

await createConfig({
  issuer: "https://{yourOktaDomain}/oauth2/default", // Optional
  clientId: "{clientId}",
  redirectUri: "{redirectUri}",
  endSessionRedirectUri: "{endSessionRedirectUri}",
  discoveryUri: "https://{yourOktaDomain}",
  scopes: ["openid", "profile", "offline_access"],
  requireHardwareBackedKeyStore: true, // Optional
  androidChromeTabColor: "#FF00AA", // Optional
  browserMatchAll: true, // Optional
  httpConnectionTimeout: 15, // Optional
  httpReadTimeout: 10, // Optional
});

Okta calls:

  const onSubmit = async () => {
      const response = await getAuthClient().signInWithCredentials({username, password})

      const {sessionToken } = response

      await authenticate({sessionToken})
  }

Extra information about the use case/user story you are trying to implement

Environment

JayNewstrom commented 3 years ago

Hi @kennyho-ml can you make sure the response is not null by using a print statement?

kennyho-ml commented 3 years ago

Hi @kennyho-ml can you make sure the response is not null by using a print statement?

@JayNewstrom I'm not able to get print the response ..as it's throwing an error ... I get

{ [TypeError: null is not an object (evaluating '_reactNative.NativeModules.OktaSdkBridge.authenticate')]
  line: 110740,
  column: 87,
  sourceURL: 'http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.oktaandroidtest&modulesOnly=false&runModule=true' }

when printing the error.

JayNewstrom commented 3 years ago

What does this print?

const response = await getAuthClient().signInWithCredentials({username, password})
console.log(response)
kennyho-ml commented 3 years ago

What does this print?

const response = await getAuthClient().signInWithCredentials({username, password})
console.log(response)

@JayNewstrom

{"cancel": [Function anonymous], "data": {"_embedded": {"user": [Object]}, "_links": {"cancel": [Object]}, "expiresAt": "2021-10-13T16:11:28.000Z", "sessionToken": "20111bvGnQPruqwMDsYC63FJEKRnwiQ40WPRcWWDiUSvgQ38LIOU3S1", "status": "SUCCESS"}, "expiresAt": "2021-10-13T16:11:28.000Z", "sessionToken": "20111bvGnQPruqwMDsYC63FJEKRnwiQ40WPRcWWDiUSvgQ38LIOU3S1", "status": "SUCCESS", "user": {"id": "00u27hp8vtU9IDa3s5d7", "passwordChanged": "2021-10-13T13:20:23.000Z", "profile": {"firstName": "mary", "lastName": "poppins", "locale": "en", "login": "marypoppinsatml@gmail.com", "timeZone": "America/Los_Angeles"}}}

Also .. I created my own personal okta instance... and I'm getting [Error: Okta Oidc error]

when doing:

  const onSubmit = async () => {
    try {
      const response = await getAuthClient().signInWithCredentials({
        username,
        password,
      });
      console.log('response: ', response);
      const {sessionToken} = response;
      console.log('SESSION TOKEN: ', sessionToken);
      const resp = await authenticate({sessionToken: sessionToken});
      console.log('AUTHENTICATE, ', resp);
    } catch (e) {
      console.log('ERROR : ', e);
    }
  };

Not sure if this might help.

JayNewstrom commented 3 years ago

@kennyho-ml which line is failing with [Error: Okta Oidc error]?

Is it the getAuthClient().signInWithCredentials line?

kennyho-ml commented 3 years ago

@kennyho-ml which line is failing with [Error: Okta Oidc error]?

Is it the getAuthClient().signInWithCredentials line? @JayNewstrom nope..

await authenticate({sessionToken})
JayNewstrom commented 3 years ago

What does your log for this line return?

console.log('SESSION TOKEN: ', sessionToken);

Is it a valid token?

kennyho-ml commented 3 years ago

What does your log for this line return?

console.log('SESSION TOKEN: ', sessionToken);

Is it a valid token?

I assume so .. 'SESSION TOKEN: ', '20111bvGnQPruqwMDsYC63FJEKRnwiQ40WPRcWWDiUSvgQ38LIOU3S1'..

For IOS I get

Screen Shot 2021-10-13 at 9 23 19 AM

I'm not sure why android doesn't have parity like so. .. (Getting to the requests past authn)


Here are the configs for android/app/build.gradle as well ... as I thought it might have to do something with the redirect

def nativeArchitectures = project.getProperties().get("reactNativeDebugArchitectures")

android {
    ndkVersion rootProject.ext.ndkVersion

    compileSdkVersion rootProject.ext.compileSdkVersion

    defaultConfig {
        applicationId "com.oktaandroidtest"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
        manifestPlaceholders = [
                appAuthRedirectScheme: 'com.oktaandroidtest'
        ]
    }
...
JayNewstrom commented 3 years ago

I've created an internal issue for us to take a look at this. OKTA-437013

Judging by what you've provided, it looks like a bug. If you have a chance, could you show the network logs for the Android version as well.

kennyho-ml commented 3 years ago

I've created an internal issue for us to take a look at this. OKTA-437013

Judging by what you've provided, it looks like a bug. If you have a chance, could you show the network logs for the Android version as well.

Here are the logs:

Device Logs:

Screen Shot 2021-10-13 at 4 10 21 PM

Network Logs:

Screen Shot 2021-10-13 at 4 10 56 PM
oleggnidets-okta commented 3 years ago

Hey @kennyho-ml Is there a reason to use await getAuthClient().signInWithCredentials?

I believe you can use a convenience method signIn, it does the same but in one line without needing to exchange session token. I'm not sure if it fixes the issue but still it's the SDK way to authenticate with creds.

kennyho-ml commented 3 years ago

@oleggnidets-okta hi -- we used signInWithCredentials because it exposed the deviceId which allows you to remember the device and skip MFA... It shouldn't matter though since we get the sessionToken either way to call authenticate ?

-- also it said https://github.com/okta/okta-auth-js#signinoptions was being deprecated.. I think that was also one of our reasons.

JSummerv commented 2 years ago

Having the same issue here has there been any movement on this?

JSummerv commented 2 years ago

I was able to get a more detailed error back from the module [Hardware Backed KeyStore. Client require hardware backed keystore, but EncryptionManager doesn't support it.]