133 lines
4.1 KiB
TypeScript
133 lines
4.1 KiB
TypeScript
import { Injectable, inject } from 'injection-js';
|
|
import { type Observable, of, throwError } from 'rxjs';
|
|
import { catchError, switchMap } from 'rxjs/operators';
|
|
import { AuthStateService } from '../../auth-state/auth-state.service';
|
|
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
|
import { LoggerService } from '../../logging/logger.service';
|
|
import { UserService } from '../../user-data/user.service';
|
|
import type { StateValidationResult } from '../../validation/state-validation-result';
|
|
import type { CallbackContext } from '../callback-context';
|
|
import { FlowsDataService } from '../flows-data.service';
|
|
import { ResetAuthDataService } from '../reset-auth-data.service';
|
|
|
|
@Injectable()
|
|
export class UserCallbackHandlerService {
|
|
private readonly loggerService = inject(LoggerService);
|
|
|
|
private readonly authStateService = inject(AuthStateService);
|
|
|
|
private readonly flowsDataService = inject(FlowsDataService);
|
|
|
|
private readonly userService = inject(UserService);
|
|
|
|
private readonly resetAuthDataService = inject(ResetAuthDataService);
|
|
|
|
// STEP 5 userData
|
|
callbackUser(
|
|
callbackContext: CallbackContext,
|
|
configuration: OpenIdConfiguration,
|
|
allConfigs: OpenIdConfiguration[]
|
|
): Observable<CallbackContext> {
|
|
const { isRenewProcess, validationResult, authResult, refreshToken } =
|
|
callbackContext;
|
|
const { autoUserInfo, renewUserInfoAfterTokenRenew } = configuration;
|
|
|
|
if (!autoUserInfo) {
|
|
if (!isRenewProcess || renewUserInfoAfterTokenRenew) {
|
|
// userData is set to the id_token decoded, auto get user data set to false
|
|
// biome-ignore lint/nursery/useCollapsedIf: <explanation>
|
|
if (validationResult?.decodedIdToken) {
|
|
this.userService.setUserDataToStore(
|
|
validationResult.decodedIdToken,
|
|
configuration,
|
|
allConfigs
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!isRenewProcess && !refreshToken) {
|
|
this.flowsDataService.setSessionState(
|
|
authResult?.session_state,
|
|
configuration
|
|
);
|
|
}
|
|
|
|
this.publishAuthState(validationResult, isRenewProcess);
|
|
|
|
return of(callbackContext);
|
|
}
|
|
|
|
return this.userService
|
|
.getAndPersistUserDataInStore(
|
|
configuration,
|
|
allConfigs,
|
|
isRenewProcess,
|
|
validationResult?.idToken,
|
|
validationResult?.decodedIdToken
|
|
)
|
|
.pipe(
|
|
switchMap((userData) => {
|
|
if (userData) {
|
|
if (!refreshToken) {
|
|
this.flowsDataService.setSessionState(
|
|
authResult?.session_state,
|
|
configuration
|
|
);
|
|
}
|
|
|
|
this.publishAuthState(validationResult, isRenewProcess);
|
|
|
|
return of(callbackContext);
|
|
}
|
|
this.resetAuthDataService.resetAuthorizationData(
|
|
configuration,
|
|
allConfigs
|
|
);
|
|
this.publishUnauthenticatedState(validationResult, isRenewProcess);
|
|
const errorMessage = `Called for userData but they were ${userData}`;
|
|
|
|
this.loggerService.logWarning(configuration, errorMessage);
|
|
|
|
return throwError(() => new Error(errorMessage));
|
|
}),
|
|
catchError((err) => {
|
|
const errorMessage = `Failed to retrieve user info with error: ${err}`;
|
|
|
|
this.loggerService.logWarning(configuration, errorMessage);
|
|
|
|
return throwError(() => new Error(errorMessage));
|
|
})
|
|
);
|
|
}
|
|
|
|
private publishAuthState(
|
|
stateValidationResult: StateValidationResult | null,
|
|
isRenewProcess: boolean
|
|
): void {
|
|
if (!stateValidationResult) {
|
|
return;
|
|
}
|
|
|
|
this.authStateService.updateAndPublishAuthState({
|
|
isAuthenticated: true,
|
|
validationResult: stateValidationResult.state,
|
|
isRenewProcess,
|
|
});
|
|
}
|
|
|
|
private publishUnauthenticatedState(
|
|
stateValidationResult: StateValidationResult | null,
|
|
isRenewProcess: boolean
|
|
): void {
|
|
if (!stateValidationResult) {
|
|
return;
|
|
}
|
|
|
|
this.authStateService.updateAndPublishAuthState({
|
|
isAuthenticated: false,
|
|
validationResult: stateValidationResult.state,
|
|
isRenewProcess,
|
|
});
|
|
}
|
|
}
|