This will run a server listening on port 3000. It's set up to use OTP at the minute, I need to add username/password to the test app, but that also needs a way to switch configs so putting it off until I get the integration test code completed as I'm just reusing all the test app code for it.
[x] naming in auth system: change the extremely verbose AuthenticationSystemFoo to AuthFoo, as it is extremely onerous to type
[x] naming of internal typings of events in auth system (TEvent) and the inferred typing of events (from EventsFrom<typeof model>), latter use above convention (AuthEvent), use better naming for internal types
[x] Errors: currently there is a union type of errors. Ideally would be something like AuthError<"ERROR_NAME"> and I'd get inference, but that's not going to happen so change this to an enum to stop accidentally writing the wrong error code when the codes are similar.TS doesn't support Rust-like parametric enums, so this is a non-starter
[x] Errors: once in enum, make the naming better -- currently a lot of them are just the name of the type, which would be fine (could just use error: true|false in the context) except that the incorrect OTP error (which includes the number of remaining tries and has to be dynamic, using a template literal type) messes up everything (and assumption would be the remaining tries would also need to be active for the reset password code as well).TS doesn't support Rust-like parametric enums, so this is a non-starter
[x] Several events have a REVIEW flag on them, where I want to see if we can be more specific about the type of error. This would help to a indicate better what the auth system should do and b allow for more informative errors for end users.this to be done in new PRs, fix one-by-one based on usage
So
Add a new package (@thingco/authentication) to prevent stepping on the existing package.
This has a much simpler system: no async requests, very little config for the provider. The system simply says which state the user is in, and the user sends messages to change the state.
This has a much more complex React implmentation: each state has a corresponding hook. That hook accepts a callback function. That hook exposes:
a function to make use of the callback and send appropriate messages
an isLoading flag for when the callback is processing
an isActive flag to say whether the state is actually currently active
an error, which is either null or one of AuthenticationSystemError string literal types
optionally, other callbacks that allow for extra messages to be sent (request a new password, or go back to previous state)
The hooks are tested to ensure that each exposed state has a corresponding hook, and that each hook can send all events specified for that state in the system.
The system is tested using model tests to ensure that a path to every state exists if the expected messages are sent, and that the system context contains the correct values at any one time.
So:
external peer dependencies are react, xstate and @xstate/react
internal (as in thingco internal) peer dependencies are @thingco/logger
exports are
the createAuthenticationSystem constructor function, which accepts a config object specifying the loginFlowType ("OTP" or "USERNAME_PASSWORD") and the deviceSecurityType ("NONE", "PIN" or "BIOMETRIC", though the latter has no implementations and probably needs to be dropped for now)
the AuthenticationSystemProvider, which accepts the result of createAuthenticationSystem as a prop.
a hook for each state, eguseAwaitingOtpInput
The library does not know anything about how the callbacks work, only what shape the functions are to be. So for example
https://user-images.githubusercontent.com/573694/131142246-aa3b87e7-e0c1-4f3a-846a-c7b94aa164e1.mp4
To view a test of this:
This will run a server listening on port 3000. It's set up to use OTP at the minute, I need to add username/password to the test app, but that also needs a way to switch configs so putting it off until I get the integration test code completed as I'm just reusing all the test app code for it.
resolves #56 resolves #50 resolves #14 resolves #57
[x] model tests for pin flow
[x] naming in auth system: change the extremely verbose
AuthenticationSystemFoo
toAuthFoo
, as it is extremely onerous to type[x] naming of internal typings of events in auth system (
TEvent
) and the inferred typing of events (fromEventsFrom<typeof model>
), latter use above convention (AuthEvent
), use better naming for internal types[x]
Errors: currently there is a union type of errors. Ideally would be something likeTS doesn't support Rust-like parametric enums, so this is a non-starterAuthError<"ERROR_NAME">
and I'd get inference, but that's not going to happen so change this to an enum to stop accidentally writing the wrong error code when the codes are similar.[x]
Errors: once in enum, make the naming better -- currently a lot of them are just the name of the type, which would be fine (could just useTS doesn't support Rust-like parametric enums, so this is a non-startererror: true|false
in the context) except that the incorrect OTP error (which includes the number of remaining tries and has to be dynamic, using a template literal type) messes up everything (and assumption would be the remaining tries would also need to be active for the reset password code as well).[x]
Several events have a REVIEW flag on them, where I want to see if we can be more specific about the type of error. This would help to a indicate better what the auth system should do and b allow for more informative errors for end users.this to be done in new PRs, fix one-by-one based on usageSo
Add a new package (
@thingco/authentication
) to prevent stepping on the existing package.This has a much simpler system: no async requests, very little config for the provider. The system simply says which state the user is in, and the user sends messages to change the state.
This has a much more complex React implmentation: each state has a corresponding hook. That hook accepts a callback function. That hook exposes:
isLoading
flag for when the callback is processingisActive
flag to say whether the state is actually currently activeerror
, which is either null or one of AuthenticationSystemError string literal typesSo:
react
,xstate
and@xstate/react
@thingco/logger
createAuthenticationSystem
constructor function, which accepts a config object specifying theloginFlowType
("OTP" or "USERNAME_PASSWORD") and thedeviceSecurityType
("NONE", "PIN" or "BIOMETRIC", though the latter has no implementations and probably needs to be dropped for now)AuthenticationSystemProvider
, which accepts the result ofcreateAuthenticationSystem
as a prop.useAwaitingOtpInput
The library does not know anything about how the callbacks work, only what shape the functions are to be. So for example