Home > Web Front-end > JS Tutorial > Setup angular authentication using OpenID Connect and Okta in your app

Setup angular authentication using OpenID Connect and Okta in your app

Joseph Gordon-Levitt
Release: 2025-02-16 11:09:10
Original
461 people have browsed it

Setup angular authentication using OpenID Connect and Okta in your app

This article was originally published on OKTA Developer Blog. Thank you for supporting the partners who make SitePoint possible.

Angular (formerly called Angular 2.0) is quickly becoming one of the most powerful ways to build a modern single-page app. A core strength is Angular’s focus on building reusable components, which help you decouple the various concerns in your application. Take authentication, for example: it can be painful to build, but once you wrap it in a component, the authentication logic can be reused throughout your application.

The Angular CLI makes it easy to scaffold new components, and even entire projects. If you haven’t used the Angular CLI to quickly generate Angular code, you’re in for a treat!

In this example, you’ll build a simple web application with Angular CLI, a tool for Angular development. You’ll create an application with search and edit features, then add authentication.

Key Takeaways

  • Quickly scaffold and run a new Angular application using Angular CLI, enhancing development efficiency.
  • Integrate authentication seamlessly by setting up an OpenID Connect app with Okta, ensuring secure user management.
  • Enhance user experience by adding search and edit features, utilizing Angular’s powerful component system.
  • Utilize routing to manage navigation within the application, allowing for a smoother user flow and better state management.
  • Implement form validation to ensure data integrity and provide feedback, improving overall usability.
  • Secure application routes using Angular’s AuthGuard to protect sensitive information and enforce authentication.

Create an Angular Application

TIP: If you’d like to skip building the Angular application and get right to adding authentication, you can clone my ng-demo project, then skip to the Create an OpenID Connect App in Okta section.

<span>git clone https://github.com/mraible/ng-demo.git
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

What You’ll Need

  • About 20 minutes
  • A favorite text editor or IDE. I recommend IntelliJ IDEA
  • Node.js and npm installed. I recommend using nvm
  • Angular CLI installed. If you don’t have Angular CLI installed, install it using npm install -g @angular/cli

Create a new project using the ng new command:

ng new ng-demo
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

This will create a ng-demo project and run npm install in it. It should take about a minute to complete, but that could vary depending on your connection speed.

<span>[mraible:~/dev] $ ng new ng-demo
</span>installing ng
  create .editorconfig
  create README.md
  create src/app/app.component.css
  create src/app/app.component.html
  create src/app/app.component.spec.ts
  create src/app/app.component.ts
  create src/app/app.module.ts
  create src/assets/.gitkeep
  create src/environments/environment.prod.ts
  create src/environments/environment.ts
  create src/favicon.ico
  create src/index.html
  create src/main.ts
  create src/polyfills.ts
  create src/styles.css
  create src/test.ts
  create src/tsconfig.app.json
  create src/tsconfig.spec.json
  create src/typings.d.ts
  create .angular-cli.json
  create e2e/app.e2e-spec.ts
  create e2e/app.po.ts
  create e2e/tsconfig.e2e.json
  create .gitignore
  create karma.conf.js
  create package.json
  create protractor.conf.js
  create tsconfig.json
  create tslint.json
Successfully initialized git.
Installing packages <span>for tooling via npm.
</span>Installed packages <span>for tooling via npm.
</span>You can <span><span>`ng set --global packageManager=yarn`</span>.
</span>Project <span>'ng-demo' successfully created.
</span><span>[mraible:~] 46s $
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

You can see the what version of Angular CLI you’re using with ng --version.

$ ng <span>--version
</span>    _                      _                 ____ _     ___
   / <span>\   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
</span>  / △ <span>\ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
</span> / ___ <span>\| | | | (_| | |_| | | (_| | |      | |___| |___ | |
</span>/_/   <span>\_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
</span>               <span>|___/
</span>@angular/cli: <span>1.3.2
</span>node: <span>8.4.0
</span>os: darwin x64
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Run Your Angular Application

The project is configured with webpack dev server. To start it, make sure you’re in the ng-demo directory, then run:

<span>git clone https://github.com/mraible/ng-demo.git
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

You should see a screen like the one below at http://localhost:4200.

Setup angular authentication using OpenID Connect and Okta in your app

You can make sure your new project’s tests pass, run ng test:

ng new ng-demo
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Add a Search Feature

To add a search feature, open the project in an IDE or your favorite text editor. For IntelliJ IDEA, use File > New Project > Static Web and point to the ng-demo directory.

In a terminal window, cd into your project’s directory and run the following command. This will create a search component.

<span>[mraible:~/dev] $ ng new ng-demo
</span>installing ng
  create .editorconfig
  create README.md
  create src/app/app.component.css
  create src/app/app.component.html
  create src/app/app.component.spec.ts
  create src/app/app.component.ts
  create src/app/app.module.ts
  create src/assets/.gitkeep
  create src/environments/environment.prod.ts
  create src/environments/environment.ts
  create src/favicon.ico
  create src/index.html
  create src/main.ts
  create src/polyfills.ts
  create src/styles.css
  create src/test.ts
  create src/tsconfig.app.json
  create src/tsconfig.spec.json
  create src/typings.d.ts
  create .angular-cli.json
  create e2e/app.e2e-spec.ts
  create e2e/app.po.ts
  create e2e/tsconfig.e2e.json
  create .gitignore
  create karma.conf.js
  create package.json
  create protractor.conf.js
  create tsconfig.json
  create tslint.json
Successfully initialized git.
Installing packages <span>for tooling via npm.
</span>Installed packages <span>for tooling via npm.
</span>You can <span><span>`ng set --global packageManager=yarn`</span>.
</span>Project <span>'ng-demo' successfully created.
</span><span>[mraible:~] 46s $
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Open src/app/search/search.component.html and replace its default HTML with the following:

$ ng <span>--version
</span>    _                      _                 ____ _     ___
   / <span>\   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
</span>  / △ <span>\ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
</span> / ___ <span>\| | | | (_| | |_| | | (_| | |      | |___| |___ | |
</span>/_/   <span>\_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
</span>               <span>|___/
</span>@angular/cli: <span>1.3.2
</span>node: <span>8.4.0
</span>os: darwin x64
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

The Router documentation for Angular provides the information you need to setup a route to the SearchComponent you just generated. Here’s a quick summary:

In src/app/app.module.ts, add an appRoutes constant and import it in @NgModule:

ng serve
Copy after login
Copy after login
Copy after login
Copy after login

In src/app/app.component.html, adjust the placeholder content and add a tag to display routes.

$ ng <span>test
</span><span>...
</span>Chrome <span>60.0.3112 (Mac OS X 10.12.6): Executed 3 of 3 SUCCESS (0.239 secs / 0.213 secs)
</span>
Copy after login
Copy after login
Copy after login
Copy after login

Now that you have routing setup, you can continue writing the search feature.

If you still have ng serve running, your browser should refresh automatically. If not, navigate to http://localhost:4200. You will likely see a blank screen. Open your JavaScript console and you’ll see the problem.

Setup angular authentication using OpenID Connect and Okta in your app

To solve this, open src/app/app.module.ts and add FormsModule as an import in @NgModule:

$ ng g component search
installing component
  create src/app/search/search.component.css
  create src/app/search/search.component.html
  create src/app/search/search.component.spec.ts
  create src/app/search/search.component.ts
  update src/app/app.module.ts
Copy after login
Copy after login
Copy after login
Copy after login

Now you should see the search form.

Setup angular authentication using OpenID Connect and Okta in your app

If you want to add CSS for this components, open src/app/search/search.component.css and add some CSS. For example:

<span><span><span><h2</span>></span>Search<span><span></h2</span>></span>
</span><span><span><span><form</span>></span>
</span>  <span><span><span><input</span> type<span>="search"</span> name<span>="query"</span> [(ngModel)]<span>="query"</span> (keyup.enter)<span>="search()"</span>></span>
</span>  <span><span><span><button</span> type<span>="button"</span> (click)<span>="search()"</span>></span>Search<span><span></button</span>></span>
</span><span><span><span></form</span>></span>
</span><span><span><span><pre</span>></span>{{searchResults | json}}<span><span></pre</span>></span>
</span>
Copy after login
Copy after login
Copy after login
Copy after login

This section has shown you how to generate a new component to a basic Angular application with Angular CLI. The next section will show you how to create and use a JSON file and localStorage to create a fake API.

To get search results, create a SearchService that makes HTTP requests to a JSON file. Start by generating a new service.

<span>import { Routes, RouterModule } from '@angular/router';
</span>
<span>const appRoutes: Routes = [
</span>  <span>{path: 'search', component: SearchComponent},
</span>  <span>{path: '', redirectTo: '/search', pathMatch: 'full'}
</span><span>];
</span>
<span><span>@NgModule</span>({
</span>  <span>...
</span>  imports<span>: [
</span>    <span>...
</span>    RouterModule<span>.forRoot(appRoutes)
</span>  <span>]
</span>  <span>...
</span><span>})
</span><span>export class AppModule { }
</span>
Copy after login
Copy after login
Copy after login

Move the generated search.service.ts and its test to app/shared/search. You’ll need to create this directory.

<span><span><span><h1</span>></span>Welcome to {{title}}!<span><span></h1</span>></span>
</span><span><!-- Routed views go here -->
</span><span><span><span><router-outlet</span>></span><span><span></router-outlet</span>></span>
</span>
Copy after login
Copy after login
Copy after login

Create src/assets/data/people.json to hold your data.

<span>import { FormsModule } from '@angular/forms';
</span>
<span><span>@NgModule</span>({
</span>  <span>...
</span>  imports<span>: [
</span>    <span>...
</span>    FormsModule
  <span>]
</span>  <span>...
</span><span>})
</span><span>export class AppModule { }
</span>
Copy after login
Copy after login
Copy after login

Modify src/app/shared/search/search.service.ts and provide Http as a dependency in its constructor. In this same file, create a getAll() method to gather all the people. Also, define the Address and Person classes that JSON will be marshalled to.

<span><span>:host</span> {
</span>  <span>display: block;
</span>  <span>padding: 0 20px;
</span><span>}
</span>
Copy after login
Copy after login
Copy after login

To make these classes available for consumption by your components, edit src/app/shared/index.ts and add the following:

<span>git clone https://github.com/mraible/ng-demo.git
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

The reason for creating this file is so you can import multiple classes on a single line rather than having to import each individual class on separate lines.

In src/app/search/search.component.ts, add imports for these classes.

ng new ng-demo
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

You can now add query and searchResults variables. While you’re there, modify the constructor to inject the SearchService.

<span>[mraible:~/dev] $ ng new ng-demo
</span>installing ng
  create .editorconfig
  create README.md
  create src/app/app.component.css
  create src/app/app.component.html
  create src/app/app.component.spec.ts
  create src/app/app.component.ts
  create src/app/app.module.ts
  create src/assets/.gitkeep
  create src/environments/environment.prod.ts
  create src/environments/environment.ts
  create src/favicon.ico
  create src/index.html
  create src/main.ts
  create src/polyfills.ts
  create src/styles.css
  create src/test.ts
  create src/tsconfig.app.json
  create src/tsconfig.spec.json
  create src/typings.d.ts
  create .angular-cli.json
  create e2e/app.e2e-spec.ts
  create e2e/app.po.ts
  create e2e/tsconfig.e2e.json
  create .gitignore
  create karma.conf.js
  create package.json
  create protractor.conf.js
  create tsconfig.json
  create tslint.json
Successfully initialized git.
Installing packages <span>for tooling via npm.
</span>Installed packages <span>for tooling via npm.
</span>You can <span><span>`ng set --global packageManager=yarn`</span>.
</span>Project <span>'ng-demo' successfully created.
</span><span>[mraible:~] 46s $
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Then implement a search() method to call the service’s getAll() method.

$ ng <span>--version
</span>    _                      _                 ____ _     ___
   / <span>\   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
</span>  / △ <span>\ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
</span> / ___ <span>\| | | | (_| | |_| | | (_| | |      | |___| |___ | |
</span>/_/   <span>\_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
</span>               <span>|___/
</span>@angular/cli: <span>1.3.2
</span>node: <span>8.4.0
</span>os: darwin x64
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

At this point, you’ll likely see the following message in your browser’s console.

ng serve
Copy after login
Copy after login
Copy after login
Copy after login

To fix the “No provider” error from above, update app.module.ts to import the SearchService and add the service to the list of providers. Because SearchService depends on Http, you’ll need to import HttpModule as well.

$ ng <span>test
</span><span>...
</span>Chrome <span>60.0.3112 (Mac OS X 10.12.6): Executed 3 of 3 SUCCESS (0.239 secs / 0.213 secs)
</span>
Copy after login
Copy after login
Copy after login
Copy after login

Now clicking the search button should work. To make the results look better, remove the

 tag and replace it with a 
Copy after login
in src/app/search/search.component.html.
$ ng g component search
installing component
  create src/app/search/search.component.css
  create src/app/search/search.component.html
  create src/app/search/search.component.spec.ts
  create src/app/search/search.component.ts
  update src/app/app.module.ts
Copy after login
Copy after login
Copy after login
Copy after login

Then add some additional CSS in src/app/search/search.component.css to improve its table layout.

<span><span><span><h2</span>></span>Search<span><span></h2</span>></span>
</span><span><span><span><form</span>></span>
</span>  <span><span><span><input</span> type<span>="search"</span> name<span>="query"</span> [(ngModel)]<span>="query"</span> (keyup.enter)<span>="search()"</span>></span>
</span>  <span><span><span><button</span> type<span>="button"</span> (click)<span>="search()"</span>></span>Search<span><span></button</span>></span>
</span><span><span><span></form</span>></span>
</span><span><span><span><pre</span>></span>{{searchResults | json}}<span><span></pre</span>></span>
</span>
Copy after login
Copy after login
Copy after login
Copy after login

Now the search results look better.

Setup angular authentication using OpenID Connect and Okta in your app

But wait, you still don’t have search functionality! To add a search feature, add a search() method to SearchService.

<span>import { Routes, RouterModule } from '@angular/router';
</span>
<span>const appRoutes: Routes = [
</span>  <span>{path: 'search', component: SearchComponent},
</span>  <span>{path: '', redirectTo: '/search', pathMatch: 'full'}
</span><span>];
</span>
<span><span>@NgModule</span>({
</span>  <span>...
</span>  imports<span>: [
</span>    <span>...
</span>    RouterModule<span>.forRoot(appRoutes)
</span>  <span>]
</span>  <span>...
</span><span>})
</span><span>export class AppModule { }
</span>
Copy after login
Copy after login
Copy after login

Then refactor SearchComponent to call this method with its query variable.

<span><span><span><h1</span>></span>Welcome to {{title}}!<span><span></h1</span>></span>
</span><span><!-- Routed views go here -->
</span><span><span><span><router-outlet</span>></span><span><span></router-outlet</span>></span>
</span>
Copy after login
Copy after login
Copy after login

Now search results will be filtered by the query value you type in.

This section showed you how to fetch and display search results. The next section builds on this and shows how to edit and save a record.

Add an Edit Feature

Modify src/app/search/search.component.html to add a link for editing a person.

<span>import { FormsModule } from '@angular/forms';
</span>
<span><span>@NgModule</span>({
</span>  <span>...
</span>  imports<span>: [
</span>    <span>...
</span>    FormsModule
  <span>]
</span>  <span>...
</span><span>})
</span><span>export class AppModule { }
</span>
Copy after login
Copy after login
Copy after login

Run the following command to generate an EditComponent.

<span><span>:host</span> {
</span>  <span>display: block;
</span>  <span>padding: 0 20px;
</span><span>}
</span>
Copy after login
Copy after login
Copy after login

Add a route for this component in src/app/app.module.ts:

$ ng g <span>service search
</span>installing <span>service
</span>  create src/app/search.service.spec.ts
  create src/app/search.service.ts
  WARNING Service is generated but not provided, it must be provided to be used
Copy after login

Update src/app/edit/edit.component.html to display an editable form. You might notice I’ve added id attributes to most elements. This is to make things easier when writing integration tests with Protractor.

<span>mkdir -p src/app/shared/search
</span><span>mv src/app/search.service.* src/app/shared/search/.
</span>
Copy after login

Modify EditComponent to import model and service classes and to use the SearchService to get data.

<span>[
</span>  <span>{
</span>    <span>"id": 1,
</span>    <span>"name": "Peyton Manning",
</span>    <span>"phone": "(303) 567-8910",
</span>    <span>"address": {
</span>      <span>"street": "1234 Main Street",
</span>      <span>"city": "Greenwood Village",
</span>      <span>"state": "CO",
</span>      <span>"zip": "80111"
</span>    <span>}
</span>  <span>},
</span>  <span>{
</span>    <span>"id": 2,
</span>    <span>"name": "Demaryius Thomas",
</span>    <span>"phone": "(720) 213-9876",
</span>    <span>"address": {
</span>      <span>"street": "5555 Marion Street",
</span>      <span>"city": "Denver",
</span>      <span>"state": "CO",
</span>      <span>"zip": "80202"
</span>    <span>}
</span>  <span>},
</span>  <span>{
</span>    <span>"id": 3,
</span>    <span>"name": "Von Miller",
</span>    <span>"phone": "(917) 323-2333",
</span>    <span>"address": {
</span>      <span>"street": "14 Mountain Way",
</span>      <span>"city": "Vail",
</span>      <span>"state": "CO",
</span>      <span>"zip": "81657"
</span>    <span>}
</span>  <span>}
</span><span>]
</span>
Copy after login

Modify SearchService to contain functions for finding a person by their id, and saving them. While you’re in there, modify the search() method to be aware of updated objects in localStorage.

<span>import { Injectable } from '@angular/core';
</span><span>import { Http, Response } from '@angular/http';
</span><span>import 'rxjs/add/operator/map';
</span>
<span><span>@Injectable</span>()
</span><span>export class SearchService {
</span>  <span>constructor(private http: Http) {}
</span>
  <span>getAll() {
</span>    <span>return this.http.get('assets/data/people.json')
</span>        <span>.map((res: Response) => res.json());
</span>  <span>}
</span><span>}
</span>
<span>export class Address {
</span>  street<span>: string;
</span>  city<span>: string;
</span>  state<span>: string;
</span>  zip<span>: string;
</span>
  <span>constructor(obj?: any) {
</span>    <span>this.street = obj && obj.street || null;
</span>    <span>this.city = obj && obj.city || null;
</span>    <span>this.state = obj && obj.state || null;
</span>    <span>this.zip = obj && obj.zip || null;
</span>  <span>}
</span><span>}
</span>
<span>export class Person {
</span>  id<span>: number;
</span>  name<span>: string;
</span>  phone<span>: string;
</span>  address<span>: Address;
</span>
  <span>constructor(obj?: any) {
</span>    <span>this.id = obj && Number(obj.id) || null;
</span>    <span>this.name = obj && obj.name || null;
</span>    <span>this.phone = obj && obj.phone || null;
</span>    <span>this.address = obj && obj.address || null;
</span>  <span>}
</span><span>}
</span>
Copy after login

You can add CSS to src/app/edit/edit.component.css if you want to make the form look a bit better.

<span>export * from './search/search.service';
</span>
Copy after login

At this point, you should be able to search for a person and update their information.

Setup angular authentication using OpenID Connect and Okta in your app

The

in src/app/edit/edit.component.html calls a save() function to update a person’s data. You already implemented this above. The function calls a gotoList() function that appends the person’s name to the URL when sending the user back to the search screen.
<span>git clone https://github.com/mraible/ng-demo.git
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Since the SearchComponent doesn’t execute a search automatically when you execute this URL, add the following logic to do so in its constructor.

ng new ng-demo
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

You’ll want to implement OnDestroy and define the ngOnDestroy method to clean up this subscription.

<span>[mraible:~/dev] $ ng new ng-demo
</span>installing ng
  create .editorconfig
  create README.md
  create src/app/app.component.css
  create src/app/app.component.html
  create src/app/app.component.spec.ts
  create src/app/app.component.ts
  create src/app/app.module.ts
  create src/assets/.gitkeep
  create src/environments/environment.prod.ts
  create src/environments/environment.ts
  create src/favicon.ico
  create src/index.html
  create src/main.ts
  create src/polyfills.ts
  create src/styles.css
  create src/test.ts
  create src/tsconfig.app.json
  create src/tsconfig.spec.json
  create src/typings.d.ts
  create .angular-cli.json
  create e2e/app.e2e-spec.ts
  create e2e/app.po.ts
  create e2e/tsconfig.e2e.json
  create .gitignore
  create karma.conf.js
  create package.json
  create protractor.conf.js
  create tsconfig.json
  create tslint.json
Successfully initialized git.
Installing packages <span>for tooling via npm.
</span>Installed packages <span>for tooling via npm.
</span>You can <span><span>`ng set --global packageManager=yarn`</span>.
</span>Project <span>'ng-demo' successfully created.
</span><span>[mraible:~] 46s $
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

After making all these changes, you should be able to search/edit/update a person’s information. If it works – nice job!

Form Validation

One thing you might notice is you can clear any input element in the form and save it. At the very least, the name field should be required. Otherwise, there’s nothing to click on in the search results.

To make name required, modify edit.component.html to add a required attribute to the name .

$ ng <span>--version
</span>    _                      _                 ____ _     ___
   / <span>\   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
</span>  / △ <span>\ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
</span> / ___ <span>\| | | | (_| | |_| | | (_| | |      | |___| |___ | |
</span>/_/   <span>\_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
</span>               <span>|___/
</span>@angular/cli: <span>1.3.2
</span>node: <span>8.4.0
</span>os: darwin x64
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

You’ll also need to wrap everything in a

element. Add after the

tag and close it before the last . You’ll also need to add an (ngSubmit) handler to the form and change the save button to be a regular submit button.
ng serve
Copy after login
Copy after login
Copy after login
Copy after login

After making these changes, any field with a required attribute will be required.

Setup angular authentication using OpenID Connect and Okta in your app

In this screenshot, you might notice the address fields are blank. This is explained by the error in your console.

$ ng <span>test
</span><span>...
</span>Chrome <span>60.0.3112 (Mac OS X 10.12.6): Executed 3 of 3 SUCCESS (0.239 secs / 0.213 secs)
</span>
Copy after login
Copy after login
Copy after login
Copy after login

To fix, add a name attribute to all the address fields. For example:

$ ng g component search
installing component
  create src/app/search/search.component.css
  create src/app/search/search.component.html
  create src/app/search/search.component.spec.ts
  create src/app/search/search.component.ts
  update src/app/app.module.ts
Copy after login
Copy after login
Copy after login
Copy after login

Now values should display in all fields and name should be required.

Setup angular authentication using OpenID Connect and Okta in your app

If you want to provide your own validation messages instead of relying on the browser’s, complete the following steps:

  1. Remove ngNativeValidate and add #editForm="ngForm" to the element.
  2. Add #name="ngModel" to the element.
  3. Add [disabled]="!editForm.form.valid" to the Save button.
  4. Add the following under the name field to display a validation error.
<span><span><span><h2</span>></span>Search<span><span></h2</span>></span>
</span><span><span><span><form</span>></span>
</span>  <span><span><span><input</span> type<span>="search"</span> name<span>="query"</span> [(ngModel)]<span>="query"</span> (keyup.enter)<span>="search()"</span>></span>
</span>  <span><span><span><button</span> type<span>="button"</span> (click)<span>="search()"</span>></span>Search<span><span></button</span>></span>
</span><span><span><span></form</span>></span>
</span><span><span><span><pre</span>></span>{{searchResults | json}}<span><span></pre</span>></span>
</span>
Copy after login
Copy after login
Copy after login
Copy after login

To learn more about forms and validation, see Angular forms documentation.

Create an OpenID Connect App in Okta

OpenID Connect (OIDC) is built on top of the OAuth 2.0 protocol. It allows clients to verify the identity of the user and, as well as to obtain their basic profile information. To learn more, see https://openid.net/connect.

To integrate Okta for user authentication, you’ll first need to register and create an OIDC application.

Login to your Okta account, or create one if you don’t have one. Navigate to Applications and click on the Add Application button. Select SPA and click Next. On the next page, specify http://localhost:4200 as a Base URI, Login redirect URI, and Logout redirect URI. Click Done and you should see settings like the following.

Setup angular authentication using OpenID Connect and Okta in your app

Install Manfred Steyer’s project to add OAuth 2 and OpenID Connect support using npm.

<span>git clone https://github.com/mraible/ng-demo.git
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Modify src/app/app.component.ts to import OAuthService and configure your app to use your Okta application’s settings.

ng new ng-demo
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Create src/app/home/home.component.ts and configure it to have Login and Logout buttons.

<span>[mraible:~/dev] $ ng new ng-demo
</span>installing ng
  create .editorconfig
  create README.md
  create src/app/app.component.css
  create src/app/app.component.html
  create src/app/app.component.spec.ts
  create src/app/app.component.ts
  create src/app/app.module.ts
  create src/assets/.gitkeep
  create src/environments/environment.prod.ts
  create src/environments/environment.ts
  create src/favicon.ico
  create src/index.html
  create src/main.ts
  create src/polyfills.ts
  create src/styles.css
  create src/test.ts
  create src/tsconfig.app.json
  create src/tsconfig.spec.json
  create src/typings.d.ts
  create .angular-cli.json
  create e2e/app.e2e-spec.ts
  create e2e/app.po.ts
  create e2e/tsconfig.e2e.json
  create .gitignore
  create karma.conf.js
  create package.json
  create protractor.conf.js
  create tsconfig.json
  create tslint.json
Successfully initialized git.
Installing packages <span>for tooling via npm.
</span>Installed packages <span>for tooling via npm.
</span>You can <span><span>`ng set --global packageManager=yarn`</span>.
</span>Project <span>'ng-demo' successfully created.
</span><span>[mraible:~] 46s $
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Create src/app/shared/auth/auth.guard.service.ts to navigate to the HomeComponent if the user is not authenticated.

$ ng <span>--version
</span>    _                      _                 ____ _     ___
   / <span>\   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
</span>  / △ <span>\ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
</span> / ___ <span>\| | | | (_| | |_| | | (_| | |      | |___| |___ | |
</span>/_/   <span>\_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
</span>               <span>|___/
</span>@angular/cli: <span>1.3.2
</span>node: <span>8.4.0
</span>os: darwin x64
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Export AuthGuard in src/shared/index.ts:

ng serve
Copy after login
Copy after login
Copy after login
Copy after login

Import the OAuthModule in src/app/app.module.ts, configure the new HomeComponent, and lock the /search and /edit routes down with the AuthGuard.

$ ng <span>test
</span><span>...
</span>Chrome <span>60.0.3112 (Mac OS X 10.12.6): Executed 3 of 3 SUCCESS (0.239 secs / 0.213 secs)
</span>
Copy after login
Copy after login
Copy after login
Copy after login

After making these changes, you should be able to run ng serve and see a login button.

Setup angular authentication using OpenID Connect and Okta in your app

Click the Login button and sign-in with one of the people that’s configured in your Okta application.

Setup angular authentication using OpenID Connect and Okta in your app

After logging in, you’ll be able to click Search and view people’s information.

Setup angular authentication using OpenID Connect and Okta in your app

If it works – great! If you want to build your own login form in your app, continue reading to learn how to use the Okta Auth SDK with OAuthService.

Authentication with the Okta Auth SDK

The Okta Auth SDK builds on top of Otka’s Authentication API and OAuth 2.0 API to enable you to create a fully branded sign-in experience using JavaScript.

Install it using npm:

$ ng g component search
installing component
  create src/app/search/search.component.css
  create src/app/search/search.component.html
  create src/app/search/search.component.spec.ts
  create src/app/search/search.component.ts
  update src/app/app.module.ts
Copy after login
Copy after login
Copy after login
Copy after login

Add a reference to this library’s main JavaScript file in .angular-cli.json:

<span><span><span><h2</span>></span>Search<span><span></h2</span>></span>
</span><span><span><span><form</span>></span>
</span>  <span><span><span><input</span> type<span>="search"</span> name<span>="query"</span> [(ngModel)]<span>="query"</span> (keyup.enter)<span>="search()"</span>></span>
</span>  <span><span><span><button</span> type<span>="button"</span> (click)<span>="search()"</span>></span>Search<span><span></button</span>></span>
</span><span><span><span></form</span>></span>
</span><span><span><span><pre</span>></span>{{searchResults | json}}<span><span></pre</span>></span>
</span>
Copy after login
Copy after login
Copy after login
Copy after login

The components in this section use Bootstrap CSS classes. Install Bootstrap 4.

<span>import { Routes, RouterModule } from '@angular/router';
</span>
<span>const appRoutes: Routes = [
</span>  <span>{path: 'search', component: SearchComponent},
</span>  <span>{path: '', redirectTo: '/search', pathMatch: 'full'}
</span><span>];
</span>
<span><span>@NgModule</span>({
</span>  <span>...
</span>  imports<span>: [
</span>    <span>...
</span>    RouterModule<span>.forRoot(appRoutes)
</span>  <span>]
</span>  <span>...
</span><span>})
</span><span>export class AppModule { }
</span>
Copy after login
Copy after login
Copy after login

Modify src/styles.css to add a reference to Bootstrap’s CSS file.

<span><span><span><h1</span>></span>Welcome to {{title}}!<span><span></h1</span>></span>
</span><span><!-- Routed views go here -->
</span><span><span><span><router-outlet</span>></span><span><span></router-outlet</span>></span>
</span>
Copy after login
Copy after login
Copy after login

Update src/app/app.component.html to use Bootstrap classes for its navbar and grid system.

<span>import { FormsModule } from '@angular/forms';
</span>
<span><span>@NgModule</span>({
</span>  <span>...
</span>  imports<span>: [
</span>    <span>...
</span>    FormsModule
  <span>]
</span>  <span>...
</span><span>})
</span><span>export class AppModule { }
</span>
Copy after login
Copy after login
Copy after login

Create src/app/shared/auth/okta.auth.wrapper.ts to wrap the Okta Auth SDK and integrate it with OAuthService. Its login() method uses OktaAuth to get a session token and exchange it for ID and access tokens.

<span><span>:host</span> {
</span>  <span>display: block;
</span>  <span>padding: 0 20px;
</span><span>}
</span>
Copy after login
Copy after login
Copy after login

In the above code, oauthService.tryLogin() parses and stores the idToken and accessToken so they can be retrieved using OAuthService.getIdToken() and OAuthService.getAccessToken().

Export OktaAuthWrapper in src/shared/index.ts:

<span>git clone https://github.com/mraible/ng-demo.git
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Add OktaAuthWrapper as a provider in app.module.ts.

ng new ng-demo
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Change HomeComponent to declare OktaAuth and modify its template so it has a button to login, as well as a sign-in form.

<span>[mraible:~/dev] $ ng new ng-demo
</span>installing ng
  create .editorconfig
  create README.md
  create src/app/app.component.css
  create src/app/app.component.html
  create src/app/app.component.spec.ts
  create src/app/app.component.ts
  create src/app/app.module.ts
  create src/assets/.gitkeep
  create src/environments/environment.prod.ts
  create src/environments/environment.ts
  create src/favicon.ico
  create src/index.html
  create src/main.ts
  create src/polyfills.ts
  create src/styles.css
  create src/test.ts
  create src/tsconfig.app.json
  create src/tsconfig.spec.json
  create src/typings.d.ts
  create .angular-cli.json
  create e2e/app.e2e-spec.ts
  create e2e/app.po.ts
  create e2e/tsconfig.e2e.json
  create .gitignore
  create karma.conf.js
  create package.json
  create protractor.conf.js
  create tsconfig.json
  create tslint.json
Successfully initialized git.
Installing packages <span>for tooling via npm.
</span>Installed packages <span>for tooling via npm.
</span>You can <span><span>`ng set --global packageManager=yarn`</span>.
</span>Project <span>'ng-demo' successfully created.
</span><span>[mraible:~] 46s $
</span>
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

After making these changes, the HomeComponent should render as follows.

Setup angular authentication using OpenID Connect and Okta in your app

Add local variables for the username and password fields, import OktaAuthWrapper, and implement a loginWithPassword() method in HomeComponent.

$ ng <span>--version
</span>    _                      _                 ____ _     ___
   / <span>\   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
</span>  / △ <span>\ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
</span> / ___ <span>\| | | | (_| | |_| | | (_| | |      | |___| |___ | |
</span>/_/   <span>\_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
</span>               <span>|___/
</span>@angular/cli: <span>1.3.2
</span>node: <span>8.4.0
</span>os: darwin x64
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

You should be able to sign in using the form, using one of your app’s registered users. After logging in, you’ll be able to click the Search link and view people’s information.

Setup angular authentication using OpenID Connect and Okta in your app

Angular Okta

If everything works – congrats! If you encountered issues, please post a question to Stack Overflow with an okta tag, or hit me up on Twitter @mraible.

You can find a completed version of the application created in this blog post on GitHub. To learn more about security in Angular, see Angular’s Security documentation. If you’d like to learn more about OpenID Connect, I’d recommend watching the soothing video below.

Frequently Asked Questions (FAQs) on Angular Authentication with OIDC

What is the Role of OIDC in Angular Authentication?

OpenID Connect (OIDC) is a simple identity layer built on top of the OAuth 2.0 protocol. It allows clients to verify the identity of the end-user based on the authentication performed by an authorization server. In Angular, OIDC is used to handle user authentication. It provides a secure and scalable framework that can handle multiple user identities, making it easier to manage user sessions and access control.

How Can I Implement OIDC in Angular?

Implementing OIDC in Angular involves several steps. First, you need to install the necessary packages, such as angular-auth-oidc-client. Then, you configure the OIDC module in your app module, specifying the necessary parameters such as the authority, client ID, and response type. After that, you can use the OIDC service to handle user login, logout, and token validation.

How Does Angular Handle JWT Tokens?

JSON Web Tokens (JWT) are used in Angular to securely transmit information between parties as a JSON object. When a user logs in, the server generates a JWT that contains the user’s identity and sends it to the client. The client stores this token and includes it in every request to the server. The server then verifies the token to ensure the user is authenticated.

What is the Difference Between OAuth2 and OIDC?

OAuth2 is a protocol that allows applications to obtain limited access to user accounts on an HTTP service. It’s used for authorization. On the other hand, OIDC is an identity layer built on top of OAuth2. It extends OAuth2 to provide authentication, allowing applications to verify the identity of users.

How Can I Secure My Angular Application?

Securing your Angular application involves several steps. First, you should use HTTPS to encrypt data in transit. Second, use JWT for user authentication and session management. Third, implement access control to restrict what resources a user can access. Finally, sanitize user input to prevent cross-site scripting (XSS) attacks.

How Can I Handle User Sessions in Angular?

User sessions in Angular can be handled using JWT. When a user logs in, the server generates a JWT that contains the user’s identity and sends it to the client. The client stores this token and includes it in every request to the server. The server then verifies the token to ensure the user is authenticated.

What is the Role of the Angular-auth-oidc-client Package?

The angular-auth-oidc-client package is a library for Angular that allows you to connect your application with Identity Providers using OpenID Connect and OAuth2. It handles user authentication, session management, and token validation.

How Can I Implement Access Control in Angular?

Access control in Angular can be implemented using route guards. Route guards are interfaces that can tell the router whether or not it should allow navigation to a requested route. They can be used to restrict access to certain routes based on the user’s role or authentication status.

How Can I Handle Errors in Angular Authentication?

Errors in Angular authentication can be handled using error handlers. An error handler is a function that takes an error as a parameter and handles it. You can use it to display an error message to the user, log the error, or even redirect the user to a different page.

How Can I Test Angular Authentication?

Testing Angular authentication involves creating unit tests for your authentication service and end-to-end tests for your application. You can use tools like Jasmine and Karma for unit testing, and Protractor for end-to-end testing. These tests should verify that the authentication process works as expected and handles errors correctly.

The above is the detailed content of Setup angular authentication using OpenID Connect and Okta in your app. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template