Auth & User Management

The 14 methods that create, authenticate and manage users. The client keeps a cookie jar, so the session established by signupUser or loginUser is replayed on every later call automatically.

Most of these are reachable with a publishable key, which is what makes them safe to call straight from a Flutter app. Three are not: getUser and checkIfUserExists enumerate arbitrary users and require a secret key.

Setup

Dart
1import 'package:neuctra_authix_dart_package/neuctra_authix_dart_package.dart';
2
3final authix = NeuctraAuthix(
4  const NeuctraAuthixConfig(
5    appId: 'your_app_id_here',
6    publishableKey: 'pk_live_xxxxxxxx_xxxxxxxxxxxxxxxx',
7    appName: 'MyApp',
8  ),
9);

Authentication

signupUser

POST /users/signup

Future<Map<String, dynamic>> signupUser(SignupParams params)
ParamTypeRequiredDescription
nameStringYesFull name.
emailStringYesEmail address.
passwordStringYesPlain password — hashed server-side.
usernameString?NoUnique handle.
phoneString?NoPhone number.
addressString?NoPostal address.
avatarUrlString?NoProfile image URL.
isActivebool?NoAccount active flag.
roleString?NoRole name, e.g. 'admin'.
extraMap<String, dynamic>NoAny further fields your app stores on the user record.

Returns: Map<String, dynamic>

Dart
1final result = await authix.signupUser(
2  const SignupParams(
3    name: 'John Doe',
4    email: '[email protected]',
5    password: 'secret123',
6    username: 'johndoe',
7    role: 'user',
8  ),
9);
10
11final userId = result['user']?['id']?.toString() ?? '';

Throws: ConfigurationError when name, email or password is empty — before any request is sent.

On success the backend sets the session cookie, so the user is signed in immediately — no separate login call needed. Null fields are omitted from the request body; use the extra map for app-specific fields.

loginUser

POST /users/login

Future<Map<String, dynamic>> loginUser(LoginParams params)
ParamTypeRequiredDescription
emailStringYesRegistered email.
passwordStringYesAccount password.

Returns: Map<String, dynamic>

Dart
1try {
2  await authix.loginUser(
3    const LoginParams(email: '[email protected]', password: 'secret123'),
4  );
5  await persistSession();
6} on AuthenticationError {
7  showError('Wrong email or password');
8} on NetworkError {
9  showError('Could not reach the server');
10}

Throws: ConfigurationError if either field is empty; AuthenticationError when the credentials are rejected.

The session cookie returned by the backend is captured into authix.session. Persist session.sessionCookie if you want the login to survive an app restart.

logoutUser

POST /users/logout

Future<bool> logoutUser({FutureOr<void> Function()? onLoggedOut})
ParamTypeRequiredDescription
onLoggedOutFunction?NoAwaited after the session is cleared — use it to navigate or wipe storage.

Returns: bool

Dart
1final ok = await authix.logoutUser(
2  onLoggedOut: () async {
3    await forgetSession();
4    navigatorKey.currentState?.pushReplacementNamed('/login');
5  },
6);

The local session is cleared whether or not the server call succeeds — a failed logout must never leave a usable session on the device. Unlike the JavaScript SDK there is no forced page reload; you control what happens next through onLoggedOut.

checkUserSession

GET /users/session

Future<CheckSessionResponse> checkUserSession()

Returns: CheckSessionResponse

Dart
1final session = await authix.checkUserSession();
2
3if (session.authenticated) {
4  final name = session.user?['name'];
5  print('Welcome back, $name');
6} else {
7  goToLogin();
8}

The only method that never throws. A rejected or missing cookie resolves to authenticated: false and clears the local session, so it is safe to call on every app launch.

Email verification

requestEmailVerificationOTP

POST /users/send-verify-otp/:userId

Future<Map<String, dynamic>> requestEmailVerificationOTP({required String userId, required String email})
ParamTypeRequiredDescription
userIdStringYesID of the user to verify.
emailStringYesAddress the OTP is sent to.

Returns: Map<String, dynamic>

Dart
1await authix.requestEmailVerificationOTP(
2  userId: userId,
3  email: '[email protected]',
4);

Sends a one-time code by email. Call it right after signup, then collect the code and pass it to verifyEmail.

verifyEmail

POST /users/verify-email

Future<Map<String, dynamic>> verifyEmail({required String email, required String otp})
ParamTypeRequiredDescription
emailStringYesAddress the OTP was sent to.
otpStringYesCode the user entered.

Returns: Map<String, dynamic>

Dart
1await authix.verifyEmail(
2  email: '[email protected]',
3  otp: '123456',
4);

Throws: Status 400 for an empty field; the backend returns an error for an expired or wrong code.

User records

getUser

GET /users/:appId/user

Future<Map<String, dynamic>> getUser({String? id, String? username})
ParamTypeRequiredDescription
idString?NoLook up by user ID.
usernameString?NoLook up by username.

Returns: Map<String, dynamic>

Dart
1final byId = await authix.getUser(id: 'user_123');
2final byName = await authix.getUser(username: 'johndoe');

Throws: ConfigurationError when neither id nor username is given. InsufficientScopeError when called with a publishable key.

Secret key only — looking up arbitrary users is an account-level operation. Pass exactly one of the two; values are URL-encoded, so usernames with spaces or symbols are safe.

getUserProfile

POST /users/profile

Future<Map<String, dynamic>> getUserProfile({required String userId})
ParamTypeRequiredDescription
userIdStringYesID of the profile to load.

Returns: Map<String, dynamic>

Dart
1final profile = await authix.getUserProfile(userId: userId);
2print(profile['email']);

With a publishable key the target is pinned to the signed-in session — userId cannot be used to read somebody else's profile. A secret key may read any user's.

updateUser

PUT /users/update/:userId

Future<Map<String, dynamic>> updateUser(UpdateUserParams params)
ParamTypeRequiredDescription
userIdStringYesID of the user to update.
nameString?NoFull name.
usernameString?NoUnique handle.
emailString?NoEmail address.
passwordString?NoPrefer changePassword instead — see the warning below.
phoneString?NoPhone number.
addressString?NoPostal address.
avatarUrlString?NoProfile image URL.
isActivebool?NoAccount active flag.
roleString?NoRole name.

Returns: Map<String, dynamic>

Dart
1await authix.updateUser(
2  UpdateUserParams(
3    userId: userId,
4    name: 'John A. Doe',
5    phone: '+1 555 0100',
6  ),
7);

Only non-null fields are sent, so this is a partial update. A null value means 'leave unchanged', not 'clear the field'.

deleteUser

DELETE /users/delete/:userId

Future<Map<String, dynamic>> deleteUser(DeleteUserParams params)
ParamTypeRequiredDescription
userIdStringYesID of the user to delete.

Returns: Map<String, dynamic>

Dart
1await authix.deleteUser(DeleteUserParams(userId: userId));
2authix.session.clearSession();

Permanent. Clear the local session afterwards if the deleted user is the one signed in.

Passwords & recovery

changePassword

PUT /users/change-password/:userId

Future<Map<String, dynamic>> changePassword(ChangePasswordParams params)
ParamTypeRequiredDescription
userIdStringYesID of the signed-in user.
currentPasswordStringYesExisting password — verified server-side.
newPasswordStringYesReplacement password.

Returns: Map<String, dynamic>

Dart
1await authix.changePassword(
2  ChangePasswordParams(
3    userId: userId,
4    currentPassword: 'secret123',
5    newPassword: 'newSecret456',
6  ),
7);

Throws: ConfigurationError when any field is empty; AuthenticationError when currentPassword is wrong.

The safe path for a signed-in user changing their own password, because it proves knowledge of the current one. Every session for that user is invalidated, including the one you are calling from — sign them back in or send them to the login screen afterwards.

requestResetUserPasswordOTP

POST /users/forgot-password

Future<Map<String, dynamic>> requestResetUserPasswordOTP({required String email})
ParamTypeRequiredDescription
emailStringYesAddress of the account to recover.

Returns: Map<String, dynamic>

Dart
1await authix.requestResetUserPasswordOTP(
2  email: '[email protected]',
3);

No session required, which is the point: the user cannot log in. Still needs a publishable key and is rate limited, so it cannot be used to flood someone's inbox anonymously.

resetUserPassword

POST /users/reset-password

Future<Map<String, dynamic>> resetUserPassword({required String email, required String otp, required String newPassword})
ParamTypeRequiredDescription
emailStringYesAddress the OTP was sent to.
otpStringYesCode from the recovery email.
newPasswordStringYesReplacement password.

Returns: Map<String, dynamic>

Dart
1await authix.resetUserPassword(
2  email: '[email protected]',
3  otp: '123456',
4  newPassword: 'newSecret456',
5);

Completes the forgot-password flow and invalidates every existing session for that account. The user still has to log in afterwards — this does not create a session.

checkIfUserExists

GET /users/check-user/:userId

Future<CheckUserResponse> checkIfUserExists(String userId)
ParamTypeRequiredDescription
userIdStringYesPassed positionally, not as a params object.

Returns: CheckUserResponse

Dart
1final result = await authix.checkIfUserExists('user_123');
2
3if (result.exists) {
4  print('User is registered for this app');
5}

Secret key only. Lightweight existence probe — appId is appended to the query string automatically.

updateUser can set a password

UpdateUserParams accepts a password field, and unlike changePassword it does not require the current one. Use changePassword for user-initiated changes.

How sessions flow

signupUser and loginUser capture the authix_user_session cookie into the client's jar, and every later call replays it. logoutUser and checkUserSession clear it when the session is gone. Persist authix.session.sessionCookie in secure storage to survive restarts, and seed it back with session.setSessionCookie() on launch.

Changing or resetting a password invalidates every session for that user server-side, so a stale cookie elsewhere stops working immediately.

Related