Azure AD B2C Embedded Webview is a very simple Flutter package that demonstrates how to use the embedded web view to sign in users with Azure AD B2C. Currently, using Flutter packages - appAuth and flutter_azure_b2c redirects to browser and doesn't provide in-app experience.
This package embeds the web view of the user flow endpoint using flutter_appview and redirects the user as per onRedirect callback method.
Embedded web view for Azure AD B2C for providing in-app experience Redirects to the route specified in redirectRoute after successful sign in Successfully secures the id token or access token in the app using flutter secure storage Navigates to screen in app after successful sign in
To use the package in your Flutter app, add the following code to your main.dart file:
dependencies:
aad_b2c_webview: <latest_version>
To add the easy to use sign in with microsoft button simply use the AADLoginButton widget and a beautiful sign in button appears as shown below.
Add the following /android/app/src/main/AndroidManifest.xml
inside the tags:
<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="myurl.com" />
</intent-filter>
Change the redirect URL in our flutter code to https://myurl.com/myappname
and add this as a redirect URL in the Azure AD B2C project
Our updated version of the main.dart file is now as follows:
import 'package:aad_b2c_webview/aad_b2c_webview.dart';
import 'package:flutter/material.dart';
import 'counterdemo.dart';
void main() {
runApp(const MyApp());
}
onRedirect(BuildContext context) {
Navigator.of(context).pushNamedAndRemoveUntil('/myappname', (Route<dynamic> route) => false);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: const Color(0xFF2F56D2),
textTheme: const TextTheme(
headlineLarge: TextStyle(
color: Colors.black,
fontSize: 32,
fontWeight: FontWeight.w700,
fontFamily: 'UberMove',
),
bodyLarge: TextStyle(
color: Color(0xFF8A8A8A),
fontSize: 17,
fontWeight: FontWeight.w400,
fontFamily: 'UberMoveText',
),
displayMedium: TextStyle(
fontSize: 18,
color: Colors.black,
fontWeight: FontWeight.w700,
fontFamily: 'UberMove',
),
),
),
debugShowCheckedModeBanner: false,
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the Create Account widget.
'/': (context) => const LoginPage(),
'/myappname': (context) => const CounterDemo(),
},
);
}
}
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
String? jwtToken;
String? refreshToken;
@override
Widget build(BuildContext context) {
const aadB2CClientID = "<app-id>";
const aadB2CRedirectURL = "https://myurl.com/myappname";
const aadB2CUserFlowName = "B2C_1_APPNAME_Signin";
const aadB2CScopes = ['openid', 'offline_access'];
const aadB2TenantName = "<tenantName>";
const aadB2CUserAuthFlow =
"https://$aadB2TenantName.b2clogin.com/$aadB2TenantName.onmicrosoft.com";
return Scaffold(
appBar: AppBar(
title: const Text("AAD B2C Login"),
backgroundColor: const Color(0xFF2F56D2)
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
/// Login flow
AADLoginButton(
userFlowUrl: aadB2CUserAuthFlow,
clientId: aadB2CClientID,
userFlowName: aadB2CUserFlowName,
redirectUrl: aadB2CRedirectURL,
context: context,
scopes: aadB2CScopes,
onAnyTokenRetrieved: (Token anyToken) {},
onIDToken: (Token token) {
jwtToken = token.value;
},
onAccessToken: (Token token) {
},
onRefreshToken: (Token token) {
refreshToken = token.value;
},
onRedirect: (context) => onRedirect(context),
),
/// Refresh token
TextButton(
onPressed: () async {
if (refreshToken != null) {
AzureTokenResponse? response =
await ClientAuthentication.refreshTokens(
refreshToken: refreshToken!,
tenant: aadB2TenantName,
policy: aadB2CUserAuthFlow,
clientId: aadB2CClientID,
);
if (response != null) {
refreshToken = response.refreshToken;
jwtToken = response.idToken;
}
}
},
child: const Text("Refresh my token"),
),
TextButton(
onPressed: () async {
Navigator.pushNamed(context, '/myappname');
},
child: const Text("Go To Counter Demo"),
)
],
),
),
);
}
}
Simply call page direct or use custom build sign in button to call web view page
import 'package:aad_b2c_webview/aad_b2c_webview.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class MyLoginPage extends StatelessWidget {
const MyLoginPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
const aadB2CClientID = "<clientId>";
const aadB2CRedirectURL = "<azure_active_directory_url_redirect>";
const aadB2CUserFlowName = "B2C_<name_of_userflow>";
const aadB2CScopes = ['openid', 'offline_access'];
const aadB2CUserAuthFlow =
"https://<tenant-name>.b2clogin.com/<tenant-name>.onmicrosoft.com"; // https://login.microsoftonline.com/<azureTenantId>/oauth2/v2.0/token/
const aadB2TenantName = "<tenant-name>";
return Scaffold(
body: ADB2CEmbedWebView(
tenantBaseUrl: aadB2CUserAuthFlow,
userFlowName: aadB2CUserFlowName,
clientId: aadB2CClientID,
redirectUrl: aadB2CRedirectURL,
scopes: aadB2CScopes,
onAnyTokenRetrieved: (Token anyToken) {},
onIDToken: (Token token) {},
onAccessToken: (Token token) {},
onRefreshToken: (Token token) {},
),
);
}
}
In the AADLoginButton
widget, you have the flexibility to include optional parameters in order to customize the URL according to your specific requirements. The optionalParameters
parameter allows you to pass a list of OptionalParam
objects, where each object consists of a key and a value that represent the parameter name and its corresponding value, respectively.
Here's an example of how you can utilize the optionalParameters
parameter to add new parameters to the URL:
optionalParameters: [
OptionalParam(key: "parameter1", value: "value1"),
OptionalParam(key: "parameter2", value: "value2"),
],
In the above example, we include two optional parameters: "parameter1" with the value "value1" and "parameter2" with the value "value2". You can include multiple OptionalParam
objects within the list to incorporate multiple optional parameters in the URL.
These optional parameters provide you with the ability to customize the behavior of the URL and conveniently transmit additional information as per your needs.
Please adapt the example to suit your specific use case or requirements.
aad_b2c_webview's People
Forkers
sleeknoah joaovvrodrigues nnoxx-inc jspersonal jaym-xa andreimorozov fullstackweb-developer szczygieldev saberza mpp-marcink udenordhorn filip8600 craig-waite saulopef jnelle alissonmmenezes ravivr-dev benedikthofer sathishcyberintelsys imfelixngaad_b2c_webview's Issues
Bug with login using web view - method call in the wrong place
Hi, first thanks for creating this library, great work and it's saving some time for us :)
After I tried to implement the web view in my app, I found issues related to it. I will try to explain it in detail and I hope you will not mind because I want to help you improve this package.
So you have the method onPageFinishedTasks(URL, response); that is being called inside of onPageFinished. That method for checking the URL is called only once when the login screen is initially loaded, and that's it. If I input the credentials for login nothing happens, because onPageFinished is calling onPageFinishedTasks(URL, response) only once, and that's the case when the login screen is being loaded.
Further debugging leads me to the conclusion that the right place to call the method onPageFinishedTasks(URL, response); is inside of navigationDelegate property because that field is being triggered every time the user interacts with the screen and tries to log in.
I tried this solution in my app and it's working perfectly, also I have tried your's and it's not working. If you have any questions or maybe I was not clear enough please text me I am open to help :)
Not compatible with webview_flutter ^4
I would like to know if support for webview_flutter ^4 is on the current roadmap.
If not, can I contribute a new version that supports webview_flutter ^4?
When ios wrapper will be release
Dear Microsoft team
Is there any plan to release iOS platform support ?
Thank you
Web support
Hi and thanks for an amazing package. Is there any plans on going web as well? That would be awesome!
Add Support For Enable Keep Me Signed In Flow - Flutter Username Password autofill from next session if already added remember me option
Hey @mohanajuhi166 @microsoftopensource @Baxi19 @Sleeknoah
I was recently wanted to add the feature option to enable keep me signed in feature using microsoft b2c login, But I don't find any support using this package. I've added changes to B2C policy as guided in the following official blog,
https://github.com/azure-ad-b2c/unit-tests/tree/main/session#enable-keep-me-signed-in-kmsi
So can you please help adding support from flutter side keep me signed in feature using this package?
Thanks
WebView does not handle email and password autocomplete during re-login
Hello,
I’m currently using version aad_b2c_webview: ^0.0.57 of the SDK.
When prompting the user to log in again, the WebView does not manage the email and password autocomplete that the browser usually handles. This behavior works as expected when the login is performed directly through the policy in the browser, but not within the WebView context.
Is there a way for this package to recognize the last-used credentials and automatically trigger the autocomplete for the user's email and password during re-login? If not, are there any recommendations or configurations to enable such behavior?
Which redirect url should I use?
Hello, first, congrats on the project, it makes the user experience with azure ad b2c much better.
I was trying to setup on my app, but I'm having trouble with the redirect url.
For example if my bundle id is com.example.mobile and the redirect url on azure ad b2c for ios is msauth.com.example.mobile://auth, what should I replace that as redirect url?
I tried to create a SPA redirect url on azure ad b2c, put a random url and it redirected after login, but I need to make it come back to the app instead of visiting another url.
Any ideas on how to fix this? Thanks!
Not getting access token
I am always getting access token as null, I can able to get IDToken and RefreshToken.
Could you please assist to resolve this issue
Not able to logout user for azure b2c login
Hey @mohanajuhi166 @microsoftopensource I was trying this official flutter package following is my code for azure b2c login.
const aadB2CClientID = 'random-95eb-val-a09b-token';
const aadB2CRedirectURL = 'https://login.live.com/oauth0_desktop.srf';
const aadB2CUserFlowName = 'B2C_1A_signin_Mobile_Dev';
const aadB2CScopes = ['openid', 'offline_access'];
const aadB2TenantName = 'testTenantName';
const aadB2CUserAuthFlow = 'https://<aadB2TenantName>.b2clogin.com/tfp/<aadB2TenantName>.onmicrosoft.com/';
return Scaffold(
body: ADB2CEmbedWebView(
tenantBaseUrl: aadB2CUserAuthFlow,
userFlowName: aadB2CUserFlowName,
clientId: aadB2CClientID,
redirectUrl: aadB2CRedirectURL,
scopes: aadB2CScopes,
onAnyTokenRetrieved: (Token anyToken) {},
onIDToken: (Token token) {
log('idToken==> ${token?.value ?? ''}');
},
onAccessToken: (Token token) {
accessToken = token.value;
log('accessToken==> ${accessToken ?? ''}');
},
onRefreshToken: (Token token) {
refreshToken = token.value;
log('refreshToken==> ${refreshToken ?? ''}');
},
optionalParameters: const [],
onRedirect: (context) {
log('accessToken==> ${accessToken ?? ''}');
log('refreshToken==> ${refreshToken ?? ''}');
return {
// Push user to new screen.
};
},
),
);
The whole flow is working perfectly fine, i'm getting accesstoken and refreshtoken both. So how can I manage the session for this user? How to logout user?
Can you please provide some solution on this?
Thanks.
Not compatible with the latest version of flutter
Thanks for making this useful package.
But I can't use this with flutter 3.0.5
The lower bound of "sdk: '>=2.3.0 <3.0.0'" must be 2.12.0 or higher to enable null safety.
I really want to use this package in my project, is there any solution?
Please let me know how I can contribute to this repository to make this possible.
Forget Password back button click is not redirect to login screen.
Library stops working after 0.0.51 for Android
Good evening,
I was using the 0.0.51 version and it works fine on Android.
To make it work on iOS I had to upgrade it but now the same stopped working on Android.
After some tests I noticed iOS starts working after version 0.0.53 while Andrid stops working after 0.0.51
My implementation is pretty much linear
return ADB2CEmbedWebView( loadingReplacement: const Loading(), optionalParameters: const [], tenantBaseUrl: aadB2CUserAuthFlow, userFlowName: aadB2CUserFlowName, clientId: aadB2CClientID, redirectUrl: aadB2CRedirectURL, onRedirect: (context) => Loading.modalLoading(), scopes: aadB2CScopes, onAnyTokenRetrieved: (Token anyToken) { ... }, onIDToken: (Token token) { ... }, onAccessToken: (Token token) { ... }, onRefreshToken: (Token token) { ... }, );
Debugging inside the library the errors seems to be the following:
Response ({"error":"invalid_request","error_description":"AADB2C90117: The scope 'openid%20offline_access%20profile%20https://myWebSite.onmicrosoft.com/exm.be.webapi/access_as_user' provided in the request is not supported.\r\nCorrelation ID: 53dc1c3f-a814-428c-8adf-a3153d5eb8b3\r\nTimestamp: 2024-03-07 13:24:06Z\r\n"})
It's strange the scopes are the problem, because on iOS the login is working fine and on Android it's working until 0.0.52
Do I have to modify something when upgrading over 0.0.51 for Android to work?
Redirect uri
Hi,
First of all thanks for this library
I have implemented the code given in the example in pubdev. After pressing the button, I am able to receive in the callbacks of the widget (onIDToken and onAnyTokenRetrieved) receiving correctly the token given by B2c auth. The callback onRedirect is also being call correctly and i am able to navigate to another screen (my home screen). My only issue, is that after logging in the browser can't find the redirect url of the schema, the message shown in the browser of the mobile phone after login is: .com.example/authapp://oauthredirect/?code........ could not be loaded because net::ERR_UNKNOWN_URL_SCHEME
I had created (in android) a schema in the manifest adding in the activity tag
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="com.example.authapp"
android:host="oauthredirect"
/>
</intent-filter>
I tried to handle the url by installing the library uni_links and adding a listener in the main function :
class _MyAppState extends State<MyApp> {
@override
void initState() {
initUniLinks();
// TODO: implement initState
super.initState();
}
void initUniLinks() async {
getInitialLink().then((String? link) {
if (link != null) {
// Handle the link
}
});
linkStream.listen((String? link) {
if (link != null &&
link.startsWith('com.example.authapp://oauthredirect')) {
final Uri uri = Uri.parse(link);
final String code = uri.queryParameters['code']!;
// Now you have the code, proceed with your authentication flow
}
if (link != null) {
// Handle the link
}
}, onError: (err) {
// Handle the error
});
}
But when I debug the code, the breakpoint in the listener (breakpoint in line if (link != null &&
link.startsWith('com.example.authapp://oauthredirect')) ) is never reached.
I am a little bit lost what I need to do in order to show instead of a broken url text a loading progress or something like that during this fraction of second between the the token retrieved and the redirect callback that is sending the user to the home page.
Thanks.
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I'm getting the resource you are looking for has been removed, had its name changed, or is temporarily unavailable on Android.
ERROR the request does not contains a client id parameter
Please help on React Native b2c login
I need MSAL plugin for react native
Google login error that says “403 disallowed_useragent,”
hi there,
I configured and tested the Azure AD B2C setup for Microsoft and Google logins. It worked.
When i use the ADB2CEmbedWebView from my Android code, Microsoft login works, but Google login errors out with “403 disallowed_useragent,”.
On google's support website, it clearly states that "_Embedded WebViews puts your security at risk because they could let third parties access and change communications between you and Google.".
update: 7/3/24 - After enabling Facebook access, get the same message "logging in to Facebook from an embedded browser is disabled".
Does this mean its not a good practice to use Embedded webviews? @mohanajuhi166 would be keen to get your thoughts
Redirecting on IOS
Hi guys, i have issue with redirection after login on IOS. Tried different redirect URI's and nothing is happening. In logs on azure I can see that user is successfully log in, but after i click Sign in button nothing is happening. Any idea how to solve redirection issue? Thank you
Occasional white screen
I am using ADB2CEmbedWebView to login in a Flutter app. Occasionally the url is not reached and the app is just showing a white screen. This mostly happens running the app in Android Studio.
Before I run ADB2CEmbedWebView I lookup the url's dns to ensure it can be reached and then only run ADB2CEmbedWebView.
Can someone please let me know how to catch the exception or fix it?
import 'dart:async';
import 'package:aad_b2c_webview/aad_b2c_webview.dart';
import 'package:dnsolve/dnsolve.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:logger/logger.dart';
import 'package:mhrm/constants/app_colors.dart';
import 'package:mhrm/constants/app_constants.dart';
import 'package:mhrm/constants/typography.dart';
import 'package:mhrm/navigation/navigation_utils.dart';
import 'package:mhrm/providers/notifiers_provider.dart';
import 'package:mhrm/services/notifiers/auth/states/auth_state.dart';
import 'package:mhrm/utils/app_localizations.dart';
import 'package:mhrm/widgets/generic/dialog/one_button_popup.dart';
class LoginPage extends ConsumerStatefulWidget {
const LoginPage({super.key});
@override
ConsumerState<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends ConsumerState<LoginPage> {
final Logger _logger = Logger();
String? _userToken;
late Timer _watchdogTimer;
late Timer _reloadTimer;
int _count = 0;
bool _canReach = false;
onRedirect(BuildContext context) async {
_logger.d('LoginPage onRedirect ');
var token = _userToken ?? "";
await ref.read(authProvider.notifier).setAccessToken(token);
}
onRefreshToken(Token token) async {
_logger.d('LoginPage onRefreshToken ');
await ref.read(authProvider.notifier).setRefreshToken(token.value);
}
backToSplash() {
_watchdogTimer.cancel();
Future.delayed(Duration.zero, () {
GoRouter.of(context).go(splashPath);
});
}
reloadLogin() {
Future.delayed(Duration.zero, () {
GoRouter.of(context).go(loginPath);
});
}
@override
void initState() {
_watchdogTimer = Timer(const Duration(seconds: 300), () {
_logger.d('LoginPage timeout');
backToSplash();
});
_reloadTimer = Timer(const Duration(milliseconds: 500), () {
_logger.d('LoginPage Reload');
reloadLogin();
});
super.initState();
}
@override
void dispose() {
_watchdogTimer.cancel();
_reloadTimer.cancel();
super.dispose();
}
Future<void> dNSolve() async {
ResolveResponse response = await dnsLookup();
if (response.answer!.records != null) {
for (final record in response.answer!.records!) {
_logger.d('LoginPage DNS resolved ${record.toBind}');
}
setState(() {
_canReach = true;
});
} else {
_logger.d('LoginPage $_count try DNS could not be resolved!! ');
setState(() {
_count++;
_canReach = false;
});
}
}
Future<ResolveResponse> dnsLookup() async {
final dnSolve = DNSolve();
return await dnSolve.lookup(
//'dgsgd',
'https://mhrb2cdev.b2clogin.com',
dnsSec: true,
type: RecordType.srv,
);
}
@override
Widget build(BuildContext context) {
final localizations = AppLocalizations.of(context);
final AuthState authState = ref.watch(authProvider);
if (_count < 4 && !_canReach) {
dNSolve();
if (_count >= 3) {
Future.delayed(Duration.zero, () {
OneButtonPopup.showPopupDialog(
context: context,
heading: localizations.translate('dns_error'),
buttonString: localizations.translate('reload'),
onButton: () {},
body: Text(
localizations.translate('dns_error_info'),
style: TypeScale.s12w500grey8x404040,
),
);
backToSplash();
});
}
}
if (authState.isAuthenticated) {
_watchdogTimer.cancel();
Future.delayed(Duration.zero, () {
GoRouter.of(context).go(homePath);
});
}
if (_canReach) {
return Scaffold(
body: Column(
children: [
Expanded(
child: ADB2CEmbedWebView(
tenantBaseUrl: AppConstants.aadB2CUserAuthFlow,
userFlowName: AppConstants.aadB2CUserFlowName,
clientId: AppConstants.aadB2CClientID,
redirectUrl: AppConstants.aadB2CRedirectURL,
scopes: AppConstants.aadB2CScopes,
onAnyTokenRetrieved: (Token anyToken) {
_logger.d('LoginPage onAnyTokenRetrieved type ${anyToken.type}');
},
onIDToken: (Token token) {
_logger.d('LoginPage onIDToken type ${token.type}');
_userToken = token.value;
},
onAccessToken: (Token token) {
_logger.d('LoginPage onAccessToken type ${token.type}');
},
onRefreshToken: onRefreshToken,
onErrorOrCancel: (context) {
_logger.d('LoginPage ADB2CEmbedWebView onErrorOrCancel');
backToSplash();
},
optionalParameters: const [],
onRedirect: onRedirect,
),
),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
AppColors.grey6x737373,
),
shadowColor: MaterialStateProperty.all(
AppColors.grey2xD9D9D9,
),
elevation: MaterialStateProperty.all<double>(0),
),
onPressed: () {
backToSplash();
},
child: Text(
localizations.translate('reload_login_page'),
style: TypeScale.s12w500white,
),
),
],
),
);
} else {
return Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/login_background.jpg"),
fit: BoxFit.cover,
),
),
child: Column(
children: [
const SizedBox(
height: 142,
),
Image.asset(
"assets/images/logo/logo.png",
fit: BoxFit.cover,
width: 232,
height: 155,
),
],
),
);
}
}
}
I/flutter (17740): │ #0 AADB2CAuthService.refreshAuthToken (package:mhrm/services/auth/aadb2c_auth_service.dart:258:12)
I/flutter (17740): │ #1
I/flutter (17740): │ 🐛 refreshAuthToken ServiceResult.success(authTokenResponse.idToken!)
I/ViewRootImpl@ca848a1MainActivity: ViewPostIme pointer 0
I/ViewRootImpl@ca848a1MainActivity: ViewPostIme pointer 1
[GoRouter] going to /login
W/WindowOnBackDispatcher(17740): sendCancelIfRunning: isInProgress=falsecallback=io.flutter.embedding.android.FlutterActivity$1@ed8ff44
I/flutter (17740): │ #0 _LoginPageState.initState. (package:mhrm/screens/login/login_screen.dart:64:15)
I/flutter (17740): │ #1 Timer._createTimer. (dart:async-patch/timer_patch.dart:18:15)
I/flutter (17740): │ 🐛 LoginPage Reload
[GoRouter] going to /login
I/flutter (17740): │ #0 _LoginPageState.dNSolve (package:mhrm/screens/login/login_screen.dart:82:17)
I/flutter (17740): │ #1
I/flutter (17740): │ 🐛 LoginPage DNS resolved https://mhrb2cdev.b2clogin.com. 300 IN CNAME "prda.aadg.msidentity.com."
I/flutter (17740): │ #0 _LoginPageState.dNSolve (package:mhrm/screens/login/login_screen.dart:82:17)
I/flutter (17740): │ #1
I/flutter (17740): │ 🐛 LoginPage DNS resolved prda.aadg.msidentity.com. 9 IN CNAME "www.tm.a.prd.aadg.akadns.net."
W/ziparchive(17740): Unable to open '/data/app/~~IGlevzahHjeBRxkXyjMtMA==/com.google.android.trichromelibrary_636705433-6hI3TlGcTqglbAKrVN1oAg==/base.dm': No such file or directory
W/ziparchive(17740): Unable to open '/data/app/~~IGlevzahHjeBRxkXyjMtMA==/com.google.android.trichromelibrary_636705433-6hI3TlGcTqglbAKrVN1oAg==/base.dm': No such file or directory
W/mhrmpanelmember(17740): Entry not found
D/nativeloader(17740): Configuring clns-5 for other apk /data/app/~~IGlevzahHjeBRxkXyjMtMA==/com.google.android.trichromelibrary_636705433-6hI3TlGcTqglbAKrVN1oAg==/base.apk. target_sdk_version=34, uses_libraries=ALL, library_path=/data/app/~~DQlDmqjEPDgxDA_qXa2JGA==/com.google.android.webview-ZbwGemP2oeVUcabVu4t7EQ==/lib/arm64:/data/app/~~DQlDmqjEPDgxDA_qXa2JGA==/com.google.android.webview-ZbwGemP2oeVUcabVu4t7EQ==/base.apk!/lib/arm64-v8a:/data/app/~~IGlevzahHjeBRxkXyjMtMA==/com.google.android.trichromelibrary_636705433-6hI3TlGcTqglbAKrVN1oAg==/base.apk!/lib/arm64-v8a, permitted_path=/data:/mnt/expand
D/nativeloader(17740): Extending system_exposed_libraries: libaudiomirroring_jni.audiomirroring.samsung.so:lib.engmodejni.samsung.so:libheifcapture_jni.media.samsung.so:libjpegsq.media.samsung.so:libslljpeg.media.samsung.so:libsemimagecrop_jni.media.samsung.so:libsimba.media.samsung.so:libamDNN.media.samsung.so:libamDNN.media.samsung.so:libapex_motionphoto_utils_jni.media.samsung.so:libsume_mediabuffer_jni.media.samsung.so:libSlowShutter_jni.media.samsung.so:libapex_jni.media.samsung.so:libsume_jni.media.samsung.so:libneural.snap.samsung.so:libsecuresnap_aidl.snap.samsung.so:libsnap_aidl.snap.samsung.so:libeden_rt_stub.edensdk.samsung.so:libSDKRecognitionOCR.spenocr.samsung.so:libSDKMoireDetector.spenocr.samsung.so:libtensorflowlite_c.spenocr.samsung.so:libSFEffect.fonteffect.samsung.so:libperfsdk.performance.samsung.so:libvesgraphicframework.videoeditor.samsung.so:libvesinterface.videoeditor.samsung.so:libvesframework.videoeditor.samsung.so:libveframework.videoeditor.samsung.so:lib_vnd_client.dk.samsung.so:lib_native_client.dk.sa
D/nativeloader(17740): Configuring clns-6 for other apk /data/app/~~DQlDmqjEPDgxDA_qXa2JGA==/com.google.android.webview-ZbwGemP2oeVUcabVu4t7EQ==/base.apk. target_sdk_version=34, uses_libraries=, library_path=/data/app/~~DQlDmqjEPDgxDA_qXa2JGA==/com.google.android.webview-ZbwGemP2oeVUcabVu4t7EQ==/lib/arm64:/data/app/~~DQlDmqjEPDgxDA_qXa2JGA==/com.google.android.webview-ZbwGemP2oeVUcabVu4t7EQ==/base.apk!/lib/arm64-v8a:/data/app/~~IGlevzahHjeBRxkXyjMtMA==/com.google.android.trichromelibrary_636705433-6hI3TlGcTqglbAKrVN1oAg==/base.apk!/lib/arm64-v8a, permitted_path=/data:/mnt/expand
I/WebViewFactory(17740): Loading com.google.android.webview version 124.0.6367.54 (code 636705433)
I/cr_WVCFactoryProvider(17740): Loaded version=124.0.6367.54 minSdkVersion=29 isBundle=true multiprocess=true packageId=2
I/chromium(17740): [0422/083738.202748:INFO:variations_seed_loader.cc(66)] Failed to open file for reading.: No such file or directory (2)
I/cr_LibraryLoader(17740): Successfully loaded native library
I/cr_CachingUmaRecorder(17740): Flushed 6 samples from 6 histograms, 0 samples were dropped.
I/cr_CombinedPProvider(17740): #registerProvider() provider:WV.V7@eb97547 isPolicyCacheEnabled:false policyProvidersSize:0
I/cr_PolicyProvider(17740): #setManagerAndSource() 0
I/cr_CombinedPProvider(17740): #linkNativeInternal() 1
I/cr_AppResProvider(17740): #getApplicationRestrictionsFromUserManager() Bundle[EMPTY_PARCEL]
I/cr_PolicyProvider(17740): #notifySettingsAvailable() 0
I/cr_CombinedPProvider(17740): #onSettingsAvailable() 0
I/cr_CombinedPProvider(17740): #flushPolicies()
D/CompatibilityChangeReporter(17740): Compat change id reported: 214741472; UID 10542; state: ENABLED
D/CompatibilityChangeReporter(17740): Compat change id reported: 171228096; UID 10542; state: ENABLED
D/ConnectivityManager(17740): StackLog:
[android.net.ConnectivityManager.sendRequestForNetwork(ConnectivityManager.java:4401)]
[android.net.ConnectivityManager.registerDefaultNetworkCallbackForUid(ConnectivityManager.java:4965)]
[android.net.ConnectivityManager.registerDefaultNetworkCallback(ConnectivityManager.java:4932)]
[WV.mD.e(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:44)]
[WV.mD.b(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:1)]
[org.chromium.android_webview.AwContentsLifecycleNotifier.onFirstWebViewCreated(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:22)]
[J.N.MFiR_zHY(Native Method)]
[org.chromium.android_webview.AwContents.(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:450)]
[com.android.webview.chromium.j.run(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:147)]
[WV.WY.b(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:20)]
[WV.VY.run(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:3)]
[org.chromium.base.task.PostTask.d(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:11)]
[WV.WY.a(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:23)]
[com.android.webview.chromium.WebViewChromiumFactoryProvider.a(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:3)]
[com.android.webview.chromium.WebViewChromium.init(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:327)]
[android.webkit.WebView.(WebView.java:444)]
[android.webkit.WebView.(WebView.java:364)]
[android.webkit.WebView.(WebView.java:346)]
[android.webkit.WebView.(WebView.java:333)]
[android.webkit.WebView.(WebView.java:323)]
[io.flutter.plugins.webviewflutter.WebViewHostApiImpl$WebViewPlatformView.(WebViewHostApiImpl.java:109)]
[io.flutter.plugins.webviewflutter.WebViewHostApiImpl$WebViewPlatformView.(WebViewHostApiImpl.java:96)]
[io.flutter.plugins.webviewflutter.WebViewHostApiImpl$WebViewProxy.createWebView(WebViewHostApiImpl.java:55)]
[io.flutter.plugins.webviewflutter.WebViewHostApiImpl.create(WebViewHostApiImpl.java:237)]
[io.flutter.plugins.webviewflutter.GeneratedAndroidWebView$WebViewHostApi$-CC.lambda$setup$0(GeneratedAndroidWebView.java:1004)]
[io.flutter.plugins.webviewflutter.GeneratedAndroidWebView$WebViewHostApi$$ExternalSyntheticLambda0.onMessage(Unknown Source:2)]
[io.flutter.plugin.common.BasicMessageChannel$IncomingMessageHandler.onMessage(BasicMessageChannel.java:261)]
[io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)]
[io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)]
[io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)]
D/ConnectivityManager(17740): StackLog: [android.net.ConnectivityManager.sendRequestForNetwork(ConnectivityManager.java:4401)] [android.net.ConnectivityManager.sendRequestForNetwork(ConnectivityManager.java:4443)] [android.net.ConnectivityManager.registerNetworkCallback(ConnectivityManager.java:4825)] [WV.mD.e(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:93)] [WV.mD.b(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:1)] [org.chromium.android_webview.AwContentsLifecycleNotifier.onFirstWebViewCreated(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:22)] [J.N.MFiR_zHY(Native Method)] [org.chromium.android_webview.AwContents.(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:450)] [com.android.webview.chromium.j.run(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:147)] [WV.WY.b(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:20)] [WV.VY.run(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:3)] [org.chromium.base.task.PostTask.d(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:11)] [WV.WY.a(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:23)] [com.android.webview.chromium.WebViewChromiumFactoryProvider.a(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:3)] [com.android.webview.chromium.WebViewChromium.init(chromium-TrichromeWebViewGoogle6432.aab-stable-636705433:327)] [android.webkit.WebView.(WebView.java:444)] [android.webkit.WebView.(WebView.java:364)] [android.webkit.WebView.(WebView.java:346)] [android.webkit.WebView.(WebView.java:333)] [android.webkit.WebView.(WebView.java:323)] [io.flutter.plugins.webviewflutter.WebViewHostApiImpl$WebViewPlatformView.(WebViewHostApiImpl.java:109)] [io.flutter.plugins.webviewflutter.WebViewHostApiImpl$WebViewPlatformView.(WebViewHostApiImpl.java:96)] [io.flutter.plugins.webviewflutter.WebViewHostApiImpl$WebViewProxy.createWebView(WebViewHostApiImpl.java:55)] [io.flutter.plugins.webviewflutter.WebViewHostApiImpl.create(WebViewHostApiImpl.java:237)] [io.flutter.plugins.webviewflutter.GeneratedAndroidWebView$WebViewHostApi$-CC.lambda$setup$0(GeneratedAndroidWebView.java:1004)] [io.flutter.plugins.webviewflutter.GeneratedAndroidWebView$WebViewHostApi$$ExternalSyntheticLambda0.onMessage(Unknown Source:2)] [io.flutter.plugin.common.BasicMessageChannel$IncomingMessageHandler.onMessage(BasicMessageChannel.java:261)] [io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)] [io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)] [io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)]
W/cr_media(17740): BLUETOOTH_CONNECT permission is missing.
W/cr_media(17740): registerBluetoothIntentsIfNeeded: Requires BLUETOOTH permission
I/PlatformViewsController(17740): Hosting view in view hierarchy for platform view: 0
I/PlatformViewsController(17740): PlatformView is using ImageReader backend
D/CompatibilityChangeReporter(17740): Compat change id reported: 236825255; UID 10542; state: DISABLED
D/CompatibilityChangeReporter(17740): Compat change id reported: 193247900; UID 10542; state: ENABLED
D/NativeCustomFrequencyManager(17740): [NativeCFMS] BpCustomFrequencyManager::BpCustomFrequencyManager()
E/FrameEvents(17740): updateAcquireFence: Did not find frame.
D/OpenGLRenderer(17740): CFMS:: SetUp Pid : 17740 Tid : 17802
I/ViewRootImpl@ca848a1MainActivity: mWNT: t=0xb400007079986030 mBlastBufferQueue=0xb400007109961f30 fn= 2 caller= android.view.ViewRootImpl$6.onFrameDraw:5539 android.view.ViewRootImpl$2.onFrameDraw:2103 android.view.ThreadedRenderer$1.onFrameDraw:788
W/mhrmpanelmember(17740): Accessing hidden field Landroid/content/pm/ApplicationInfo;->primaryCpuAbi:Ljava/lang/String; (unsupported, reflection, allowed)
E/FrameEvents(17740): updateAcquireFence: Did not find frame.
W/AudioCapabilities(17740): Unsupported mime audio/x-ape
W/AudioCapabilities(17740): Unsupported mime audio/x-ima
W/AudioCapabilities(17740): Unsupported mime audio/mpeg-L1
W/AudioCapabilities(17740): Unsupported mime audio/mpeg-L2
W/VideoCapabilities(17740): Unsupported mime video/wvc1
W/VideoCapabilities(17740): Unsupported mime video/x-ms-wmv
W/cr_VAUtil(17740): Unknown level: 131072 for profile 65536 of codec video/avc
Tokens returned but App does not redirect properly
Hi,
I'm having trouble even getting the very basic demo app to work correctly. The problem I'm having is that I can log in to AAD B2C (and I can see from the network traffic that the tokens are all coming back correctly) via the plugin code provided, but once I'm logged in I get the following error:
I am currently only trying to get the flutter demo counter page hidden behind a login screen. Below is my main.dart file. The only other change I've made is to add manifestPlaceholders += [ appAuthRedirectScheme: 'com.my.app.name' ]
to the defaultConfig section of the /android/app/build.gradle
file.
Any help you could provide would be amazing as we've been going round in circles on this a for a couple of days now.
import 'package:aad_b2c_webview/aad_b2c_webview.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
onRedirect(BuildContext context) {
Navigator.pushNamed(context, '/');
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
initialRoute: '/',
routes: {
'/': (context) => const MyLoginPage(),
'/oauthredirect/': (context) => const MyHomePage(title: 'Flutter Demo Redirect Route')
},
);
}
}
class MyLoginPage extends StatelessWidget {
const MyLoginPage({super.key});
@override
Widget build(BuildContext context) {
const aadB2CClientID = "################################";
const aadB2CRedirectURL = "com.my.app.name://oauthredirect/";
const aadB2CUserFlowName = "B2C_1_MyAppName_Signin";
const aadB2CScopes = ['openid', 'offline_access'];
const aadB2CUserAuthFlow =
"https://<tenantName>.b2clogin.com/<tenantName>.onmicrosoft.com";
const aadB2TenantName = "<tenantName>";
return Scaffold(
body: ADB2CEmbedWebView(
tenantBaseUrl: aadB2CUserAuthFlow,
userFlowName: aadB2CUserFlowName,
clientId: aadB2CClientID,
redirectUrl: aadB2CRedirectURL,
scopes: aadB2CScopes,
onAnyTokenRetrieved: (Token anyToken) {},
onIDToken: (Token token) {},
onAccessToken: (Token token) {},
onRefreshToken: (Token token) {},
optionalParameters: [],
onRedirect: (context) => const MyHomePage(title: 'Flutter Demo On Redirect'),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
Google Sign In issue
Hi,
I've added Google as an identity provider to my Azure Entra instance. Unfortunately I faced the following error message from after trying to sign in via Google.
You'll find the description of the error message here:
https://support.google.com/accounts/answer/12917337?hl=en#403disallowed&zippy=%2Cdisallowed-useragent
It seems like an user agent is missing.
ResponseType as default / code throws error
Hallo everybody,
trying to Login with ADB2CEmbedWebView
using responseType: Constants.default or authCode (which is the same)
throws Dio exception.
responseType: idToken or accessToken works fine.
It comes to my understanding that the authCode is used to implement the UserFlow login and call and extract both idToken and refreshToken.
Thanks in advance and best regards.
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: DioException [bad response]: This exception was thrown because the response has a status code of 400 and RequestOptions.validateStatus was configured to throw for this status code. E/flutter (11937): The status code of 400 has the following meaning: "Client error - the request contains bad syntax or cannot be fulfilled" E/flutter (11937): Read more about status codes at https://developer.mozilla.org/en-US/docs/Web/HTTP/Status E/flutter (11937): In order to resolve this exception you typically have either to verify and fix your request code or you have to fix the server code. E/flutter (11937): E/flutter (11937): #0 DioMixin.fetch.<anonymous closure> (package:dio/src/dio_mixin.dart:507:7) E/flutter (11937): #1 _FutureListener.handleError (dart:async/future_impl.dart:180:22) E/flutter (11937): #2 Future._propagateToListeners.handleError (dart:async/future_impl.dart:858:47) E/flutter (11937): #3 Future._propagateToListeners (dart:async/future_impl.dart:879:13) E/flutter (11937): #4 Future._completeError (dart:async/future_impl.dart:655:5) E/flutter (11937): #5 _SyncCompleter._completeError (dart:async/future_impl.dart:63:12) E/flutter (11937): #6 _Completer.completeError (dart:async/future_impl.dart:27:5) E/flutter (11937): #7 Future.any.onError (dart:async/future.dart:618:45) E/flutter (11937): #8 _RootZone.runBinary (dart:async/zone.dart:1666:54) E/flutter (11937): #9 _FutureListener.handleError (dart:async/future_impl.dart:177:22) E/flutter (11937): #10 Future._propagateToListeners.handleError (dart:async/future_impl.dart:858:47) E/flutter (11937): #11 Future._propagateToListeners (dart:async/future_impl.dart:879:13) E/flutter (11937): #12 Future._completeError (dart:async/future_impl.dart:655:5) E/flutter (11937): #13 Future._asyncCompleteError.<anonymous closure> (dart:async/future_impl.dart:745:7) E/flutter (11937): #14 _microtaskLoop (dart:async/schedule_microtask.dart:40:21) E/flutter (11937): #15 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5) E/flutter (11937):
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.