Skip to content

Commit

Permalink
Fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Raible committed Apr 12, 2019
1 parent df389b6 commit 2ff25d9
Show file tree
Hide file tree
Showing 14 changed files with 174 additions and 30 deletions.
6 changes: 4 additions & 2 deletions src/add-auth/index.ts
Expand Up @@ -43,7 +43,7 @@ function addPackageJsonDependencies(framework: string, options: any): Rule {
} else if (framework === IONIC_ANGULAR) {
dependencies.push({type: NodeDependencyType.Default, version: '0.3.3', name: 'ionic-appauth'});
dependencies.push({type: NodeDependencyType.Default, version: '^2.2.0', name: '@ionic/storage'});
if (options.container === 'capacitor') {
if (options.platform === 'capacitor') {
dependencies.push({type: NodeDependencyType.Default, version: '^1.0.0-beta.19', name: '@capacitor/core'});
}
}
Expand Down Expand Up @@ -155,7 +155,7 @@ export function addAuth(options: any): Rule {
+ parts[0].substring(parts[0].lastIndexOf('/') + 1);

// add cordova to package.json
if (options.container === 'cordova') {
if (options.platform === 'cordova') {
const content: Buffer | null = host.read('./package.json');
if (content) {
const pkgJson: any = JSON.parse(content.toString());
Expand All @@ -169,6 +169,8 @@ export function addAuth(options: any): Rule {
'HttpClientModule', '@angular/common/http');
addModuleImportToModule(host, 'src/app/app.module.ts',
'AuthModule', './auth/auth.module');
addModuleImportToModule(host, 'src/app/app.module.ts',
'IonicStorageModule.forRoot()', '@ionic/storage');
}

// Setup sources to add to the project
Expand Down
140 changes: 140 additions & 0 deletions src/add-auth/ionic/angular/README.md
@@ -0,0 +1,140 @@
# Ionic 4 OIDC Login Example

This example shows how to use [Ionic AppAuth](https://github.com/wi3land/ionic-appauth) and authenticate using Okta. The majority of its code comes from [@wi3land/ionic-appauth-ng-demo](https://github.com/wi3land/ionic-appauth-ng-demo).

**Prerequisites:** [Node 11](https://nodejs.org/) and [Ionic 4](https://ionicframework.com/). After installing Node, install Ionic's CLI:

```
npm i -g ionic
```

* [Getting Started](#getting-started)
* [Configure for Mobile](#mobile)
* [iOS](#ios)
* [Android](#android)
* [Links](#links)
* [Help](#help)
* [License](#license)

## Getting Started

This app was created using the following commands:

```bash
ionic start $name tabs
cd $name
ng add @oktadev/schematics --issuer=$issuer --clientId=$clientId
```

**NOTE:** You can switch to Capacitor by passing in `--platform=capacitor`. The default is Cordova.


See [Ionic's iOS](https://ionicframework.com/docs/building/ios) and [Android Development](https://ionicframework.com/docs/building/android) docs for more information.

### Create an Application in Okta

Log in to your Okta Developer account (or [sign up](https://developer.okta.com/signup/) if you don’t have an account).

From the **Applications** page, choose **Add Application**. On the Create New Application page, select **SPA**.
Give your app a memorable name, and configure it as follows:

* Login redirect URIs:
* `http://localhost:8100/implicit/callback`
* `com.okta.dev-737523:/callback` (where `dev-737523.okta.com` is your Okta URL)
* Grant type allowed: **Authorization Code**
* Click **Done**
* Click **Edit** and add Logout redirect URIs:
* `http://localhost:8100/implicit/logout`
* `com.okta.dev-737523:/logout`
* Click **Save**

Copy your issuer (found under **API** > **Authorization Servers**), and client ID into `src/app/core/auth.service.ts` as follows:

```ts
private addConfig() {
const clientId = '{yourClientId}';
const issuer = 'https://{yourOktaDomain}/oauth2/default';
const scopes = 'openid profile offline_access';

if (this.platform.is('cordova')) {
this.authConfig = {
identity_client: clientId,
identity_server: issuer,
redirect_url: '{yourReversedOktaDomain}:/callback',
scopes: scopes,
usePkce: true,
end_session_redirect_url: '{yourReversedOktaDomain}:/logout',
};
}
...
}
```

**NOTE:** The value of `{yourOktaDomain}` should be something like `dev-123456.okta.com`. Make sure you don't include `-admin` in the value!

After modifying this file, start the app and you should be able to authenticate with Okta.

```
ionic serve
```

## Mobile

If you'd like to run this app on a mobile emulator or device, you'll need to modify `package.json` to use your reversed Okta domain.

```xml
"cordova": {
"plugins": {
...
"cordova-plugin-customurlscheme": {
"URL_SCHEME": "com.oktapreview.dev-737523",
...
},
}
}
```

This configures the [Custom URL scheme](https://github.com/EddyVerbruggen/Custom-URL-scheme) Cordova plugin so redirects back to your app will work.

## iOS

You can deploy this app to iOS Simulator using:

```shell
ionic cordova run ios
```

Then, in another terminal:

```
open platforms/ios/MyApp.xcworkspace
```

Configure signing in Xcode, then run the app.

See <https://ionicframework.com/docs/building/ios> for more information.

## Android

You can deploy this app to an AVD (Android Virtual Device) using:

```shell
ionic cordova run android
```

**NOTE:** You will need to create an AVD using Android Studio first.

## Links

This example uses the following open source libraries:

* [Ionic AppAuth](https://github.com/wi3land/ionic-appauth)
* [Ionic](https://github.com/ionic-team/ionic)

## Help

Please post any questions as issues in this repository, or on the [Okta Developer Forums](https://devforum.okta.com/).

## License

Apache 2.0, see [LICENSE](LICENSE).
2 changes: 1 addition & 1 deletion src/add-auth/ionic/angular/src/app/app.component.ts
Expand Up @@ -3,7 +3,7 @@ import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AuthService } from '../../cordova/auth.service';
import { AuthService } from './auth/auth.service';

@Component({
selector: 'app-root',
Expand Down
4 changes: 2 additions & 2 deletions src/add-auth/ionic/angular/src/app/auth/auth-guard.service.ts
@@ -1,7 +1,7 @@
import { map, skipWhile, take } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import { AuthServiceCordova } from '../../../cordova/auth.service';
import { AuthService } from './auth.service';
import { AuthActions, IAuthAction } from 'ionic-appauth';
import { NavController } from '@ionic/angular';

Expand All @@ -10,7 +10,7 @@ import { NavController } from '@ionic/angular';
})
export class AuthGuardService implements CanActivate {

constructor(private authService: AuthServiceCordova, private navCtrl: NavController) {
constructor(private authService: AuthService, private navCtrl: NavController) {
}

public async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
Expand Down
4 changes: 2 additions & 2 deletions src/add-auth/ionic/angular/src/app/auth/auth-http.service.ts
Expand Up @@ -2,7 +2,7 @@ import { Platform } from '@ionic/angular';
import { Injectable } from '@angular/core';
import { Requestor, TokenResponse } from '@openid/appauth';

import { AuthServiceCordova } from '../../../cordova/auth.service';
import { AuthService } from './auth.service';
import { CordovaRequestor } from 'ionic-appauth/lib/cordova';
import { RequestorService } from './requestor.service';

Expand All @@ -17,7 +17,7 @@ export class AuthHttpService {
angularRequestor: RequestorService,
cordovaRequestor: CordovaRequestor,
platform: Platform,
private auth: AuthServiceCordova
private auth: AuthService
) {
this.requestor = platform.is('cordova') ? cordovaRequestor : angularRequestor;

Expand Down
14 changes: 7 additions & 7 deletions src/add-auth/ionic/angular/src/app/auth/auth.service.ts
Expand Up @@ -3,9 +3,9 @@ import { Injectable, NgZone } from '@angular/core';
import { map, skipWhile, take } from 'rxjs/operators';

import { AuthActions, IAuthAction, IonicAuth } from 'ionic-appauth';
import { StorageService } from '../src/app/auth/storage.service';
import { RequestorService } from '../src/app/auth/requestor.service';
<% if (container === 'cordova') { %>import { CordovaBrowser, CordovaRequestor, CordovaSecureStorage } from 'ionic-appauth/lib/cordova';
import { StorageService } from './storage.service';
import { RequestorService } from './requestor.service';
<% if (platform === 'cordova') { %>import { CordovaBrowser, CordovaRequestor, CordovaSecureStorage } from 'ionic-appauth/lib/cordova';
<% } else { %>import { Plugins, AppLaunchUrl } from '@capacitor/core';
import { CapacitorBrowser, CapacitorStorage } from 'ionic-appauth/lib/capacitor';

Expand All @@ -17,19 +17,19 @@ const { App } = Plugins;<% } %>
export class AuthService extends IonicAuth {

constructor(requestor: RequestorService, storage: StorageService,
private platform: Platform, private ngZone: NgZone) {<% if (container === 'cordova') { %>
private platform: Platform, private ngZone: NgZone) {<% if (platform === 'cordova') { %>
super((platform.is('cordova')) ? new CordovaBrowser() : undefined,
(platform.is('cordova')) ? new CordovaSecureStorage() : storage,
(platform.is('cordova')) ? new CordovaRequestor() : requestor);<% } else { %>
super(platform.is('mobile') && !platform.is('mobileweb')) ? new CapacitorBrowser() : undefined,
super((platform.is('mobile') && !platform.is('mobileweb')) ? new CapacitorBrowser() : undefined,
(platform.is('mobile') && !platform.is('mobileweb')) ? new CapacitorStorage() : storage,
requestor);<% } %>

this.addConfig();
}

public async startUpAsync() {
<% if (container === 'cordova') { %>if (this.platform.is('cordova')) {
<% if (platform === 'cordova') { %>if (this.platform.is('cordova')) {
(<any>window).handleOpenURL = (callbackUrl) => {
this.ngZone.run(() => {
this.handleCallback(callbackUrl);
Expand All @@ -50,7 +50,7 @@ export class AuthService extends IonicAuth {
const issuer = '<%= issuer %>';
const scopes = 'openid profile offline_access';

if (<% if (container === 'cordova') { %>this.platform.is('cordova')<% } else { %>this.platform.is('mobile') && !this.platform.is('mobileweb')<% } %>) {
if (<% if (platform === 'cordova') { %>this.platform.is('cordova')<% } else { %>this.platform.is('mobile') && !this.platform.is('mobileweb')<% } %>) {
this.authConfig = {
identity_client: clientId,
identity_server: issuer,
Expand Down
Expand Up @@ -3,15 +3,15 @@ import { NavController } from '@ionic/angular';
import { Router } from '@angular/router';
import { AuthActions } from 'ionic-appauth';
import { skipWhile, take } from 'rxjs/operators';
import { AuthServiceCordova } from '../../../../../cordova/auth.service';
import { AuthService } from './../../auth.service';

@Component({
template: '<p style="margin-left: 10px">Signing in...</p>'
})
export class AuthCallbackPage implements OnInit {

constructor(
private authService: AuthServiceCordova,
private authService: AuthService,
private navCtrl: NavController,
private router: Router
) {
Expand Down
@@ -1,14 +1,14 @@
import { Component, OnInit } from '@angular/core';
import { NavController } from '@ionic/angular';
import { AuthServiceCordova } from '../../../../../cordova/auth.service';
import { AuthService } from './../../auth.service';

@Component({
template: '<p>Signing Out...</p>'
})
export class EndSessionPage implements OnInit {

constructor(
private authService: AuthServiceCordova,
private authService: AuthService,
private navCtrl: NavController,
) {
}
Expand Down
4 changes: 2 additions & 2 deletions src/add-auth/ionic/angular/src/app/login/login.page.ts
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { AuthActions, IAuthAction } from 'ionic-appauth';
import { AuthServiceCordova } from '../../../cordova/auth.service';
import { AuthService } from './../auth/auth.service';
import { NavController } from '@ionic/angular';

@Component({
Expand All @@ -11,7 +11,7 @@ import { NavController } from '@ionic/angular';
export class LoginPage implements OnInit {
action: IAuthAction;

constructor(private auth: AuthServiceCordova, private navCtrl: NavController) {
constructor(private auth: AuthService, private navCtrl: NavController) {
}

ngOnInit() {
Expand Down
4 changes: 2 additions & 2 deletions src/add-auth/ionic/angular/src/app/tab1/tab1.page.ts
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { NavController } from '@ionic/angular';
import { AuthServiceCordova } from '../../../cordova/auth.service';
import { AuthService } from './../auth/auth.service';
import { IUserInfo } from '../auth/user-info.model';
import { AuthActions, IAuthAction } from 'ionic-appauth';

Expand All @@ -13,7 +13,7 @@ export class Tab1Page implements OnInit {
userInfo: IUserInfo;
action: IAuthAction;

constructor(private navCtrl: NavController, private authService: AuthServiceCordova) {
constructor(private navCtrl: NavController, private authService: AuthService) {
}

ngOnInit() {
Expand Down
8 changes: 5 additions & 3 deletions src/add-auth/ionic_spec.ts
Expand Up @@ -53,9 +53,10 @@ describe('OktaDev Schematics: Ionic/Angular', () => {
const runner = new SchematicTestRunner('schematics', collectionPath);
runner.runSchematic('add-auth', {...defaultOptions}, tree);

expect(tree.files.length).toEqual(22);
expect(tree.files.length).toEqual(24);
expect(tree.files.sort()).toEqual([ '/package.json',
'/src/app/app-routing.module.ts',
'/src/app/app.component.spec.ts',
'/src/app/app.component.ts',
'/src/app/app.module.ts',
'/src/app/auth/auth-guard.service.ts',
Expand All @@ -75,6 +76,7 @@ describe('OktaDev Schematics: Ionic/Angular', () => {
'/src/app/login/login.page.spec.ts',
'/src/app/login/login.page.ts',
'/src/app/tab1/tab1.page.html',
'/src/app/tab1/tab1.page.spec.ts',
'/src/app/tab1/tab1.page.ts' ]);

const appModule = tree.readContent('/src/app/app.module.ts');
Expand All @@ -97,12 +99,12 @@ describe('OktaDev Schematics: Ionic/Angular', () => {
tree.create('/src/app/app.module.ts', defaultAppModule);

const capacitorOptions: any = {...defaultOptions};
capacitorOptions.container = 'capacitor';
capacitorOptions.platform = 'capacitor';

const runner = new SchematicTestRunner('schematics', collectionPath);
runner.runSchematic('add-auth', capacitorOptions, tree);

expect(tree.files.length).toEqual(22);
expect(tree.files.length).toEqual(24);

const appModule = tree.readContent('/src/app/app.module.ts');

Expand Down
2 changes: 1 addition & 1 deletion src/add-auth/schema.json
Expand Up @@ -21,7 +21,7 @@
"description": "Okta OIDC App client ID",
"x-prompt": "What is your OIDC app's client ID?"
},
"container": {
"platform": {
"type": "string",
"default": "cordova"
}
Expand Down
2 changes: 1 addition & 1 deletion test-all.sh
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
rm -rf apps
./test-app.sh a && ./test-app.sh r && ./test-app.sh rts && ./test-app.sh v && ./test-app.sh vts
./test-app.sh a && ./test-app.sh r && ./test-app.sh rts && ./test-app.sh v && ./test-app.sh vts && ./test-app.sh i && ./test-app.sh icap
6 changes: 3 additions & 3 deletions test-app.sh
Expand Up @@ -92,12 +92,12 @@ then
cd ionic-cordova
npm install ../../oktadev*.tgz
ng add @oktadev/schematics --issuer=$issuer --clientId=$clientId
CI=true npm test
ng test --watch=false
elif [ "$1" == "ionic-cap" ] || [ "$1" == "icap" ]
then
ionic start ionic-capacitor tabs --no-interactive
cd ionic-capacitor
npm install ../../oktadev*.tgz
ng add @oktadev/schematics --issuer=$issuer --clientId=$clientId --container=capacitor
npm test --watch=false
ng add @oktadev/schematics --issuer=$issuer --clientId=$clientId --platform=capacitor
ng test --watch=false
fi

0 comments on commit 2ff25d9

Please sign in to comment.