diff --git a/docs/06-concepts/11-authentication/01-setup.md b/docs/06-concepts/11-authentication/01-setup.md index 5bc4f982..2198def1 100644 --- a/docs/06-concepts/11-authentication/01-setup.md +++ b/docs/06-concepts/11-authentication/01-setup.md @@ -268,10 +268,10 @@ class SignInPage extends StatelessWidget { body: SignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -289,4 +289,8 @@ This widget is a convenient way to use identity providers out-of-the-box, but yo #### Updating the UI based on authentication state -Instead of navigating to the home screen using the `onAuthenticated` callback, you can listen to authentication state changes and update the UI accordingly. See the [Client-side authentication](./basics#monitor-authentication-changes) section for more details. +To update the UI based on authentication state, you must listen to authentication state changes using the `authInfoListenable` getter. See the [Client-side authentication](./basics#monitor-authentication-changes) section for more details. + +:::warning +Do not navigate to the home screen using the `onAuthenticated` callback. This will cause the user to have to sign in again every time they open the app. +::: diff --git a/docs/06-concepts/11-authentication/03-working-with-users.md b/docs/06-concepts/11-authentication/03-working-with-users.md index 788f2d66..22a95abf 100644 --- a/docs/06-concepts/11-authentication/03-working-with-users.md +++ b/docs/06-concepts/11-authentication/03-working-with-users.md @@ -20,6 +20,34 @@ await AuthServices.instance.authUsers.delete(session, userIdUuidValue); For the full list of operations, see the [AuthUsers](https://pub.dev/documentation/serverpod_auth_core_server/latest/serverpod_auth_core_server/AuthUsers-class.html) class documentation. +## Blocking users + +You can block users to prevent them from signing in to your application. When a blocked user attempts to authenticate, an `AuthUserBlockedException` will be thrown, and the authentication will fail. + +### Blocking or unblocking a user + +To block/unblock a user, use the `update` method of the `AuthUsers` class: + +```dart +await AuthServices.instance.authUsers.update( + session, + authUserId: authUserId, + blocked: true, // or false to unblock +); +``` + +Users can also be created with the blocked status set from the start: +```dart +await AuthServices.instance.authUsers.create( + session, + blocked: true, +); +``` + +:::note +When a user is blocked, they will not be able to sign in until they are unblocked. However, blocking a user does not automatically revoke their existing sessions. Be sure to revoke existing sessions for a complete block operation. See [Revoking tokens](./token-managers/managing-tokens#revoking-tokens) for more details. +::: + ## User profiles By default, all authenticated users have a `UserProfile` object that contains information about the signed-in user. To access the `UserProfile` object, you can use the `userProfile` extension on the `AuthenticationInfo` object. @@ -83,6 +111,17 @@ indexes: unique: true ``` +:::note +Note that the `AuthUser` model is declared in the `serverpod_auth_core` module, which is automatically included in your project as a dependency of the `serverpod_auth_idp` module. If you are not ignoring the generated files in your `analysis_options.yaml`, you might need to explicitly add the `serverpod_auth_core` module to your project to prevent `depend_on_referenced_packages` lint errors. The general recommendation, however, is to ignore linting on generated files: + +```yaml +# analysis_options.yaml +analyzer: + exclude: + - lib/src/generated/** +``` +::: + :::tip When referencing module classes in your model files, you can use a nickname for the module instead of the full module name. See the [modules documentation](../modules) for more information. ::: diff --git a/docs/06-concepts/11-authentication/04-providers/01-email/01-setup.md b/docs/06-concepts/11-authentication/04-providers/01-email/01-setup.md index de59331d..fdaabc57 100644 --- a/docs/06-concepts/11-authentication/04-providers/01-email/01-setup.md +++ b/docs/06-concepts/11-authentication/04-providers/01-email/01-setup.md @@ -102,10 +102,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; EmailSignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen or update UI - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/docs/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md b/docs/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md index 7c622051..1768584a 100644 --- a/docs/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md +++ b/docs/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md @@ -58,7 +58,10 @@ EmailSignInWidget( // Open privacy policy }, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -115,7 +118,10 @@ final controller = EmailAuthController( client: client, startScreen: EmailFlowScreen.login, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/docs/06-concepts/11-authentication/04-providers/02-google/01-setup.md b/docs/06-concepts/11-authentication/04-providers/02-google/01-setup.md index 88138546..349943b1 100644 --- a/docs/06-concepts/11-authentication/04-providers/02-google/01-setup.md +++ b/docs/06-concepts/11-authentication/04-providers/02-google/01-setup.md @@ -226,10 +226,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; GoogleSignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen or update UI - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/docs/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md b/docs/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md index 738dc84a..a1901960 100644 --- a/docs/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md +++ b/docs/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md @@ -46,7 +46,10 @@ GoogleSignInWidget( attemptLightweightSignIn: true, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -64,7 +67,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; final controller = GoogleAuthController( client: client, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/docs/06-concepts/11-authentication/04-providers/03-apple/01-setup.md b/docs/06-concepts/11-authentication/04-providers/03-apple/01-setup.md index 621430b0..8423a2dc 100644 --- a/docs/06-concepts/11-authentication/04-providers/03-apple/01-setup.md +++ b/docs/06-concepts/11-authentication/04-providers/03-apple/01-setup.md @@ -188,10 +188,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; AppleSignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen or update UI - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/docs/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md b/docs/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md index 02fd8681..8a474823 100644 --- a/docs/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md +++ b/docs/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md @@ -42,7 +42,10 @@ AppleSignInWidget( ], onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -60,7 +63,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; final controller = AppleAuthController( client: client, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/docs/06-concepts/11-authentication/06-ui-components.md b/docs/06-concepts/11-authentication/06-ui-components.md index 7cef777a..c1c1c795 100644 --- a/docs/06-concepts/11-authentication/06-ui-components.md +++ b/docs/06-concepts/11-authentication/06-ui-components.md @@ -30,10 +30,10 @@ class SignInPage extends StatelessWidget { body: SignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -62,7 +62,10 @@ SignInWidget( disableGoogleSignInWidget: false, disableAppleSignInWidget: true, // Disable Apple sign-in onAuthenticated: () { - // Handle authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, ) ``` diff --git a/docs/08-upgrading/01-upgrade-to-three.md b/docs/08-upgrading/01-upgrade-to-three.md index 99c433ee..ec7a16ac 100644 --- a/docs/08-upgrading/01-upgrade-to-three.md +++ b/docs/08-upgrading/01-upgrade-to-three.md @@ -241,6 +241,10 @@ class MyEndpoint extends Endpoint { Serverpod 3.0 includes several changes to the authentication system that improve type safety and performance. +:::note +Besides minor interface changes described in this section, the legacy authentication system is still supported and can be used alongside the new version. This allows to safely upgrade your project to Serverpod 3.0 while using the legacy authentication and gradually migrate to the new one. +::: + ### Custom authentication handlers In the new authentication system, the default authentication header has changed from `Basic` to `Bearer` - which is now officially supported. This introduced a change for custom `AuthenticationHandler` implementations: the `token` parameter will now receive the token unwrapped from the `Bearer` prefix - just as it does for `Basic` tokens. @@ -304,6 +308,10 @@ Client(host)..authenticationKeyManager = myManager; Client(host)..authKeyProvider = myProvider; ``` +:::note +To keep backwards compatibility with the old authentication system, the `FlutterAuthenticationKeyManager` from the legacy package now implements the `AuthKeyProvider` interface, so you can safely pass it to the client as the `authKeyProvider`. +::: + ## Enum serialization The default enum serialization strategy has changed from `byIndex` to `byName`. This change improves robustness when reordering or adding enum values, as serialized data remains valid even if the enum definition changes. With `byName`, the string representation is stored instead of the numeric index, making your data more resilient and easier to debug. diff --git a/versioned_docs/version-3.0.0/06-concepts/11-authentication/01-setup.md b/versioned_docs/version-3.0.0/06-concepts/11-authentication/01-setup.md index 5bc4f982..0fedc17c 100644 --- a/versioned_docs/version-3.0.0/06-concepts/11-authentication/01-setup.md +++ b/versioned_docs/version-3.0.0/06-concepts/11-authentication/01-setup.md @@ -268,10 +268,10 @@ class SignInPage extends StatelessWidget { body: SignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.0.0/06-concepts/11-authentication/03-working-with-users.md b/versioned_docs/version-3.0.0/06-concepts/11-authentication/03-working-with-users.md index 788f2d66..22a95abf 100644 --- a/versioned_docs/version-3.0.0/06-concepts/11-authentication/03-working-with-users.md +++ b/versioned_docs/version-3.0.0/06-concepts/11-authentication/03-working-with-users.md @@ -20,6 +20,34 @@ await AuthServices.instance.authUsers.delete(session, userIdUuidValue); For the full list of operations, see the [AuthUsers](https://pub.dev/documentation/serverpod_auth_core_server/latest/serverpod_auth_core_server/AuthUsers-class.html) class documentation. +## Blocking users + +You can block users to prevent them from signing in to your application. When a blocked user attempts to authenticate, an `AuthUserBlockedException` will be thrown, and the authentication will fail. + +### Blocking or unblocking a user + +To block/unblock a user, use the `update` method of the `AuthUsers` class: + +```dart +await AuthServices.instance.authUsers.update( + session, + authUserId: authUserId, + blocked: true, // or false to unblock +); +``` + +Users can also be created with the blocked status set from the start: +```dart +await AuthServices.instance.authUsers.create( + session, + blocked: true, +); +``` + +:::note +When a user is blocked, they will not be able to sign in until they are unblocked. However, blocking a user does not automatically revoke their existing sessions. Be sure to revoke existing sessions for a complete block operation. See [Revoking tokens](./token-managers/managing-tokens#revoking-tokens) for more details. +::: + ## User profiles By default, all authenticated users have a `UserProfile` object that contains information about the signed-in user. To access the `UserProfile` object, you can use the `userProfile` extension on the `AuthenticationInfo` object. @@ -83,6 +111,17 @@ indexes: unique: true ``` +:::note +Note that the `AuthUser` model is declared in the `serverpod_auth_core` module, which is automatically included in your project as a dependency of the `serverpod_auth_idp` module. If you are not ignoring the generated files in your `analysis_options.yaml`, you might need to explicitly add the `serverpod_auth_core` module to your project to prevent `depend_on_referenced_packages` lint errors. The general recommendation, however, is to ignore linting on generated files: + +```yaml +# analysis_options.yaml +analyzer: + exclude: + - lib/src/generated/** +``` +::: + :::tip When referencing module classes in your model files, you can use a nickname for the module instead of the full module name. See the [modules documentation](../modules) for more information. ::: diff --git a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/01-email/01-setup.md b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/01-email/01-setup.md index de59331d..fdaabc57 100644 --- a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/01-email/01-setup.md +++ b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/01-email/01-setup.md @@ -102,10 +102,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; EmailSignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen or update UI - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md index 7c622051..1768584a 100644 --- a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md +++ b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md @@ -58,7 +58,10 @@ EmailSignInWidget( // Open privacy policy }, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -115,7 +118,10 @@ final controller = EmailAuthController( client: client, startScreen: EmailFlowScreen.login, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/01-setup.md b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/01-setup.md index 88138546..349943b1 100644 --- a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/01-setup.md +++ b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/01-setup.md @@ -226,10 +226,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; GoogleSignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen or update UI - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/02-configuration.md b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/02-configuration.md index 2b88189b..67d28d38 100644 --- a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/02-configuration.md +++ b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/02-configuration.md @@ -110,7 +110,10 @@ GoogleSignInWidget( client: client, attemptLightweightSignIn: false, // Disable lightweight sign-in onAuthenticated: () { - // User was automatically signed in + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, ) ``` diff --git a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md index 738dc84a..a1901960 100644 --- a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md +++ b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md @@ -46,7 +46,10 @@ GoogleSignInWidget( attemptLightweightSignIn: true, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -64,7 +67,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; final controller = GoogleAuthController( client: client, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/03-apple/01-setup.md b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/03-apple/01-setup.md index 621430b0..8423a2dc 100644 --- a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/03-apple/01-setup.md +++ b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/03-apple/01-setup.md @@ -188,10 +188,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; AppleSignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen or update UI - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md index 02fd8681..8a474823 100644 --- a/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md +++ b/versioned_docs/version-3.0.0/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md @@ -42,7 +42,10 @@ AppleSignInWidget( ], onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -60,7 +63,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; final controller = AppleAuthController( client: client, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.0.0/06-concepts/11-authentication/06-ui-components.md b/versioned_docs/version-3.0.0/06-concepts/11-authentication/06-ui-components.md index 7cef777a..c1c1c795 100644 --- a/versioned_docs/version-3.0.0/06-concepts/11-authentication/06-ui-components.md +++ b/versioned_docs/version-3.0.0/06-concepts/11-authentication/06-ui-components.md @@ -30,10 +30,10 @@ class SignInPage extends StatelessWidget { body: SignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -62,7 +62,10 @@ SignInWidget( disableGoogleSignInWidget: false, disableAppleSignInWidget: true, // Disable Apple sign-in onAuthenticated: () { - // Handle authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, ) ``` diff --git a/versioned_docs/version-3.0.0/08-upgrading/01-upgrade-to-three.md b/versioned_docs/version-3.0.0/08-upgrading/01-upgrade-to-three.md index 6a44205a..8ed5d9fc 100644 --- a/versioned_docs/version-3.0.0/08-upgrading/01-upgrade-to-three.md +++ b/versioned_docs/version-3.0.0/08-upgrading/01-upgrade-to-three.md @@ -241,6 +241,10 @@ class MyEndpoint extends Endpoint { Serverpod 3.0 includes several changes to the authentication system that improve type safety and performance. +:::note +Besides minor interface changes described in this section, the legacy authentication system is still supported and can be used alongside the new version. This allows to safely upgrade your project to Serverpod 3.0 while using the legacy authentication and gradually migrate to the new one. +::: + ### Custom authentication handlers In the new authentication system, the default authentication header has changed from `Basic` to `Bearer` - which is now officially supported. This introduced a change for custom `AuthenticationHandler` implementations: the `token` parameter will now receive the token unwrapped from the `Bearer` prefix - just as it does for `Basic` tokens. @@ -288,6 +292,10 @@ Client(host)..authenticationKeyManager = myManager; Client(host)..authKeyProvider = myProvider; ``` +:::note +To keep backwards compatibility with the old authentication system, the `FlutterAuthenticationKeyManager` from the legacy package now implements the `AuthKeyProvider` interface, so you can safely pass it to the client as the `authKeyProvider`. +::: + ## Enum serialization The default enum serialization strategy has changed from `byIndex` to `byName`. This change improves robustness when reordering or adding enum values, as serialized data remains valid even if the enum definition changes. With `byName`, the string representation is stored instead of the numeric index, making your data more resilient and easier to debug. diff --git a/versioned_docs/version-3.1.0/06-concepts/11-authentication/01-setup.md b/versioned_docs/version-3.1.0/06-concepts/11-authentication/01-setup.md index 5bc4f982..0fedc17c 100644 --- a/versioned_docs/version-3.1.0/06-concepts/11-authentication/01-setup.md +++ b/versioned_docs/version-3.1.0/06-concepts/11-authentication/01-setup.md @@ -268,10 +268,10 @@ class SignInPage extends StatelessWidget { body: SignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.1.0/06-concepts/11-authentication/03-working-with-users.md b/versioned_docs/version-3.1.0/06-concepts/11-authentication/03-working-with-users.md index 788f2d66..22a95abf 100644 --- a/versioned_docs/version-3.1.0/06-concepts/11-authentication/03-working-with-users.md +++ b/versioned_docs/version-3.1.0/06-concepts/11-authentication/03-working-with-users.md @@ -20,6 +20,34 @@ await AuthServices.instance.authUsers.delete(session, userIdUuidValue); For the full list of operations, see the [AuthUsers](https://pub.dev/documentation/serverpod_auth_core_server/latest/serverpod_auth_core_server/AuthUsers-class.html) class documentation. +## Blocking users + +You can block users to prevent them from signing in to your application. When a blocked user attempts to authenticate, an `AuthUserBlockedException` will be thrown, and the authentication will fail. + +### Blocking or unblocking a user + +To block/unblock a user, use the `update` method of the `AuthUsers` class: + +```dart +await AuthServices.instance.authUsers.update( + session, + authUserId: authUserId, + blocked: true, // or false to unblock +); +``` + +Users can also be created with the blocked status set from the start: +```dart +await AuthServices.instance.authUsers.create( + session, + blocked: true, +); +``` + +:::note +When a user is blocked, they will not be able to sign in until they are unblocked. However, blocking a user does not automatically revoke their existing sessions. Be sure to revoke existing sessions for a complete block operation. See [Revoking tokens](./token-managers/managing-tokens#revoking-tokens) for more details. +::: + ## User profiles By default, all authenticated users have a `UserProfile` object that contains information about the signed-in user. To access the `UserProfile` object, you can use the `userProfile` extension on the `AuthenticationInfo` object. @@ -83,6 +111,17 @@ indexes: unique: true ``` +:::note +Note that the `AuthUser` model is declared in the `serverpod_auth_core` module, which is automatically included in your project as a dependency of the `serverpod_auth_idp` module. If you are not ignoring the generated files in your `analysis_options.yaml`, you might need to explicitly add the `serverpod_auth_core` module to your project to prevent `depend_on_referenced_packages` lint errors. The general recommendation, however, is to ignore linting on generated files: + +```yaml +# analysis_options.yaml +analyzer: + exclude: + - lib/src/generated/** +``` +::: + :::tip When referencing module classes in your model files, you can use a nickname for the module instead of the full module name. See the [modules documentation](../modules) for more information. ::: diff --git a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/01-email/01-setup.md b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/01-email/01-setup.md index de59331d..fdaabc57 100644 --- a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/01-email/01-setup.md +++ b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/01-email/01-setup.md @@ -102,10 +102,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; EmailSignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen or update UI - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md index 7c622051..1768584a 100644 --- a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md +++ b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/01-email/03-customizing-the-ui.md @@ -58,7 +58,10 @@ EmailSignInWidget( // Open privacy policy }, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -115,7 +118,10 @@ final controller = EmailAuthController( client: client, startScreen: EmailFlowScreen.login, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/01-setup.md b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/01-setup.md index 88138546..349943b1 100644 --- a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/01-setup.md +++ b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/01-setup.md @@ -226,10 +226,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; GoogleSignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen or update UI - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/02-configuration.md b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/02-configuration.md index 2b88189b..67d28d38 100644 --- a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/02-configuration.md +++ b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/02-configuration.md @@ -110,7 +110,10 @@ GoogleSignInWidget( client: client, attemptLightweightSignIn: false, // Disable lightweight sign-in onAuthenticated: () { - // User was automatically signed in + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, ) ``` diff --git a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md index 738dc84a..a1901960 100644 --- a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md +++ b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/02-google/03-customizing-the-ui.md @@ -46,7 +46,10 @@ GoogleSignInWidget( attemptLightweightSignIn: true, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -64,7 +67,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; final controller = GoogleAuthController( client: client, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/03-apple/01-setup.md b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/03-apple/01-setup.md index 621430b0..8423a2dc 100644 --- a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/03-apple/01-setup.md +++ b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/03-apple/01-setup.md @@ -188,10 +188,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; AppleSignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen or update UI - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md index 02fd8681..8a474823 100644 --- a/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md +++ b/versioned_docs/version-3.1.0/06-concepts/11-authentication/04-providers/03-apple/03-customizing-the-ui.md @@ -42,7 +42,10 @@ AppleSignInWidget( ], onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -60,7 +63,10 @@ import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; final controller = AppleAuthController( client: client, onAuthenticated: () { - // Handle successful authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors diff --git a/versioned_docs/version-3.1.0/06-concepts/11-authentication/06-ui-components.md b/versioned_docs/version-3.1.0/06-concepts/11-authentication/06-ui-components.md index 7cef777a..c1c1c795 100644 --- a/versioned_docs/version-3.1.0/06-concepts/11-authentication/06-ui-components.md +++ b/versioned_docs/version-3.1.0/06-concepts/11-authentication/06-ui-components.md @@ -30,10 +30,10 @@ class SignInPage extends StatelessWidget { body: SignInWidget( client: client, onAuthenticated: () { - // Navigate to home screen - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => HomePage()), - ); + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, onError: (error) { // Handle errors @@ -62,7 +62,10 @@ SignInWidget( disableGoogleSignInWidget: false, disableAppleSignInWidget: true, // Disable Apple sign-in onAuthenticated: () { - // Handle authentication + // Do something when the user is authenticated. + // + // NOTE: You should not navigate to the home screen here, otherwise + // the user will have to sign in again every time they open the app. }, ) ``` diff --git a/versioned_docs/version-3.1.0/08-upgrading/01-upgrade-to-three.md b/versioned_docs/version-3.1.0/08-upgrading/01-upgrade-to-three.md index 99c433ee..ec7a16ac 100644 --- a/versioned_docs/version-3.1.0/08-upgrading/01-upgrade-to-three.md +++ b/versioned_docs/version-3.1.0/08-upgrading/01-upgrade-to-three.md @@ -241,6 +241,10 @@ class MyEndpoint extends Endpoint { Serverpod 3.0 includes several changes to the authentication system that improve type safety and performance. +:::note +Besides minor interface changes described in this section, the legacy authentication system is still supported and can be used alongside the new version. This allows to safely upgrade your project to Serverpod 3.0 while using the legacy authentication and gradually migrate to the new one. +::: + ### Custom authentication handlers In the new authentication system, the default authentication header has changed from `Basic` to `Bearer` - which is now officially supported. This introduced a change for custom `AuthenticationHandler` implementations: the `token` parameter will now receive the token unwrapped from the `Bearer` prefix - just as it does for `Basic` tokens. @@ -304,6 +308,10 @@ Client(host)..authenticationKeyManager = myManager; Client(host)..authKeyProvider = myProvider; ``` +:::note +To keep backwards compatibility with the old authentication system, the `FlutterAuthenticationKeyManager` from the legacy package now implements the `AuthKeyProvider` interface, so you can safely pass it to the client as the `authKeyProvider`. +::: + ## Enum serialization The default enum serialization strategy has changed from `byIndex` to `byName`. This change improves robustness when reordering or adding enum values, as serialized data remains valid even if the enum definition changes. With `byName`, the string representation is stored instead of the numeric index, making your data more resilient and easier to debug.