@asgardeo/auth-angular
Version:
Asgardeo Auth Angular SDK for Angular Applications.
638 lines (623 loc) • 22.6 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, Injectable, Injector, Inject, Component, NgModule } from '@angular/core';
import { AsgardeoSPAClient, Hooks, SPAUtils } from '@asgardeo/auth-spa';
export { Hooks, ResponseMode, Storage } from '@asgardeo/auth-spa';
import { __awaiter } from 'tslib';
import { BehaviorSubject, Subject, from } from 'rxjs';
import { Router } from '@angular/router';
import { takeUntil, mergeMap, catchError } from 'rxjs/operators';
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
const ASGARDEO_CONFIG = new InjectionToken("Asgardeo.config.angular");
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
class AsgardeoNavigatorService {
constructor(injector) {
try {
this.router = injector.get(Router);
}
catch (_a) {
console.warn("Router is Not Provided");
}
}
navigateByUrl(url) {
if (this.router) {
return this.router.navigateByUrl(url);
}
else {
return Promise.resolve(false);
}
}
setRedirectUrl() {
sessionStorage.setItem("redirectUrl", this.getCurrentRoute());
}
getRedirectUrl() {
return sessionStorage.getItem("redirectUrl") || "/";
}
getRouteWithoutParams(url) {
return new URL(url).pathname;
}
getCurrentRoute() {
if (this.router) {
return this.router.url.split("?")[0];
}
else {
return window.location.href.split("?")[0];
}
}
getCurrentUrl() {
if (this.router) {
return this.router.url;
}
else {
return window.location.href;
}
}
}
AsgardeoNavigatorService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AsgardeoNavigatorService_Factory() { return new AsgardeoNavigatorService(i0.ɵɵinject(i0.INJECTOR)); }, token: AsgardeoNavigatorService, providedIn: "root" });
AsgardeoNavigatorService.decorators = [
{ type: Injectable, args: [{
providedIn: "root"
},] }
];
AsgardeoNavigatorService.ctorParameters = () => [
{ type: Injector }
];
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
class AsgardeoAuthStateStoreService {
constructor() {
this.DEFAULT_STATE = {
allowedScopes: "",
displayName: "",
email: "",
isAuthenticated: false,
isLoading: true,
sub: "",
username: ""
};
// Readonly State BehaviorSubject. Not accessible from outside.
this._state = new BehaviorSubject(this.DEFAULT_STATE);
// Outside can access this readonly state object by subscribing.
this.state$ = this._state.asObservable();
}
/**
* Getter for the state.
* @return {AuthStateInterface}
*/
get state() {
return this._state.getValue();
}
/**
* Setter for the state.
* @param {AuthStateInterface} newState - New state.
*/
set state(newState) {
this._state.next(Object.assign(Object.assign({}, this._state), newState));
}
/**
* Set the Loading state.
* @param {boolean} isLoading - State.
*/
setIsLoading(isLoading) {
this._state.next(Object.assign(Object.assign({}, this.state), { isLoading }));
}
/**
* Resets the state back to the default.
*/
reset() {
this._state.next(this.DEFAULT_STATE);
}
}
AsgardeoAuthStateStoreService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AsgardeoAuthStateStoreService_Factory() { return new AsgardeoAuthStateStoreService(); }, token: AsgardeoAuthStateStoreService, providedIn: "root" });
AsgardeoAuthStateStoreService.decorators = [
{ type: Injectable, args: [{
providedIn: "root"
},] }
];
class AsgardeoAuthService {
constructor(authConfig, navigator, stateStore) {
this.authConfig = authConfig;
this.navigator = navigator;
this.stateStore = stateStore;
this.state$ = this.stateStore.state$;
this.auth = AsgardeoSPAClient.getInstance();
this.subscriptionDestroyer$ = new Subject();
/**
* This method allows you to sign in silently.
* First, this method sends a prompt none request to see if there is an active user session in the identity server.
* If there is one, then it requests the access token and stores it. Else, it returns false.
*
* @return {Promise<BasicUserInfo | boolean>} - A Promise that resolves with the user information after signing in
* or with `false` if the user is not signed in.
*
* @example
*```
* this.auth.trySignInSilently()
*```
*/
this.trySignInSilently = () => __awaiter(this, void 0, void 0, function* () {
this.stateStore.setIsLoading(true);
return this.auth
.trySignInSilently()
.then((response) => __awaiter(this, void 0, void 0, function* () {
if (!response) {
return false;
}
if (yield this.auth.isAuthenticated()) {
const basicUserInfo = response;
this.stateStore.state = {
allowedScopes: basicUserInfo.allowedScopes,
displayName: basicUserInfo.displayName,
email: basicUserInfo.email,
isAuthenticated: true,
isLoading: false,
sub: basicUserInfo.sub,
username: basicUserInfo.username
};
}
return response;
}))
.catch((error) => Promise.reject(error))
.finally(() => {
this.stateStore.setIsLoading(false);
});
});
this.config = authConfig;
this.auth = AsgardeoSPAClient.getInstance();
this.initializeHooks();
(() => __awaiter(this, void 0, void 0, function* () {
yield this.auth.initialize(this.authConfig);
yield this.handleSingleLogoutOnRedirect();
this.handleAutoLogin()
.pipe(takeUntil(this.subscriptionDestroyer$))
.subscribe();
}))();
}
/**
* Runs on service unmount.
* @remarks Housekeeping logic such as un-subscribing should go here.
*/
ngOnDestroy() {
this.subscriptionDestroyer$.next(true);
this.subscriptionDestroyer$.unsubscribe();
}
/**
* Registering a sign-out hook clears user session data internally if there was a successful logout.
*/
initializeHooks() {
this.auth.on(Hooks.SignOut, () => { });
}
signIn(config, authorizationCode, sessionState) {
this.stateStore.setIsLoading(true);
return this.auth
.signIn(config, authorizationCode, sessionState)
.then((response) => __awaiter(this, void 0, void 0, function* () {
if (!response) {
return;
}
if (yield this.auth.isAuthenticated()) {
this.stateStore.state = {
allowedScopes: response.allowedScopes,
displayName: response.displayName,
email: response.email,
isAuthenticated: true,
isLoading: false,
sub: response.sub,
username: response.username
};
}
return response;
}))
.catch((error) => Promise.reject(error))
.finally(() => {
this.stateStore.setIsLoading(false);
});
}
signInWithRedirect() {
this.navigator.setRedirectUrl();
const redirectRoute = this.navigator.getRouteWithoutParams(this.authConfig.signInRedirectURL);
return this.navigator.navigateByUrl(redirectRoute);
}
signOut() {
this.stateStore.setIsLoading(true);
return this.auth
.signOut()
.then((response) => {
// Reset the state.
this.stateStore.reset();
return response;
})
.catch((error) => Promise.reject(error))
.finally(() => {
this.stateStore.setIsLoading(false);
});
}
isAuthenticated() {
return this.auth.isAuthenticated();
}
getBasicUserInfo() {
return this.auth.getBasicUserInfo();
}
getAccessToken() {
return this.auth.getAccessToken();
}
getIDToken() {
return this.auth.getIDToken();
}
getDecodedIDToken() {
return this.auth.getDecodedIDToken();
}
getOIDCServiceEndpoints() {
return this.auth.getOIDCServiceEndpoints();
}
refreshAccessToken() {
return this.auth.refreshAccessToken();
}
revokeAccessToken() {
return this.auth
.revokeAccessToken()
.then(() => {
// Reset the state.
this.stateStore.reset();
return true;
})
.catch((error) => Promise.reject(error))
.finally(() => {
this.stateStore.setIsLoading(false);
});
}
on(hook, callback, id) {
if (hook === Hooks.CustomGrant) {
return this.auth.on(hook, callback, id);
}
return this.auth.on(hook, callback);
}
requestCustomGrant(config) {
return this.auth.requestCustomGrant(config);
}
httpRequest(config) {
return this.auth.httpRequest(config);
}
httpRequestAll(config) {
return this.auth.httpRequestAll(config);
}
/**
* Handles auto login by trying to exchange tokens if auth params i.e `code` and `session_state` is
* available in the URL or else, tries to silently login.
*
* @private
* @return {Observable<BasicUserInfo | boolean>}
*/
handleAutoLogin() {
this.stateStore.setIsLoading(true);
// If `skipRedirectCallback` is not true, check if the URL has `code` and `session_state` params.
// If so, initiate the sign in. If not, try to login silently.
if (!this.config.skipRedirectCallback &&
SPAUtils.hasAuthSearchParamsInURL()) {
return from(this.signIn());
}
// This uses the RP iframe to get the session. Hence, will not work if 3rd party cookies are disabled.
// If the browser has these cookies disabled, we'll not be able to retrieve the session on refreshes.
return from(this.trySignInSilently());
}
/**
* Handles single logout if a prompt none sign in response is received with an error parameter on the URL.
*
* @private
* @return {Promise<BasicUserInfo | void>}
*/
handleSingleLogoutOnRedirect() {
return __awaiter(this, void 0, void 0, function* () {
if (SPAUtils.hasErrorInURL()) {
// The signIn method call will call receivePromptNoneResponse method internally to handle the prompt none
// response in the single logout flow.
return this.signIn({ callOnlyOnRedirect: true });
}
});
}
}
AsgardeoAuthService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AsgardeoAuthService_Factory() { return new AsgardeoAuthService(i0.ɵɵinject(ASGARDEO_CONFIG), i0.ɵɵinject(AsgardeoNavigatorService), i0.ɵɵinject(AsgardeoAuthStateStoreService)); }, token: AsgardeoAuthService, providedIn: "root" });
AsgardeoAuthService.decorators = [
{ type: Injectable, args: [{
providedIn: "root"
},] }
];
AsgardeoAuthService.ctorParameters = () => [
{ type: undefined, decorators: [{ type: Inject, args: [ASGARDEO_CONFIG,] }] },
{ type: AsgardeoNavigatorService },
{ type: AsgardeoAuthStateStoreService }
];
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
class AsgardeoSignInRedirectComponent {
constructor(auth, navigator) {
this.auth = auth;
this.navigator = navigator;
}
ngOnInit() {
this.auth.on(Hooks.SignIn, () => {
this.navigator.navigateByUrl(this.navigator.getRedirectUrl());
});
if (!SPAUtils.hasAuthSearchParamsInURL(this.navigator.getCurrentUrl())) {
this.auth.signIn();
}
}
}
AsgardeoSignInRedirectComponent.decorators = [
{ type: Component, args: [{
selector: "lib-asgardeo-sign-in-redirect",
template: ""
},] }
];
AsgardeoSignInRedirectComponent.ctorParameters = () => [
{ type: AsgardeoAuthService },
{ type: AsgardeoNavigatorService }
];
class AsgardeoAuthGuard {
constructor(auth) {
this.auth = auth;
}
canActivate() {
return __awaiter(this, void 0, void 0, function* () {
const isAuthenticated = yield this.auth.isAuthenticated();
if (isAuthenticated) {
return true;
}
return false;
});
}
canActivateChild() {
return __awaiter(this, void 0, void 0, function* () {
return this.canActivate();
});
}
}
AsgardeoAuthGuard.ɵprov = i0.ɵɵdefineInjectable({ factory: function AsgardeoAuthGuard_Factory() { return new AsgardeoAuthGuard(i0.ɵɵinject(AsgardeoAuthService)); }, token: AsgardeoAuthGuard, providedIn: "root" });
AsgardeoAuthGuard.decorators = [
{ type: Injectable, args: [{
providedIn: "root"
},] }
];
AsgardeoAuthGuard.ctorParameters = () => [
{ type: AsgardeoAuthService }
];
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
class AsgardeoAuthModule {
static forRoot(config) {
return {
ngModule: AsgardeoAuthModule,
providers: [
AsgardeoAuthService,
AsgardeoAuthGuard,
{
provide: ASGARDEO_CONFIG,
useValue: config
}
]
};
}
}
AsgardeoAuthModule.decorators = [
{ type: NgModule, args: [{
declarations: [AsgardeoSignInRedirectComponent]
},] }
];
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
class AsgardeoAuthInterceptor {
constructor(auth, authConfig) {
this.auth = auth;
this.authConfig = authConfig;
}
intercept(request, next) {
if (this.canAttachToken(request, this.authConfig["resourceServerURLs"])) {
return from(this.auth.getAccessToken())
.pipe(mergeMap(token => {
if (token) {
const header = "Bearer " + token;
const headers = request.headers.set("Authorization", header);
request = request.clone({ headers });
}
return next.handle(request);
}), catchError(error => {
console.error(error);
return next.handle(request);
}));
}
else {
return next.handle(request);
}
}
canAttachToken(request, allowedUrls) {
let matches = false;
if (allowedUrls) {
allowedUrls.forEach((baseUrl) => {
var _a;
if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.startsWith(baseUrl)) {
matches = true;
}
});
}
return matches;
}
}
AsgardeoAuthInterceptor.decorators = [
{ type: Injectable }
];
AsgardeoAuthInterceptor.ctorParameters = () => [
{ type: AsgardeoAuthService },
{ type: undefined, decorators: [{ type: Inject, args: [ASGARDEO_CONFIG,] }] }
];
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/**
* Generated bundle index. Do not edit.
*/
export { AsgardeoAuthGuard, AsgardeoAuthInterceptor, AsgardeoAuthModule, AsgardeoAuthService, AsgardeoSignInRedirectComponent, ASGARDEO_CONFIG as ɵa, AsgardeoNavigatorService as ɵc, AsgardeoAuthStateStoreService as ɵd, AsgardeoAuthService as ɵe };
//# sourceMappingURL=asgardeo-auth-angular.js.map