Skip to content

Ionic 4 mobile app with angular-auth2-oidc #803

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
CodeDangler opened this issue Apr 28, 2020 · 14 comments
Closed

Ionic 4 mobile app with angular-auth2-oidc #803

CodeDangler opened this issue Apr 28, 2020 · 14 comments
Labels
question For tagging support requests and general questions.

Comments

@CodeDangler
Copy link

Hi
I could successfully launch the ionic app in mobile. But the identity server login page is getting launched in external browser. But I want to launch the page in inappbrowser for both android and iOS.

How can I achieve the same with angular-auth2-oidc and ionic cordova.

@jeroenheijmans
Copy link
Collaborator

Hmm, that's a bit broad question, we're but a small community, typically focused on helping out on bugs and feature requests. I suggest trying your luck to find someone who created a tutorial on your scenario, or be the first to write it. Otherwise, we'd have to hope for a community member here to pop up to answer your question...

@jeroenheijmans jeroenheijmans added the question For tagging support requests and general questions. label Apr 28, 2020
@CodeDangler
Copy link
Author

Hi, sorry if I missed anything.
The existing code angular-auth2-oidc is launching the url in external browser in mobile app.
How to open the same in inapp browser if there is a facility already there.

@marcelonnunes
Copy link

Hello, @CodeDangler

I would also like to use this library in mobile applications, as it is one of the best I have found.

I tried to implement a solution suggested by @nhance without success:

But I found another library, not as good as angled-oauth2-oidc from @manfredsteyer but that somehow works:

@philly-vanilly
Copy link

philly-vanilly commented Jul 13, 2020

@jeroenheijmans is it possible to turn this from a question into a feature request? The Ionic community is huge and we would profit a lot from such a well-maintained lib as this one, if it offered the option to use an own redirect instead of a static one.

Another useful feature request for Ionic would be being able to provide your own httpClient in order to use a cordova-http-client (with HTTPS pinning) for logout calls etc.

Or is Ionic support out of question in general?

@jeroenheijmans
Copy link
Collaborator

OP kicked off this thread with:

How can I achieve the same with angular-auth2-oidc and ionic cordova.?

In that I read a question for guidance around using this library within a specific ecosystem.

I'm happy to change the labels (they're just labels anyways) to a 'feature request', but then what is the specific feature being requested?

If it's about getting a specific tutorial for using the library within Ionic, I'm not sure if the community around this library is big enough to support that. It would possibly be written by someone, but then quickly go out of date. I much prefer then someone takes up the gauntlet of writing one, and we add it to the list of Tutorials.

In fact.... if you look at that list, there is already an external "Ionic" sample linked.

What do you think, does this make sense?

@philly-vanilly
Copy link

philly-vanilly commented Jul 13, 2020

@jeroenheijmans Thanks for the quick reply. I am aware of that tutorial, but the solution used there (additionally using an okta plugin) works around many of the features that this lib (angular-oauth2-oidc) already provides, thus reducing the benefits of this lib. If you take a look at this chunk of code from the tutorial:

oktaLogin(): Promise<any> {
  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);
      const browser = window.cordova.InAppBrowser.open(oauthUrl, '_blank',
        'location=no,clearsessioncache=yes,clearcache=yes');
      browser.addEventListener('loadstart', (event) => {
        if ((event.url).indexOf('http://localhost:8100') === 0) {
          browser.removeEventListener('exit', () => {});
          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';
          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');
      });
    });
  });
}

all this response parameters parsing is something that you already have in the lib. It would be better if one could pass that window.cordova.InAppBrowser.open into the lib and let the URL parsing etc be handled by the lib as with Angular for the web.

And as mentioned above, one should be able to provide a custom httpClient for HTTPS-pinning (I would see that in a separate feature).

So basically, I am asking for "real" Ionic support, not documentation or a tutorial. Is this something that this lib could provide in the future or do you not want to open that can of worms?

@jeroenheijmans
Copy link
Collaborator

I'm starting to understand a little better.

I'm asking for "real" Ionic support...
Is this something that this lib could provide?

I think it's good to have interception points in the library, as long as they're not tightly coupled to another framework such as Ionic: we don't want to give all users of the library Ionic-specific features, I think?

I have not read through the tutorial, nor do I know much about Ionic. The code you posted does look off to me indeed, you shouldn't need that when using the library. But it could also be that you could do better than that specific tutorial? I just don't know.

What we really need to know what the actual, concrete feature request is. Because "real Ionic support" is still too vague for me. And with that, a bit too hard to know if it'd be a good fit.

Would you have a concrete prototype or proposed change for the library, that would make it more useful in e.g. Ionic environments?

@philly-vanilly
Copy link

philly-vanilly commented Jul 13, 2020

@jeroenheijmans This is what I had in mind, sounds good 👍

I will make two new feature-requests with detailed requirements. EDIT:

        if (isMobile) {
            implicitFlowConfig.openUri = (uri) => {
                const browser = this.iab.create(uri, "_blank",
                    "location=no,clearsessioncache=yes,clearcache=yes");
                browser.on("loadstart").subscribe(event => {
                    if ((event.url).indexOf("http://localhost:8100") === 0) {
                        browser.close();
                        const responseParameters = ((event.url).split('#')[1]).split('&');
                        const parsedResponse: any = {};
                        for (let i = 0; i < responseParameters.length; i++) {
                            parsedResponse[responseParameters[i].split('=')[0]] =
                                responseParameters[i].split('=')[1];
                        }

                        const idToken = parsedResponse.id_token;
                        const accessToken = parsedResponse.access_token;
                        const keyValuePair = `#id_token=${encodeURIComponent(idToken)}&access_token=${encodeURIComponent(accessToken)}`;
                        this.oauthService.tryLogin({
                            customHashFragment: keyValuePair,
                            disableOAuth2StateCheck: true
                        }).then(sucess => {
                             if (success) { /* after-login-actions, like redirect to welcome page */}
                        });
                    }
                });
                browser.show();
            };
        }
        this.oauthService.configure(implicitFlowConfig);

If you have any idea how to change it to code-flow, that would be greatly appreciated. The code flow seems not to receive a URL based response at all? This part is never executed for me when I change to code-flow: if ((event.url).indexOf("http://localhost:8100") === 0) {...}

@jeroenheijmans
Copy link
Collaborator

Thx @philly-vanilly!

Fair warning: the community at the library is small, and PRs sometimes move a bit slow. I moderate the issues a lot, but it's largely the core maintainer looking at a bunch of PRs all at once every few months. So you might not get fast or huge interaction (but the effort is still appreciated! <3).

@philly-vanilly
Copy link

I assume, with code flow, I would need to use customRedirectUri instead of customHashFragment?

@jensharder91
Copy link

Hi @philly-vanilly ,
thanks for your code snippet!
Did you fine a solution for code flow?

@mrmkrs
Copy link

mrmkrs commented Oct 1, 2020

I've been looking for a similair solution. After lots of debugging and looking at the source code of this library I figured out what to do when using capacitor.
Our current setup: Angular 8
angular-oauth2-oidc: 10.0.3
capacitor: 2.4.2

Implicit flow was working fine at first, but the code flow+PKCE gave some issues which where caused by an outdated version of angular-oauth2-oidc, but was resolved in this PR

The little bit of code that was needed to get things working:

import {NgZone} from '@angular/core';
import {Plugins} from '@capacitor/core';
import {OAuthService} from 'angular-oauth2-oidc';
import {Router} from '@angular/router';

const {App, Browser, Device} = Plugins;

export class AppComponent {

  constructor(
    private zone: NgZone,
    private oauthService: OAuthService,
    private router: Router,
  ) {
    this.listenForOAuthRedirect();
  }

  private async listenForOAuthRedirect() {
    // example of the important stuff
    const oauthParameters = {
      responseType: 'code',
      // the IDP must redirect to the App URI (it should be whitelisted)
      redirectUri: 'custom-app-uri://localhost',
      // open a new browser window when starting implicit flow
      openUri: url => Browser.open({url})
    };

    this.oauthService.configure(oauthParameters);

    App.addListener('appUrlOpen', async data => {
      const platform = (await Device.getInfo()).platform as Platform;
      
      // because reasons
      if (platform === 'ios') {
        await Browser.close();
      }

      await this.zone.run(async () => {
        await this.oauthService.tryLogin({customHashFragment: data.url.substr(data.url.indexOf('?'))});

        const hasValidAccessToken = await this.oauthService.hasValidAccessToken();

        if(hasValidAccessToken){
          await this.router.navigate(['/your-protected-route-after-login']);
        }
      });
    });
  }

}

@Maryannah
Copy link

@mrmkrs thank you for that snippet, you saved me from hours (if not days) of hassle !

@julien-andre
Copy link

julien-andre commented Aug 19, 2022

Hi,

I'm already using the auth lib for a regular Angular project, and I tried to adapt my code for an Ionic version of the app.

Angular 13
angular-oauth2-oidc: 13.0.1
Ionic 6.1.9

I tried the above sample from @mrmkrs for Ionic but I don't get the App.addListener('appUrlOpen', () => ...) triggered in my android simulator.
What is supposed to trigger the appUrlOpen event? Because obviously we must get inside to execute this.oauthService.tryLogin() method. Maybe I should mention I'm very new to Ionic :).

I don't get neither this part:

// the IDP must redirect to the App URI (it should be whitelisted)
 redirectUri: 'custom-app-uri://localhost',

How should I setup the app URI in Ionic? I didn't find the concept in the doc except for "DeepLink plugin".
Also, by whitelisted I guess you mean the server side config (keycloak) to allow the redirection to the url.

For comparison, here is my (working) code for the web app:

// Called by an APP_INITIALIZER
initialize(): Observable<boolean> {
    const authSubject = new Subject<boolean>();
    this.oauthService.configure(environment.config.authConfig);
    this.oauthService.loadDiscoveryDocumentAndLogin().then(authenticated => {
      if (authenticated) {
        this.oauthService.setupAutomaticSilentRefresh();
        // Perform login in App state
        this.login();
      } else {
        this.oauthService.initImplicitFlow();
      }
      authSubject.next(authenticated);
      authSubject.complete();
    });
    return authSubject.asObservable();
  }

I would really appreciate some help here. Thanks a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question For tagging support requests and general questions.
Projects
None yet
Development

No branches or pull requests

8 participants