Skip to content

Update to new HttpClient #151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions angular-oauth2-oidc/gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ gulp.task('rollup:fesm', function () {

// Bundle's entry point
// See https://github.com/rollup/rollup/wiki/JavaScript-API#entry
entry: `${buildFolder}/index.js`,
input: `${buildFolder}/index.js`,

// Allow mixing of hypothetical and actual files. "Actual" files can be files
// accessed by Rollup or produced by plugins further down the chain.
Expand Down Expand Up @@ -105,7 +105,7 @@ gulp.task('rollup:umd', function () {

// Bundle's entry point
// See https://github.com/rollup/rollup/wiki/JavaScript-API#entry
entry: `${buildFolder}/index.js`,
input: `${buildFolder}/index.js`,

// Allow mixing of hypothetical and actual files. "Actual" files can be files
// accessed by Rollup or produced by plugins further down the chain.
Expand All @@ -131,7 +131,7 @@ gulp.task('rollup:umd', function () {
// The name to use for the module for UMD/IIFE bundles
// (required for bundles with exports)
// See https://github.com/rollup/rollup/wiki/JavaScript-API#modulename
moduleName: 'angular-oauth2-oidc',
name: 'angular-oauth2-oidc',

// See https://github.com/rollup/rollup/wiki/JavaScript-API#globals
globals: {
Expand Down
4 changes: 2 additions & 2 deletions angular-oauth2-oidc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"del": "^2.2.2",
"gulp": "^3.9.1",
"gulp-rename": "^1.2.2",
"gulp-rollup": "^2.11.0",
"gulp-rollup": "^2.15.0",
"jasmine-core": "~2.5.2",
"jasmine-spec-reporter": "~3.2.0",
"karma": "~1.4.1",
Expand All @@ -55,7 +55,7 @@
"node-sass-tilde-importer": "^1.0.0",
"node-watch": "^0.5.2",
"protractor": "~5.1.0",
"rollup": "^0.41.6",
"rollup": "^0.50.0",
"run-sequence": "^1.2.2",
"rxjs": "^5.1.0",
"ts-node": "~2.0.0",
Expand Down
4 changes: 3 additions & 1 deletion angular-oauth2-oidc/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';

import { OAuthService } from './oauth-service';
import { UrlHelperService } from './url-helper.service';

Expand All @@ -26,7 +28,7 @@ export * from './tokens';
@NgModule({
imports: [
CommonModule,
//HttpModule
HttpClientModule
],
declarations: [
],
Expand Down
90 changes: 44 additions & 46 deletions angular-oauth2-oidc/src/oauth-service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Http, URLSearchParams, Headers } from '@angular/http';
import { Injectable, Optional } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';

import { ValidationHandler, ValidationParams } from './token-validation/validation-handler';
import { UrlHelperService } from './url-helper.service';
import { Subscription } from 'rxjs/Subscription';
import { OAuthEvent, OAuthInfoEvent, OAuthErrorEvent, OAuthSuccessEvent } from './events';
import { OAuthStorage, LoginOptions, ParsedIdToken } from './types';
import { OAuthStorage, LoginOptions, ParsedIdToken, OidcDiscoveryDoc, TokenResponse, UserInfo } from './types';
import { b64DecodeUnicode } from './base64-helper';
import { AuthConfig } from './auth.config';

Expand Down Expand Up @@ -65,7 +66,7 @@ export class OAuthService
private silentRefreshSubject: string;

constructor(
private http: Http,
private http: HttpClient,
@Optional() storage: OAuthStorage,
@Optional() tokenValidationHandler: ValidationHandler,
@Optional() private config: AuthConfig,
Expand All @@ -92,7 +93,6 @@ export class OAuthService

this.setupRefreshTimer();


}

/**
Expand Down Expand Up @@ -140,14 +140,13 @@ export class OAuthService
* @param params Additional parameter to pass
*/
public setupAutomaticSilentRefresh(params: object = {}) {
this
.events
.filter(e => e.type === 'token_expires')
.subscribe(e => {
this.silentRefresh(params).catch(_ => {
this.debug('automatic silent refresh did not work');
})
});
this.events
.filter(e => e.type === 'token_expires')
.subscribe(e => {
this.silentRefresh(params).catch(_ => {
this.debug('automatic silent refresh did not work');
});
});

this.restartRefreshTimerIfStillLoggedIn();
}
Expand Down Expand Up @@ -306,7 +305,7 @@ export class OAuthService
fullUrl = this.issuer || '';
if (!fullUrl.endsWith('/')) {
fullUrl += '/';
}
}
fullUrl += '.well-known/openid-configuration';
}

Expand All @@ -315,7 +314,7 @@ export class OAuthService
return;
}

this.http.get(fullUrl).map(r => r.json()).subscribe(
this.http.get<OidcDiscoveryDoc>(fullUrl).subscribe(
(doc) => {

if (!this.validateDiscoveryDocument(doc)) {
Expand Down Expand Up @@ -368,7 +367,7 @@ export class OAuthService
private loadJwks(): Promise<object> {
return new Promise<object>((resolve, reject) => {
if (this.jwksUri) {
this.http.get(this.jwksUri).map(r => r.json()).subscribe(
this.http.get(this.jwksUri).subscribe(
jwks => {
this.jwks = jwks;
this.eventsSubject.next(new OAuthSuccessEvent('discovery_document_loaded'));
Expand All @@ -388,55 +387,55 @@ export class OAuthService

}

private validateDiscoveryDocument(doc: object): boolean {
private validateDiscoveryDocument(doc: OidcDiscoveryDoc): boolean {

let errors: string[];

if (doc['issuer'] !== this.issuer) {
if (doc.issuer !== this.issuer) {
console.error(
'invalid issuer in discovery document',
'expected: ' + this.issuer,
'current: ' + doc['issuer']
'current: ' + doc.issuer
);
return false;
}

errors = this.validateUrlFromDiscoveryDocument(doc['authorization_endpoint']);
errors = this.validateUrlFromDiscoveryDocument(doc.authorization_endpoint);
if (errors.length > 0) {
console.error('error validating authorization_endpoint in discovery document', errors);
return false;
}

errors = this.validateUrlFromDiscoveryDocument(doc['end_session_endpoint']);
errors = this.validateUrlFromDiscoveryDocument(doc.end_session_endpoint);
if (errors.length > 0) {
console.error('error validating end_session_endpoint in discovery document', errors);
return false;
}

errors = this.validateUrlFromDiscoveryDocument(doc['token_endpoint']);
errors = this.validateUrlFromDiscoveryDocument(doc.token_endpoint);
if (errors.length > 0) {
console.error('error validating token_endpoint in discovery document', errors);
}

errors = this.validateUrlFromDiscoveryDocument(doc['userinfo_endpoint']);
errors = this.validateUrlFromDiscoveryDocument(doc.userinfo_endpoint);
if (errors.length > 0) {
console.error('error validating userinfo_endpoint in discovery document', errors);
return false;
}

errors = this.validateUrlFromDiscoveryDocument(doc['jwks_uri']);
errors = this.validateUrlFromDiscoveryDocument(doc.jwks_uri);
if (errors.length > 0) {
console.error('error validating jwks_uri in discovery document', errors);
return false;
}

if (this.sessionChecksEnabled && !doc['check_session_iframe']) {
if (this.sessionChecksEnabled && !doc.check_session_iframe) {
console.warn(
'sessionChecksEnabled is activated but discovery document'
+ ' does not contain a check_session_iframe field');
}

this.sessionChecksEnabled = doc['check_session_iframe'];
this.sessionChecksEnabled = !!doc.check_session_iframe;

return true;
}
Expand All @@ -458,7 +457,7 @@ export class OAuthService
public fetchTokenUsingPasswordFlowAndLoadUserProfile(
userName: string,
password: string,
headers: Headers = new Headers()): Promise<object> {
headers: HttpHeaders = new HttpHeaders()): Promise<object> {
return this
.fetchTokenUsingPasswordFlow(userName, password, headers)
.then(() => this.loadUserProfile());
Expand All @@ -481,17 +480,17 @@ export class OAuthService

return new Promise((resolve, reject) => {

let headers = new Headers();
headers.set('Authorization', 'Bearer ' + this.getAccessToken());
const headers = new HttpHeaders()
.set('Authorization', 'Bearer ' + this.getAccessToken());

this.http.get(this.userinfoEndpoint, { headers }).map(r => r.json()).subscribe(
(doc) => {
this.debug('userinfo received', doc);
this.http.get<UserInfo>(this.userinfoEndpoint, { headers }).subscribe(
(info) => {
this.debug('userinfo received', info);

let existingClaims = this.getIdentityClaims() || {};

if (!this.skipSubjectCheck) {
if (this.oidc && (!existingClaims['sub'] || doc.sub !== existingClaims['sub'])) {
if (this.oidc && (!existingClaims['sub'] || info.sub !== existingClaims['sub'])) {
let err = 'if property oidc is true, the received user-id (sub) has to be the user-id '
+ 'of the user that has logged in with oidc.\n'
+ 'if you are not using oidc but just oauth2 password flow set oidc to false';
Expand All @@ -501,11 +500,11 @@ export class OAuthService
}
}

doc = Object.assign({}, existingClaims, doc);
info = Object.assign({}, existingClaims, info);

this._storage.setItem('id_token_claims_obj', JSON.stringify(doc));
this._storage.setItem('id_token_claims_obj', JSON.stringify(info));
this.eventsSubject.next(new OAuthSuccessEvent('user_profile_loaded'));
resolve(doc);
resolve(info);
},
(err) => {
console.error('error loading user info', err);
Expand All @@ -522,7 +521,7 @@ export class OAuthService
* @param password
* @param headers Optional additional http-headers.
*/
public fetchTokenUsingPasswordFlow(userName: string, password: string, headers: Headers = new Headers()): Promise<object> {
public fetchTokenUsingPasswordFlow(userName: string, password: string, headers: HttpHeaders = new HttpHeaders()): Promise<object> {

if (!this.validateUrlForHttps(this.tokenEndpoint)) {
throw new Error('tokenEndpoint must use Http. Also check property requireHttps.');
Expand All @@ -544,7 +543,7 @@ export class OAuthService

let params = search.toString();

this.http.post(this.tokenEndpoint, params, { headers }).map(r => r.json()).subscribe(
this.http.post<TokenResponse>(this.tokenEndpoint, params, { headers }).subscribe(
(tokenResponse) => {
this.debug('tokenResponse', tokenResponse);
this.storeAccessTokenResponse(tokenResponse.access_token, tokenResponse.refresh_token, tokenResponse.expires_in);
Expand Down Expand Up @@ -586,12 +585,12 @@ export class OAuthService
search.set('client_secret', this.dummyClientSecret);
}

let headers = new Headers();
headers.set('Content-Type', 'application/x-www-form-urlencoded');
const headers = new HttpHeaders()
.set('Content-Type', 'application/x-www-form-urlencoded');

let params = search.toString();

this.http.post(this.tokenEndpoint, params, { headers }).map(r => r.json()).subscribe(
this.http.post<TokenResponse>(this.tokenEndpoint, params, { headers }).subscribe(
(tokenResponse) => {
this.debug('refresh tokenResponse', tokenResponse);
this.storeAccessTokenResponse(tokenResponse.access_token, tokenResponse.refresh_token, tokenResponse.expires_in);
Expand Down Expand Up @@ -785,8 +784,7 @@ export class OAuthService
}

private waitForSilentRefreshAfterSessionChange() {
this
.events
this.events
.filter((e: OAuthEvent) =>
e.type === 'silently_refreshed'
|| e.type === 'silent_refresh_timeout'
Expand Down Expand Up @@ -1396,7 +1394,7 @@ export class OAuthService
this._storage.removeItem('id_token_expires_at');
this._storage.removeItem('id_token_stored_at');
this._storage.removeItem('access_token_stored_at');

this.silentRefreshSubject = null;

if (!this.logoutUrl) return;
Expand All @@ -1406,7 +1404,7 @@ export class OAuthService
let logoutUrl: string;

if (!this.validateUrlForHttps(this.logoutUrl)) throw new Error('logoutUrl must use Http. Also check property requireHttps.');

// For backward compatibility
if (this.logoutUrl.indexOf('{{') > -1) {
logoutUrl = this.logoutUrl.replace(/\{\{id_token\}\}/, id_token);
Expand Down
58 changes: 58 additions & 0 deletions angular-oauth2-oidc/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,61 @@ export interface ParsedIdToken {
idTokenHeaderJson: string;
idTokenExpiresAt: number;
}

/**
* Represents the response from the token endpoint
* http://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
*/
export interface TokenResponse {
access_token: string;
token_type: string;
expires_in: number;
refresh_token: string;
scope: string;
state?: string;
}

/**
* Represents the response from the user info endpoint
* http://openid.net/specs/openid-connect-core-1_0.html#UserInfo
*/
export interface UserInfo {
sub: string;
[key: string]: any;
}

/**
* Represents an OpenID Connect discovery document
*/
export interface OidcDiscoveryDoc {
issuer: string;
authorization_endpoint: string;
token_endpoint: string;
token_endpoint_auth_methods_supported: string[];
token_endpoint_auth_signing_alg_values_supported: string[];
userinfo_endpoint: string;
check_session_iframe: string;
end_session_endpoint: string;
jwks_uri: string;
registration_endpoint: string;
scopes_supported: string[];
response_types_supported: string[];
acr_values_supported: string[];
response_modes_supported: string[];
grant_types_supported: string[];
subject_types_supported: string[];
userinfo_signing_alg_values_supported: string[];
userinfo_encryption_alg_values_supported: string[];
userinfo_encryption_enc_values_supported: string[];
id_token_signing_alg_values_supported: string[];
id_token_encryption_alg_values_supported: string[];
id_token_encryption_enc_values_supported: string[];
request_object_signing_alg_values_supported: string[];
display_values_supported: string[];
claim_types_supported: string[];
claims_supported: string[];
claims_parameter_supported: boolean;
service_documentation: string;
ui_locales_supported: string[];
}

Loading