diff --git a/src/common/interfaces/event.interface.ts b/src/common/interfaces/event.interface.ts index 82392d419..dd8683419 100644 --- a/src/common/interfaces/event.interface.ts +++ b/src/common/interfaces/event.interface.ts @@ -12,6 +12,8 @@ import { } from '../../organizations/interfaces'; import { Connection, ConnectionResponse } from '../../sso/interfaces'; import { + AuthenticationEvent, + AuthenticationEventResponse, EmailVerificationEvent, EmailVerificationEventResponse, InvitationEvent, @@ -44,6 +46,95 @@ interface EventResponseBase { created_at: string; } +export interface AuthenticationEmailVerificationSucceededEvent + extends EventBase { + event: 'authentication.email_verification_succeeded'; + data: AuthenticationEvent; +} + +export interface AuthenticationEmailVerificationSucceededEventResponse + extends EventResponseBase { + event: 'authentication.email_verification_succeeded'; + data: AuthenticationEventResponse; +} + +export interface AuthenticationMagicAuthFailedEvent extends EventBase { + event: 'authentication.magic_auth_failed'; + data: AuthenticationEvent; +} + +export interface AuthenticationMagicAuthFailedEventResponse + extends EventResponseBase { + event: 'authentication.magic_auth_failed'; + data: AuthenticationEventResponse; +} + +export interface AuthenticationMagicAuthSucceededEvent extends EventBase { + event: 'authentication.magic_auth_succeeded'; + data: AuthenticationEvent; +} + +export interface AuthenticationMagicAuthSucceededEventResponse + extends EventResponseBase { + event: 'authentication.magic_auth_succeeded'; + data: AuthenticationEventResponse; +} + +export interface AuthenticationMfaSucceededEvent extends EventBase { + event: 'authentication.mfa_succeeded'; + data: AuthenticationEvent; +} + +export interface AuthenticationMfaSucceededEventResponse + extends EventResponseBase { + event: 'authentication.mfa_succeeded'; + data: AuthenticationEventResponse; +} + +export interface AuthenticationOAuthSucceededEvent extends EventBase { + event: 'authentication.oauth_succeeded'; + data: AuthenticationEvent; +} + +export interface AuthenticationOAuthSucceededEventResponse + extends EventResponseBase { + event: 'authentication.oauth_succeeded'; + data: AuthenticationEventResponse; +} + +export interface AuthenticationPasswordFailedEvent extends EventBase { + event: 'authentication.password_failed'; + data: AuthenticationEvent; +} + +export interface AuthenticationPasswordFailedEventResponse + extends EventResponseBase { + event: 'authentication.password_failed'; + data: AuthenticationEventResponse; +} + +export interface AuthenticationPasswordSucceededEvent extends EventBase { + event: 'authentication.password_succeeded'; + data: AuthenticationEvent; +} + +export interface AuthenticationPasswordSucceededEventResponse + extends EventResponseBase { + event: 'authentication.password_succeeded'; + data: AuthenticationEventResponse; +} + +export interface AuthenticationSSOSucceededEvent extends EventBase { + event: 'authentication.sso_succeeded'; + data: AuthenticationEvent; +} + +export interface AuthenticationSSOSucceededEventResponse + extends EventResponseBase { + event: 'authentication.sso_succeeded'; + data: AuthenticationEventResponse; +} + export interface ConnectionActivatedEvent extends EventBase { event: 'connection.activated'; data: Connection; @@ -398,6 +489,14 @@ export interface SessionCreatedEventResponse extends EventResponseBase { } export type Event = + | AuthenticationEmailVerificationSucceededEvent + | AuthenticationMfaSucceededEvent + | AuthenticationOAuthSucceededEvent + | AuthenticationSSOSucceededEvent + | AuthenticationPasswordFailedEvent + | AuthenticationPasswordSucceededEvent + | AuthenticationMagicAuthFailedEvent + | AuthenticationMagicAuthSucceededEvent | ConnectionActivatedEvent | ConnectionDeactivatedEvent | ConnectionDeletedEvent @@ -432,6 +531,14 @@ export type Event = | OrganizationDeletedEvent; export type EventResponse = + | AuthenticationEmailVerificationSucceededEventResponse + | AuthenticationMagicAuthFailedEventResponse + | AuthenticationMagicAuthSucceededEventResponse + | AuthenticationMfaSucceededEventResponse + | AuthenticationOAuthSucceededEventResponse + | AuthenticationPasswordFailedEventResponse + | AuthenticationPasswordSucceededEventResponse + | AuthenticationSSOSucceededEventResponse | ConnectionActivatedEventResponse | ConnectionDeactivatedEventResponse | ConnectionDeletedEventResponse diff --git a/src/common/serializers/event.serializer.ts b/src/common/serializers/event.serializer.ts index ea1d76708..84a7f875e 100644 --- a/src/common/serializers/event.serializer.ts +++ b/src/common/serializers/event.serializer.ts @@ -9,6 +9,7 @@ import { import { deserializeOrganization } from '../../organizations/serializers'; import { deserializeConnection } from '../../sso/serializers'; import { + deserializeAuthenticationEvent, deserializeEmailVerificationEvent, deserializeInvitationEvent, deserializeMagicAuthEvent, @@ -27,6 +28,19 @@ export const deserializeEvent = (event: EventResponse): Event => { }; switch (event.event) { + case 'authentication.email_verification_succeeded': + case 'authentication.magic_auth_failed': + case 'authentication.magic_auth_succeeded': + case 'authentication.mfa_succeeded': + case 'authentication.oauth_succeeded': + case 'authentication.password_failed': + case 'authentication.password_succeeded': + case 'authentication.sso_succeeded': + return { + ...eventBase, + event: event.event, + data: deserializeAuthenticationEvent(event.data), + }; case 'connection.activated': case 'connection.deactivated': case 'connection.deleted': diff --git a/src/user-management/interfaces/authentication-event.interface.ts b/src/user-management/interfaces/authentication-event.interface.ts new file mode 100644 index 000000000..0254958b6 --- /dev/null +++ b/src/user-management/interfaces/authentication-event.interface.ts @@ -0,0 +1,34 @@ +interface AuthenticationEventError { + code: string; + message: string; +} + +type AuthenticationEventType = + | 'sso' + | 'password' + | 'oauth' + | 'mfa' + | 'magic_auth' + | 'email_verification'; + +type AuthenticationEventStatus = 'failed' | 'succeeded'; + +export type AuthenticationEvent = { + email: string | null; + error?: AuthenticationEventError; + ipAddress: string | null; + status: AuthenticationEventStatus; + type: AuthenticationEventType; + userAgent: string | null; + userId: string | null; +}; + +export interface AuthenticationEventResponse { + email: string | null; + error?: AuthenticationEventError; + ip_address: string | null; + status: AuthenticationEventStatus; + type: AuthenticationEventType; + user_agent: string | null; + user_id: string | null; +} diff --git a/src/user-management/interfaces/index.ts b/src/user-management/interfaces/index.ts index 344b6d4f1..3930c4c5d 100644 --- a/src/user-management/interfaces/index.ts +++ b/src/user-management/interfaces/index.ts @@ -1,3 +1,4 @@ +export * from './authentication-event.interface'; export * from './authenticate-with-magic-auth-options.interface'; export * from './authenticate-with-password-options.interface'; export * from './authenticate-with-code-options.interface'; diff --git a/src/user-management/serializers/authentication-event.serializer.ts b/src/user-management/serializers/authentication-event.serializer.ts new file mode 100644 index 000000000..49fc33892 --- /dev/null +++ b/src/user-management/serializers/authentication-event.serializer.ts @@ -0,0 +1,16 @@ +import { + AuthenticationEvent, + AuthenticationEventResponse, +} from '../interfaces'; + +export const deserializeAuthenticationEvent = ( + authenticationEvent: AuthenticationEventResponse, +): AuthenticationEvent => ({ + email: authenticationEvent.email, + error: authenticationEvent.error, + ipAddress: authenticationEvent.ip_address, + status: authenticationEvent.status, + type: authenticationEvent.type, + userAgent: authenticationEvent.user_agent, + userId: authenticationEvent.user_id, +}); diff --git a/src/user-management/serializers/index.ts b/src/user-management/serializers/index.ts index d55b67608..f4eb1989d 100644 --- a/src/user-management/serializers/index.ts +++ b/src/user-management/serializers/index.ts @@ -3,6 +3,7 @@ export * from './authenticate-with-magic-auth-options.serializer'; export * from './authenticate-with-password-options.serializer'; export * from './authenticate-with-refresh-token.options.serializer'; export * from './authenticate-with-totp-options.serializer'; +export * from './authentication-event.serializer'; export * from './authentication-response.serializer'; export * from './create-magic-auth-options.serializer'; export * from './create-password-reset-options.serializer';