Okta Sign In Widget using Cordova SPA (Angular)

I’m using Okta to build Authentication in my Angular App.

I already implemented the widget and it works well on browser using localhost (or whatever).

There is a problem when the app is packaged using Cordova, Okta Server throws a 400 error saying that redirect_uri is invalid or not whitelisted.

I whitelisted localhost:4200 for the browser but when using cordova, Origin is file://.

I used InAppBrowser cordova plugin but it seems not useful when using Okta Sign In Widget.

P.S.: I’m not using Ionic :slight_smile:

Hey @Lyrod,

Good practice is to hardcode the redirect_uri into the configuration of your application along with white-listing it in Okta. The issue you’re describing sounds as if you’re referencing the window.location property to determine the redirect_uri.

Can you verify at least one Login Redirect URIs in Okta match the redirectUri passed when constructing the Widget?

If that doesn’t seem to be the issue, can you could provide us with a code snippet/sample project we can use to reproduce this?

Hope this helps!

@Lyrod I am stuck with a similar situation. Were you able to solve the issue yet? If so I am interested to know what helped. Thanks

@Swetha

I finally find a way with InAppBrowser cordova plugin. Here a piece of code I found/edit :

redirectLogin () {
this.oktaLogin().then(success => {
  const idToken = success.id_token;
  const accessToken = success.access_token;
  console.log(`ID TOKEN = '${idToken}'`);
  console.log(`ACCESS TOKEN = '${accessToken}'`);
  const keyValuePair = `#id_token=${encodeURIComponent(idToken)}&access_token=${encodeURIComponent(accessToken)}`;
  this.oauthService.tryLogin({
    customHashFragment: keyValuePair,
    disableOAuth2StateCheck: true
  }).then(() => {
    console.log('LOGGED');
    console.log('REDIRECT TO /');
    this.router.navigate(['/']).then(() => {
      console.log('LOAD APP DATA');
      this.app.ngOnInit();
    });
  })
}, (error) => {
  this.errorMessage = error;
  console.log(`ERROR DURING LOGIN = ${error}`);
});

}

oktaLogin(): Promise {
return this.oauthService.createAndSaveNonce().then(nonce => {
let state: string = Math.floor(Math.random() * 1000000000).toString();
if (window.crypto) {
const array = new Uint32Array(1);
window.crypto.getRandomValues(array);
state = array.join().toString();
}
return new Promise((resolve, reject) => {
const oauthUrl = this.buildOAuthUrl(state, nonce);
console.log(‘OPEN INAPPBROWSER’);
const browser = window.cordova.InAppBrowser.open(oauthUrl, ‘_blank’,
‘location=no,clearsessioncache=yes,clearcache=yes’);
browser.addEventListener(‘loadstart’, (event) => {
if ((event.url).indexOf(‘http://localhost:4200’) === 0) {
browser.removeEventListener(‘exit’, () => {});
console.log(‘CLOSE INAPPBROWSER’);
browser.close();
const responseParameters = ((event.url).split(’#’)[1]).split(’&’);
const parsedResponse = {};
for (let i = 0; i < responseParameters.length; i++) {
parsedResponse[responseParameters[i].split(’=’)[0]] =
responseParameters[i].split(’=’)[1];
}
const defaultError = ‘Problem authenticating with Okta’;
console.log(JSON.stringify(parsedResponse));
if (parsedResponse[‘error’] === ‘access_denied’) {
reject(‘Email ou mot de passe incorrect.’);
} else if (parsedResponse[‘state’] !== state) {
reject(defaultError);
} else if (parsedResponse[‘access_token’] !== undefined &&
parsedResponse[‘access_token’] !== null) {
resolve(parsedResponse);
} else {
reject(defaultError);
}
}
});
browser.addEventListener(‘exit’, function (event) {
reject(‘The Okta sign in flow was canceled’);
});
});
});
}

buildOAuthUrl(state, nonce): string {
return this.oauthService.issuer + ‘/v1/authorize?’ +
‘client_id=’ + this.oauthService.clientId + ‘&’ +
‘redirect_uri=’ + this.oauthService.redirectUri + ‘&’ +
‘response_type=id_token%20token&’ +
‘scope=’ + encodeURI(this.oauthService.scope) + ‘&’ +
‘state=’ + state + ‘&nonce=’ + nonce;
}

You’ll need to call « redirectLogin » when button/link is clicked.

Sorry for the message formatting, I’m on mobile phone. :smile:

@Lyrod My understanding here is that you are creating the /v1/authorize url with the parameters instaed of passing this parameters to okta widget and then calling the authorization url through inapp browser. In this flow where is the user id and password being passed? Or does the okta login screen appear in the inapp browser? You are using cordova with angular js right?

@Swetha After calling the « redirectLogin » function, the inappbrowser render the okta login form (opening the form hosted by Okta).

The form has username/password fields.

I’m not using the widget here because it’s not supporting implicit flow in mobiles (or maybe I was not using it right).

Maybe there is misunderstanding, I’m using Angular 6 not AngularJS.