Code Monkey home page Code Monkey logo

Comments (7)

SidMorad avatar SidMorad commented on May 24, 2024 1

@mraible I start to work on it, and I will update you as I progress forward. I'm planning to 1) generate a project with the master branch 2) apply required changes to generated project 3) test it. And if everything did work well, I will try to modify templates here which I guess that will be more time consuming for me.

p.s. Thanks to this project, JHipster and Ionic we went into production stage very fluently and confidently. Thanks Matt!

from generator-jhipster-ionic.

mraible avatar mraible commented on May 24, 2024 1

Closing since I think this will be solved by Ionic 4 and Ionic AppAuth. See https://scotch.io/tutorials/build-an-ionic-4-app-with-user-login-and-registration for more information.

from generator-jhipster-ionic.

SidMorad avatar SidMorad commented on May 24, 2024

If you are interested, you can see my current solution for this in following git-diff output:

diff --git a/config.xml b/config.xml
index 5e0203d..4dba799 100644
--- a/config.xml
+++ b/config.xml
@@ -7,6 +7,7 @@
     <access origin="*" />
     <allow-intent href="http://*/*" />
     <allow-intent href="https://*/*" />
+    <allow-intent href="marsroo://*" />
     <allow-intent href="tel:*" />
     <allow-intent href="sms:*" />
     <allow-intent href="mailto:*" />
@@ -19,6 +20,7 @@
     <preference name="SplashShowOnlyFirstTime" value="false" />
     <preference name="SplashScreen" value="screen" />
     <preference name="SplashScreenDelay" value="3000" />
+    <preference name="AndroidLaunchMode" value="singleInstance" />
     <platform name="android">
         <allow-intent href="market:*" />
         <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
@@ -82,5 +84,12 @@
     <plugin name="cordova-plugin-ionic-webview" spec="^1.1.16" />
     <plugin name="cordova-plugin-ionic-keyboard" spec="^2.0.5" />
     <plugin name="cordova-plugin-inappbrowser" spec="~2.0.2" />
-    <engine name="android" spec="~7.0.0" />
+    <engine name="android" spec="6.3.0" />
+    <plugin name="cordova-plugin-browsertab" spec="~0.2.0" />
+    <plugin name="cordova-plugin-customurlscheme" spec="~4.3.0">
+        <variable name="URL_SCHEME" value="marsroo" />
+        <variable name="ANDROID_SCHEME" value=" " />
+        <variable name="ANDROID_HOST" value=" " />
+        <variable name="ANDROID_PATHPREFIX" value="/" />
+    </plugin>
 </widget>
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 979f66f..0ecbd39 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -8,6 +8,9 @@ import { MainPage } from '../pages/pages';
 import { Settings } from '../providers/providers';
 import { AuthConfig, JwksValidationHandler, OAuthService } from 'angular-oauth2-oidc';
 import { Api } from '../providers/api/api';
+import { TabsPage } from '../pages/tabs/tabs';
+
+declare const window: any;
 
 @Component({
     template: `
@@ -44,7 +47,7 @@ export class MyApp {
         {title: 'Entities', component: 'EntityPage'}
     ];
 
-    constructor(private translate: TranslateService, platform: Platform, settings: Settings, private config: Config,
+    constructor(private translate: TranslateService, private platform: Platform, settings: Settings, private config: Config,
                 private statusBar: StatusBar, private splashScreen: SplashScreen, private oauthService: OAuthService, private api: Api) {
         platform.ready().then(() => {
             // Okay, so the platform is ready and our plugins are available.
@@ -55,6 +58,30 @@ export class MyApp {
 
         this.initTranslate();
         this.initAuthentication();
+
+        const me = this;
+        window.handleOpenURL = (url) => {
+          setTimeout(function() {
+            const responseParameters = (url.split('#')[1]).split('&');
+            const parsedResponse = {};
+            for (let i = 0; i < responseParameters.length; i++) {
+                parsedResponse[responseParameters[i].split('=')[0]] =
+                    responseParameters[i].split('=')[1];
+            }
+            if (parsedResponse['access_token'] !== undefined &&
+                parsedResponse['access_token'] !== null) {
+                const idToken = parsedResponse['id_token'];
+                const accessToken = parsedResponse['access_token'];
+                const keyValuePair = `#id_token=${encodeURIComponent(idToken)}&access_token=${encodeURIComponent(accessToken)}`;
+                me.oauthService.tryLogin({
+                    customHashFragment: keyValuePair,
+                    disableOAuth2StateCheck: true
+                });
+                me.oauthService.getIdentityClaims();
+                me.nav.setRoot(TabsPage);
+            }
+          }, 0);
+        };
     }
 
     initAuthentication() {
@@ -68,21 +95,28 @@ export class MyApp {
         } else {
             // Try to get the oauth settings from the server
             this.api.get('/api/auth-info').subscribe((data: any) => {
-              console.log("Received data, ", data);
-                    data.redirectUri = 'http://localhost:8100';
-                    // save in localStorage so redirect back gets config immediately
-                    localStorage.setItem(AUTH_CONFIG, JSON.stringify(data));
-                    this.oauthService.configure(data);
-                    this.tryLogin();
-                }, error => {
-                    console.error('ERROR fetching authentication information, defaulting to Keycloak settings');
-                    this.oauthService.redirectUri = 'http://localhost:8100';
-                    this.oauthService.clientId = 'web_app';
-                    this.oauthService.scope = 'openid profile email';
-                    this.oauthService.issuer = 'http://localhost:9080/auth/realms/jhipster';
-                    this.tryLogin();
-                }
-            );
+                const me = this;
+                this.platform.ready().then(() => {
+                    window.cordova.plugins.browsertab.isAvailable(function(result) {
+                        if (result) {
+                            data.redirectUri = 'marsroo://oauth2redirect';
+                        } else {
+                            data.redirectUri = 'http://localhost:8100';
+                        }
+                        // save in localStorage so redirect back gets config immediately
+                        localStorage.setItem(AUTH_CONFIG, JSON.stringify(data));
+                        me.oauthService.configure(data);
+                        me.tryLogin();
+                    });
+                });
+            }, error => {
+                console.error('ERROR fetching authentication information, defaulting to Keycloak settings');
+                this.oauthService.redirectUri = 'http://localhost:8100';
+                this.oauthService.clientId = 'web_app';
+                this.oauthService.scope = 'openid profile email';
+                this.oauthService.issuer = 'http://localhost:9080/auth/realms/jhipster';
+                this.tryLogin();
+            });
         }
     }
 
diff --git a/src/providers/login/login.service.ts b/src/providers/login/login.service.ts
index d6681e1..4aee62d 100644
--- a/src/providers/login/login.service.ts
+++ b/src/providers/login/login.service.ts
@@ -40,32 +40,43 @@ export class LoginService {
             }
             return new Promise((resolve, reject) => {
                 const oauthUrl = this.buildUrl(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 OAuth';
-                        if (parsedResponse['state'] !== state) {
-                            reject(defaultError);
-                        } else if (parsedResponse['access_token'] !== undefined &&
-                            parsedResponse['access_token'] !== null) {
-                            resolve(parsedResponse);
+                const defaultError = 'Problem authenticating with OAuth';
+                this.platform.ready().then(()=> {
+                    window.cordova.plugins.browsertab.isAvailable(function(result) {
+                        if (result) {
+                            window.cordova.plugins.browsertab.openUrl(oauthUrl,
+                                function(success) { console.log("Success ", success); },
+                                function(error) { reject(defaultError) }
+                            );
                         } else {
-                            reject(defaultError);
+                            const browser = window.cordova.InAppBrowser.open(oauthUrl, '_blank',
+                                'location=no,clearsessioncache=no,clearcache=no');
+                            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];
+                                    }
+                                    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 OAuth sign in flow was canceled');
+                            });
                         }
-                    }
-                });
-                browser.addEventListener('exit', function (event) {
-                    reject('The OAuth sign in flow was canceled');
+                    });
                 });
             });
         });

issue28_diff.txt

Note: I have to set AndroidLaunchMode value to singleInstance otherwise new instance of the application will get launched on browser-tab callback.

UPDATE for Note: AndroidLaunchMode can be singleTask also but app will go to background mode on login-success-callback. and users have to click app icon again to enter the app as an authenticated customer.

Note2: I have to downgrade Cordova Android spec engine from 7.0.0 to 6.3.0 because of cordova-plugin-browsertab plugin.

UPDATE for Note2: At the moment my project works with the latest android platform, so downgrade to spec 6.3.0 is not necessary anymore.

Please let me know if there is a better way for solving this? thanks.

Cheers,
Sid

from generator-jhipster-ionic.

mraible avatar mraible commented on May 24, 2024

@SidMorad If you have the time, I'd love to see a pull request with this change in it. I added continuous integration with Travis today, and hope to add a login test shortly.

from generator-jhipster-ionic.

SidMorad avatar SidMorad commented on May 24, 2024

@mraible this commit shows just enough changes to make things work as expected. I did test wanted functionality in ionic serve and ionic cordova run android modes which is kind of documented here.

I also went through source code of this project for creating a pull request, but I think someone more experienced with the code base can progress a lot faster than me. So I don't want to be a blocker for this, and I will be happy to contribute more on this as a tester(of Android platform) or somethings else(please let me know). Thanks again for jhipster-ionic!

from generator-jhipster-ionic.

mraible avatar mraible commented on May 24, 2024

p.s. Thanks to this project, JHipster and Ionic we went into production stage very fluently and confidently. Thanks Matt!

This made my day! 😃

from generator-jhipster-ionic.

mraible avatar mraible commented on May 24, 2024

@SidMorad Please review PR #44 when you get a chance. I also created jhipster/generator-jhipster#7538 in JHipster so the custom URL is available in Keycloak by default.

from generator-jhipster-ionic.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.