(使用 pub.dev 中的 aad_oauth、flutter_bloc 和 go_router)
访问 Web 应用程序的根目录时,例如 https://example.com,一切都按预期运行。但是,当您尝试直接访问子路由(例如 https://example.com/some/dynamic/route)时,Azure AD 会中断流程。它失败是因为 Azure 无法识别重定向 URI 中的 URL,该 URL 尚未添加到 Azure 配置中。这尤其成问题,因为这些 URL 是动态生成的,无法硬编码到 Azure AD 的配置中。我正在使用 BLoC 状态管理。 让我们分解一下应用程序结构以及问题发生的位置: 直接在我的 main.dart runApp(); 之后我有这个小部件:
class PlatformWidget extends StatelessWidget {
PlatformWidget({super.key});
final AuthRepository authRepository = AuthRepository();
final ReportedBugsRepository reportedBugsRepository = ReportedBugsRepository();
@override
Widget build(BuildContext context) {
print("This gets Called at first");
return MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => AuthBloc(authRepository: authRepository)..add(AuthInitializationEvent()),
),
//.... More Providers
],
child: const AppView(),
));
}
}
然后我来到我的 AppView,在身份验证时进行了切换:
class _AppViewState extends State<AppView> {
@override
Widget build(BuildContext context) {
return BlocBuilder<AuthBloc, AuthState>(builder: (context, state) {
switch (state.status) {
case AuthStatus.inProgress:
//... If AuthStatus.success the GoRouter and RootWidget is getting Loaded
但是,GoRouter 和 rootwidget 甚至没有加载,因为 azure 在树的早期、身份验证期间、我的业务逻辑内部打断了我:
class AuthBloc extends Bloc<AuthEvent, AuthState> {
AuthBloc({required AuthRepository authRepository})
: _authRepository = authRepository,
super(const AuthState.inProgress()) {
on<AuthInitializationEvent>(_onAuthInitialization);
on<AuthLogoutEvent>(_logOut);
}
final AuthRepository _authRepository;
Future<void> _onAuthInitialization(AuthInitializationEvent event, Emitter<AuthState> emit) async {
print("This gets called");
emit(const AuthState.inProgress());
try {
final token = await _authRepository.getToken();
final email = await _authRepository.authenticate(token);
emit(AuthState.authenticated(email));
} catch (e) {
emit(AuthState.failure(e.toString()));
}
}
}
然后我们来到 Repos,Azure 打断了我并抛出了未知路由的错误页面:
class AuthRepository {
late AadOAuth oauth;
AuthRepository() {
final config = Config(
tenant: "...",
clientId: "...",
scope: "User.Read",
navigatorKey: globalNavigatorKey,
webUseRedirect: true,
loader: const Center(child: CircularProgressIndicator()),
);
oauth = AadOAuth(config);
}
Future<String> getToken() async {
String accessToken = "";
try {
final result = await oauth.login();
result.fold(
(failure) => throw Exception(failure.toString()),
(token) => accessToken = token.accessToken!,
);
} catch (e) {
print("Error: $e");
rethrow;
}
return accessToken;
}
Future<String> authenticate(String token) async {
final response = await http.post(
Uri.parse('${BUSINESSLOGIC_URL}/auth/getauth'),
headers: {'Content-Type': 'application/json'},
body: json.encode(token),
);
if (response.statusCode == 200) {
return response.body;
} else {
throw AuthException(response.body, response.statusCode);
}
}
}
首要问题是:如何设置以下身份验证流程? “如果我访问主路由,则正常验证。但是,如果是子路由,请先将我重定向到主路由,在那里验证我的身份,然后将我发送回子路由。”
!!!!!!阅读文档!!!!!!!!! :-D aad包里面有解决这个问题的方法:
final config = Config(
tenant: "-",
clientId: "-",
scope: "User.Read",
navigatorKey: globalNavigatorKey,
redirectUri: "${WEBSITE_URL}", //<--- You can place root URL or auth url here
webUseRedirect: true,
loader: const Center(child: CircularProgressIndicator()),
);
现在我正确重定向了。