Skip to content

Commit

Permalink
M1: User Auth with Okta
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Raible committed Jan 12, 2018
1 parent a2e32da commit 034e7ab
Show file tree
Hide file tree
Showing 25 changed files with 636 additions and 76 deletions.
5 changes: 5 additions & 0 deletions .firebaserc
@@ -0,0 +1,5 @@
{
"projects": {
"default": "cryptopwa-oidc"
}
}
79 changes: 79 additions & 0 deletions README.md
@@ -0,0 +1,79 @@
# Ionic App with Okta Authentication

This example shows how to create an Ionic application that uses Cordova's in-app browser to log in with Okta.

Please read [Build an Ionic App with User Authentication](https://developer.okta.com/blog/2017/08/22/build-an-ionic-app-with-user-authentication) to see how this application was created.

**Prerequisites:** [Node.js](https://nodejs.org/).

> [Okta](https://developer.okta.com/) has Authentication and User Management APIs that reduce development time with instant-on, scalable user infrastructure. Okta's intuitive API and expert support make it easy for developers to authenticate, manage, and secure users and roles in any application.
* [Getting Started](#getting-started)
* [Links](#links)
* [Help](#help)
* [License](#license)

## Getting Started

To install this example application, run the following commands:

```bash
git clone git@github.com:oktadeveloper/okta-ionic-auth-example.git
cd okta-ionic-auth-example
```

This will get a copy of the project installed locally. Then run the following command to install Ionic and Cordova.

```
npm install -g cordova ionic
```

Then run the application:

```
npm install
ionic serve
```

To integrate Okta's Identity Platform for user authentication, you'll first need to:

* [Register](https://www.okta.com/developer/signup/) and create an OIDC application
* Log in to your Okta account and navigate to **Applications > Add Application**
* Select **SPA** and click **Next**
* Give your application a name (e.g. "Ionic OIDC")
* Change the **Base URI** and **Login redirect URI** to `http://localhost:8100` and click **Done**.

After performing these steps, copy the `clientId` into `src/pages/login/login.ts` and change `{yourOktaDomain}` to match your account's id.

```typescript
constructor(private navCtrl: NavController, private oauthService: OAuthService) {
oauthService.redirectUri = 'http://localhost:8100';
oauthService.clientId = '{clientId}';
oauthService.scope = 'openid profile email';
oauthService.issuer = 'https://{youtOktaDomain}.com/oauth2/default';
oauthService.tokenValidationHandler = new JwksValidationHandler();
...
}
```

Your OIDC app should have settings like the following:

<img src="https://developer.okta.com/assets/blog/ionic-authentication/oidc-settings-46747e5e9af164cf56d05f055a659520252558872d9319cadd831d5e7104b990.png" width="700" alt="Okta OIDC Settings"/>

## Links

This example uses the following libraries provided by Okta:

* [Okta Auth SDK](https://github.com/okta/okta-auth-js)

It also uses the following library provided by [Manfred Steyer](https://github.com/manfredsteyer):

* [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc)

## Help

Please post any questions as comments on the [blog post](https://developer.okta.com/blog/2017/08/22/build-an-ionic-app-with-user-authentication), or visit our [Okta Developer Forums](https://devforum.okta.com/). You can also email developers@okta.com if would like to create a support ticket.

## License

Apache 2.0, see [LICENSE](LICENSE).
16 changes: 16 additions & 0 deletions firebase.json
@@ -0,0 +1,16 @@
{
"hosting": {
"public": "www",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -24,6 +24,7 @@
"@ionic-native/splash-screen": "4.4.0",
"@ionic-native/status-bar": "4.4.0",
"@ionic/storage": "2.1.3",
"angular-oauth2-oidc": "^3.1.4",
"ionic-angular": "3.9.2",
"ionicons": "3.0.0",
"rxjs": "5.5.2",
Expand Down
22 changes: 10 additions & 12 deletions src/app/app.component.ts
@@ -1,22 +1,20 @@
import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { OAuthService } from 'angular-oauth2-oidc';

import { HomePage } from '../pages/home/home';
@Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = HomePage;
rootPage:any = 'HomePage';

constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
constructor(oauthService: OAuthService) {
console.log('oauthService.hasValidIdToken()', oauthService.hasValidIdToken());
if (oauthService.hasValidIdToken()) {
this.rootPage = 'HomePage';
} else {
this.rootPage = 'LoginPage';
}
console.log('rootPage', this.rootPage);
}
}

26 changes: 18 additions & 8 deletions src/app/app.module.ts
@@ -1,30 +1,40 @@
import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { IonicStorageModule } from '@ionic/storage';
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { HoldingsProvider } from '../providers/holdings/holdings';
import { OAuthService, UrlHelperService } from 'angular-oauth2-oidc';
import { AuthInterceptor } from '../providers/auth/auth.interceptor';

@NgModule({
declarations: [
MyApp,
HomePage
MyApp
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp)
IonicModule.forRoot(MyApp, {
preloadModules: true
}),
IonicStorageModule.forRoot(),
HttpClientModule
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage
MyApp
],
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler}
{provide: ErrorHandler, useClass: IonicErrorHandler},
HoldingsProvider,
OAuthService,
UrlHelperService
]
})
export class AppModule {}
export class AppModule {
}
27 changes: 13 additions & 14 deletions src/app/app.scss
@@ -1,16 +1,15 @@
// http://ionicframework.com/docs/theming/
.toolbar-title {
font-family: 'Courier New', sans-serif;
font-weight: bold;
}

.warning-text {
color: map-get($colors, danger) !important;
}

// App Global Sass
// --------------------------------------------------
// Put style rules here that you want to apply globally. These
// styles are for the entire app and not just one component.
// Additionally, this file can be also used as an entry point
// to import other Sass files to be included in the output CSS.
//
// Shared Sass variables, which can be used to adjust Ionic's
// default Sass variables, belong in "theme/variables.scss".
//
// To declare rules for a specific mode, create a child rule
// for the .md, .ios, or .wp mode classes. The mode class is
// automatically applied to the <body> element in the app.
.message {
margin: 20px;
padding: 20px;
background-color: map-get($colors, light);
font-size: 0.8em;
}
6 changes: 1 addition & 5 deletions src/index.html
Expand Up @@ -15,17 +15,13 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">

<!-- cordova.js required for cordova apps (remove if not needed) -->
<script src="cordova.js"></script>

<!-- un-comment this code to enable service worker
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js')
.then(() => console.log('service worker installed'))
.catch(err => console.error('Error', err));
}
</script>-->
</script>

<link href="build/main.css" rel="stylesheet">

Expand Down
60 changes: 50 additions & 10 deletions src/manifest.json
@@ -1,13 +1,53 @@
{
"name": "Ionic",
"short_name": "Ionic",
"name": "cryptoPWA",
"short_name": "cryptoPWA",
"start_url": "index.html",
"display": "standalone",
"icons": [{
"src": "assets/imgs/logo.png",
"sizes": "512x512",
"type": "image/png"
}],
"background_color": "#4e8ef7",
"theme_color": "#4e8ef7"
}
"description": "Simple wealth tracker for cryptocurrencies.",
"icons": [
{
"src": "assets/imgs/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "assets/imgs/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "assets/imgs/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "assets/imgs/icon-144x144.png",
"sizes": "144x144",
"type": "assets/imgs/image/png"
},
{
"src": "assets/imgs/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "assets/imgs/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "assets/imgs/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "assets/imgs/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"orientation": "portrait",
"splash_pages": null,
"background_color": "#000000",
"theme_color": "#000000"
}
44 changes: 44 additions & 0 deletions src/pages/add-holding/add-holding.html
@@ -0,0 +1,44 @@
<ion-header>
<ion-navbar color="primary">
<ion-title>Add Holding</ion-title>
</ion-navbar>
</ion-header>

<ion-content padding>

<div class="message">
<p>To add a holding you will need to supply the appropriate symbol for the cryptocurrency, and the symbol for the currency you would like to display the values in.</p>

<p><strong>Note:</strong> Listed prices are estimated. Rates may vary significantly across different exchanges.</p>
</div>

<ion-list>
<ion-item>
<ion-label stacked>Crypto Code</ion-label>
<ion-input [(ngModel)]="cryptoCode" placeholder="(e.g. BTC, LTC, ETH)" type="text"></ion-input>
</ion-item>
<ion-item>
<ion-label stacked>Display Currency Code</ion-label>
<ion-input [(ngModel)]="displayCurrency" placeholder="(e.g. USD, CAD, AUD)" type="text"></ion-input>
</ion-item>
<ion-item>
<ion-label stacked>Amount Holding</ion-label>
<ion-input [(ngModel)]="amountHolding" type="number"></ion-input>
</ion-item>
</ion-list>

<button ion-button full (click)="addHolding()" [disabled]="checkingValidity">Add Holding
<ion-spinner *ngIf="checkingValidity"></ion-spinner>
</button>

<p class="error-message" *ngIf="cryptoUnavailable">
Sorry, that combination is not currently available. Make sure to only include a single code.
</p>

<p class="error-message" *ngIf="noConnection">Sorry, you need to be online to add new holdings.</p>

</ion-content>

<ion-footer padding>
<p><strong>Note:</strong> This web application allows you to track your Cryptocurrency without creating an account. This means that all data is stored locally, and may be permanently deleted without warning.</p>
</ion-footer>
13 changes: 13 additions & 0 deletions src/pages/add-holding/add-holding.module.ts
@@ -0,0 +1,13 @@
import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { AddHoldingPage } from './add-holding';

@NgModule({
declarations: [
AddHoldingPage,
],
imports: [
IonicPageModule.forChild(AddHoldingPage),
],
})
export class AddHoldingPageModule {}

0 comments on commit 034e7ab

Please sign in to comment.