Comments (7)
@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.
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.
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');
+ });
});
});
});
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.
@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.
@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.
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.
@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)
- I can't run jhipster-ionic blueprint v8.1.0
- Replace ionic-native with awesome-cordova-plugins. HOT 4
- Update ionic-appauth to released version. HOT 2
- Investigate to reuse main generator components
- Error when creating entity in frontend HOT 3
- Error getting when try to create entity in front end HOT 4
- Getting error when try to create new entity HOT 2
- Error when generating the code if the jdl file has an entity with no fields HOT 5
- Conflict when an entity has two image fields HOT 5
- JWT Token issue HOT 2
- Release 8.1.0 HOT 2
- jhipster server and jhipster-ionic App Continuous Integration HOT 3
- OneToOne Relationship with jdl doesn't work HOT 8
- CORS Error HOT 12
- Are you sure you added CORS information in the correct part of `application.yml`? You might look at the [`application-dev.yml` template](https://github.com/jhipster/generator-jhipster/blob/main/generators/server/templates/src/main/resources/config/application-dev.yml.ejs#L292) to see where it should be.
- Oauth2 Social Sign-In In Android App
- Migrate to JHipster v8 HOT 5
- Release new version with Node 18 support HOT 3
- npx ionic capacitor add ios. is throwing an issue below HOT 1
- Update to angular 17 and update implementation to new angular standards. HOT 14
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from generator-jhipster-ionic.