How to Add Auth to Your PWA with Okta and Stencil

This article was originally published on OKTA Blog. Thank you for supporting the partners who make SitePoint possible.
Progressive Web Applications (PWAs) are the newest technology on the web dev block, and they’ve arrived just in time to solve a growing problem. Many companies are struggling to keep isolated development teams across their organization up-to-date when new features are released. Some companies are even trying to decide if it’s worth the cost to develop both a web app and a mobile application. Not surprisingly, it’s a headache most companies are looking to avoid. PWAs can give companies a lot of the features they need from a mobile app without the need to manage multiple teams and codebases.
A PWA performs spectacularly when on a fast connection, and still performs well when offline or on Wi-Fi that’s not really fast enough to be called Wi-Fi (sometimes called “Lie-Fi”). It does so via caching and a JavaScript “Service Worker” that intercepts server calls and tries to serve the data from cache first, then when the server finally responds, it will replace the cached data with possibly “fresher” data from the server.
Recently, the Ionic team released a new project called Stencil. Stencil is a compiler that generates standards-compliant web components. Unlike most JavaScript frameworks, it doesn’t deliver a “framework” of code to the browser. It simply takes the code you write and uses its compiler to create vanilla components. You can also use Stencil’s compiler with your favorite framework. The Stencil starter project is the easiest way to get started with Stencil and produces a base application that scores nearly a 100% score on Lighthouse’s progressive web app scorecard.
To get started building a PWA using Stencil, clone the starter application and detach it from the GitHub remote.
WARNING: Stencil is not at a 1.0 release yet (as of this writing). So be aware that if you continue, you’re in early-adopter territory. If you find bugs, submit an issue.
Set Up the Starter Application
git clone https://github.com/ionic-team/stencil-starter.git first-stencil
cd first-stencil
git remote rm origin

Then, install all the dependencies that your new Stencil app will need.
npm install

You may see a couple of warnings from node-pre-gyp around fsevents. There’s nothing to see here. This is just to get around a nasty little npm bug.
Next, add the Okta Auth SDK (via CDN) to the bottom of the index.html page, right before the closing tag.
<script src=”https://ok1static.oktacdn.com/assets/js/sdk/okta-auth-js/1.8.0/okta-auth-js.min.js" type="text/javascript"></script>

While there is an npm package for Okta’s Auth SDK, Stencil has a hard time compiling it. Overall it works better for now if you just use the CDN to include it.
If you’re like me, the next thing you’ll want to do is run npm start and check the site with Lighthouse. If you do, you’ll notice that the score is kind of low. In particular, it doesn’t register a service worker or return a 200 when offline. That’s because it’s a development build, and generally, you don’t want the service worker intercepting server calls and returning cached data in development.
To ensure an accurate depiction of the kind of PWA you get out of the box with Stencil, make sure to run a production build using npm run build. Once you do, you’ll see a www folder and inside that folder, you’ll see a sw.js file. That’s your service worker!
Set Up Your Okta Application
If you haven’t already done so, create a free-forever developer account.
Once you’ve registered, click on Applications in the top menu. Then click Add Application.

You will then be taken to the application creation wizard. Choose Single-Page App and click Next at the bottom.

On the next screen, you’ll see the default settings provided by the single-page application template. Change the name of the application to something more descriptive, like “Stencil SPA”. Also, change the base URIs and the login redirect URIs settings to use port 3333 because that’s where your application will be running. The rest of the default settings are fine.

Click Done at the bottom.
Select your newly created application from the listing, and click on the General tab to view the general settings.

At the bottom, you’ll see a Client ID setting (yours won’t be blurred out, obviously). Copy this to use in your Stencil application. You will also need your Okta organization URL, which you can find at the top right of the dashboard page. It will probably look something like “https://dev-XXXXXX.oktapreview.com”.
Add the Authentication Component
In the components folder, add a new folder called app-auth. This is where your login page component will go. You can call it whatever you want, I’m just following the naming conventions set out by the starter app here. I’d definitely recommend deciding on a naming convention early and sticking with it.
Inside the newly created app-auth folder create two files: app-auth.css and app-auth.tsx. Start by creating the shell of the app-auth.tsx file.
import { Component } from ‘@stencil/core’;

@Component({
tag: ‘app-auth’,
styleUrl: ‘app-auth.css’
})
export class AppAuth {
render() {
return <div>Hello</div>;
}
}

If you are like I was, you might be thinking, “What kind of Frankenstein framework is this?”
You’ll notice the @Component decorator over the AppAuth class declaration like Angular, and then a render() method at the bottom like React. To me, that’s the beauty of Stencil. It takes some of the best parts of both popular frameworks and uses them to compile reusable components!
Add a Login Form
Next, you’ll add the JSX (that’s right, I said it) to the new component. Change the render() method to:
render() {
return (
<form class="app-auth">
<div class="form-item">
<label>
Username:
<input type="text" name="username" autocomplete="username" />
</label>
</div>
<div class="form-item">
<label>
Password:
<input
type="password"
name="password"
autocomplete="current-password"
/>
</label>
</div>
<div class="form-actions">
<button type="button" onClick={() => this.login()}>
Login
</button>
</div>
</form>
);
}

This is just a regular JSX form, but the login button’s onClick event is currently wired to function that doesn’t exist.
Add the Login Method’s Dependencies
Before you create that function, you’ll need to set up the OktaAuth JavaScript object to call the Okta API for authentication. You’ll add the object to the component’s state, so right below the class declaration, add the following line:
@State() authClient: any;

You will also have to import the @State() decorator. This is is used for values related to the internal state of the component. In the first import statement add State to the deconstruction list.
import { Component, State } from ‘@stencil/core’

You’ll also need to get the username and password values from the form itself, so add an @Element() to the code right below that @State() like you just created, so it read like this:
@State() authClient: any;
@Element() host: HTMLElement;

Then also add the @Element() decorator to the import so it reads:
import { Component, State, Element } from ‘@stencil/core’;

One last thing that the login() function will need is access to the router, so you can redirect the user to their profile page if their authentication is successful. You’ll need a class property, so add it right below the @Element.
@State() authClient: any;
@Element() host: HTMLElement;
@Prop() history: RouterHistory;

To import it, add the @Prop() decorator to the main import and then import the RouterHistory from @stencil/router right below the core import statement. The @Prop decorator is used to define properties that can be passed in to your component. In this case, it’s not a passed in value, but it could be if need be. Your final import section should read:
import { Component, Prop, State, Element, Listen } from ‘@stencil/core’;
import { RouterHistory } from ‘@stencil/router’;

Finally, to use the OktaAuth JavaScript library you brought in from the CDN, add a declaration for it right below the import statements.
declare const OktaAuth: any;

Add the Login Method
Now you included everything you’ll need to get the login function to authenticate users with your Okta organization. First, set up the OktaAuth object in the constructor of the AppAuth class. Right below the property for the RouterHistory object, add:
constructor() {
this.authClient = new OktaAuth({
clientId: ‘{yourClientId}’,
url: ‘https://{yourOktaDomain}.com’,
issuer: ‘default’
});
}

You can get your Client ID from that general settings page of your Okta application.
The post How to Add Auth to Your PWA with Okta and Stencil appeared first on SitePoint.

Link: https://www.sitepoint.com/how-to-add-auth-to-your-pwa-with-okta-and-stencil/