Skip to main content
Version: Next

Configuration

This page covers configuration options for the Microsoft identity provider beyond the basic setup.

Configuration options

Below is a non-exhaustive list of some of the most common configuration options. For more details on all options, check the MicrosoftIdpConfig in-code documentation.

Tenant configuration

The tenant parameter determines which accounts can sign in to your application:

  • 'common' (default) - Allows both personal Microsoft accounts and work/school accounts.
  • 'organizations' - Allows only work/school accounts (any organization).
  • 'consumers' - Allows only personal Microsoft accounts.
  • A specific tenant ID - Restricts to accounts from a specific Microsoft Entra ID tenant.
final microsoftIdpConfig = MicrosoftIdpConfig(
clientId: pod.getPassword('microsoftClientId')!,
clientSecret: pod.getPassword('microsoftClientSecret')!,
tenant: 'organizations', // Only allow work/school accounts
);
tip

Use 'common' for the widest user base. Use a specific tenant ID when building internal applications for a single organization.

Custom account validation

You can customize the validation for Microsoft account details before allowing sign-in. By default, the validation checks that the received account details contain a non-empty userIdentifier.

final microsoftIdpConfig = MicrosoftIdpConfigFromPasswords(
// Optional: Custom validation for Microsoft account details
microsoftAccountDetailsValidation: (MicrosoftAccountDetails accountDetails) {
// Throw an exception if account doesn't meet custom requirements
if (accountDetails.userIdentifier.isEmpty) {
throw MicrosoftUserInfoMissingDataException();
}
// Example: Require email to be present
if (accountDetails.email == null || accountDetails.email!.isEmpty) {
throw MicrosoftUserInfoMissingDataException();
}
},
);
note

Users may choose not to share their email or other information during the Microsoft login flow. Adjust your validation function carefully to avoid blocking legitimate users.

MicrosoftAccountDetails

The microsoftAccountDetailsValidation callback receives a MicrosoftAccountDetails record with the following properties:

PropertyTypeDescription
userIdentifierStringThe Microsoft user's unique identifier (Object ID)
emailString?The user's email address (may be null)
nameString?The user's display name from Microsoft
imageUri?URL to the user's profile image

Example of accessing these properties:

microsoftAccountDetailsValidation: (accountDetails) {
print('Microsoft Object ID: ${accountDetails.userIdentifier}');
print('Email: ${accountDetails.email}');
print('Display name: ${accountDetails.name}');
print('Profile image: ${accountDetails.image}');

// Custom validation logic
if (accountDetails.email == null) {
throw MicrosoftUserInfoMissingDataException();
}
},
info

The properties available depend on the scopes requested and what the user consented to share.

Accessing Microsoft APIs

The default setup allows access to basic user information, such as name, email. You may require additional access scopes to access other Microsoft APIs, such as accessing a user's calendar, mail, or OneDrive files.

The default scopes requested are:

  • openid: Required for OpenID Connect authentication.
  • profile: Access to user's basic profile information.
  • email: Access to user's email address.
  • offline_access: Allows refresh tokens for long-lived sessions.
  • https://graph.microsoft.com/User.Read: Access to user's Microsoft Graph profile.

To request additional scopes, you will need to:

  • Ensure the required API permissions are configured in your Microsoft Entra ID app registration (navigate to API permissions in the Azure Portal).
  • Request access to the scopes when signing in. Do this by setting the scopes parameter of the MicrosoftSignInWidget or MicrosoftAuthController.

A full list of available scopes and Microsoft Graph API permissions can be found in the Microsoft Graph permissions reference.

info

Adding additional scopes may require admin consent depending on your tenant configuration and the sensitivity of the requested permissions.

Accessing Microsoft APIs on the server

On the server side, you can access Microsoft APIs using the access token. The getExtraMicrosoftInfoCallback in MicrosoftIdpConfig receives the access token and can be used to call Microsoft Graph APIs:

import 'package:http/http.dart' as http;

final microsoftIdpConfig = MicrosoftIdpConfigFromPasswords(
// Optional: Extract additional info from Microsoft Graph APIs
getExtraMicrosoftInfoCallback: (session, {
required accountDetails,
required accessToken,
required transaction,
}) async {
// Use accessToken to call Microsoft Graph APIs and store additional info
// Example: Access user's calendar
final response = await http.get(
Uri.https('graph.microsoft.com', '/v1.0/me/calendar'),
headers: {'Authorization': 'Bearer $accessToken'},
);
// Process response and store additional info in the database
},
);

Reacting to account creation

You can use the onAfterMicrosoftAccountCreated callback to run logic after a new Microsoft account has been created and linked to an auth user. This callback is only invoked for new accounts, not for returning users.

This callback is complimentary to the core onAfterAuthUserCreated callback to perform side-effects that are specific to a login on this provider - like storing analytics, sending a welcome email, or storing additional data.

final microsoftIdpConfig = MicrosoftIdpConfigFromPasswords(
onAfterMicrosoftAccountCreated: (
session,
authUser,
microsoftAccount, {
required transaction,
}) async {
// e.g. store additional data, send a welcome email, or log for analytics
},
);
info

This callback runs inside the same database transaction as the account creation. Throwing an exception inside this callback will abort the process. If you perform external side-effects, make sure to safeguard them with a try/catch to prevent unwanted failures.

caution

If you need to assign Serverpod scopes based on provider account data, note that updating the database alone (via AuthServices.instance.authUsers.update()) is not enough for the current login session. The token issuance uses the in-memory authUser.scopes, which is already set before this callback runs. You would need to update authUser.scopes as well for the scopes to be reflected in the issued tokens. For assigning scopes at creation time, consider using onBeforeAuthUserCreated in combination with getExtraMicrosoftInfoCallback to fetch and store the data you need before the auth user is created.

Configuring client IDs on the app

Passing client IDs in code

You can pass the clientId, redirectUri, and tenant directly when initializing the Microsoft Sign-In service:

await client.auth.initializeMicrosoftSignIn(
clientId: 'YOUR_MICROSOFT_CLIENT_ID',
redirectUri: 'yourapp://auth',
tenant: 'common', // Optional, defaults to 'common'
);

This approach is useful when you need different client IDs per platform and want to manage them in your Dart code.

Using environment variables

Alternatively, you can pass client configuration during build time using the --dart-define option. The Microsoft Sign-In provider supports the following environment variables:

  • MICROSOFT_CLIENT_ID: Your Microsoft Application (client) ID
  • MICROSOFT_REDIRECT_URI: The callback URI

Example usage:

flutter run -d <device> \
--dart-define="MICROSOFT_CLIENT_ID=your_client_id" \
--dart-define="MICROSOFT_REDIRECT_URI=msauth://auth" \
--dart-define="MICROSOFT_TENANT=common"

This approach is useful when you need to:

  • Manage separate client IDs for different platforms (Android, iOS, Web, macOS) in a centralized way
  • Avoid committing client IDs to version control
  • Configure different credentials for different build environments (development, staging, production)
tip

You can also set these environment variables in your IDE's run configuration or CI/CD pipeline to avoid passing them manually each time.