How to validate if a user exist in KeyCloak userModel - keycloak

I am trying to write a custom Authenticator. So in my action() method I am trying to look for existing user based on there userId.
import org.keycloak.models.UserModel;
.....
#Override
public void action(AuthenticationFlowContext context) {
System.out.println("*******I AM INSIDE THE ACTION CONTROLLER***********");
String userId = "8837fe42-0ec7-4117-aedb-75746078a101";
//Code to look for user with userId then validate .
}
I am new to keycloak, when I try to user the UserModel it says nullpointer exception
Regars

You have to acquire KeycloakSession object first and then retrieve UserProvider as follows:
UserModel user = context.getSession().users().getUserById(userId, context.getRealm());
KeycloakSession is the starting point to access various application services.

Related

How to seperate google signed-in user and native mail user in flutter?

I am creating an application where I am implementing both Google Sign-In as well as Native mail. Firstly I implemented google sign-in to my application and it works properly.Then I created a Firebase Firestore to store data for registration. The registration also works properly but when I try to sign-in, I cannot seem to find the conditional logic to seperate which one is from Firestore/Native Mail and which one is from Google Sign-In.I am new to flutter so I might have some problem in my regular code too.
I also found similar questions here asked but when I implemented those, it still didn't work for me. This is why I have put this question again to solve for this particular situation.
Here's my initial code for the page that must be shown when a user logs in.
class LoggedInWidget extends StatefulWidget{
const LoggedInWidget({super.key});
#override
LoggedInWidgetState createState() => LoggedInWidgetState();
}
class LoggedInWidgetState extends State<LoggedInWidget> {
final ref = FirebaseDatabase.instance.ref('users'); // Firestore Database
final user = FirebaseAuth.instance.currentUser; // FirebaseAuth to get the current user.
UserModel loggedInUser = UserModel(); // Created a model in another page called UserModel
var name;
var email;
var photo;
#override
Widget build(BuildContext context) {
FirebaseFirestore.instance // Gets data from the current logged in user data and
.collection("users") // saves it in a model called loggedInUser.
.doc(user?.uid)
.get()
.then((value){
loggedInUser = UserModel.fromMap(value.data());
// setState(() {});
});
// This is the logic I implemented for seperating native mail and google sign-in as
// the loggedInUser will have no name there and will be directly associated to the User variable
if(loggedInUser.name == null){ /
name = user?.displayName;
email = user?.email;
photo = user?.photoURL;
}
else{
name = loggedInUser.name!;
email = loggedInUser.email;
}
When running this code, I am able to get my google sign-in data successfully whereas when using Native mail to sign-in. I get the email (probably due to it being saved on the FirebaseAuth), but not the name and other details that is saved in the Firestore.

GetX Controller - Wait for firebase RTDB stream to be populated

I am new to GetX and want to get some concepts right. This is my process to get the groups that a current user is in using Firebase Realtime Database:
Create an AuthController to get current user id (works perfectly)
class AuthController extends GetxController {
FirebaseAuth auth = FirebaseAuth.instance;
Rx<User?> firebaseUser = Rx<User?>(FirebaseAuth.instance.currentUser);
User? get user => firebaseUser.value;
#override
void onInit() {
firebaseUser.bindStream(auth.authStateChanges());
super.onInit();
}
} ```
Create a UserController to get ids of groups that the user has (working partially)
class FrediUserController extends GetxController {
Rx<List<String>> groupIdList = Rx<List<String>>([]);
List<String> get groupIds => groupIdList.value;
#override
void onInit() {
User? user = Get.find<AuthController>().user;
if (user != null) {
String uid = user.uid;
groupIdList.bindStream(DatabaseManager().userGroupIdsStream(uid));
print(groupIds); //prints [] when it should be populated
}
super.onInit();
}
}
Create a GroupsController to get the groups from those ids (not working) --> Dependant on UserController to have been populated with the id's.
class FrediGroupController extends GetxController {
Rx<List<FrediUserGroup>> groupList = Rx<List<FrediUserGroup>>([]);
List<FrediUserGroup> get groups => groupList.value;
void bindStream() {}
#override
void onInit() {
final c = Get.find<FrediUserController>();
List<String> groupIds = c.groupIds;
print(groupIds); //prints [], when it should have ids
groupList.bindStream(DatabaseManager().groupsStream(groupIds)); //won't load anything without id's
super.onInit();
}
}
Observations
Get.put is called sequentially in the main.dart file:
Get.put(AuthController());
Get.put(FrediUserController());
Get.put(FrediGroupController());
Inside my HomePage() Stateful Widget, if I call the UserController, the data loads correctly:
GetX<FrediUserController>(
builder: (controller) {
List<String> groups = controller.groupIds;
print(groups); //PRINTS the list of correct ids. THE DATA LOADS.
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: groups.length,
itemBuilder: (context, index) {
return Text('${groups[index]}',
style: TextStyle(color: Colors.white));
},),); },),
QUESTION
It is as if the stream takes some time to populate, but the UserController doesn't wait for it and initializes the controller as empty at first, but after some time it populates (not in time to pass the data to the GroupController.
How can I fix this? I have tried async but not with much luck.
Behaviour I would Like:
Streams may/may not be ready, so it can initialize as empty or not.
HOWEVER, if the stream arrives, everything should be updted, including the initialization of controllers that depend on UserController like GroupController.
Consequently, the UI is rebuilt with new values.
THANK YOU!
There are two things that you can add:
Future Builder to show some loading screen while it fetch data from RTDB
ever function
class AuthController extends GetxController {
late Rx<User?> firebaseuser;
#override
void onReady() {
super.onReady();
firebaseuser = Rx<User?>(FirebaseAuth.instance.currentUser);
firebaseuser.bindStream(FirebaseAuth.instance.idTokenChanges());
ever(firebaseuser, _setInitialScreen);
}
_setInitialScreen(User? user) {
if (user != null) {
//User Logged IN
} else {
//User Logged out
}
}
}
You only take the user once, in the method onInit. You are not getting user changes. To get every change you would have to use "ever" function. For example, "firebaseUser.value" is like a photography of the firebaseUser observable in the moment.
If I can make a sugestion, don't mistake controllers with providers. Think Firebase as a provider and the controller as a mid point between the UI and the provider. You can listen to Firebase Streams at the controller to update UI and make calls from the UI change parameters in your Firebase provider. Separate your concerns into two distinct classes and you'll, potentially, have a better design.
Use of "ever" function example:
ever(firebaseUser, (user) {
// do something
});
"Ever" assigned function runs whenever the observable emits a new value

Flutter : Call value from second function class

I have Auth class which has sgin in function and inside of this function value for example user value , so how to get this value from Auth class to Home class ?
Here Auth class and Home Class :
class Auth {
void signIn(){
String user = "I LOVE PROGRAMMING";
}
}
class Home {
return Text("$user") //Iwant user value from clas AUTH
}
You would want to have the signIn function return the user.
class Auth {
String signIn() {
String user = "I LOVE PROGRAMMING";
return user;
}
}
Then you can call that from another class:
class Home {
Widget someFunction() {
final auth = Auth(); // create a new instance of Auth
final user = auth.signIn(); // call the function and put the return value in a `user` variable
return Text(user); // use the `user` String in the Text widget
}
}
I would advice you to have a look at the Dart language tour and learn about these things step by step. These are the basics you will need to get anything done. Good luck!
You should be implement below way
class Auth {
static String _user;
void signIn() {
_user = "dfsdfgdfgfdgdfgfdgfdgfdgfd";
}
static String getUser() => _user;
}
class Home {
return Text(Auth.getUser())
}
Firstly, you need to create a global variable for the String user that you have set in the Auth class and create a getter for it. You also would need to use some type of state management to simulate the value changes. In this case I'll use the provider package.
class Auth extends ChangeNotifier{
String _user = '';
void signIn() {
_user = 'SomethinInteresting';
}
String get userName => _user;
}
Whenever the signIn() function is being called from other component, the value for the user would be set. And finally if you want to access the value from other component you can use the getter to set the value in the Text component.
class Home {
final _auth = Provider.of<Auth>(context);
#override
Widget build(BuildContext context) {
return text(_auth.userName);
}
}
This would also facilitate dyanmic changes to the fields in the Auth class.
For accessing the value from the "Auth" class you first need to make the method type String and return the value when the method is called. In the Home class there must be main method as it is from where the execution of the program starts. Now, create an object of class "Auth" and call the method using the same object. You'll get the user value.
class Auth {
String signIn(){
String user = "dfsdfgdfgfdgdfgfdgfdgfdgfd";
return user;
}
}
class Home {
public static void main(String args[]){
Auth ob=new Auth();
System.out.println(ob.signIn());//I want user value from clas AUTH
}
}

how is the best way to manage session and navigation in flutter web

I have 2 web pages on my proyect
I need to manage the user session. If the user is logged it appears the home page, and if the user is not logged it appears the login page.
I am using a provider to check the state of the session
#override
Widget build(BuildContext context) {
return Consumer<LoginGeneralNotifier>(
builder: (context, appGenaralNotifier, _) {
return appGenaralNotifier.getLogged()
? HomePage()
: LoginPage();
},
);
}
}
The problem is that the url does not change after I am logged
You may want to use Navigator.of(context).pushNamed(HomePageNamedRoute);
This can be done in initState as shown here:
Flutter Redirect to a page on initState
what I do is
I have created a class where I am keeping all the global variables
there I create a variable bool loginStatus;
and create two methods get and set for handling the value
and whenever login is successful I set the value to true loginStatus=true;
and on the new page in init() method I am checking the value of variable if value is false then throw the user to login page else continue
class GlobalValues{
static bool loginStatus;
static void setLoginStatus(bool val) {
loginStatus = val;
}
static bool getLoginStatus() {
return loginStatus == null ? false : loginStatus;
}
}
on login page if login is successful
GlobalValues.setLoginStatus(true);
on other class pages in init method
#override
void initState() {
if (GlobalValues.getLoginStatus()) {
// call your login page class here
//Navigator.of(context).pushNamed(LoginPageNamedRoute);
Navigator.pop(context);
}
super.initState();
}
Global variables are highly-frowned upon in the programming world (unless absolutely no other alternatives are available). Use user sessions instead. Check out FlutterSession. The package adds user session support in Flutter and is easy to use.
// Store value to session
await FlutterSession().set("token", myJWTToken);
// Retrieve item from session
dynamic token = await FlutterSession().get("token");

Create an object in stateful widget's state that has a dependency on provider

I have a class Store that is dependent on say class Credentials like
class Credentials {
...
}
class Store {
...
Store(#required Credentials)
...
}
My stateful widget's build method uses things inside Store to generate the widget.
Credentials object is supplied via provider.
I have done this
#override
didChangeDependencies() {
super.didChangeDependencies();
Credentials creds = Provider.of<Credentials>(context);
_store = Store(creds);
...
}
But is see _store recreated even when creds remain same.
(I can do a creds equality check and put creation of store inside it, but that to me seems just a fix).
I just dont think this is the right approach.
How do we solve this pattern in flutter gracefully?
Depending on how Store is used, you may either use ProxyProvider:
ProxyProvider<Credentials, Store>(
builder: (_, creds, __) => Store(creds),
child: ...,
)
or do an equality check of Credentials before creating a new Store:
Credentials credentials;
Store store;
#override
void didChangeDependencies() {
super.didChangeDependencies();
final credentials = Provider.of<Credentials>(context);
if (this.credentials != credentials) {
this.credentials = credentials;
store = Store(credentials);
}
}