Skip to main content

@axinom/mosaic-user-auth library

Introduction

@axinom/mosaic-user-auth is a React library that wraps the core functionality in the User Service that is related to frontend end-user applications. Developers can use the methods provided by this library to perform all end-user authenticated operations such as signing in, signing out, access token handling etc.

UserServiceProvider

UserServiceProvider is a React Provider which has 3 properties. It provides the User Service Client which can be retrieved using the useUserService hook.

  • userAuthConfig - Configuration for the User Service Auth API. This is an object of UserAuthConfig type.
  • userServiceConfig - Configuration for the User Service GraphQL API. This is an object of UserServiceConfig type.
  • tokenRenewalMethod - Token Renewal method the application want to use. This is a value from TokenRenewalMethod enumeration.

UserAuthConfig

interface UserAuthConfig {
userAuthEndpointUrl: string;
tenantId: string;
environmentId: string;
applicationId: string;
}
PropertyDescription
userAuthEndpointUrlURL of the User Service authentication endpoint.
tenantIdThe tenant ID connected to the end-user application. This is the tenant which the User Service Application is registered against.
environmentIdThe environment ID connected to the end-user application. This is the environment which the User Service Application is registered against.
applicationIdThe ID of the Application created in the User Service configuration.

UserServiceConfig

interface UserAuthConfig {
userServiceEndpointUrl: string;
}
PropertyDescription
userServiceEndpointUrlURL of the User Service GraphQL endpoint.

TokenRenewalMethod

ValueDescription
PRE_EMPTIVEThe token is continuously renewed just before expiry. A TokenChangedCallback can be registered using addTokenChangedHandler method to get notified when the token changes.
ON_DEMANDThe token is renewed only if needed upon calling getToken method.

Usage

The UserServiceProvider should be used as a context provider for the react app, at the top of the component hierarchy. This way we can ensure that all child components will have access to the UserServiceClient. Ideally, these properties can be retrieved through environment variables.

const userAuthConfig = {
userAuthEndpointUrl: 'https://id.ottstream.com',
tenantId: 'ace73f47-b654-43e3-bc23-a7ba83c6ea63',
environmentId: '559d0282-2e64-430c-8c4d-93f1777bba07'
applicationId: 'd5091350-4868-4efa-b508-f7438d910a70'
}

const userServiceConfig = {
userServiceEndpointUrl = 'https://user.service.eu.axinom.net'
}

<UserServiceProvider
userAuthConfig={userAuthConfig}
userServiceConfig={userServiceConfig}
tokenRenewalMethod={TokenRenewalMethod.PRE_EMPTIVE}
>
<App />
</UserServiceProvider>

UserServiceClient

UserServiceClient is an object instance created through the UserServiceProvider which provides a set of methods to perform tasks related to the User Service such as sign in, sign out, create user profile etc.

The instance created through the UserServiceProvider can be retrieved through the hook useUserService.

Interfaces

The library makes use of the following interfaces to structure data in its methods.

Interface NameDescription
UserAuthConfigConfiguration for the user service auth API.
UserServiceConfigConfiguration for the user service API.
UserTokenRepresents the information in a User Token.
TokenResponseResponse for a getToken request.
SignInRequestRepresents the information required to perform a username/password Sign In flow.
UserSignUpRequestRepresents the information required for a new user sign up.
CheckUserSignUpOtpRequestRepresents information required to check if a User Sign Up OTP is valid.
CompleteUserSignUpRequestRepresents the information required to verify a new user sign up.
CheckPasswordResetOtpRequestRepresents information required to check if a Password Reset OTP is valid.
CheckPasswordResetOtpRequestRepresents the require information for Complete Password Reset request.
AuthenticateEndUserApplicationRequestRepresents the information required to authenticate an End-User Application.
EndUserApplicationTokenRepresents an End-User Application Access Token.
AuthenticateEndUserApplicationResponseResponse for a authenticateEndUserApplication request.

UserAuthConfig

UserAuthConfig interface holds the configuration for the User Service Auth API.

interface UserAuthConfig {
userAuthEndpointUrl: string;
tenantId: string;
environmentId: string;
applicationId: string;
}

UserServiceConfig

UserServiceConfig interface holds the configuration for the User Service API.

interface UserServiceConfig {
userServiceEndpointUrl: string;
}

UserToken

UserToken interface holds the information related to a User Token that is returned by the User Service Auth API.

interface UserToken {
tenantId: string;
environmentId: string;
applicationId: string;
userId: string;
profileId: string;
email: string | null;
name: string | null;
extensions?: unknown;
accessToken: string;
expiresInSeconds: number;
}

UserProfile

UserProfile interface contains information related to a User Profile.

interface UserProfile {
id: string;
displayName: string;
profilePictureUrl?: string;
profileData?: unknown;
defaultProfile: boolean;
}

TokenResponse

TokenResponse interface stores the information that will be returned by a call to getToken method.

interface TokenResponse {
code: 'SUCCESS' | 'ERROR';
message?: string;
userToken?: UserToken;
userProfile?: UserProfile;
/**
* This will indicate the next automatic token renewal timestamp when the
* `PRE_EMPTIVE` token renewal method is configured on the `UserServiceProvider`.
*
* For `ON_DEMAND` token renewal method, this value can be dismissed.
*/
nextTokenRenewalAt?: Date;
}

SignInRequest

SignInRequest interface represents the information required by the signIn method to perform a Sign In request using the username/password Sign In flow.

interface SignInRequest {
email: string;
password: string;
}

UserSignUpRequest

UserSignUpRequest interface represents the information required by the initiateUserSignUp method which will start the user sign up process.

interface UserSignUpRequest {
email: string;
password: string;
}

CheckUserSignUpOtpRequest

CheckUserSignUpOtpRequest interface represents the information required by checkUserSignUpOTP method which will check if a given User Sign Up OTP is valid.

interface CheckUserSignUpOtpRequest {
signUpOtp: string;
}

CompleteUserSignUpRequest

CompleteUserSignUpRequest interface represents the information required by completeUserSignUp method which will complete the User Sign Up flow.

interface CompleteUserSignUpRequest {
signUpOtp: string;
password?: string;
}

CheckPasswordResetOtpRequest

CheckPasswordResetOtpRequest interface represents the information required by checkResetPasswordOTP method which will check if a given Reset Password OTP is valid.

interface CheckPasswordResetOtpRequest {
resetOtp: string;
}

CompletePasswordResetRequest

CompletePasswordResetRequest interface represents the information required by completeResetPassword method which will complete the Reset Password flow.

interface CompletePasswordResetRequest {
resetOtp: string;
newPassword: string;
}

AuthenticateEndUserApplicationRequest

AuthenticateEndUserApplicationRequest interface represents the information required by authenticateEndUserApplication method to authenticate an end-user application with User Service.

interface AuthenticateEndUserApplicationRequest {
tenantId: string;
environmentId: string;
applicationId: string;
applicationKey: string;
}

EndUserApplicationToken

EndUserApplicationToken holds the information related to an End-User Application Access Token.

interface EndUserApplicationToken {
accessToken: string;
expiresInSeconds: number;
tokenType: string;
}

AuthenticateEndUserApplicationResponse

AuthenticateEndUserApplicationResponse interface represents the response data returned by authenticateEndUserApplication method.

interface AuthenticateEndUserApplicationResponse {
code: 'SUCCESS' | 'ERROR';
message?: string;
endUserApplicationToken?: EndUserApplicationToken;
}

Methods

The UserServiceClient provides the following methods.

Method NameDescription
getTokenReturns a access token. The method will ensure to avoid unnecessary API calls by caching valid tokens. It is not recommended to save the token for later use. When in need of a token, call this method to get a new token.
addTokenChangedHandlerAdds an event handler that will be invoked whenever a new token response is loaded from the backend.
removeTokenChangedHandlerRemoves an event handler for the TokenChanged event
getIdpConfigurationsReturns an array of IDP Configurations that are configured for the application. The authentication URL for IDPs will be sent along with this, which the frontend app should navigate to perform the sign in. This list will exclude connections for provider id AX_AUTH as it is used for user sign-up and sign-in flows.
logoutUserLogs out the user.
initiateUserSignUpInitiates the process to register a new user for the application. To use this flow, an IDP connection for the provider managed IDP AxAuth must be configured.
checkUserSignUpOTPChecks if a given User Sign-Up OTP Code is valid.
completeUserSignUpCompletes a user sign up process using the AxAuth IDP.The user needs to input the OTP along with a password (if not provided earlier) to finish the process.
signInStarts the Sign-In flow for signed up users using the AxAuth IDP configured for the application. This sign in is executed using username/password Sign In flow.
initiateResetPasswordInitiates the process of resetting the password for a self signed up user through AxAuth. This will initiate the call to the webhook configured in AxAuth to send the generated OTP.
checkResetPasswordOTPChecks if a given Reset Password OTP Code is valid.
completeResetPasswordCompletes the password reset flow for a user registered using the AxAuth IDP. The user needs to input the OTP along with a new password to finish the process.
setActiveProfileSets a given profile ID as the active profile.
getUserProfileReturns user profile details for a given ID.
getUserProfilesReturns all user profiles for a given user.
createUserProfileCreates a new user profile for a user.
updateUserProfileUpdate user profile for a given ID.
deleteUserProfileDeletes a user profile for a given ID.
authenticateEndUserApplicationAuthenticates an end-user application and returns an Application Token. This token can be used within the application to make requests to end-user facing APIs exposed by Mosaic Services. (i.e. query subscription plans from the Billing Service.)

getToken

getToken method can be used to fetch the user access token from User Service after the authentication is completed. If a User Token Enrichment Webhook is defined for the Application, that will be called at this point, and the returned user access token will contain the additional information added under the extensions property.

Usage
import { TokenResponse, useUserService } from '@axinom/mosaic-user-auth';

const {getToken} = useUserService();
const [tokenResponse, setTokenResponse] = useState<TokenResponse | null>(
null,
);
setTokenResponse(await getToken());

getToken returns a TokenResponse object.

addTokenChangedHandler

addTokenChangeHandler can be used as an event listener for the frontend to be notified whenever a new token is loaded from User Service.

Usage
import { TokenResponse, useUserService } from '@axinom/mosaic-user-auth';

const {getToken, addTokenChangedHandler} = useUserService();
const [tokenResponse, setTokenResponse] = useState<TokenResponse | null>(
null,
);
useEffect(() => {
(async () => {
setTokenResponse(await getToken());
})();
}, [addTokenChangedHandler, getToken]);

Using addTokenChangeHandler in the dependency list like above when calling getToken from within a useEffect block will make the getToken method to be called whenever the token is changed and refresh it.

removeTokenChangedHandler

removeTokenChangedHandler can be used to remove the event handler from the TokenChanged event.

Usage
import { TokenResponse, useUserService } from '@axinom/mosaic-user-auth';

const {getToken, removeTokenChangedHandler} = useUserService();
const [tokenResponse, setTokenResponse] = useState<TokenResponse | null>(
null,
);
useEffect(() => {
(async () => {
setTokenResponse(await getToken());
})();
}, [removeTokenChangedHandler, getToken]);

getIdpConfigurations

An end-user application may retrieve all the available IDP Connections by calling getIdpConfigurations method.

Usage
import { IdpConfiguration, useUserService } from '@axinom/mosaic-user-auth';

const { getIdpConfigurations } = useUserService();
const [idpConfigurations, setIDPConfigurations] = useState<
IdpConfiguration[]
>([]);

useEffect(() => {
(async () => {
const idpConfigs = await getIdpConfigurations(
`app.ottstream.com`,
);
setIDPConfigurations(idpConfigs);
})();
}, [getIdpConfigurations]);

logoutUser

When logoutUser is called from an end-user application, it will remove any authentication related cookies(AX_REFRESH_TOKEN) from the browser and remove the user token from User Service backend.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { logoutUser } = useUserService();

await logoutUser();

logoutUser can be ideally called from a onClick event of Sign Out button.

initiateUserSignUp

The user sign up flow consists of two steps. First the application needs to make an initiateUserSignUp request, which will create a record with the user’s email address and generate a Sign Up OTP.

initiateUserSignUp returns a UserSignUpResponse object.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { initiateUserSignUp } = useUserService();

const signUpResponse = await initiateUserSignUp(`app.ottstream.com/signup`, {email, password});

checkUserSignUpOTP

After initiateUserSignUp is called, the AxAuth Service generates Sign Up OTP for against the user’s email address. Frontend applications can use checkUserSignUpOTP method to check if any given OTP code is valid, before making the call to completeUserSignUp method.

This is not a mandatory call, and can be done at the developer’s discretion to make the user experience more seamless.

checkUserSignUpOTP returns a CheckUserSignUpOtpResponse where the isOtpValid property can be extracted from.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { checkUserSignUpOTP } = useUserService();

const { isOtpValid } = await checkUserSignUpOTP('app.ottstream.com', { signUpOtp });

completeUserSignUp

The second and final step of the user sign up flow is to call completeUserSignUp method. This call takes the Sign Up OTP as an argument, and a password if a password was not provided at the initiateUserSignUp stage. (If no password was provided at either in the first step or this, an error will be raised.) This call will mark the newly sign up user account as verified in the backend, and make it available for future use.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { completeUserSignUp } = useUserService();

const completeUserSignUpResponse = await completeUserSignUp({signUpOtp, password});

signIn

The signIn method must be used when a user that was registered through AxAuth is signing in to the application.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { signIn } = useUserService();

const handlesSignIn = async(event: React.FormEvent<HTMLFormElement>): Promise<void> => {
event.preventDefault();
const signInResponse = await signIn({
email: email,
password: password
});
if (signInResponse.code === SignInResponseCode.SUCCESS) {
window.location.assign('/');
} else {
setError(`Unable to Sign In. ${signInResponse.details?.error ?? signInResponse.message}`)
}
}

The handleSignIn method in the example could be called from the onClick event of the Sign-In button.

initiateResetPassword

The application developers can use initiateResetPassword method when implementing password reset feature for AxAuth users. This is the first step of a two step process where a Password Reset OTP would be generated against the user’s email.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { initiateResetPassword } = useUserService();

const initiatePasswordReset = async(event: React.FormEvent<HTMLFormElement>): Promise<void> => {
event.preventDefault();
const initiatePasswordResetResponse = await initiateResetPassword(`${ottstream_APP_BASE_URL}/reset-password`, email);
if (initiatePasswordResetResponse.code === PasswordResponseCode.SUCCESS) {
window.location.assign('/complete-reset-password');
} else {
setError(initiatePasswordResetResponse.message ?? 'Error resetting password.');
}
}

The initiatePasswordReset method in the example could be called from the onClick event of the Forgot Password button.

checkResetPasswordOTP

Application developers may use the checkResetPasswordOTP method to validate if a given Password Reset OTP is valid. checkResetPasswordOTP returns a CheckPasswordResetOtpResponse where the isOtpValid property can be extracted from.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { checkResetPasswordOTP } = useUserService();

const { isOtpValid } = await checkResetPasswordOTP('app.ottstream.com', { resetOtp });

completeResetPassword

The second and final step of password reset flow is to call the completeResetPassword method, along with the Password Reset OTP.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { completeResetPassword } = useUserService();

const completePasswordReset = async(event: React.FormEvent<HTMLFormElement>): Promise<void> => {
event.preventDefault();
const completePasswordResetResponse = await completeResetPassword({newPassword: password, resetOtp: otp});
if (completePasswordResetResponse.code === PasswordResponseCode.SUCCESS) {
window.location.assign('/login');
} else {
setError(completePasswordResetResponse.message ?? 'Error resetting password.');
}
}

The completePasswordReset method in the example could be called from the onClick event of the Confirm Password button.

setActiveProfile

In a application where a user can have multiple user profiles, the setActiveProfile method can be used to set the active profile for a given session. This profile will be attached to access token and will be sent along with any subsequent requests to end-user services.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { setActiveProfile } = useUserService();

const handleSelectProfileClick = async (profileId: string) => {
await setActiveProfile(profileId);
history.replace('/');
};

The handleSelectProfileClick method in the example could be called from the onClick event of a Select Profile button.

getUserProfile

Application developers can use getUserProfile to retrieve profile related information by providing a profileId. getUserProfile returns a UserProfile object.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { getUserProfile } = useUserService();

const userProfile = await getUserProfile(profileId);

getUserProfiles

getUserProfiles method can be used to retrieved all user profiles for a specific signed in user. getUserProfiles returns an array of UserProfile objects.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { getUserProfiles } = useUserService();

const userProfiles = await getUserProfiles();

createUserProfile

This method can be used to create a new user profile for a user.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { createUserProfile } = useUserService();

const handleAddProfileClick = async () => {
await createUserProfile(displayName);
};

updateUserProfile

This method can be used to update any profile related information for a user.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { updateUserProfile } = useUserService();

const [userProfiles, setUserProfiles] = useState<UserProfile[] | undefined>(
undefined,
);

const handleEditProfileClick = async (userProfileToUpdate: UserProfile) => {
const profileIndex = userProfiles?.findIndex(
(profile) => profile.id === userProfileToUpdate.id,
);

if (profileIndex !== undefined) {
const updatedUserProfiles = [...(userProfiles ?? [])];
updatedUserProfiles[profileIndex] = {
...updatedUserProfiles[profileIndex],
...userProfileToUpdate,
profilePictureUrl: `https://avatars.dicebear.com/api/bottts/${tokenResponse?.userToken?.userId}-${userProfileToUpdate.displayName}.svg`,
};

setUserProfiles(updatedUserProfiles);
}

await updateUserProfile(userProfileToUpdate);
};

deleteUserProfile

This method can be used to delete a user profile.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { updateUserProfile } = useUserService();

const [userProfiles, setUserProfiles] = useState<UserProfile[] | undefined>(
undefined,
);

const handleDeleteProfileClick = async (profileIdToDelete: string) => {
setUserProfiles(
userProfiles?.filter((profile) => profile.id !== profileIdToDelete),
);

await deleteUserProfile(profileIdToDelete);
};

authenticateEndUserApplication

There can be instances where the application developers need to display certain information retrieved from an end-user service, without having a signed in user.

For example, the application needs to list down all the available subscription plans a user can select from when a user registers for the service. At this point, there is no user signed in, but a valid authorization token is required to make the GraphQL call to the Subscription service. Application Tokens can be used for this purpose.

The idea is that just like a user is authenticated, an Application registered in the User Service can be authenticated and in return an access token tailor made for an end-user application can be received. This token can then be used to call any end-user facing GraphQL services, that does not require a signed in user.

authenticateEndUserApplication returns an AuthenticateEndUserApplicationResponse. A EndUserApplicationToken object can be extracted through the endUserApplicationToken property.

Usage
import { useUserService } from '@axinom/mosaic-user-auth';

const { authenticateEndUserApplication } = useUserService();

const {endUserApplicationToken} = await authenticateEndUserApplication({tenantId, environmentId, applicationId, applicationKey});