keycloak-angular
Version:
Easy Keycloak setup for Angular applications
1,078 lines (1,077 loc) • 82.7 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @license
* Copyright Mauricio Gemelli Vigolo and contributors.
*
* Use of this source code is governed by a MIT-style license that can be
* found in the LICENSE file at https://github.com/mauriciovigolo/keycloak-angular/LICENSE
*/
import * as tslib_1 from "tslib";
import { Injectable } from '@angular/core';
import { HttpHeaders } from '@angular/common/http';
import * as Keycloak_ from 'keycloak-js';
/** @type {?} */
export var Keycloak = Keycloak_;
import { Observable, Subject } from 'rxjs';
import { KeycloakEventType } from '../interfaces/keycloak-event';
/**
* Service to expose existent methods from the Keycloak JS adapter, adding new
* functionalities to improve the use of keycloak in Angular v > 4.3 applications.
*
* This class should be injected in the application bootstrap, so the same instance will be used
* along the web application.
*/
var KeycloakService = /** @class */ (function () {
function KeycloakService() {
this._keycloakEvents$ = new Subject();
}
/**
* Sanitizes the bearer prefix, preparing it to be appended to
* the token.
*
* @param {?} bearerPrefix
* Prefix to be appended to the authorization header as
* Authorization: <bearer-prefix> <token>.
* @return {?}
* The bearer prefix sanitized, meaning that it will follow the bearerPrefix
* param as described in the library initilization or the default value bearer,
* with a space append in the end for the token concatenation.
*/
KeycloakService.prototype.sanitizeBearerPrefix = /**
* Sanitizes the bearer prefix, preparing it to be appended to
* the token.
*
* @param {?} bearerPrefix
* Prefix to be appended to the authorization header as
* Authorization: <bearer-prefix> <token>.
* @return {?}
* The bearer prefix sanitized, meaning that it will follow the bearerPrefix
* param as described in the library initilization or the default value bearer,
* with a space append in the end for the token concatenation.
*/
function (bearerPrefix) {
/** @type {?} */
var prefix = (bearerPrefix || 'bearer').trim();
return prefix.concat(' ');
};
/**
* Sets default value to true if it is undefined or null.
*
* @param {?} value - boolean value to be checked
* @return {?}
*/
KeycloakService.prototype.ifUndefinedIsTrue = /**
* Sets default value to true if it is undefined or null.
*
* @param {?} value - boolean value to be checked
* @return {?}
*/
function (value) {
/** @type {?} */
var returnValue = value;
if (returnValue === undefined || returnValue === null) {
returnValue = true;
}
return returnValue;
};
/**
* Binds the keycloak-js events to the keycloakEvents Subject
* which is a good way to monitor for changes, if needed.
*
* The keycloakEvents returns the keycloak-js event type and any
* argument if the source function provides any.
* @return {?}
*/
KeycloakService.prototype.bindsKeycloakEvents = /**
* Binds the keycloak-js events to the keycloakEvents Subject
* which is a good way to monitor for changes, if needed.
*
* The keycloakEvents returns the keycloak-js event type and any
* argument if the source function provides any.
* @return {?}
*/
function () {
var _this = this;
if (!this._instance) {
console.warn('Keycloak Angular events could not be registered as the keycloak instance is undefined.');
return;
}
this._instance.onAuthError = function (errorData) {
_this._keycloakEvents$.next({ args: errorData, type: KeycloakEventType.OnAuthError });
};
this._instance.onAuthLogout = function () {
_this._keycloakEvents$.next({ type: KeycloakEventType.OnAuthLogout });
};
this._instance.onAuthRefreshError = function () {
_this._keycloakEvents$.next({ type: KeycloakEventType.OnAuthRefreshError });
};
this._instance.onAuthSuccess = function () {
_this._keycloakEvents$.next({ type: KeycloakEventType.OnAuthSuccess });
};
this._instance.onTokenExpired = function () {
_this._keycloakEvents$.next({ type: KeycloakEventType.OnTokenExpired });
};
this._instance.onReady = function (authenticated) {
_this._keycloakEvents$.next({ args: authenticated, type: KeycloakEventType.OnReady });
};
};
/**
* Keycloak initialization. It should be called to initialize the adapter.
* Options is a object with 2 main parameters: config and initOptions. The first one
* will be used to create the Keycloak instance. The second one are options to initialize the
* keycloak instance.
*
* @param options
* Config: may be a string representing the keycloak URI or an object with the
* following content:
* - url: Keycloak json URL
* - realm: realm name
* - clientId: client id
*
* initOptions:
* - onLoad: Specifies an action to do on load. Supported values are 'login-required' or
* 'check-sso'.
* - token: Set an initial value for the token.
* - refreshToken: Set an initial value for the refresh token.
* - idToken: Set an initial value for the id token (only together with token or refreshToken).
* - timeSkew: Set an initial value for skew between local time and Keycloak server in seconds
* (only together with token or refreshToken).
* - checkLoginIframe: Set to enable/disable monitoring login state (default is true).
* - checkLoginIframeInterval: Set the interval to check login state (default is 5 seconds).
* - responseMode: Set the OpenID Connect response mode send to Keycloak server at login
* request. Valid values are query or fragment . Default value is fragment, which means
* that after successful authentication will Keycloak redirect to javascript application
* with OpenID Connect parameters added in URL fragment. This is generally safer and
* recommended over query.
* - flow: Set the OpenID Connect flow. Valid values are standard, implicit or hybrid.
*
* enableBearerInterceptor:
* Flag to indicate if the bearer will added to the authorization header.
*
* loadUserProfileInStartUp:
* Indicates that the user profile should be loaded at the keycloak initialization,
* just after the login.
*
* bearerExcludedUrls:
* String Array to exclude the urls that should not have the Authorization Header automatically
* added.
*
* authorizationHeaderName:
* This value will be used as the Authorization Http Header name.
*
* bearerPrefix:
* This value will be included in the Authorization Http Header param.
*
* @returns
* A Promise with a boolean indicating if the initialization was successful.
*/
/**
* Keycloak initialization. It should be called to initialize the adapter.
* Options is a object with 2 main parameters: config and initOptions. The first one
* will be used to create the Keycloak instance. The second one are options to initialize the
* keycloak instance.
*
* @param {?=} options
* Config: may be a string representing the keycloak URI or an object with the
* following content:
* - url: Keycloak json URL
* - realm: realm name
* - clientId: client id
*
* initOptions:
* - onLoad: Specifies an action to do on load. Supported values are 'login-required' or
* 'check-sso'.
* - token: Set an initial value for the token.
* - refreshToken: Set an initial value for the refresh token.
* - idToken: Set an initial value for the id token (only together with token or refreshToken).
* - timeSkew: Set an initial value for skew between local time and Keycloak server in seconds
* (only together with token or refreshToken).
* - checkLoginIframe: Set to enable/disable monitoring login state (default is true).
* - checkLoginIframeInterval: Set the interval to check login state (default is 5 seconds).
* - responseMode: Set the OpenID Connect response mode send to Keycloak server at login
* request. Valid values are query or fragment . Default value is fragment, which means
* that after successful authentication will Keycloak redirect to javascript application
* with OpenID Connect parameters added in URL fragment. This is generally safer and
* recommended over query.
* - flow: Set the OpenID Connect flow. Valid values are standard, implicit or hybrid.
*
* enableBearerInterceptor:
* Flag to indicate if the bearer will added to the authorization header.
*
* loadUserProfileInStartUp:
* Indicates that the user profile should be loaded at the keycloak initialization,
* just after the login.
*
* bearerExcludedUrls:
* String Array to exclude the urls that should not have the Authorization Header automatically
* added.
*
* authorizationHeaderName:
* This value will be used as the Authorization Http Header name.
*
* bearerPrefix:
* This value will be included in the Authorization Http Header param.
*
* @return {?}
* A Promise with a boolean indicating if the initialization was successful.
*/
KeycloakService.prototype.init = /**
* Keycloak initialization. It should be called to initialize the adapter.
* Options is a object with 2 main parameters: config and initOptions. The first one
* will be used to create the Keycloak instance. The second one are options to initialize the
* keycloak instance.
*
* @param {?=} options
* Config: may be a string representing the keycloak URI or an object with the
* following content:
* - url: Keycloak json URL
* - realm: realm name
* - clientId: client id
*
* initOptions:
* - onLoad: Specifies an action to do on load. Supported values are 'login-required' or
* 'check-sso'.
* - token: Set an initial value for the token.
* - refreshToken: Set an initial value for the refresh token.
* - idToken: Set an initial value for the id token (only together with token or refreshToken).
* - timeSkew: Set an initial value for skew between local time and Keycloak server in seconds
* (only together with token or refreshToken).
* - checkLoginIframe: Set to enable/disable monitoring login state (default is true).
* - checkLoginIframeInterval: Set the interval to check login state (default is 5 seconds).
* - responseMode: Set the OpenID Connect response mode send to Keycloak server at login
* request. Valid values are query or fragment . Default value is fragment, which means
* that after successful authentication will Keycloak redirect to javascript application
* with OpenID Connect parameters added in URL fragment. This is generally safer and
* recommended over query.
* - flow: Set the OpenID Connect flow. Valid values are standard, implicit or hybrid.
*
* enableBearerInterceptor:
* Flag to indicate if the bearer will added to the authorization header.
*
* loadUserProfileInStartUp:
* Indicates that the user profile should be loaded at the keycloak initialization,
* just after the login.
*
* bearerExcludedUrls:
* String Array to exclude the urls that should not have the Authorization Header automatically
* added.
*
* authorizationHeaderName:
* This value will be used as the Authorization Http Header name.
*
* bearerPrefix:
* This value will be included in the Authorization Http Header param.
*
* @return {?}
* A Promise with a boolean indicating if the initialization was successful.
*/
function (options) {
var _this = this;
if (options === void 0) { options = {}; }
return new Promise(function (resolve, reject) {
_this._enableBearerInterceptor = _this.ifUndefinedIsTrue(options.enableBearerInterceptor);
_this._loadUserProfileAtStartUp = _this.ifUndefinedIsTrue(options.loadUserProfileAtStartUp);
_this._bearerExcludedUrls = options.bearerExcludedUrls || [];
_this._authorizationHeaderName = options.authorizationHeaderName || 'Authorization';
_this._bearerPrefix = _this.sanitizeBearerPrefix(options.bearerPrefix);
_this._silentRefresh = options.initOptions ? options.initOptions.flow === 'implicit' : false;
_this._instance = Keycloak(options.config);
_this.bindsKeycloakEvents();
_this._instance
.init(/** @type {?} */ ((options.initOptions)))
.success(function (authenticated) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(authenticated && this._loadUserProfileAtStartUp)) return [3 /*break*/, 2];
return [4 /*yield*/, this.loadUserProfile()];
case 1:
_a.sent();
_a.label = 2;
case 2:
resolve(authenticated);
return [2 /*return*/];
}
});
}); })
.error(function (error) {
reject('An error happened during Keycloak initialization.');
});
});
};
/**
* Redirects to login form on (options is an optional object with redirectUri and/or
* prompt fields).
*
* @param options
* Object, where:
* - redirectUri: Specifies the uri to redirect to after login.
* - prompt:By default the login screen is displayed if the user is not logged-in to Keycloak.
* To only authenticate to the application if the user is already logged-in and not display the
* login page if the user is not logged-in, set this option to none. To always require
* re-authentication and ignore SSO, set this option to login .
* - maxAge: Used just if user is already authenticated. Specifies maximum time since the
* authentication of user happened. If user is already authenticated for longer time than
* maxAge, the SSO is ignored and he will need to re-authenticate again.
* - loginHint: Used to pre-fill the username/email field on the login form.
* - action: If value is 'register' then user is redirected to registration page, otherwise to
* login page.
* - locale: Specifies the desired locale for the UI.
* @returns
* A void Promise if the login is successful and after the user profile loading.
*/
/**
* Redirects to login form on (options is an optional object with redirectUri and/or
* prompt fields).
*
* @param {?=} options
* Object, where:
* - redirectUri: Specifies the uri to redirect to after login.
* - prompt:By default the login screen is displayed if the user is not logged-in to Keycloak.
* To only authenticate to the application if the user is already logged-in and not display the
* login page if the user is not logged-in, set this option to none. To always require
* re-authentication and ignore SSO, set this option to login .
* - maxAge: Used just if user is already authenticated. Specifies maximum time since the
* authentication of user happened. If user is already authenticated for longer time than
* maxAge, the SSO is ignored and he will need to re-authenticate again.
* - loginHint: Used to pre-fill the username/email field on the login form.
* - action: If value is 'register' then user is redirected to registration page, otherwise to
* login page.
* - locale: Specifies the desired locale for the UI.
* @return {?}
* A void Promise if the login is successful and after the user profile loading.
*/
KeycloakService.prototype.login = /**
* Redirects to login form on (options is an optional object with redirectUri and/or
* prompt fields).
*
* @param {?=} options
* Object, where:
* - redirectUri: Specifies the uri to redirect to after login.
* - prompt:By default the login screen is displayed if the user is not logged-in to Keycloak.
* To only authenticate to the application if the user is already logged-in and not display the
* login page if the user is not logged-in, set this option to none. To always require
* re-authentication and ignore SSO, set this option to login .
* - maxAge: Used just if user is already authenticated. Specifies maximum time since the
* authentication of user happened. If user is already authenticated for longer time than
* maxAge, the SSO is ignored and he will need to re-authenticate again.
* - loginHint: Used to pre-fill the username/email field on the login form.
* - action: If value is 'register' then user is redirected to registration page, otherwise to
* login page.
* - locale: Specifies the desired locale for the UI.
* @return {?}
* A void Promise if the login is successful and after the user profile loading.
*/
function (options) {
var _this = this;
if (options === void 0) { options = {}; }
return new Promise(function (resolve, reject) {
_this._instance
.login(options)
.success(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this._loadUserProfileAtStartUp) return [3 /*break*/, 2];
return [4 /*yield*/, this.loadUserProfile()];
case 1:
_a.sent();
_a.label = 2;
case 2:
resolve();
return [2 /*return*/];
}
});
}); })
.error(function (error) {
reject('An error happened during the login.');
});
});
};
/**
* Redirects to logout.
*
* @param redirectUri
* Specifies the uri to redirect to after logout.
* @returns
* A void Promise if the logout was successful, cleaning also the userProfile.
*/
/**
* Redirects to logout.
*
* @param {?=} redirectUri
* Specifies the uri to redirect to after logout.
* @return {?}
* A void Promise if the logout was successful, cleaning also the userProfile.
*/
KeycloakService.prototype.logout = /**
* Redirects to logout.
*
* @param {?=} redirectUri
* Specifies the uri to redirect to after logout.
* @return {?}
* A void Promise if the logout was successful, cleaning also the userProfile.
*/
function (redirectUri) {
var _this = this;
return new Promise(function (resolve, reject) {
/** @type {?} */
var options = {
redirectUri: redirectUri
};
_this._instance
.logout(options)
.success(function () {
_this._userProfile = /** @type {?} */ ((undefined));
resolve();
})
.error(function (error) {
reject('An error happened during logout.');
});
});
};
/**
* Redirects to registration form. Shortcut for login with option
* action = 'register'. Options are same as for the login method but 'action' is set to
* 'register'.
*
* @param options
* login options
* @returns
* A void Promise if the register flow was successful.
*/
/**
* Redirects to registration form. Shortcut for login with option
* action = 'register'. Options are same as for the login method but 'action' is set to
* 'register'.
*
* @param {?=} options
* login options
* @return {?}
* A void Promise if the register flow was successful.
*/
KeycloakService.prototype.register = /**
* Redirects to registration form. Shortcut for login with option
* action = 'register'. Options are same as for the login method but 'action' is set to
* 'register'.
*
* @param {?=} options
* login options
* @return {?}
* A void Promise if the register flow was successful.
*/
function (options) {
var _this = this;
if (options === void 0) { options = { action: 'register' }; }
return new Promise(function (resolve, reject) {
_this._instance
.register(options)
.success(function () {
resolve();
})
.error(function () {
reject('An error happened during the register execution');
});
});
};
/**
* Check if the user has access to the specified role. It will look for roles in
* realm and clientId, but will not check if the user is logged in for better performance.
*
* @param role
* role name
* @returns
* A boolean meaning if the user has the specified Role.
*/
/**
* Check if the user has access to the specified role. It will look for roles in
* realm and clientId, but will not check if the user is logged in for better performance.
*
* @param {?} role
* role name
* @return {?}
* A boolean meaning if the user has the specified Role.
*/
KeycloakService.prototype.isUserInRole = /**
* Check if the user has access to the specified role. It will look for roles in
* realm and clientId, but will not check if the user is logged in for better performance.
*
* @param {?} role
* role name
* @return {?}
* A boolean meaning if the user has the specified Role.
*/
function (role) {
/** @type {?} */
var hasRole;
hasRole = this._instance.hasResourceRole(role);
if (!hasRole) {
hasRole = this._instance.hasRealmRole(role);
}
return hasRole;
};
/**
* Return the roles of the logged user. The allRoles parameter, with default value
* true, will return the clientId and realm roles associated with the logged user. If set to false
* it will only return the user roles associated with the clientId.
*
* @param allRoles
* Flag to set if all roles should be returned.(Optional: default value is true)
* @returns
* Array of Roles associated with the logged user.
*/
/**
* Return the roles of the logged user. The allRoles parameter, with default value
* true, will return the clientId and realm roles associated with the logged user. If set to false
* it will only return the user roles associated with the clientId.
*
* @param {?=} allRoles
* Flag to set if all roles should be returned.(Optional: default value is true)
* @return {?}
* Array of Roles associated with the logged user.
*/
KeycloakService.prototype.getUserRoles = /**
* Return the roles of the logged user. The allRoles parameter, with default value
* true, will return the clientId and realm roles associated with the logged user. If set to false
* it will only return the user roles associated with the clientId.
*
* @param {?=} allRoles
* Flag to set if all roles should be returned.(Optional: default value is true)
* @return {?}
* Array of Roles associated with the logged user.
*/
function (allRoles) {
if (allRoles === void 0) { allRoles = true; }
/** @type {?} */
var roles = [];
if (this._instance.resourceAccess) {
for (var key in this._instance.resourceAccess) {
if (this._instance.resourceAccess.hasOwnProperty(key)) {
/** @type {?} */
var resourceAccess = this._instance.resourceAccess[key];
/** @type {?} */
var clientRoles = resourceAccess['roles'] || [];
roles = roles.concat(clientRoles);
}
}
}
if (allRoles && this._instance.realmAccess) {
/** @type {?} */
var realmRoles = this._instance.realmAccess['roles'] || [];
roles.push.apply(roles, tslib_1.__spread(realmRoles));
}
return roles;
};
/**
* Check if user is logged in.
*
* @returns
* A boolean that indicates if the user is logged in.
*/
/**
* Check if user is logged in.
*
* @return {?}
* A boolean that indicates if the user is logged in.
*/
KeycloakService.prototype.isLoggedIn = /**
* Check if user is logged in.
*
* @return {?}
* A boolean that indicates if the user is logged in.
*/
function () {
var _this = this;
return new Promise(function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var error_1;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, this.updateToken(20)];
case 1:
_a.sent();
resolve(true);
return [3 /*break*/, 3];
case 2:
error_1 = _a.sent();
resolve(false);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); });
};
/**
* Returns true if the token has less than minValidity seconds left before
* it expires.
*
* @param minValidity
* Seconds left. (minValidity) is optional. Default value is 0.
* @returns
* Boolean indicating if the token is expired.
*/
/**
* Returns true if the token has less than minValidity seconds left before
* it expires.
*
* @param {?=} minValidity
* Seconds left. (minValidity) is optional. Default value is 0.
* @return {?}
* Boolean indicating if the token is expired.
*/
KeycloakService.prototype.isTokenExpired = /**
* Returns true if the token has less than minValidity seconds left before
* it expires.
*
* @param {?=} minValidity
* Seconds left. (minValidity) is optional. Default value is 0.
* @return {?}
* Boolean indicating if the token is expired.
*/
function (minValidity) {
if (minValidity === void 0) { minValidity = 0; }
return this._instance.isTokenExpired(minValidity);
};
/**
* If the token expires within minValidity seconds the token is refreshed. If the
* session status iframe is enabled, the session status is also checked.
* Returns a promise telling if the token was refreshed or not. If the session is not active
* anymore, the promise is rejected.
*
* @param minValidity
* Seconds left. (minValidity is optional, if not specified 5 is used)
* @returns
* Promise with a boolean indicating if the token was succesfully updated.
*/
/**
* If the token expires within minValidity seconds the token is refreshed. If the
* session status iframe is enabled, the session status is also checked.
* Returns a promise telling if the token was refreshed or not. If the session is not active
* anymore, the promise is rejected.
*
* @param {?=} minValidity
* Seconds left. (minValidity is optional, if not specified 5 is used)
* @return {?}
* Promise with a boolean indicating if the token was succesfully updated.
*/
KeycloakService.prototype.updateToken = /**
* If the token expires within minValidity seconds the token is refreshed. If the
* session status iframe is enabled, the session status is also checked.
* Returns a promise telling if the token was refreshed or not. If the session is not active
* anymore, the promise is rejected.
*
* @param {?=} minValidity
* Seconds left. (minValidity is optional, if not specified 5 is used)
* @return {?}
* Promise with a boolean indicating if the token was succesfully updated.
*/
function (minValidity) {
var _this = this;
if (minValidity === void 0) { minValidity = 5; }
return new Promise(function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
// TODO: this is a workaround until the silent refresh (issue #43)
// is not implemented, avoiding the redirect loop.
if (this._silentRefresh) {
if (this.isTokenExpired()) {
reject('Failed to refresh the token, or the session is expired');
}
else {
resolve(true);
}
return [2 /*return*/];
}
if (!this._instance) {
reject();
return [2 /*return*/];
}
this._instance
.updateToken(minValidity)
.success(function (refreshed) {
resolve(refreshed);
})
.error(function (error) {
reject('Failed to refresh the token, or the session is expired');
});
return [2 /*return*/];
});
}); });
};
/**
* Loads the users profile.
* Returns promise to set functions to be invoked if the profile was loaded successfully, or if
* the profile could not be loaded.
*
* @param forceReload
* If true will force the loadUserProfile even if its already loaded.
* @returns
* A promise with the KeycloakProfile data loaded.
*/
/**
* Loads the users profile.
* Returns promise to set functions to be invoked if the profile was loaded successfully, or if
* the profile could not be loaded.
*
* @param {?=} forceReload
* If true will force the loadUserProfile even if its already loaded.
* @return {?}
* A promise with the KeycloakProfile data loaded.
*/
KeycloakService.prototype.loadUserProfile = /**
* Loads the users profile.
* Returns promise to set functions to be invoked if the profile was loaded successfully, or if
* the profile could not be loaded.
*
* @param {?=} forceReload
* If true will force the loadUserProfile even if its already loaded.
* @return {?}
* A promise with the KeycloakProfile data loaded.
*/
function (forceReload) {
var _this = this;
if (forceReload === void 0) { forceReload = false; }
return new Promise(function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var _this = this;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (this._userProfile && !forceReload) {
resolve(this._userProfile);
return [2 /*return*/];
}
return [4 /*yield*/, this.isLoggedIn()];
case 1:
if (!(_a.sent())) {
reject('The user profile was not loaded as the user is not logged in.');
return [2 /*return*/];
}
this._instance
.loadUserProfile()
.success(function (result) {
_this._userProfile = /** @type {?} */ (result);
resolve(_this._userProfile);
})
.error(function (err) {
reject('The user profile could not be loaded.');
});
return [2 /*return*/];
}
});
}); });
};
/**
* Returns the authenticated token, calling updateToken to get a refreshed one if
* necessary. If the session is expired this method calls the login method for a new login.
*
* @returns
* Promise with the generated token.
*/
/**
* Returns the authenticated token, calling updateToken to get a refreshed one if
* necessary. If the session is expired this method calls the login method for a new login.
*
* @return {?}
* Promise with the generated token.
*/
KeycloakService.prototype.getToken = /**
* Returns the authenticated token, calling updateToken to get a refreshed one if
* necessary. If the session is expired this method calls the login method for a new login.
*
* @return {?}
* Promise with the generated token.
*/
function () {
var _this = this;
return new Promise(function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var error_2;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, this.updateToken(10)];
case 1:
_a.sent();
resolve(this._instance.token);
return [3 /*break*/, 3];
case 2:
error_2 = _a.sent();
this.login();
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); });
};
/**
* Returns the logged username.
*
* @returns
* The logged username.
*/
/**
* Returns the logged username.
*
* @return {?}
* The logged username.
*/
KeycloakService.prototype.getUsername = /**
* Returns the logged username.
*
* @return {?}
* The logged username.
*/
function () {
if (!this._userProfile) {
throw new Error('User not logged in or user profile was not loaded.');
}
return /** @type {?} */ ((this._userProfile.username));
};
/**
* Clear authentication state, including tokens. This can be useful if application
* has detected the session was expired, for example if updating token fails.
* Invoking this results in onAuthLogout callback listener being invoked.
*/
/**
* Clear authentication state, including tokens. This can be useful if application
* has detected the session was expired, for example if updating token fails.
* Invoking this results in onAuthLogout callback listener being invoked.
* @return {?}
*/
KeycloakService.prototype.clearToken = /**
* Clear authentication state, including tokens. This can be useful if application
* has detected the session was expired, for example if updating token fails.
* Invoking this results in onAuthLogout callback listener being invoked.
* @return {?}
*/
function () {
this._instance.clearToken();
};
/**
* Adds a valid token in header. The key & value format is:
* Authorization Bearer <token>.
* If the headers param is undefined it will create the Angular headers object.
*
* @param headers
* Updated header with Authorization and Keycloak token.
* @returns
* An observable with with the HTTP Authorization header and the current token.
*/
/**
* Adds a valid token in header. The key & value format is:
* Authorization Bearer <token>.
* If the headers param is undefined it will create the Angular headers object.
*
* @param {?=} headersArg
* @return {?}
* An observable with with the HTTP Authorization header and the current token.
*/
KeycloakService.prototype.addTokenToHeader = /**
* Adds a valid token in header. The key & value format is:
* Authorization Bearer <token>.
* If the headers param is undefined it will create the Angular headers object.
*
* @param {?=} headersArg
* @return {?}
* An observable with with the HTTP Authorization header and the current token.
*/
function (headersArg) {
var _this = this;
return Observable.create(function (observer) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var headers, token, error_3;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
headers = headersArg;
if (!headers) {
headers = new HttpHeaders();
}
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.getToken()];
case 2:
token = _a.sent();
headers = headers.set(this._authorizationHeaderName, this._bearerPrefix + token);
observer.next(headers);
observer.complete();
return [3 /*break*/, 4];
case 3:
error_3 = _a.sent();
observer.error(error_3);
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
}); });
};
/**
* Returns the original Keycloak instance, if you need any customization that
* this Angular service does not support yet. Use with caution.
*
* @returns
* The KeycloakInstance from keycloak-js.
*/
/**
* Returns the original Keycloak instance, if you need any customization that
* this Angular service does not support yet. Use with caution.
*
* @return {?}
* The KeycloakInstance from keycloak-js.
*/
KeycloakService.prototype.getKeycloakInstance = /**
* Returns the original Keycloak instance, if you need any customization that
* this Angular service does not support yet. Use with caution.
*
* @return {?}
* The KeycloakInstance from keycloak-js.
*/
function () {
return this._instance;
};
Object.defineProperty(KeycloakService.prototype, "bearerExcludedUrls", {
/**
* Returns the excluded URLs that should not be considered by
* the http interceptor which automatically adds the authorization header in the Http Request.
*
* @returns
* The excluded urls that must not be intercepted by the KeycloakBearerInterceptor.
*/
get: /**
* Returns the excluded URLs that should not be considered by
* the http interceptor which automatically adds the authorization header in the Http Request.
*
* @return {?}
* The excluded urls that must not be intercepted by the KeycloakBearerInterceptor.
*/
function () {
return this._bearerExcludedUrls;
},
enumerable: true,
configurable: true
});
Object.defineProperty(KeycloakService.prototype, "enableBearerInterceptor", {
/**
* Flag to indicate if the bearer will be added to the authorization header.
*
* @returns
* Returns if the bearer interceptor was set to be disabled.
*/
get: /**
* Flag to indicate if the bearer will be added to the authorization header.
*
* @return {?}
* Returns if the bearer interceptor was set to be disabled.
*/
function () {
return this._enableBearerInterceptor;
},
enumerable: true,
configurable: true
});
Object.defineProperty(KeycloakService.prototype, "keycloakEvents$", {
/**
* Keycloak subject to monitor the events triggered by keycloak-js.
* The following events as available (as described at keycloak docs -
* https://www.keycloak.org/docs/latest/securing_apps/index.html#callback-events):
* - OnAuthError
* - OnAuthLogout
* - OnAuthRefreshError
* - OnAuthRefreshSuccess
* - OnAuthSuccess
* - OnReady
* - OnTokenExpire
* In each occurrence of any of these, this subject will return the event type,
* described at {@link KeycloakEventType} enum and the function args from the keycloak-js
* if provided any.
*
* @returns
* A subject with the {@link KeycloakEvent} which describes the event type and attaches the
* function args.
*/
get: /**
* Keycloak subject to monitor the events triggered by keycloak-js.
* The following events as available (as described at keycloak docs -
* https://www.keycloak.org/docs/latest/securing_apps/index.html#callback-events):
* - OnAuthError
* - OnAuthLogout
* - OnAuthRefreshError
* - OnAuthRefreshSuccess
* - OnAuthSuccess
* - OnReady
* - OnTokenExpire
* In each occurrence of any of these, this subject will return the event type,
* described at {\@link KeycloakEventType} enum and the function args from the keycloak-js
* if provided any.
*
* @return {?}
* A subject with the {\@link KeycloakEvent} which describes the event type and attaches the
* function args.
*/
function () {
return this._keycloakEvents$;
},
enumerable: true,
configurable: true
});
KeycloakService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
KeycloakService.ctorParameters = function () { return []; };
return KeycloakService;
}());
export { KeycloakService };
function KeycloakService_tsickle_Closure_declarations() {
/**
* Keycloak-js instance.
* @type {?}
*/
KeycloakService.prototype._instance;
/**
* User profile as KeycloakProfile interface.
* @type {?}
*/
KeycloakService.prototype._userProfile;
/**
* Flag to indicate if the bearer will not be added to the authorization header.
* @type {?}
*/
KeycloakService.prototype._enableBearerInterceptor;
/**
* When the implicit flow is choosen there must exist a silentRefresh, as there is
* no refresh token.
* @type {?}
*/
KeycloakService.prototype._silentRefresh;
/**
* Indicates that the user profile should be loaded at the keycloak initialization,
* just after the login.
* @type {?}
*/
KeycloakService.prototype._loadUserProfileAtStartUp;
/**
* The bearer prefix that will be appended to the Authorization Header.
* @type {?}
*/
KeycloakService.prototype._bearerPrefix;
/**
* Value that will be used as the Authorization Http Header name.
* @type {?}
*/
KeycloakService.prototype._authorizationHeaderName;
/**
* The excluded urls patterns that must skip the KeycloakBearerInterceptor.
* @type {?}
*/
KeycloakService.prototype._bearerExcludedUrls;
/**
* Observer for the keycloak events
* @type {?}
*/
KeycloakService.prototype._keycloakEvents$;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5Y2xvYWsuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2tleWNsb2FrLWFuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvY29yZS9zZXJ2aWNlcy9rZXljbG9hay5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQVFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFM0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBR25ELE9BQU8sS0FBSyxTQUFTLE1BQU0sYUFBYSxDQUFDOztBQUN6QyxXQUFhLFFBQVEsR0FBRyxTQUFTLENBQUM7QUFFbEMsT0FBTyxFQUFFLFVBQVUsRUFBWSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFHckQsT0FBTyxFQUFpQixpQkFBaUIsRUFBRSxNQUFNLDhCQUE4QixDQUFDOzs7Ozs7Ozs7SUFrRDlFO1FBQ0UsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksT0FBTyxFQUFpQixDQUFDO0tBQ3REOzs7Ozs7Ozs7Ozs7O0lBY08sOENBQW9COzs7Ozs7Ozs7Ozs7Y0FBQyxZQUFnQzs7UUFDM0QsSUFBSSxNQUFNLEdBQVcsQ0FBQyxZQUFZLElBQUksUUFBUSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdkQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7Ozs7Ozs7O0lBUXBCLDJDQUFpQjs7Ozs7O2NBQUMsS0FBYzs7UUFDdEMsSUFBSSxXQUFXLEdBQVksS0FBSyxDQUFDO1FBQ2pDLEVBQUUsQ0FBQyxDQUFDLFdBQVcsS0FBSyxTQUFTLElBQUksV0FBVyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDdEQsV0FBVyxHQUFHLElBQUksQ0FBQztTQUNwQjtRQUNELE1BQU0sQ0FBQyxXQUFXLENBQUM7Ozs7Ozs7Ozs7SUFVYiw2Q0FBbUI7Ozs7Ozs7Ozs7UUFDekIsRUFBRSxDQUFDLENBQUMsQ0FBQyxJ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