Skip to content

KostiantynDrozd-okta/okta-angular

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

99 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Okta Angular SDK

npm version build status

Okta Angular SDK builds on top of the Okta Auth SDK. This SDK adds integration with @angular/router and provides additional logic and components designed to help you quickly add authentication and authorization to your Angular single-page web application.

With the Okta Auth SDK, you can:

  • Login and logout from Okta using the OAuth 2.0 API
  • Retrieve user information
  • Determine authentication status
  • Validate the current user's session

All of these features are supported by this SDK. Additionally, using this SDK, you can:

  • Add "protected" routes, which will require authentication before render
  • Define custom logic/behavior when authentication is required
  • Subscribe to changes in authentication state using an Observable property
  • Provide an instance of the Auth service to your components using Dependency Injection

This SDK does not provide any UI components.

This SDK does not currently support Server Side Rendering (SSR)

This library currently supports:

This library has been tested for compatibility with the following Angular versions: 4, 5, 6, 7, 8, 9

Getting Started

  • If you do not already have a Developer Edition Account, you can create one at https://developer.okta.com/signup/.
  • An Okta Application, configured for Single-Page App (SPA) mode. This is done from the Okta Developer Console and you can find instructions here. When following the wizard, use the default properties. They are are designed to work with our sample applications.

Helpful Links

Installation

This library is available through npm. To install it, simply add it to your project:

npm install --save @okta/okta-angular

Usage

Add OktaAuthModule to your module's imports. Create a configuration object and provide this as OKTA_CONFIG.

// myApp.module.ts

import {
  OKTA_CONFIG,
  OktaAuthModule
} from '@okta/okta-angular';

const oktaConfig = {
  issuer: 'https://{yourOktaDomain}.com/oauth2/default',
  clientId: '{clientId}',
  redirectUri: window.location.origin + '/implicit/callback',
  pkce: true
}

@NgModule({
  imports: [
    ...
    OktaAuthModule
  ],
  providers: [
    { provide: OKTA_CONFIG, useValue: oktaConfig }
  ],
})
export class MyAppModule { }

OKTA_CONFIG

An Angular InjectionToken used to configure the OktaAuthService. This value must be provided by your own application. It is initialized by a plain object which can have the following properties:

  • issuer (required): The OpenID Connect issuer

  • clientId (required): The OpenID Connect client_id

  • redirectUri (required): Where the callback is hosted

  • postLogoutRedirectUri | Specify the url where the browser should be redirected after logout. This url must be added to the list of Logout redirect URIs on the application's General Settings tab.

  • scope (deprecated in v1.2.2): Use scopes instead

  • scopes (optional): Reserved for custom claims to be returned in the tokens. Defaults to ['openid'], which will only return the sub claim. To obtain more information about the user, use openid profile. For a list of scopes and claims, please see Scope-dependent claims for more information.

  • responseType (optional): Desired token grant types. Default: ['id_token', 'token']. For PKCE flow, this should be left undefined or set to ['code'].

  • pkce (optional) - If true, Authorization Code w/PKCE Flow will be used. See the @okta/okta-auth-js README regarding PKCE OAuth2 Flow for requirements, including any required polyfills. If you are using the Implicit Flow, you should set pkce: false. Default: true.

  • onAuthRequired (optional): - callback function. Called when authentication is required. If not supplied, okta-angular will redirect directly to Okta for authentication. This is triggered when:

    1. login is called
    2. A route protected by OktaAuthGuard is accessed without authentication
  • onSessionExpired deprecated (optional) - callback function. Called on token renew failure. :warning: This option will be removed in an upcoming version. When a token renew fails, an "error" event will be fired from the TokenManager and the token will be removed from storage. Presense of a token in storage can be used to determine if a login flow is needed in the isAuthenticated method. Take care when beginning a new login flow that there is not another login flow already in progress. Be careful not to initiate the token renew process in this callback, explicitly with tokenManager.renew() or implicitly with tokenManager.get(), as your app may end up in an infinite loop.

  • isAuthenticated (optional) - callback function. By default, OktaAuthService.isAuthenticated will return true if either getIdToken() or getAccessToken() return a value. Setting a isAuthenticated function on the config will skip the default logic and call the supplied function instead. The function should return a Promise and resolve to either true or false. NOTE The default behavior of this callback will be changed in the next major release to resolve to true when both getIdToken() and getAccessToken() return a value. Currently, you can achieve this behavior as shown:

    // myApp.module.ts
    
    import {
      OKTA_CONFIG,
      OktaAuthModule
    } from '@okta/okta-angular';
    
    const oktaConfig = {
      // other config ...
      isAuthenticated: async function(authService: OktaAuthService) {
        const accessToken = await authService.getAccessToken();
        const idToken = await authService.getIdToken();
        return !!(accessToken && idToken);
      }
    }
    
    @NgModule({
      imports: [
        ...
        OktaAuthModule
      ],
      providers: [
        { provide: OKTA_CONFIG, useValue: oktaConfig }
      ],
    })
    export class MyAppModule { }
  • tokenManager (optional): An object containing additional properties used to configure the internal token manager. See AuthJS TokenManager for more detailed information.

    • autoRenew (optional): By default, the library will attempt to renew expired tokens. When an expired token is requested by the library, a renewal request is executed to update the token. If you wish to to disable auto renewal of tokens, set autoRenew to false.

    • secure: If true then only "secure" https cookies will be stored. This option will prevent cookies from being stored on an HTTP connection. This option is only relevant if storage is set to cookie, or if the client browser does not support localStorage or sessionStorage, in which case cookie storage will be used.

    • storage (optional): Specify the type of storage for tokens. The types are:

OktaAuthModule

The top-level Angular module which provides these components and services:

OktaAuthGuard

Routes are protected by the OktaAuthGuard, which verifies there is a valid accessToken stored. To ensure the user has been authenticated before accessing your route, add the canActivate guard to one of your routes:

// myApp.module.ts

import {
  OktaAuthGuard,
  ...
} from '@okta/okta-angular';

const appRoutes: Routes = [
  {
    path: 'protected',
    component: MyProtectedComponent,
    canActivate: [ OktaAuthGuard ],
    children: [{
      // children of a protected route are also protected
      path: 'also-protected'
    }]
  },
  ...
]

You can use canActivateChild to protect children of an unprotected route:

// myApp.module.ts

import {
  OktaAuthGuard,
  ...
} from '@okta/okta-angular';

const appRoutes: Routes = [
  {
    path: 'public',
    component: MyPublicComponent,
    canActivateChild: [ OktaAuthGuard ],
    children: [{
      path: 'protected',
      component: MyProtectedComponent
    }]
  },
  ...
]

If a user does not have a valid session, they will be redirected to the Okta Login Page for authentication. Once authenticated, they will be redirected back to your application's protected page.

OktaCallbackComponent

Handles the callback after the redirect. By default, it parses the tokens from the uri, stores them, then redirects to /. If a protected route (using OktaAuthGuard) caused the redirect, then the callback will redirect back to the protected route. If an error is thrown while processing tokens, the component will display the error and not perform any redirect. This logic can be customized by copying the component to your own source tree and modified as needed. For example, you may want to capture or display errors differently or provide a helpful link for your users in case they encounter an error on the callback route. The most common error is the user does not have permission to access the application. In this case, they may be able to contact an administrator to obtain access.

You should define a route to handle the callback URL (/implicit/callback by default). Also add OktaCallbackComponent to the declarations section of in your NgModule.

// myApp.module.ts
import {
  OktaCallbackComponent,
  ...
} from '@okta/okta-angular';

const appRoutes: Routes = [
  {
    path: 'implicit/callback',
    component: OktaCallbackComponent
  },
  ...
]

@NgModule({
  ...
  declarations: [
    ...
    OktaCallbackComponent
  ]
})

OktaLoginRedirectComponent

The OktaLoginRedirect component redirects the user's browser to the Okta-hosted login page for your organization. For more advanced cases, this component can be copied to your own source tree and modified as needed.

// myApp.module.ts
import {
  OktaLoginRedirectComponent,
  ...
} from '@okta/okta-angular';

const appRoutes: Routes = [
  {
    path: 'login',
    component: OktaLoginRedirectComponent
  },
  ...
]

Using a custom login-page

The okta-angular SDK supports the session token redirect flow for custom login pages. For more information, see the basic Okta Sign-in Widget functionality.

To handle the session-token redirect flow, you can set an onAuthRequired callback by adding a data attribute directly to your Route:

// myApp.module.ts

import {
  OktaAuthGuard,
  ...
} from '@okta/okta-angular';

export function onAuthRequired(oktaAuth, injector) {
  // Use injector to access any service available within your application
  const router = injector.get(Router);

  // Redirect the user to your custom login page
  router.navigate(['/custom-login']);
}

const appRoutes: Routes = [
  ...
  {
    path: 'protected',
    component: MyProtectedComponent,
    canActivate: [ OktaAuthGuard ],
    data: {
      onAuthRequired: onAuthRequired
    }
  }
]

Alternatively, set this behavior globally by adding it to your configuration object:

const oktaConfig = {
  issuer: environment.ISSUER,
  ...
  onAuthRequired: onAuthRequired
};

OktaAuthService

In your components, your can take advantage of all of okta-angular's features by importing the OktaAuthService. The example below shows connecting two buttons to handle login and logout:

// sample.component.ts

import { OktaAuthService } from '@okta/okta-angular';

@Component({
  selector: 'app-component',
  template: `
    <button *ngIf="!isAuthenticated" (click)="login()">Login</button>
    <button *ngIf="isAuthenticated" (click)="logout()">Logout</button>

    <router-outlet></router-outlet>
  `,
})
export class MyComponent {
  isAuthenticated: boolean;
  constructor(public oktaAuth: OktaAuthService) {
    // get authentication state for immediate use
    await this.isAuthenticated = this.oktaAuth.isAuthenticated();

    // subscribe to authentication state changes
    this.oktaAuth.$authenticatedState.subscribe(
      (isAuthenticated: boolean)  => this.isAuthenticated = isAuthenticated
    );
  }
  login() {
    this.oktaAuth.loginRedirect('/profile');
  }
  logout() {
    this.oktaAuth.logout('/');
  }
}

oktaAuth.login(fromUri?, additionalParams?)

Calls onAuthRequired function if it was set on the initial configuration. Otherwise, it will call loginRedirect. This method accepts a fromUri parameter to push the user to after successful authentication, and an optional additionalParams object.

For more information on additionalParams, see the oktaAuth.loginRedirect method below.

oktaAuth.loginRedirect(fromUri?, additionalParams?)

Performs a full page redirect to Okta based on the initial configuration. This method accepts a fromUri parameter to push the user to after successful authentication.

The optional parameter additionalParams is mapped to the AuthJS OpenID Connect Options. This will override any existing configuration. As an example, if you have an Okta sessionToken, you can bypass the full-page redirect by passing in this token. This is recommended when using the Okta Sign-In Widget. Simply pass in a sessionToken into the loginRedirect method follows:

this.oktaAuth.loginRedirect('/profile', {
  sessionToken: /* sessionToken */
})

Note: For information on obtaining a sessionToken using the Okta Sign-In Widget, please see the renderEl() example.

oktaAuth.isAuthenticated()

Returns a promise that resolves true if there is a valid access token or ID token.

oktaAuth.$authenticationState

An observable that returns true/false when the authenticate state changes. This will happen after a successful login via oktaAuth.handleAuthentication() or logout via oktaAuth.logout().

oktaAuth.getUser()

Returns a promise that will resolve with the result of the OpenID Connect /userinfo endpoint. For more information see documentation for the UserInfo endpoint, ID Token Claims, and Customizing Your Authorization Server.

oktaAuth.getAccessToken() Promise<string>

Returns a promise that returns the access token string from storage (if it exists).

oktaAuth.getIdToken() Promise<string>

Returns a promise that returns the ID token string from storage (if it exists).

oktaAuth.handleAuthentication()

Parses the tokens returned as hash fragments in the OAuth 2.0 Redirect URI, then redirects to the URL specified when calling loginRedirect. Returns a promise that will be resolved when complete.

oktaAuth.logout(uri?)

Terminates the user's session in Okta and clears all stored tokens. Accepts an optional uri parameter to push the user to after logout.

oktaAuth.setFromUri(uri)

Used to capture the current URL state before a redirect occurs. Used by custom canActivate navigation guards.

oktaAuth.getFromUri()

Returns the URI stored when the OktaAuthGuard and/or setFromUri was used.

oktaAuth.getTokenManager()

Returns the internal TokenManager.

Contributing

We welcome contributions to all of our open-source packages. Please see the contribution guide to understand how to structure a contribution.

Installing dependencies for contributions

We use yarn for dependency management when developing this package:

yarn install

Commands

Command Description
yarn start Start the sample app using the SDK
yarn test Run unit and integration tests
yarn lint Run eslint linting tests

About

Angular SDK for Okta's OIDC flow

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 76.9%
  • JavaScript 14.8%
  • Shell 8.0%
  • HTML 0.3%