Skip to content

Commit

Permalink
docs: Docs improvements for authentication section
Browse files Browse the repository at this point in the history
  • Loading branch information
klkucaj committed Oct 29, 2024
1 parent f94bddd commit a0914ac
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 59 deletions.
39 changes: 20 additions & 19 deletions docs/06-concepts/11-authentication/01-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,24 +182,24 @@ void main() async {
}
```

The `SessionManager` provides several methods to monitor and control the user's session state:
The `SessionManager` has useful methods for viewing and monitoring the user's current state:

- **`isSignedIn`**
- **Check authentication state**
Check the users authentication status.

```dart
sessionManager.isSignedIn;
```

- **`signedInUser`**
Retrieves the `UserInfo` object for the currently signed-in user, or `null` if no user is signed in.
- **Access current user**
Will return a `UserInfo` if the user is currently signed in (or `null` if the user isn't signed in).

```dart
sessionManager.signedInUser;
```

- **`registerSignedInUser`**
Registers a signed-in user in the session manager after successful authentication.
- **Register authentication**
Set up a new authenticated session after successful login.
For more details, visit [Custom Providers - Client Setup](providers/custom-providers#client-setup).

```dart
Expand All @@ -210,37 +210,38 @@ The `SessionManager` provides several methods to monitor and control the user's
);
```

- **`addListener`**
Notifies listeners of changes in the user's signed-in status, useful for triggering UI updates or other responses when the session state changes.
- **Monitor session changes**
React to changes in authentication state, useful for updating UI or handling session events.

```dart
@override
void initState() {
super.initState();
// Rebuild the page if authentication state changes.
sessionManager.addListener(() {
setState(() {});
});
}
```

- **`signOutDevice`**
Signs the user out from the current device, keeping them signed in on other devices. This is the most common scenario when signing out.
- **Sign Out Current Device**
Signs the user out on this device only, preserving access on other devices. This is the recommended way to handle sign-outs.

```dart
await sessionManager.signOutDevice();
```

- **`signOutAllDevices`**
Signs the user out from all devices, revoking active access across every device.
- **Sign Out All Devices**
Signs the user out across all devices where they are signed in.

```dart
await sessionManager.signOutAllDevices();
```

- **Deprecated `signOut` Method**
The original `signOut` method is deprecated. If the same behavior is desired, use `signOutAllDevices` instead.

```dart
// Deprecated usage
await sessionManager.signOut();
```
:::info Deprecated Method
The original `signOut` method is deprecated. If the same behavior is desired, use `signOutAllDevices` instead.
```dart
await sessionManager.signOut();
```
:::
9 changes: 4 additions & 5 deletions docs/06-concepts/11-authentication/02-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The `Session` object provides information about the current user. A unique `user

```dart
Future<void> myMethod(Session session) async {
var userId = await session.auth.authenticatedUserId;
var userId = (await session.authenticated)?.userId;
...
}
```
Expand Down Expand Up @@ -103,15 +103,15 @@ The `StatusEndpoint` class includes methods for handling user sign-outs, whether

- **Sign out device**

Use the `signOutDevice` method to log the user out of the current device only, leaving other devices active.
Use the `signOutDevice` method to log the user out of the current device only, closing streaming connections for this device while keeping other devices active.

```dart
await endpoints.status.signOutDevice(session);
```
- **Sign out all devices**
Use the `signOutAllDevices` method to log the user out from all devices, effectively ending all active access.
Use the `signOutAllDevices` method to log the user out from all devices, closing all streaming connections and synchronizing server state.
```dart
await endpoints.status.signOutAllDevices(session);
Expand All @@ -129,5 +129,4 @@ The `StatusEndpoint` class includes methods for handling user sign-outs, whether

In addition to the `StatusEndpoint` methods, Serverpod provides more comprehensive tools for managing user authentication and sign-out processes across multiple devices.

For more detailed information on managing authentication keys, revoking specific tokens, and ensuring client notifications are handled correctly during the sign-out process, please refer to the [Managing Authentication Keys and Signing Out Users](providers/custom-providers#managing-authentication-keys-and-signing-out-users) section.

For more detailed information on managing authentication keys, revoking specific tokens, and handling streaming connections during the sign-out process, please refer to the [Revoking authentication keys](providers/custom-providers#revoking-authentication-keys) section.
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ if (userInfo == null) {
The example above tries to find a user by email and user identifier. If no user is found, a new user is created with the provided information.

:::note

For many authentication platforms the `userIdentifier` is the user's email, but it can also be another unique identifier such as a phone number or a social security number.

:::

### Custom identification methods
Expand Down Expand Up @@ -113,13 +111,17 @@ class MyAuthenticationEndpoint extends Endpoint {

The example above shows how to create an `AuthenticationResponse` with the auth token and user information.

## Managing Authentication Keys and Signing Out Users
### Revoking authentication keys

Serverpod provides built-in methods for managing user authentication across multiple devices. These methods handle several critical security and state management processes automatically, ensuring consistent and secure authentication state across your application. When using the authentication management methods (`signOutUser` or `revokeAuthKey`), the following key actions are automatically handled:

Serverpod provides built-in methods for managing user authentication across multiple devices. Below are the key functions for signing out users and revoking authentication keys. It is crucial to use these methods to ensure that all required steps, such as notifying clients and clearing session data, are properly handled.
- Closing all affected streaming connections to maintain connection integrity.
- Synchronizing authentication state across all connected servers.
- Updating the session's authentication state with `session.updateAuthenticated(null)` if the affected user is currently authenticated.

### Revoking Authentication Keys (Per Device)
#### Revoking specific keys

To sign a user out from a specific device, you can revoke the authentication key associated with that session using the `revokeAuthKey` method. This method targets a specific session and allows the user to remain signed in on other devices.
To revoke specific authentication keys, use the `revokeAuthKey` method. This method handles all required processes, including closing streaming connections and synchronizing authentication state across servers.

#### Usage:

Expand All @@ -130,9 +132,26 @@ await UserAuthentication.revokeAuthKey(
);
```

#### Example: Fetching and Revoking an Authentication Key
#### Fetching and revoking an authentication key using AuthenticationInfo

To revoke a specific authentication key for the current session, you can directly access the session's authentication information and call the `revokeAuthKey` method.

```dart
// Fetch the authentication information for the current session
var authId = (await session.authenticated)?.authId;
// Revoke the authentication key if the session is authenticated and has an authId
if (authId != null) {
await UserAuthentication.revokeAuthKey(
session,
authKeyId: authId,
);
}
```

#### Fetching and revoking a specific authentication key for a user

To revoke a specific authentication key, you first need to fetch the keys associated with a user. You can then select the key you want to revoke and call the `revokeAuthKey` method.
To revoke a specific authentication key associated with a user, you can retrieve all authentication keys for that user and select the key you wish to revoke.

```dart
// Fetch all authentication keys for the user
Expand All @@ -151,15 +170,7 @@ if (authKeys.isNotEmpty) {
}
```

#### Importance of Using Built-In Methods

Directly deleting authentication keys from the `AuthKey` table is not recommended, as this bypasses essential steps such as notifying connected clients and clearing the session's authentication data. The `revokeAuthKey` method performs several additional actions, including:
- Sending a notification to the client via `session.messages.authenticationRevoked`.
- Clearing the session’s authentication data with `session.updateAuthenticated(null)` if the user being signed out is the one currently authenticated.

Failure to use these built-in methods can lead to inconsistencies, such as clients not being aware that their session has been revoked.

#### Example: Removing Specific Tokens (Direct Deletion)
#### Removing specific tokens (direct deletion)

```dart
await AuthKey.db.deleteWhere(
Expand All @@ -168,13 +179,13 @@ await AuthKey.db.deleteWhere(
);
```

> ⚠️ **Warning**: While this approach removes authentication tokens directly from the `AuthKey` table, it does not handle the necessary notifications and session updates. It is strongly recommended to use `UserAuthentication.revokeAuthKey` to ensure a complete and consistent sign-out process, including notifying clients and clearing session data.
> ⚠️ **Warning**: Directly removing authentication tokens from the `AuthKey` table bypasses necessary processes such as closing streaming connections and synchronizing server state. It is strongly recommended to use `UserAuthentication.revokeAuthKey` to ensure a complete and consistent sign-out.
### Signing Out from All Devices
#### Signing out all devices

The `signOutUser` method logs a user out from all devices where they are signed in. This method deletes all active authentication keys associated with the user, effectively ending all sessions for that user across all devices.
The `signOutUser` method logs a user out from all devices where they are signed in. This method deletes all authentication keys associated with the user, effectively ending all streaming connections across all devices.

#### Usage:
#### Usage with signOutUser

```dart
await UserAuthentication.signOutUser(
Expand All @@ -183,7 +194,7 @@ await UserAuthentication.signOutUser(
);
```

#### Example 1: Signing Out a Specific User (With `userId`)
#### Signing out a specific user

In this example, a specific `userId` is provided to sign out that user from all their devices.

Expand All @@ -195,11 +206,7 @@ await UserAuthentication.signOutUser(
);
```

In addition to deleting the user's authentication tokens, the `signOutUser` method also:
- Notifies clients about the revoked authentication using `session.messages.authenticationRevoked`.
- Updates the session’s authentication state with `session.updateAuthenticated(null)` if the user being signed out is the one currently authenticated.

#### Example 2: Signing Out the Currently Authenticated User (Without `userId`)
#### Signing out the currently authenticated user

If no `userId` is provided, `signOutUser` will automatically sign out the user who is currently authenticated in the session.

Expand All @@ -210,11 +217,9 @@ await UserAuthentication.signOutUser(
);
```

This method handles all necessary steps, including token deletion, client notifications, and session updates.
#### Creating a logout endpoint

### Example: Removing All Auth Tokens in an Endpoint

To sign out a user on all devices using an endpoint, the `signOutUser` method in the `UserAuthentication` class can be employed. This method ensures that all authentication tokens associated with the user are removed and that all related processes are correctly handled.
To sign out a user on all devices using an endpoint, the `signOutUser` method in the `UserAuthentication` class can be employed.

```dart
class AuthenticatedEndpoint extends Endpoint {
Expand All @@ -227,9 +232,7 @@ class AuthenticatedEndpoint extends Endpoint {
}
```

In this example, the `logout` endpoint ensures that all authentication tokens are removed, and the user is signed out from all devices. The necessary client notifications and session updates are handled automatically.

## Client Setup
## Client setup

The client must store and include the auth token in communication with the server. Luckily, the client-side authentication module handles this for you through the `SessionManager`.

Expand All @@ -251,4 +254,4 @@ if (serverResponse.success) {
}
```

The example above shows how to register a signed-in user in the session manager.
The example above shows how to register a signed-in user in the session manager.

0 comments on commit a0914ac

Please sign in to comment.