SMART on FHIR : Benefits and Application through NestJS

An image uploaded to Strapi
An image uploaded to Strapi

Musharraf Ali Khan

Technology

SMART on FHIR : Benefits and Application through NestJS

SMART on FHIR

SMART (Substitutable Medical Applications and Reusable Technologies) is a platform for providing interoperability to medical applications based on FHIR(Fast Healthcare Interoperability Resources) to exchange data amongst them without any concern about formatting and failure of protocols.

Today, SMART on FHIR represents an open, standardized, and practical means of exchanging data among EHRs, health system sites, and data sources.

Untitled design (12).png

Benefits of SMART on FHIR

For modern medical systems, SMART on FHIR is becoming a requirement worldwide because of its various capabilities and benefits :

  1. Interoperability: Smart on FHIR allows healthcare applications to seamlessly exchange data, enabling interoperability between different systems and organizations. It promotes the sharing of patient information and facilitates coordinated care across various healthcare settings.

  2. App ecosystem: Smart on FHIR fosters the development of an app ecosystem where third-party developers can create innovative healthcare applications. These apps can integrate with electronic health records (EHRs), clinical decision support systems, and other health IT systems, enhancing the functionality and usability of these systems.

  3. Improved user experience: By leveraging FHIR resources and SMART's user interface framework, Smart on FHIR provides a consistent and user-friendly experience for healthcare professionals. It enables developers to create intuitive and customizable interfaces that can be accessed from various devices, improving workflow efficiency and user satisfaction.

  4. Enhanced clinical decision support: Smart on FHIR enables the integration of clinical decision support (CDS) tools directly into EHR systems. This integration allows real-time access to patient data, enabling CDS systems to provide relevant information, alerts, reminders, and evidence-based recommendations to healthcare providers, ultimately improving the quality of care and patient outcomes.

  5. Patient engagement: Smart on FHIR empowers patients by enabling them to access their health data through secure and patient-facing applications. Patients can view their medical records, track their health progress, and actively participate in their care management. This increased engagement can lead to better patient outcomes and improved patient satisfaction.

  6. Security and privacy: Smart on FHIR follows industry-standard security protocols and ensures the protection of patient health information. It utilises OAuth 2.0 authentication, which allows secure and authorised access to health data. The standard also supports granular access controls, ensuring that sensitive information is shared only with authorised individuals or applications.

  7. Rapid app development and deployment: The Smart on FHIR framework simplifies the development and deployment of healthcare applications. Developers can leverage existing FHIR resources and SMART's standardised APIs, saving time and effort in building interoperable solutions. This streamlined process promotes rapid innovation and adoption of new applications.

  8. Research and population health management: Smart on FHIR supports population health management initiatives by enabling the aggregation and analysis of health data from multiple sources. Researchers can use the framework to develop applications that analyse population health trends, conduct clinical trials, and generate real-world evidence for healthcare research and policy-making.

  9. Continuity of care: Smart on FHIR facilitates seamless data exchange between healthcare systems, ensuring that patient information is accessible across different care settings. This promotes care continuity, reduces duplicate tests and procedures, and improves care coordination among healthcare providers.

  10. Scalability and future-proofing: Smart on FHIR is designed to be scalable and adaptable to evolving healthcare needs and technologies. The use of FHIR resources provides a flexible foundation for integrating new data elements and accommodating future advancements in healthcare standards and protocols.

It's important to note that while Smart on FHIR offers numerous benefits, the successful implementation and realisation of these benefits depend on factors such as proper system integration, data governance, and user adoption.

Implementing SMART on FHIR using NestJS

Starting with application of SMART on FHIR with NestJS we are going to create Oauth 2.0 authentication strategy first :

   const buffer = crypto.randomBytes(size);
   return buffer.toString('base64');
 }

 generateSecretHash(key) {
   const salt = crypto.randomBytes(8).toString('hex');
   const buffer = crypto.scryptSync(key, salt, 64) as Buffer;
   return `${buffer.toString('hex')}.${salt}`;
 }

Use crypto and bcrypt libraries for creating ClientId and ClientSecret for users registering for Oauth 2.0.

   const clientId = this.generateKey();
   const clientSecret = this.generateSecretHash(clientId);
   const username =
     data.email.substring(0, 3) +
     String(Math.floor(Math.random() * 90000) + 10000);
   const secretCode = String(Math.floor(Math.random() * 900000) + 100000);
   const dataObj = {
     email: data.email,
     password: await bcrypt.hash(data.password, 10),
     clientId: clientId,
     clientSecret: clientSecret,
     username: username,
     secretCode: secretCode,
   };
   const res = await this.oauth2Repository.save({ ...dataObj });
   if (res) {
     delete res.password;
     delete res.secretCode;
     this.smartMailService.registerEmail({ ...res, password: data.password });
     return { message: 'Email with credentials sent to registered email!' };
   }
   return new UnprocessableEntityException(
     'Unable to register client for Smart Oauth!',
   );
 }

Register client using email and password and generating clientId and secret through generating functions above.

Once registered use the Oauth 2.0 credentials for authentication and provide callback URL with updated secret code for generating SMART on FHIR based authentication token

   const found = await this.oauth2Repository.findOne({
     where: {
       username: data.username,
       clientId: data.clientId,
       clientSecret: data.clientSecret,
     },
   });
   if (!!found) {
     const clientSecretCheck = this.compareKeys(found.clientSecret,data.clientSecret)
     if(clientSecretCheck)
     return {
       redirectUri:
         process.env.BASE_URL +
         'smart/token/' +
         found.id +
         '/' +
         +found.secretCode,
     };
   }
   return new NotFoundException(
     'No Resource found against username, clientId or clientSecret',
   );
 }

compareKeys(storedKey, suppliedKey) {
   const [hashedPassword, salt] = storedKey.split('.');

   const buffer = crypto.scryptSync(suppliedKey, salt, 64) as Buffer;
   return crypto.timingSafeEqual(Buffer.from(hashedPassword, 'hex'), buffer);
 }

The callback URL provided can be used to retrieve an authentication token for using SMART based endpoints

   const details = await this.oauth2Repository.findOne({
     where: { id: data.oauthId, secretCode: data.secretCode },
   });
   if (details) {
     const oauthScopes = await this.oauthHasScopesRepository.find({
       where: { oauthId: details.id },
       relations: { scope: true },
     });
     const scopesAssigned = oauthScopes.map((item) => {
       return item.scope.scope;
     });
     const payload = {
       oauthId: details.id,
       username: details.username,
       email: details.email,
       secretCode: details.secretCode,
       scopes: scopesAssigned.length ? scopesAssigned : [],
     };
     const newSecretCode = String(Math.floor(Math.random() * 900000) + 100000);
     await await this.oauth2Repository.update(
       { id: details.id },
       { secretCode: newSecretCode },
     );
     return {

oauthId: details.id,
       accessToken: await this.jwtService.sign(payload),
       refreshToken: await this.generateRefreshToken(payload),
     };
   }
   return new NotFoundException('No data found with given credentials!');
 }


In the context of SMART on FHIR, scopes refer to the permissions or access levels granted to an application when requesting access to a user's health data. Scopes determine what actions an application can perform and what resources it can access. They help define the boundaries of access and ensure appropriate security and privacy measures are in place. Here are some commonly used scopes in SMART on FHIR:

Examples include:

  • patient/*r: Read access to all data for a specific patient.
  • patient/Condition.read: Read access to the patient's conditions or diagnoses.
  • patient/MedicationOrder.write: Write access to create or modify medication orders for the patient.
 Injectable,
 CanActivate,
 ExecutionContext,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ClientProxyFactory, Transport } from '@nestjs/microservices';
import { timeout } from 'rxjs';

@Injectable()
export class SmartAuthorizationGuard implements CanActivate {
 constructor(private reflector: Reflector) {}
 async canActivate(context: ExecutionContext) {
   const res = ClientProxyFactory.create({
     transport: Transport.TCP,
     options: { host: 'localhost', port: 4012 },
   });
   const scopes = this.reflector.get<string[]>(
     'scopes',
     context.getHandler(),
   );
   const request = context.switchToHttp().getRequest();
   let data = await res.send({ purpose: 'smart-authorize' }, { scopes, user: request.user }).pipe(timeout(10000)).toPromise();
   return data;
 }
}

We can create an auth guard which can check for various scope based permissions for our SMART on FHIR based endpoints:

 @UseGuards(AuthGuard('jwt'), SmartAuthorizationGuard)
 @ApiBearerAuth('access-token')
 @Get(':patientMrn')
 findPatientMrn(@Param() param: PatientMrnDto) {
   return this.smartPatientService.findPatientMrn(param);
 }

 @Scopes('patient/*r')
 @UseGuards(AuthGuard('jwt'), SmartAuthorizationGuard)
 @ApiBearerAuth('access-token')
 @Get('patient-allergies/:patientMrn')
 findPatientAllergies(@Param() param: PatientMrnDto) {
   return this.smartPatientService.findPatientAllergies(param);
 }

 @Scopes('patient/*r')
 @UseGuards(AuthGuard('jwt'), SmartAuthorizationGuard)
 @ApiBearerAuth('access-token')
 @Get('patient-health-conditions/:patientMrn')
 findPatientConditions(@Param() param: PatientMrnDto) {
   return this.smartPatientService.findPatientConditions(param);
 }

Conclusion

In conclusion, SMART on FHIR (Fast Healthcare Interoperability Resources) is a powerful and transformative framework that brings numerous benefits to the healthcare industry. By combining the SMART platform with FHIR resources, it enables secure and interoperable healthcare applications that improve the delivery of care and enhance the patient experience.

The interoperability provided by SMART on FHIR promotes seamless data exchange and coordination among healthcare systems and applications. It breaks down data silos and enables the sharing of patient information, leading to better care coordination, reduced errors, and improved patient outcomes. The standardised approach to accessing health data through FHIR resources ensures consistency and facilitates the development of innovative applications that leverage patient information effectively.

An image uploaded to Strapi
Musharraf Ali Khan

Hi there, the combination of SMART on FHIR and NestJS presents a remarkable opportunity to bridge the gap between healthcare systems and improve patient outcomes. By harnessing the potential of this powerful duo, healthcare professionals can streamline workflows, access comprehensive patient data, and deliver personalized care like never before. Embrace the future of healthcare interoperability with SMART on FHIR and NestJS, and witness the transformative impact it can have on the way we practice medicine. Thank you for your time