|
| 1 | +# Setup |
| 2 | + |
| 3 | +To set up **Sign in with Microsoft**, you must create an app registration on [Microsoft Entra ID (formerly Azure AD)](https://portal.azure.com/) and configure your Serverpod application accordingly. |
| 4 | + |
| 5 | +:::caution |
| 6 | +You need to install the auth module before you continue, see [Setup](../../setup). |
| 7 | +::: |
| 8 | + |
| 9 | +## Create your Microsoft Entra ID App |
| 10 | + |
| 11 | +1. Go to [Microsoft Azure Portal](https://portal.azure.com/) and log in with your Microsoft account. |
| 12 | +2. Navigate to **Microsoft Entra ID** from the portal menu. |
| 13 | + |
| 14 | +  |
| 15 | + |
| 16 | +3. Go to **App registrations** and click **New registration**. |
| 17 | + |
| 18 | +  |
| 19 | + |
| 20 | +4. Fill in the required fields: |
| 21 | + - **Name**: Enter a name for your application (e.g., "MyApp Authentication"). |
| 22 | + - **Supported account types**: Choose one of the following: |
| 23 | + - Single tenant only - Default Directory |
| 24 | + - Multiple Entra ID tenants |
| 25 | + - Any Entra ID Tenant + Personal Microsoft accounts |
| 26 | + - Personal accounts only |
| 27 | + - **Redirect URI (optional)**: Leave this blank for now. We'll add platform-specific URIs later. |
| 28 | + |
| 29 | +  |
| 30 | + |
| 31 | +5. Click **Register** to create your app. |
| 32 | + |
| 33 | +## Get app credentials |
| 34 | + |
| 35 | +### Get the client ID |
| 36 | + |
| 37 | +After registration, you'll be redirected to the app overview page where you can find your **Application (client) ID**. Copy this value - you'll need it for server configuration. |
| 38 | + |
| 39 | + |
| 40 | + |
| 41 | +### Create a client secret |
| 42 | + |
| 43 | +1. In your app's menu, navigate to **Certificates & secrets**. |
| 44 | +2. Under **Client secrets**, click **New client secret**. |
| 45 | + |
| 46 | +  |
| 47 | + |
| 48 | +3. Add a description (e.g., "Serverpod Authentication") and choose an expiration period. |
| 49 | +4. Click **Add** and immediately copy the **Value** (not the Secret ID). This is your **Client Secret**. |
| 50 | + |
| 51 | +:::warning |
| 52 | +The client secret value is only shown once. Store it securely immediately after creation. Never commit this value to version control. |
| 53 | +::: |
| 54 | + |
| 55 | +### Get the tenant ID (Optional) |
| 56 | + |
| 57 | +If you're restricting authentication to a specific tenant, you'll need your **Directory (tenant) ID**, which is also shown on the app overview page. For most applications, you can use one of these common values: |
| 58 | + |
| 59 | +- `common`: Allows both personal Microsoft accounts and work/school accounts (default). |
| 60 | +- `organizations`: Allows only work/school accounts. |
| 61 | +- `consumers`: Allows only personal Microsoft accounts. |
| 62 | + |
| 63 | +### Configure redirect URIs |
| 64 | + |
| 65 | +You need to configure redirect URIs for each platform you want to support. |
| 66 | + |
| 67 | +1. In your app's menu, navigate to **Authentication**. |
| 68 | +2. Click **Add a platform** to configure platform-specific settings. |
| 69 | + |
| 70 | +  |
| 71 | + |
| 72 | +#### Web |
| 73 | + |
| 74 | +1. Select **Web** as the platform. |
| 75 | +2. Add your redirect URI, typically in the format: `https://yourdomain.com/auth.html` |
| 76 | + |
| 77 | +  |
| 78 | + |
| 79 | +3. Click **Configure**. |
| 80 | + |
| 81 | +#### iOS and macOS |
| 82 | + |
| 83 | +1. Select **iOS / macOS** as the platform. |
| 84 | +2. For the Bundle ID, enter your app's bundle identifier (e.g., `com.yourcompany.yourapp`). |
| 85 | + |
| 86 | +  |
| 87 | + |
| 88 | +3. Click **Configure**. |
| 89 | + |
| 90 | +:::note |
| 91 | +For iOS/macOS, Microsoft will automatically generate the redirect URI based on your bundle ID. You can also add custom redirect URIs as needed. |
| 92 | +::: |
| 93 | + |
| 94 | +#### Android |
| 95 | + |
| 96 | +1. Select **Android** as the platform. |
| 97 | +2. Enter your Package name (e.g., `com.yourcompany.yourapp`). |
| 98 | +3. Enter your Signature hash. You can get this by running: |
| 99 | + |
| 100 | + ```bash |
| 101 | + keytool -exportcert -alias SIGNATURE_ALIAS -keystore PATH_TO_KEYSTORE | openssl sha1 -binary | openssl base64 |
| 102 | + ``` |
| 103 | + |
| 104 | +  |
| 105 | + |
| 106 | +4. Click **Configure**. |
| 107 | + |
| 108 | +:::tip |
| 109 | +For development, use your debug keystore signature hash. For production builds, use your release keystore signature hash. You can add both to Microsoft Entra ID during setup. |
| 110 | +::: |
| 111 | + |
| 112 | +## Server-side configuration |
| 113 | + |
| 114 | +### Store the credentials |
| 115 | + |
| 116 | +Add your Microsoft credentials to the `config/passwords.yaml` file, or set them as environment variables `SERVERPOD_PASSWORD_microsoftClientId`, `SERVERPOD_PASSWORD_microsoftClientSecret`, and `SERVERPOD_PASSWORD_microsoftTenant`. |
| 117 | + |
| 118 | +```yaml |
| 119 | +development: |
| 120 | + microsoftClientId: 'YOUR_MICROSOFT_CLIENT_ID' |
| 121 | + microsoftClientSecret: 'YOUR_MICROSOFT_CLIENT_SECRET' |
| 122 | + microsoftTenant: 'common' # or 'organizations', 'consumers', or your specific tenant ID |
| 123 | +``` |
| 124 | +
|
| 125 | +:::warning |
| 126 | +Keep your Client Secret confidential. Never commit this value to version control. Store it securely using environment variables or secret management. |
| 127 | +::: |
| 128 | +
|
| 129 | +### Configure the Microsoft Identity Provider |
| 130 | +
|
| 131 | +In your main `server.dart` file, configure the Microsoft identity provider: |
| 132 | + |
| 133 | +```dart |
| 134 | +import 'package:serverpod/serverpod.dart'; |
| 135 | +import 'package:serverpod_auth_idp_server/core.dart'; |
| 136 | +import 'package:serverpod_auth_idp_server/providers/microsoft.dart'; |
| 137 | +
|
| 138 | +void run(List<String> args) async { |
| 139 | + final pod = Serverpod( |
| 140 | + args, |
| 141 | + Protocol(), |
| 142 | + Endpoints(), |
| 143 | + ); |
| 144 | +
|
| 145 | + pod.initializeAuthServices( |
| 146 | + tokenManagerBuilders: [ |
| 147 | + JwtConfigFromPasswords(), |
| 148 | + ], |
| 149 | + identityProviderBuilders: [ |
| 150 | + MicrosoftIdpConfig( |
| 151 | + clientId: pod.getPassword('microsoftClientId')!, |
| 152 | + clientSecret: pod.getPassword('microsoftClientSecret')!, |
| 153 | + tenant: pod.getPassword('microsoftTenant') ?? 'common', |
| 154 | + ), |
| 155 | + ], |
| 156 | + ); |
| 157 | +
|
| 158 | + await pod.start(); |
| 159 | +} |
| 160 | +``` |
| 161 | + |
| 162 | +:::tip |
| 163 | +You can use `MicrosoftIdpConfigFromPasswords()` to automatically load credentials from `config/passwords.yaml` or the `SERVERPOD_PASSWORD_microsoftClientId`, `SERVERPOD_PASSWORD_microsoftClientSecret`, and `SERVERPOD_PASSWORD_microsoftTenant` environment variables: |
| 164 | + |
| 165 | +```dart |
| 166 | +identityProviderBuilders: [ |
| 167 | + MicrosoftIdpConfigFromPasswords(), |
| 168 | +], |
| 169 | +``` |
| 170 | + |
| 171 | +::: |
| 172 | + |
| 173 | +### Expose the endpoint |
| 174 | + |
| 175 | +Create an endpoint that extends `MicrosoftIdpBaseEndpoint` to expose the Microsoft authentication API: |
| 176 | + |
| 177 | +```dart |
| 178 | +import 'package:serverpod_auth_idp_server/providers/microsoft.dart'; |
| 179 | +
|
| 180 | +class MicrosoftIdpEndpoint extends MicrosoftIdpBaseEndpoint {} |
| 181 | +``` |
| 182 | + |
| 183 | +### Generate and migrate |
| 184 | + |
| 185 | +Finally, run `serverpod generate` to generate the client code and create a migration to initialize the database for the provider. More detailed instructions can be found in the general [identity providers setup section](../../setup#identity-providers-configuration). |
| 186 | + |
| 187 | +### Basic configuration options |
| 188 | + |
| 189 | +- `clientId`: Required. The Application (client) ID of your Microsoft Entra ID app. |
| 190 | +- `clientSecret`: Required. The Client Secret generated for your Microsoft Entra ID app. |
| 191 | +- `tenant`: Optional. Defaults to `'common'`. Can be `'common'`, `'organizations'`, `'consumers'`, or a specific tenant ID. |
| 192 | + |
| 193 | +For more details on configuration options, see the [configuration section](./configuration). |
| 194 | + |
| 195 | +## Client-side configuration |
| 196 | + |
| 197 | +Add the `serverpod_auth_idp_flutter` package to your Flutter app. The Microsoft provider uses [`flutter_web_auth_2`](https://pub.dev/packages/flutter_web_auth_2) to handle the OAuth2 flow, so any documentation there should also apply to this setup. |
| 198 | + |
| 199 | +### iOS and macOS |
| 200 | + |
| 201 | +There is no special configuration needed for iOS and macOS for "normal" authentication flows. |
| 202 | +However, if you are using **Universal Links** on iOS, they require redirect URIs to use **https**. |
| 203 | +Follow the instructions in the [flutter_web_auth_2](https://pub.dev/packages/flutter_web_auth_2#ios) documentation. |
| 204 | + |
| 205 | +### Android |
| 206 | + |
| 207 | +In order to capture the callback URL, add the following activity to your `AndroidManifest.xml`. Replace `YOUR_CALLBACK_URL_SCHEME_HERE` and `YOUR_CALLBACK_URL_HOST_HERE` with your actual callback URL scheme and host registered in your Microsoft Entra ID app. |
| 208 | + |
| 209 | +```xml |
| 210 | +<manifest> |
| 211 | + <application> |
| 212 | +
|
| 213 | + <activity |
| 214 | + android:name="com.linusu.flutter_web_auth_2.CallbackActivity" |
| 215 | + android:exported="true" |
| 216 | + android:taskAffinity=""> |
| 217 | + <intent-filter android:label="Microsoft Authentication"> |
| 218 | + <action android:name="android.intent.action.VIEW" /> |
| 219 | + <category android:name="android.intent.category.DEFAULT" /> |
| 220 | + <category android:name="android.intent.category.BROWSABLE" /> |
| 221 | + <data |
| 222 | + android:scheme="YOUR_CALLBACK_URL_SCHEME_HERE" |
| 223 | + android:host="YOUR_CALLBACK_URL_HOST_HERE" /> |
| 224 | + </intent-filter> |
| 225 | + </activity> |
| 226 | +
|
| 227 | + </application> |
| 228 | +</manifest> |
| 229 | +``` |
| 230 | + |
| 231 | +### Web |
| 232 | + |
| 233 | +On the web, you need a specific endpoint to capture the OAuth2 callback. To set this up, create an HTML file (e.g., `auth.html`) inside your project's `./web` folder and add the following content: |
| 234 | + |
| 235 | +```html |
| 236 | +<!DOCTYPE html> |
| 237 | +<title>Authentication complete</title> |
| 238 | +<p>Authentication is complete. If this does not happen automatically, please close the window.</p> |
| 239 | +<script> |
| 240 | + function postAuthenticationMessage() { |
| 241 | + const message = { |
| 242 | + 'flutter-web-auth-2': window.location.href |
| 243 | + }; |
| 244 | +
|
| 245 | + if (window.opener) { |
| 246 | + window.opener.postMessage(message, window.location.origin); |
| 247 | + window.close(); |
| 248 | + } else if (window.parent && window.parent !== window) { |
| 249 | + window.parent.postMessage(message, window.location.origin); |
| 250 | + } else { |
| 251 | + localStorage.setItem('flutter-web-auth-2', window.location.href); |
| 252 | + window.close(); |
| 253 | + } |
| 254 | + } |
| 255 | +
|
| 256 | + postAuthenticationMessage(); |
| 257 | +</script> |
| 258 | +``` |
| 259 | + |
| 260 | +:::note |
| 261 | +You only need a single callback file (e.g. `auth.html`) in your `./web` folder. |
| 262 | +This file is shared across all IDPs that use the OAuth2 utility, as long as your redirect URIs point to it. |
| 263 | +::: |
| 264 | + |
| 265 | +## Present the authentication UI |
| 266 | + |
| 267 | +### Initializing the `MicrosoftSignInService` |
| 268 | + |
| 269 | +Before presenting any sign-in UI, initialize the Microsoft Sign-In service. This step is necessary to configure the service with your Microsoft app credentials. |
| 270 | + |
| 271 | +```dart |
| 272 | +await client.auth.initializeMicrosoftSignIn( |
| 273 | + clientId: 'YOUR_MICROSOFT_CLIENT_ID', |
| 274 | + redirectUri: 'YOUR_REGISTERED_REDIRECT_URI', |
| 275 | +); |
| 276 | +``` |
| 277 | + |
| 278 | +:::info |
| 279 | +For more information on configuration options and environment variables, see the [configuration section](./configuration). |
| 280 | +::: |
| 281 | + |
| 282 | +### Using the `MicrosoftSignInWidget` |
| 283 | + |
| 284 | +If you have configured the `SignInWidget` as described in the [setup section](../../setup#present-the-authentication-ui), the Microsoft identity provider will be automatically detected and displayed in the sign-in widget. |
| 285 | + |
| 286 | +You can also use the `MicrosoftSignInWidget` to include the Microsoft authentication flow in your own custom UI. |
| 287 | + |
| 288 | +```dart |
| 289 | +import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; |
| 290 | +
|
| 291 | +MicrosoftSignInWidget( |
| 292 | + client: client, |
| 293 | + onAuthenticated: () { |
| 294 | + // Do something when the user is authenticated. |
| 295 | + // |
| 296 | + // NOTE: You should not navigate to the home screen here, otherwise |
| 297 | + // the user will have to sign in again every time they open the app. |
| 298 | + }, |
| 299 | + onError: (error) { |
| 300 | + // Handle errors |
| 301 | + ScaffoldMessenger.of(context).showSnackBar( |
| 302 | + SnackBar(content: Text('Error: $error')), |
| 303 | + ); |
| 304 | + }, |
| 305 | +) |
| 306 | +``` |
| 307 | + |
| 308 | +The widget automatically handles: |
| 309 | + |
| 310 | +- Microsoft Sign-In flow for iOS, Android, Web, and macOS. |
| 311 | +- OAuth2 authentication flow. |
| 312 | +- Token management. |
| 313 | +- Underlying OAuth2 package error handling. |
| 314 | + |
| 315 | +For details on how to customize the Microsoft Sign-In UI in your Flutter app, see the [customizing the UI section](./customizing-the-ui). |
0 commit comments