-
Implement Okta Authentication in Angular
In this blog, we will walk you step by step process of how to integrate authentication in angular app by Okta. Before we start, consider that you have already sign up with Okta account if not please click here
Following are steps for implementation:
Step1: Add an OpenID Connect Client in Okta- Log into the Okta Developer Dashboard
- Click on Application menu and Create new application by click on “Add Application”
- Choose Single Page App (SPA) as the platform and then populate your new OpenID Connection application with following settings and theirs values.
Setting Value Application Name OpenID Connect App (must be unique) Login redirect URIs http://localhost:4200/callback Logout redirect URIs http://localhost:4200/login Allowed grant types Authorization Code
Step 2: Create an Angular AppTo create the new angular application if you have not installed the Angular CLI then first install the angular CLI with following command
PS E:\>npm install -g @angular/cli
Run the CLI command ng new and provide the name my-app, as show below. As we are implementing Okta Authentication, given name is “Okta-app”
PS E:\> ng new Okta-app
Step 3: Install DependenciesInstall the dependencies NPM packages as below
PS E:\> cd okta-app
PS E:\> npm install @okta/okta-signin-widget --save
PS E:\> npm install @okta/okta-angular --save
Step 4: Create RoutesYou'll need to provide these routes in your sample application, so that we can sign the user in and handle the callback from Okta.
- /: A default page to handle basic control of the app.
- /protected: A protected route that can only be accessed by an authenticated user.
- /login: A custom login page to handle signing users into your app.
- /implicit/callback: Handle the response from Okta and store the returned tokens.
Step 5: Implement Login and Logout FunctionalityOpen the app.component.html and put the login page code as per below code snippet.
<button routerLink="/"> Home </button> <button *ngIf="!isAuthenticated" routerLink="/login" > Login </button> <button *ngIf="isAuthenticated" (click)="logout()" > Logout </button> <button routerLink="/protected" > Protected </button> <router-outlet></router-outlet>
To handle the logout call open the app.component.ts file and put following snippet.
export class AppComponent { isAuthenticated: boolean; constructor(public oktaAuth: OktaAuthService, public router: Router) { this.oktaAuth.$authenticationState.subscribe( (isAuthenticated: boolean) =>: this.isAuthenticated = isAuthenticated ); } async ngOnInit() { this.isAuthenticated = await this.oktaAuth.isAuthenticated(); } login() { this.oktaAuth.loginRedirect('/profile'); } async logout() { await this.oktaAuth.logout(); this.router.navigateByUrl('/'); } }
Step 6: Create the new component called protectedCreate a new component called protected which will use to identify that authentication is working or not, put following code snippet.
import { Component } from '@angular/core'; @Component({ selector: 'app-secure', template: `{{message}}` }) export class ProtectedComponent { message; constructor() { this.message = 'Protected endpoint!'; } }
Step 7: Create the new component called loginCreate new component called login and put following code snippet on it:
export class LoginComponent { signIn; widget = new OktaSignIn({ baseUrl: 'https://${https://dev-322431.okta.com}', authParams: { pkce: true } }); constructor(oktaAuth: OktaAuthService, router: Router) { this.signIn = oktaAuth; router.events.forEach(event =>: { if (event instanceof NavigationStart) { switch(event.url) { case '/login': break; case '/protected': break; default: this.widget.remove(); break; } } }); } ngOnInit() { this.widget.renderEl({ el: '#okta-signin-container'}, (res) =>: { if (res.status === 'SUCCESS') { this.signIn.loginRedirect('/', { sessionToken: res.session.token }); // Hide the widget this.widget.hide(); } }, (err) =>: { throw err; } ); }
Step 8: Update the app.module fileOpen the app.module.ts file and update the update modules which include your project components and routes. Following is code snippet for the app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { OktaAuthModule, OktaCallbackComponent, OktaAuthGuard } from '@okta/okta-angular'; import { AppComponent } from './app.component'; import { ProtectedComponent } from './protected.component'; import { LoginComponent } from './login.component'; const config = { issuer: 'https://dev-322431.okta.com/oauth2/default', redirectUri: 'http://localhost:4200/callback', clientId: '0oai1wrfhfAr9ZYX74x6', pkce: true } export function onAuthRequired({ oktaAuth, router }) { // Redirect the user to your custom login page router.navigate(['/login']); } const appRoutes: Routes = [ { path: 'implicit/callback', component: OktaCallbackComponent }, { path: 'login', component: LoginComponent }, { path: 'protected', component: ProtectedComponent, canActivate: [ OktaAuthGuard ], data: { onAuthRequired } } ] @NgModule({ declarations: [ AppComponent, LoginComponent, ProtectedComponent ], imports: [ BrowserModule, RouterModule.forRoot(appRoutes), OktaAuthModule.initAuth(config) ], bootstrap: [AppComponent] }) export class AppModule { }
Step 9: Read the access token after logged inYour Angular application now has an access token in local storage that was issued by your Okta Authorization server. You can use this token to authenticate further server API requests.
Just to test the message of Authentication you can create new component called message.component.ts and put following code snippet.
import { Component, OnInit } from '@angular/core'; import { Http, Headers, RequestOptions } from '@angular/http'; import { OktaAuthService } from '@okta/okta-angular'; import 'rxjs/Rx'; interface Message { date: String, text: String } @Component({ template: ` <div *ngIf="messages.length"> <li *ngFor="let message of messages">{{message.message}}</li> </div> ` }) export class MessageListComponent implements OnInit{ messages: Array<Message> []; constructor(private oktaAuth: OktaAuthService, private http: Http) { this.messages = []; } async ngOnInit() { const accessToken = await this.oktaAuth.getAccessToken(); const headers = new Headers({ Authorization: 'Bearer ' + accessToken }); // Make request this.http.get( 'http://localhost:{serverPort}/api/messages', new RequestOptions({ headers: headers }) ) .map(res => res.json()) .subscribe((messages: Array<Message>) => messages.forEach(message => this.messages.push(message))); } }
Done!
Run the Application.