Skip to content
This repository has been archived by the owner on Jul 26, 2022. It is now read-only.

Commit

Permalink
service inherits from okta-auth-js instance
Browse files Browse the repository at this point in the history
  • Loading branch information
aarongranick-okta committed Sep 2, 2020
1 parent 3ad4522 commit b8f10c6
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 169 deletions.
3 changes: 2 additions & 1 deletion packages/okta-angular/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ All of these features are supported by this SDK. Additionally, using this SDK, y
This library currently supports:

- [OAuth 2.0 Implicit Flow](https://tools.ietf.org/html/rfc6749#section-1.3.2)
- [OAuth 2.0 Authorization Code Flow](https://tools.ietf.org/html/rfc6749#section-1.3.1) with [Proof Key for Code Exchange (PKCE)](https://tools.ietf.org/html/rfc7636)
- [OAuth 2.0 Authorization Code Flow](https://tools.ietf.org/html/rfc6749#section-1.3.1) with [Proof Key for Code Exchange (PKCE)](https://tools.ietf.org/html/rfc7636)

> This library has been tested for compatibility with the following Angular versions: 4, 5, 6, 7, 8, 9
> :warning: Angular versions older than 7 may not be fully compatible with all dependencies of this library, due to an older Typescript version. You may be able to workaround this issue by setting `skipLibChecks: true` in your `tsconfig.json` file.
## Getting Started

Expand Down
11 changes: 8 additions & 3 deletions packages/okta-angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@
"rxjs": ">=5.4.3"
},
"jest": {
"moduleNameMapper": {
"@okta/okta-auth-js": "<rootDir>/node_modules/@okta/okta-auth-js/dist/okta-auth-js.umd.js"
},
"restoreMocks": true,
"transform": {
"^.+\\.(ts|html)$": "ts-jest"
Expand All @@ -104,13 +107,15 @@
],
"globals": {
"ts-jest": {
"tsConfig": "<rootDir>/tsconfig.spec.json"
"tsConfig": "<rootDir>/test/spec/tsconfig.spec.json"
}
},
"preset": "jest-preset-angular",
"rootDir": "./test/spec",
"roots": [
"./test/spec"
],
"setupFilesAfterEnv": [
"../support/setupJest.ts"
"<rootDir>/test/support/setupJest.ts"
]
},
"sideEffects": false
Expand Down
78 changes: 40 additions & 38 deletions packages/okta-angular/src/okta/services/okta.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,46 @@ import packageInfo from '../packageInfo';
import { OktaAuth, TokenManager, AccessToken, IDToken, UserClaims } from '@okta/okta-auth-js';
import { Observable, Observer } from 'rxjs';

/**
* Scrub scopes to ensure 'openid' is included
* @param scopes
*/
function scrubScopes(scopes: string[]): void {
if (scopes.indexOf('openid') >= 0) {
return;
}
scopes.unshift('openid');
}

@Injectable()
export class OktaAuthService {
oktaAuth: OktaAuth;
export class OktaAuthService extends OktaAuth {
private config: OktaConfig;
private observers: Observer<boolean>[];
private injector: Injector;

$authenticationState: Observable<boolean>;

constructor(@Inject(OKTA_CONFIG) config: OktaConfig, private injector: Injector) {
this.observers = [];
constructor(@Inject(OKTA_CONFIG) config: OktaConfig, injector: Injector) {
config = Object.assign({}, config);
config.scopes = config.scopes || ['openid', 'email'];

/**
* Cache the auth config.
*/
this.config = Object.assign({}, config);
this.config.scopes = this.config.scopes || ['openid', 'email'];
// Scrub scopes to ensure 'openid' is included
scrubScopes(config.scopes);

/**
* Scrub scopes to ensure 'openid' is included
*/
// Assert Configuration
assertIssuer(config.issuer, config.testing);
assertClientId(config.clientId);
assertRedirectUri(config.redirectUri);

this.scrubScopes(this.config.scopes);
super(config);
this.config = config;
this.injector = injector;

// Assert Configuration
assertIssuer(this.config.issuer, this.config.testing);
assertClientId(this.config.clientId);
assertRedirectUri(this.config.redirectUri);
// Customize user agent
this.userAgent = `${packageInfo.name}/${packageInfo.version} ${this.userAgent}`;

this.oktaAuth = new OktaAuth(this.config);
this.oktaAuth.userAgent = `${packageInfo.name}/${packageInfo.version} ${this.oktaAuth.userAgent}`;
// Initialize observers
this.observers = [];
this.$authenticationState = new Observable((observer: Observer<boolean>) => { this.observers.push(observer); });
}

Expand All @@ -71,7 +82,7 @@ export class OktaAuthService {
}

getTokenManager(): TokenManager {
return this.oktaAuth.tokenManager;
return this.tokenManager;
}

/**
Expand All @@ -98,7 +109,7 @@ export class OktaAuthService {
*/
async getAccessToken(): Promise<string | undefined> {
try {
const accessToken: AccessToken = await this.oktaAuth.tokenManager.get('accessToken') as AccessToken;
const accessToken: AccessToken = await this.tokenManager.get('accessToken') as AccessToken;
return accessToken.accessToken;
} catch (err) {
// The user no longer has an existing SSO session in the browser.
Expand All @@ -113,7 +124,7 @@ export class OktaAuthService {
*/
async getIdToken(): Promise<string | undefined> {
try {
const idToken: IDToken = await this.oktaAuth.tokenManager.get('idToken') as IDToken;
const idToken: IDToken = await this.tokenManager.get('idToken') as IDToken;
return idToken.idToken;
} catch (err) {
// The user no longer has an existing SSO session in the browser.
Expand All @@ -127,7 +138,7 @@ export class OktaAuthService {
* Returns user claims from the /userinfo endpoint.
*/
async getUser(): Promise<UserClaims> {
return this.oktaAuth.token.getUserInfo();
return this.token.getUserInfo();
}

/**
Expand All @@ -152,7 +163,7 @@ export class OktaAuthService {
responseType: this.config.responseType
}, additionalParams);

return this.oktaAuth.token.getWithRedirect(params); // can throw
return this.token.getWithRedirect(params); // can throw
}

/**
Expand Down Expand Up @@ -183,13 +194,13 @@ export class OktaAuthService {
* Parses the tokens from the callback URL.
*/
async handleAuthentication(): Promise<void> {
const res = await this.oktaAuth.token.parseFromUrl();
const res = await this.token.parseFromUrl();
const tokens = res.tokens;
if (tokens.accessToken) {
this.oktaAuth.tokenManager.add('accessToken', tokens.accessToken as AccessToken);
this.tokenManager.add('accessToken', tokens.accessToken as AccessToken);
}
if (tokens.idToken) {
this.oktaAuth.tokenManager.add('idToken', tokens.idToken as IDToken);
this.tokenManager.add('idToken', tokens.idToken as IDToken);
}
if (await this.isAuthenticated()) {
this.emitAuthenticationState(true);
Expand All @@ -214,18 +225,9 @@ export class OktaAuthService {
postLogoutRedirectUri: redirectUri
};
}
await this.oktaAuth.signOut(options);
await this.signOut(options);
this.emitAuthenticationState(false);
}

/**
* Scrub scopes to ensure 'openid' is included
* @param scopes
*/
scrubScopes(scopes: string[]): void {
if (scopes.indexOf('openid') >= 0) {
return;
}
scopes.unshift('openid');
}

}
15 changes: 0 additions & 15 deletions packages/okta-angular/test/spec/guard.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { OktaAuth } from '@okta/okta-auth-js';

jest.mock('@okta/okta-auth-js', () => {
// Works and lets you check for constructor calls:
return {
OktaAuth: jest.fn().mockImplementation(() => {}),
};
});

import {
OktaAuthModule,
Expand All @@ -27,10 +19,6 @@ const VALID_CONFIG = {
function createService(options: any) {
options = options || {};

const oktaAuth = options.oktaAuth || {};
oktaAuth.tokenManager = oktaAuth.tokenManager || { on: jest.fn() };
(OktaAuth as any).mockImplementation(() => oktaAuth);

TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([{ path: 'foo', redirectTo: '/foo' }]),
Expand All @@ -54,9 +42,6 @@ function createService(options: any) {

describe('Angular auth guard', () => {

beforeEach(() => {
(OktaAuth as any).mockClear();
});
afterEach(() => {
jest.restoreAllMocks();
});
Expand Down
Loading

0 comments on commit b8f10c6

Please sign in to comment.