@healthcloudai/hc-login-connector
v0.0.11
Published
Healthcheck Login authentication SDK with TypeScrip and token refresh
Downloads
838
Maintainers
Readme
Healthcheck Login Connector
This library provides a tenant-aware client for patient registration, onboarding, authentication, password reset flows, token refresh, authenticated patient context retrieval, and local auth helper methods.
The connector is built on top of the shared Healthcheck HTTP layer, and the examples
below follow the current behavior implemented in src/client.ts.
Features
- Patient registration with tenant-scoped request payloads
- Generic onboarding step submission through
submitOnboardingStep(...) - Convenience helpers for email verification and SMS verification steps
- Convenience helpers for health profile and address onboarding steps
- Patient login with in-memory access, refresh, and ID token storage
- Password reset initiation and password reset confirmation
- Access token, ID token, tenant, and base URL helper methods
- Token refresh using the current authenticated token state
- Authenticated patient header retrieval through
getUserInfo()andgetHeader() - Built on the shared Healthcheck HttpClient layer
Installation
npm install @healthcloudai/hc-login-connector \
@healthcloudai/hc-httpImport
import { HCLoginClient } from "@healthcloudai/hc-login-connector";
import { FetchClient } from "@healthcloudai/hc-http";Usage
Configuration
Call configure() before any other method.
It stores the tenant configuration locally on the client instance, and the same
configured client should be reused across registration, onboarding, login, refresh,
and authenticated calls.
const httpClient = new FetchClient();
const loginClient = new HCLoginClient(httpClient);
loginClient.configure("demo-tenant", "dev");
// The current source signature also accepts an optional region argument:
// loginClient.configure("demo-tenant", "dev", "region-code");Full API request
configure() does not send an HTTP request.
The configuration example above updates local client state only.
API response
configure() does not receive an API response.
It stores the tenant configuration locally for later requests.
Methods
Get Base URL
Public signature: loginClient.getBaseUrl()
Returns the base URL derived from the current configuration.
const baseUrl = loginClient.getBaseUrl();Full API request
getBaseUrl() does not send an HTTP request.
The usage example above reads the value from local state.
API response
getBaseUrl() returns the currently configured base URL from local state.
https://dev-api-healthcheck.healthcloud-services.com/apiGet Tenant ID
Public signature: loginClient.getTenantId()
Returns the tenant ID currently stored by configure(...).
const tenantId = loginClient.getTenantId();Full API request
getTenantId() does not send an HTTP request.
The usage example above reads the value from local state.
API response
getTenantId() returns the configured tenant ID from local state.
demo-tenantSubmit Onboarding Step
Public signature: loginClient.submitOnboardingStep(step, user, data?, language?)
This is the step-driven onboarding API.
The selected step determines the final shape of Data.User, and TenantID is
injected internally from configure(...).
Callers should provide only the fields relevant to the selected step.
Supported steps:
EMAIL_VERIFYRESEND_EMAIL_VERIFYRESEND_SMS_VERIFYSMS_VERIFYSAVE_HEALTH_PROFILESAVE_ADDRESS
await loginClient.submitOnboardingStep(
"SAVE_HEALTH_PROFILE",
{
Email: "[email protected]",
FirstName: "John",
LastName: "Doe",
BirthDate: "1990-01-01",
Gender: "male",
Race: "White",
Ethnicity: "Not Hispanic or Latino",
Status: 0,
Sex: "Male"
},
"",
"en"
);Full API request
Request sent for the usage example above:
{
"Data": {
"Data": "",
"Step": "SAVE_HEALTH_PROFILE",
"User": {
"Email": "[email protected]",
"TenantID": "demo-tenant",
"FirstName": "John",
"LastName": "Doe",
"BirthDate": "1990-01-01",
"Gender": "male",
"Sex": "Male",
"Status": 0,
"Race": "White",
"Ethnicity": "Not Hispanic or Latino"
},
"Language": "en"
}
}API response
Status:
200{
"Data": "",
"ErrorMessage": null,
"IsOK": true
}Register
Public signature: loginClient.register(email, password, firstName?, lastName?, options?)
Registers a patient for the configured tenant.
TenantID is injected internally from configure(...).
options.attributes can be used to pass arbitrary additional custom fields.
Every key/value pair from options.attributes is forwarded into User.Attributes.
This is the extension point for arbitrary extra registration fields, so the module
does not need to know those field names in advance.
All values inside options.attributes / User.Attributes should be sent as
strings. If a field needs to contain multiple values, serialize those values into
one string value, such as a comma separated list or another separator-separated
list expected by the integration.
verifyEmailCode is a dedicated boolean option that controls whether User.Attributes.VERIFY_EMAIL_CODE is included in the registration payload, depending on whether email verification should be handled through an OTP code.
- If
verifyEmailCodeistrue, the client sendsVERIFY_EMAIL_CODE: "true". - If
verifyEmailCodeisfalseor omitted,VERIFY_EMAIL_CODEis not sent.
await loginClient.register(
"[email protected]",
"ExamplePassword123!",
"John",
"Doe",
{
verifyEmailCode: true,
attributes: {
Specialty: "Cardiology",
NPINumber: "1234567890",
FullName: "John Doe",
PracticeLegalName: "Acme Medical Group",
CurrentTreatments: "Physical Therapy,Blood Pressure Monitoring,Insulin Therapy",
// CurrentTreatments: "Physical Therapy | Blood Pressure Monitoring | Insulin Therapy"
}
}
);Full API request
Request sent for the usage example above:
{
"Data": {
"TenantID": "demo-tenant",
"Credentials": {
"Email": "[email protected]",
"Password": "ExamplePassword123!"
},
"User": {
"FirstName": "John",
"LastName": "Doe",
"Email": "[email protected]",
"Attributes": {
"Specialty": "Cardiology",
"NPINumber": "1234567890",
"FullName": "John Doe",
"PracticeLegalName": "Acme Medical Group",
"CurrentTreatments": "Physical Therapy,Blood Pressure Monitoring,Insulin Therapy",
"VERIFY_EMAIL_CODE": "true"
}
}
}
}API response
Status:
200{
"Data": "",
"ErrorMessage": null,
"IsOK": true
}Notes:
TenantIDis taken from the configured client instance.attributesis the extension point for arbitrary additional registration fields.- The module does not need to know custom attribute names in advance.
- All
attributesvalues should be strings. Multi-value attributes should be serialized into one string value, such as a comma separated list or another integration-specific separator-separated list. verifyEmailCodetakes precedence over any manually providedVERIFY_EMAIL_CODEinsideattributes.
Verify Email
Public signature: loginClient.verifyEmail(email, code, language?, options?)
Convenience wrapper around submitOnboardingStep(...).
The caller provides email, code, an optional language, and optional
verification settings.
VERIFY_EMAIL_CODE handling is aligned with the register(...) method behavior:
when email verification should be handled through an OTP code, the client sends
VERIFY_EMAIL_CODE: "true" inside User.Attributes.
- If
options.verifyEmailCodeistrue, the client sendsVERIFY_EMAIL_CODE: "true". - The value is sent as a string inside
User.Attributes, matching theregister(...)method behavior whenverifyEmailCodeistrue. - If
options.verifyEmailCodeisfalseor omitted,VERIFY_EMAIL_CODEis not sent. - Calling
verifyEmail(...)withoutoptionskeeps OTP email verification disabled by default.
await loginClient.verifyEmail(
"[email protected]",
"123456",
"en",
{
verifyEmailCode: true
}
);Full API request
Request sent for the usage example above:
{
"Data": {
"Data": "123456",
"Step": "EMAIL_VERIFY",
"User": {
"Email": "[email protected]",
"TenantID": "demo-tenant",
"Attributes": {
"VERIFY_EMAIL_CODE": "true"
}
},
"Language": "en"
}
}API response
Status:
200{
"Data": "",
"ErrorMessage": null,
"IsOK": true
}Resend Email Verify
Public signature: loginClient.resendEmailVerify(email, language?, options?)
Convenience wrapper around submitOnboardingStep(...).
The caller provides email, an optional language, and optional verification
settings.
VERIFY_EMAIL_CODE handling is aligned with the register(...) method behavior:
when email verification should be handled through an OTP code, the client sends
VERIFY_EMAIL_CODE: "true" inside User.Attributes.
- If
options.verifyEmailCodeistrue, the client sendsVERIFY_EMAIL_CODE: "true". - The value is sent as a string inside
User.Attributes, matching theregister(...)method behavior whenverifyEmailCodeistrue. - If
options.verifyEmailCodeisfalseor omitted,VERIFY_EMAIL_CODEis not sent. - Calling
resendEmailVerify(...)withoutoptionskeeps OTP email verification disabled by default.
await loginClient.resendEmailVerify(
"[email protected]",
"en",
{
verifyEmailCode: true
}
);Full API request
Request sent for the usage example above:
{
"Data": {
"Data": "",
"Step": "RESEND_EMAIL_VERIFY",
"User": {
"Email": "[email protected]",
"TenantID": "demo-tenant",
"Attributes": {
"VERIFY_EMAIL_CODE": "true"
}
},
"Language": "en"
}
}API response
Status:
200{
"Data": "",
"ErrorMessage": null,
"IsOK": true
}Resend SMS Verify
Public signature: loginClient.resendSmsVerify(email, phone, language?)
Convenience wrapper around submitOnboardingStep(...).
The caller provides email, phone, and an optional language.
await loginClient.resendSmsVerify(
"[email protected]",
"+15555550123",
"en"
);Full API request
Request sent for the usage example above:
{
"Data": {
"Data": "",
"Step": "RESEND_SMS_VERIFY",
"User": {
"Email": "[email protected]",
"TenantID": "demo-tenant",
"Phone": "+15555550123"
},
"Language": "en"
}
}API response
Status:
200{
"Data": "",
"ErrorMessage": null,
"IsOK": true
}Verify SMS
Public signature: loginClient.verifySms(email, phone, code, language?)
Convenience wrapper around submitOnboardingStep(...).
The caller provides email, phone, code, and an optional language.
await loginClient.verifySms(
"[email protected]",
"+15555550123",
"123456",
"en"
);Full API request
Request sent for the usage example above:
{
"Data": {
"Data": "123456",
"Step": "SMS_VERIFY",
"User": {
"Email": "[email protected]",
"TenantID": "demo-tenant",
"Phone": "+15555550123"
},
"Language": "en"
}
}API response
Status:
200{
"Data": "",
"ErrorMessage": null,
"IsOK": true
}Save Health Profile
Public signature: loginClient.saveHealthProfile(profile, language?)
Convenience wrapper around submitOnboardingStep(...).
The caller provides the SAVE_HEALTH_PROFILE input fields, such as Email,
FirstName, LastName, BirthDate, Gender, Race, Ethnicity, Status,
and Sex.
await loginClient.saveHealthProfile({
Email: "[email protected]",
FirstName: "John",
LastName: "Doe",
BirthDate: "1990-01-01",
Gender: "male",
Race: "White",
Ethnicity: "Not Hispanic or Latino",
Status: 0,
Sex: "Male"
});Full API request
Request sent for the usage example above:
{
"Data": {
"Data": "",
"Step": "SAVE_HEALTH_PROFILE",
"User": {
"Email": "[email protected]",
"TenantID": "demo-tenant",
"FirstName": "John",
"LastName": "Doe",
"BirthDate": "1990-01-01",
"Gender": "male",
"Sex": "Male",
"Status": 0,
"Race": "White",
"Ethnicity": "Not Hispanic or Latino"
},
"Language": "en"
}
}API response
Status:
200{
"Data": "",
"ErrorMessage": null,
"IsOK": true
}Save Address
Public signature: loginClient.saveAddress(email, address, language?)
Convenience wrapper around submitOnboardingStep(...).
The caller provides email, an Address, and an optional language.
await loginClient.saveAddress("[email protected]", {
StreetAndNumber: "123 Main St",
Extension: null,
City: "Springfield",
State: "CA",
PostalCode: "90210",
Country: "US"
});Full API request
Request sent for the usage example above:
{
"Data": {
"Data": "",
"Step": "SAVE_ADDRESS",
"User": {
"Email": "[email protected]",
"TenantID": "demo-tenant",
"Address": {
"StreetAndNumber": "123 Main St",
"Extension": null,
"City": "Springfield",
"State": "CA",
"PostalCode": "90210",
"Country": "US"
}
},
"Language": "en"
}
}API response
Status:
200{
"Data": "",
"ErrorMessage": null,
"IsOK": true
}Login
Public signature: loginClient.login(email, password)
login(...) accepts only email and password.
The client builds the full backend Data payload internally, and stores the
returned tokens in memory.
On tenants that require onboarding completion, login may depend on the relevant
onboarding steps already being finished.
await loginClient.login(
"[email protected]",
"ExamplePassword123!"
);Full API request
Request sent for the usage example above:
{
"Data": {
"FirstName": "",
"LastName": "",
"Email": "[email protected]",
"Password": "ExamplePassword123!",
"TenantID": "demo-tenant",
"AppPoolID": "",
"GoogleIdToken": "",
"AppleIdToken": "",
"AppleCode": ""
}
}API response
Status:
200{
"Data": {
"Email": "[email protected]",
"RefreshToken": "eyJ_refresh_token_example",
"AccessToken": "eyJ_access_token_example",
"IDToken": "eyJ_id_token_example",
"EHR": "fhir",
"HasInsurance": false,
"HasIDCard": false,
"HasSelfie": false,
"Attributes": {
"EHR": "fhir"
},
"TenantID": "demo-tenant",
"Expiration": "2030-01-01T00:00:00.000Z",
"Type": 0
},
"ErrorMessage": null,
"IsOK": true
}Reset Password
Public signature: loginClient.resetPassword(email, isPasswordResetWithOTP?)
TenantID is injected automatically from configure(...).
If an ID token is already available, the client may also include an
Authorization header.
await loginClient.resetPassword(
"[email protected]",
true
);Full API request
Request sent for the usage example above:
{
"Data": {
"Email": "[email protected]",
"TenantID": "demo-tenant",
"IsPasswordResetWithOTP": true
}
}Authorization: Bearer eyJ_id_token_example may also be included when an ID token
is already stored.
API response
Status:
200{
"Data": true,
"ErrorMessage": null,
"IsOK": true
}Reset Password Confirm
Public signature: loginClient.resetPasswordConfirm(email, password, code, isPasswordResetWithOTP?)
TenantID is injected automatically from configure(...).
If an ID token is already available, the client may also include an
Authorization header.
await loginClient.resetPasswordConfirm(
"[email protected]",
"ExamplePassword123!",
"123456",
true
);Full API request
Request sent for the usage example above:
{
"Data": {
"Email": "[email protected]",
"TenantID": "demo-tenant",
"Password": "ExamplePassword123!",
"code": "123456",
"IsPasswordResetWithOTP": true
}
}Authorization: Bearer eyJ_id_token_example may also be included when an ID token
is already stored.
API response
Status:
200{
"Data": true,
"ErrorMessage": null,
"IsOK": true
}Refresh Token
Public signature: loginClient.refreshToken()
refreshToken() requires a successful prior login and an available refresh token.
The client sends the stored refresh token, and stores the returned token set in
memory.
await loginClient.refreshToken();Full API request
Request sent for the usage example above:
{
"Data": {
"RefreshToken": "eyJ_refresh_token_example",
"TenantID": "demo-tenant"
}
}API response
Status:
200{
"Data": {
"Email": null,
"RefreshToken": "eyJ_refresh_token_example",
"AccessToken": "eyJ_access_token_example",
"IDToken": "eyJ_id_token_example",
"TenantID": "demo-tenant",
"Expiration": "2030-01-01T00:00:00.000Z",
"Type": 0
},
"ErrorMessage": null,
"IsOK": true
}Get Auth Header
Public signature: loginClient.getAuthHeader()
Returns the authorization headers required for authenticated API requests. This method does not send an HTTP request, and other Healthcheck connectors can reuse the returned header object directly.
const headers = loginClient.getAuthHeader();Full API request
getAuthHeader() does not send an HTTP request.
The usage example above reads the value from local state.
API response
getAuthHeader() returns the current local header object.
{
"Authorization": "Bearer eyJ_id_token_example",
"X-Tenant-ID": "demo-tenant"
}Get User Info
Public signature: loginClient.getUserInfo()
The current implementation calls the patient header endpoint and returns the raw
server response.
It requires a stored ID token, and it currently targets the same endpoint as
getHeader().
const userInfo = await loginClient.getUserInfo();Full API request
getUserInfo() does not send a request body.
API response
Status:
200{
"Data": {
"Record": {
"ID": "record-id-example",
"TenantID": "demo-tenant",
"FirstName": "John",
"LastName": "Doe",
"Email": "[email protected]",
"Phone": "+15555550123",
"BirthDate": "1990-01-01T00:00:00",
"Gender": "male",
"Sex": "Male",
"Race": "White",
"Ethnicity": "Not Hispanic or Latino",
"HasInsurance": false,
"HasIDCard": false,
"HasSelfie": false,
"Address": {
"StreetAndNumber": "123 Main St",
"Extension": null,
"City": "Springfield",
"State": "CA",
"PostalCode": "90210",
"Country": "US"
},
"Attributes": {
"FHIRPatientID": "patient-id-example",
"CompositeID": "composite-id-example",
"VERIFY_EMAIL_CODE": "true"
},
"CompositeID": "composite-id-example",
"FHIRID": "fhir-id-example"
},
"Encounters": null,
"EHR": "fhir",
"PendingActions": [
"ADD_INSURANCE",
"ADD_ID",
"IMPORT_VITALS"
]
},
"ErrorMessage": null,
"IsOK": true
}Get Header
Public signature: loginClient.getHeader()
The current implementation also calls the patient header endpoint.
It requires a stored ID token, and the response shape is effectively the same as
getUserInfo().
await loginClient.getHeader();Full API request
getHeader() does not send a request body.
API response
Status:
200{
"Data": {
"Record": {
"ID": "record-id-example",
"TenantID": "demo-tenant",
"FirstName": "John",
"LastName": "Doe",
"Email": "[email protected]",
"Phone": "+15555550123",
"BirthDate": "1990-01-01T00:00:00",
"Gender": "male",
"Sex": "Male",
"Race": "White",
"Ethnicity": "Not Hispanic or Latino",
"HasInsurance": false,
"HasIDCard": false,
"HasSelfie": false,
"Address": {
"StreetAndNumber": "123 Main St",
"Extension": null,
"City": "Springfield",
"State": "CA",
"PostalCode": "90210",
"Country": "US"
},
"Attributes": {
"FHIRPatientID": "patient-id-example",
"CompositeID": "composite-id-example",
"VERIFY_EMAIL_CODE": "true"
},
"CompositeID": "composite-id-example",
"FHIRID": "fhir-id-example"
},
"Encounters": null,
"EHR": "fhir",
"PendingActions": [
"ADD_INSURANCE",
"ADD_ID",
"IMPORT_VITALS"
]
},
"ErrorMessage": null,
"IsOK": true
}Get Access Token
Public signature: loginClient.getAccessToken()
Returns the current in-memory access token.
const accessToken = loginClient.getAccessToken();Full API request
getAccessToken() does not send an HTTP request.
The usage example above reads the value from local state.
API response
getAccessToken() returns the current local access token value.
eyJ_access_token_exampleGet ID Token
Public signature: loginClient.getIDToken()
Returns the current in-memory ID token.
const idToken = loginClient.getIDToken();Full API request
getIDToken() does not send an HTTP request.
The usage example above reads the value from local state.
API response
getIDToken() returns the current local ID token value.
eyJ_id_token_exampleHow It Works
- Create a shared
HttpClientinstance and a singleHCLoginClient. - Call
configure(...)once to store tenant and environment settings locally. - Call
register(...)if the patient account needs to be created. - Use
submitOnboardingStep(...)or the onboarding helper methods to complete required onboarding steps. - Call
login(...)to authenticate and store the returned access, refresh, and ID tokens in memory. - Use
refreshToken()to replace the current token set when needed. - Use
getAuthHeader(),getAccessToken(),getIDToken(),getUserInfo(), andgetHeader()for authenticated flows after login. - Other Healthcheck connectors can consume
getAuthHeader()instead of managing auth tokens directly.
Notes
configure()stores tenant configuration locally and does not send an HTTP request.TenantIDis injected by the client into tenant-bound register, onboarding, login, refresh, and password requests.register(),verifyEmail(), andresendEmailVerify()all follow the same string-basedUser.Attributes.VERIFY_EMAIL_CODEpattern for OTP email verification flows.saveAddress()accepts anAddress.login()andrefreshToken()both store returned tokens internally for later helper calls.getUserInfo()andgetHeader()both currently call the patient header endpoint.getAuthHeader(),getAccessToken(),getIDToken(),getBaseUrl(), andgetTenantId()return local values and do not perform HTTP requests.- This connector is intended to be reused by other Healthcheck SDK connectors built on the same HTTP layer.
