I currently trying to realize an Azure Active Directory authentication in Flutter Web using the aad_OAuth (v1.0.0, last version) plackage from pub.dev.
I just grab the example from the package and configure it with my informations.
Here is the main.dart file:
import 'package:aad_oauth/aad_oauth.dart';
import 'package:aad_oauth/model/config.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
final navigatorKey = GlobalKey<NavigatorState>();
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AAD OAuth Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'AAD OAuth Home'),
navigatorKey: navigatorKey,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static final Config config = Config(
redirectUri: "http://localhost:64444/",
tenant: '******',
clientId: '******',
scope: 'openid profile offline_access',
navigatorKey: navigatorKey,
loader: SizedBox(),
appBar: AppBar(
title: Text('AAD OAuth Demo'),
),
clientSecret: '******',
);
final AadOAuth oauth = AadOAuth(config);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView(
children: <Widget>[
ListTile(
title: Text(
'AzureAD OAuth',
style: Theme.of(context).textTheme.headlineSmall,
),
),
ListTile(
leading: Icon(Icons.launch),
title: Text('Login${kIsWeb ? ' (web popup)' : ''}'),
onTap: () {
login(false);
},
),
if (kIsWeb)
ListTile(
leading: Icon(Icons.launch),
title: Text('Login (web redirect)'),
onTap: () {
login(true);
},
),
ListTile(
leading: Icon(Icons.data_array),
title: Text('HasCachedAccountInformation'),
onTap: () => hasCachedAccountInformation(),
),
ListTile(
leading: Icon(Icons.logout),
title: Text('Logout'),
onTap: () {
logout();
},
),
],
),
);
}
void showError(dynamic ex) {
print(ex.toString());
showMessage(ex.toString());
}
void showMessage(String text) {
var alert = AlertDialog(content: Text(text), actions: <Widget>[
TextButton(
child: const Text('Ok'),
onPressed: () {
Navigator.pop(context);
})
]);
showDialog(context: context, builder: (BuildContext context) => alert);
}
void login(bool redirect) async {
config.webUseRedirect = redirect;
final result = await oauth.login();
result.fold(
(l) => showError(l.toString()),
(r) => showMessage('Logged in successfully, your access token: $r'),
);
var accessToken = await oauth.getAccessToken();
if (accessToken != null) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(accessToken)));
}
}
void hasCachedAccountInformation() async {
var hasCachedAccountInformation = await oauth.hasCachedAccountInformation;
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text('HasCachedAccountInformation: $hasCachedAccountInformation'),
),
);
}
void logout() async {
await oauth.logout();
showMessage('Logged out');
}
}
When executing this dart code with flutter run -d chrome --web-port=64444
and using the popup method for authenticating, popup start well, i can authenticate with Microsot AZURE well.
But when the popup close, i return on Flutter application and the MSAL Browser library call the url https://login.microsoftonline.com/****/oauth2/v2.0/token
to get access token. And the POST request fail with:
AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.
It try with setting a secret in AZURE AD and without. In both case i get this message.
AZURE AD is configure with a web redirect URY equal to http://localhost:64444/
I have read many post asking to set Allow public customer flows to yes, that'"s what i do.
At this time i don't know if it's a problem with my AZURE configuration or if it's a problem with my code or aad_OAuth code.
Last, i also try with an SPA redirection URI, but in this case i got this error:
AADSTS9002327: Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests.
EDIT
The POST request to token endpoint don't contains the client_secret parameter.
So what i do is capturing the POST request as curl format from chrome devtools. Then, if i execute the curl after adding manually the client_secret, the token endpoint respond by sending the access token.
So it seems that the MSAL lib used by aad_oauth package not using the clientSecret provide by the package.
FIXED
Problem is with headers sent by chrome navigator to AZURE AD.
For debugging purpose, chrome browser was launched by the
flutter run -d chrome
command with the--disable-web-security
flag.With this flag, AZURE AD issue the AADSTS9002327: Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests. error message.
Launching chrome without this flag make the request accepted by AZURE AD.