async verifyAccessToken()

in src/smartHandler.ts [99:177]


    async verifyAccessToken(request: VerifyAccessTokenRequest): Promise<UserIdentity> {
        let decodedToken: any;
        if (this.config.tokenIntrospection) {
            decodedToken = await introspectJwtToken(
                request.accessToken,
                this.config.expectedAudValue,
                this.config.expectedIssValue,
                this.config.tokenIntrospection,
            );
        } else if (this.jwksClient) {
            decodedToken = await verifyJwtToken(
                request.accessToken,
                this.config.expectedAudValue,
                this.config.expectedIssValue,
                this.jwksClient,
            );
        } else {
            throw Error(
                `Authorization configuration not properly set up. Either 'tokenIntrospection' or 'jwksEndpoint' must be present`,
            );
        }

        const fhirUserClaim = get(decodedToken, this.config.fhirUserClaimPath);
        const patientContextClaim = get(decodedToken, `${this.config.launchContextPathPrefix}patient`);
        const fhirServiceBaseUrl = request.fhirServiceBaseUrl ?? this.apiUrl;

        // get just the scopes that apply to this request
        const scopes = getScopes(decodedToken[this.config.scopeKey]);
        const usableScopes = filterOutUnusableScope(
            scopes,
            this.config.scopeRule,
            request.operation,
            this.isUserScopeAllowedForSystemExport,
            request.resourceType,
            request.bulkDataAuth,
            patientContextClaim,
            fhirUserClaim,
        );
        if (!usableScopes.length) {
            logger.warn('User supplied scopes are insufficient', {
                usableScopes,
                operation: request.operation,
                resourceType: request.resourceType,
            });
            throw new UnauthorizedError('access_token does not have permission for requested operation');
        }
        const userIdentity: UserIdentity = clone(decodedToken);

        if (request.bulkDataAuth) {
            if (!userIdentity.sub) {
                logger.error('A JWT token is without a `sub` claim; we cannot process the bulk action without one.');
                throw new UnauthorizedError('User does not have permission for requested operation');
            }
            if (
                !usableScopes.some((scope: string) => {
                    return scope.startsWith('system');
                })
            ) {
                // if requestor is relying on the "user" scope we need to verify they are coming from the correct endpoint & resourceType
                const fhirUser = getFhirUser(fhirUserClaim);
                if (
                    fhirUser.hostname !== fhirServiceBaseUrl ||
                    !this.bulkDataAccessTypes.includes(fhirUser.resourceType)
                ) {
                    throw new UnauthorizedError('User does not have permission for requested operation');
                }
            }
        }

        if (fhirUserClaim && usableScopes.some((scope) => scope.startsWith('user/'))) {
            userIdentity.fhirUserObject = getFhirUser(fhirUserClaim);
        }
        if (patientContextClaim && usableScopes.some((scope) => scope.startsWith('patient/'))) {
            userIdentity.patientLaunchContext = getFhirResource(patientContextClaim, fhirServiceBaseUrl);
        }
        userIdentity.scopes = scopes;
        userIdentity.usableScopes = usableScopes;
        return userIdentity;
    }