Next Auth V4 (With Redux Toolkit): Pass in Redux Store Data to Next Auth while performing sign In - redux-toolkit

I want to trigger the Sign In callback in Next Auth along with the redux store data. How can I access the store within my nextAuth sign In the callback, here's what I want to do:
async signIn({ user, account, reduxStore }) {
const {geoLocation} = reduxStore.geoData;
// pushGeoDataToBQ(geoLocation); Pushes the Data to a database and not needed to be async as it can run in background and user gets their active session
return true;
}
I want to somehow access my reduxStore variable inside the signIn block.

Related

Pause and resume FirebaseAuth state changes listener in flutter

I am working on an application in which When a user is new, he must fill a form before going to the home page after registration. I am using Firebase authentication with social logins and with email also.
The issue is that as soon as the auth state is changed in social logins module, the listener is notified and it goes to homePage instead of going to that form page (the listener is in the wrapper class that is listening to the state changes whether the user is signed in or not). But when I register with email directly it works fine.
Below is the StreamBuilder which is listening to the auth state changes
StreamBuilder<User>(
stream: Authentication().auth.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
User user = snapshot.data;
if (user != null) {
return Layout();
}
else {
return SignIn();
}
}
else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
)
By checking the console logs, I saw that the listener is notified and the state is changed to logged in and the homepage is called immediately, the homepage should only be called if the user is logged in && is an old user. If the user is new && logged in then the form page should be called. I am not sure how to handle this condition as the authSateChanges() is returning a Stream which does not give detail that the user is new or old.
Is there a way to pause the listener in AUthentication class when we get the credentials because there I get a chance to see if the user is new or not by the following line of code
UserCredential result = await auth.signInWithCredential(credential);
if(result.additionalUserInfo!.isNewUser){}
Using .isNewUser is probably not a good method to know if the user is newly created if you strictly want the user to fill up the form before going to homepage. Because consider the situation where user uninstalls app right after login without filling up the form and then reinstalling again which will then make the user as old user and would thus not ask to fill up the form, when it actually should ask, so this is why this method is suitable.
I suggest you using Custom Claims in firebase authentication using Cloud Functions. With custom claims you can set key, value pairs to denote whether a user is fully registered or not. Once registered you can update the custom claims and pass on that to user with updated claims which can thus make user to land up on homepage everytime he signs in.
To update a custom claims from nodejs environment, you can use admin.auth().setCustomUserClaims(uid, {formFilled: true}) when you see the form data is updated.
On the client side update the idToken, to receive updated claims using var result = currentUser.getIdTokenResult() and get claims using result.claims and check if result.claims["formFilled"] == true
Note that once the custom claims are updated, the client would have to explicitly call the getIdTokenResult() to force refresh tokens.

How can I keep my user's login session open in my flutter application?

in my application flutter after a user logs in, I would like the session to remain open. That is, if a user opens the app, he logs in, if he were to close the application and open it later I would like him to be still logged in and not have to re-enter his credentials.
I found this flutter_session library but I didn't understand if it's right for me or just to keep the session active between one page and another
if you are not using firebase there is still various option for this task. here's come local storage SharedPreference or GetStorage to store data (credential ) locally until user is logged in. and whenever user logout we will clear stored data.
visit this package https://pub.dev/packages/get_storage
when user first time login store credentials like
GetStorage box = GetStorage();
box.write('email',email.value);
When user logout, clear the data
box.remove('email');
and further when user launch the app we will check if email key has value in it then redirect to home screen or else Login Screen.
if(box.read('email')!='' || box.read('email')!=null)
Get.to(HomeScreen());
else
Get.to(LoginScreen());
There are several ways how to do that. You didn't tell about the server you're using to accomplish that. If your'e using firebase for example, you can do it like this:
class LoginScreenState extends State<LoginScreen> {
AuthService auth = AuthService();
#override
void initState() {
super.initState();
auth.getUser.then(
(user) {
if (user != null) {
Navigator.pushReplacementNamed(context, '/topics');
}
else {
//force to login page
}
},
);
}
You can get informations about the current user session inside the auth. This is the perfect entry point for user login sessions: https://firebase.flutter.dev/docs/auth/usage/

Can we get FacebookAccessToken from FirebaseAuth?

With Flutter, I am able to login with Facebook, and later I want to get the FacebookAccessToken because it is needed to correctly get the user photoURL.
Is there a way to get the token from FirebaseAuth? Or I must store this value in my code?
Login part, we have the access token:
FacebookLoginResult result = await new FacebookLogin().logIn(['email', 'public_profile']);
...
FacebookAccessToken accessToken = result.accessToken;
Now, let's say in another Widget, we want to get the user photoURL
final auth = FirebaseAuth.instance;
String url = auth.currentUser.photoURL;
This url must be appended with ?accessToken=<access_token> retrieved during the first step. There is a bug created. But for now, can we directly get it from FirebaseAuth?
The Facebook access token is available from the auth result immediately after the user signs in from the FacebookAuthCredential object as result.credential.accessToken. It is not available from the current user, so if you don't capture immediately after sign-in there's no way to find it later without going back to the Facebook SDK.
Also see:
Can I get a facebook access token from firebase.auth().currentUser?
How to get provider access token in Firebase functions?
Get Facebook/Google access token on Firebase Auth#onAuthStateChanged?

Passing user id with AuthController

I just made simple authentication app using aqueduct as a back end. I used codes from aqueduct documentation pages for login and registering. When I login with this code in backend
router
.route('/auth/token')
.link(() => AuthController(authServer));
I get back token, token type and expiration date, Is there any chance to also pass userId? Or do I have to create my own controller to do that?
UPDATE
or how can I in my backend to save user id when saving the data
#Operation.post()
Future<Response> addData(#Bind.body(ignore: ['id']) Data newData) async {
final query = Query<Data>(context)..values = newData;
final insertData = await query.insert();
return Response.ok(insertData);
}
Flutter frontend
Login initially with the username/email and password. You will get an authorization token back from the server if the username and password are valid. Then use that token to make further privileged requests to the server.
You don't need to save any personal data about the user (email or password) on the client. You can save the token, though, if you don't want to make the user log in again the next time they use the app. When saving the token you should use a secure storage option. The flutter_secure_storage plugin uses KeyChain on iOS and KeyStore on Android.
Aqueduct backend
You can use the user IDs all you want on the backend. I don't know of any need to pass them to the client, though. On the backend you can query the user ID and then use it to fetch other information from the database.
Here is an example from the documentation:
class NewsFeedController extends ResourceController {
NewsFeedController(this.context);
ManagedContext context;
#Operation.get()
Future<Response> getNewsFeed() async {
var forUserID = request.authorization.ownerID;
var query = Query<Post>(context)
..where((p) => p.author).identifiedBy(forUserID);
return Response.ok(await query.fetch());
}
}
The client only passed in the token. Aqueduct looks up the user id for you based on that token. Now you know the user ID.
Your other tables can have a column for the user ID so that only that user may save and retrieve their data. In the example above, Posts have an Author and an Author has an ID, that is, the user ID.
where((p) => p.author).identifiedBy(forUserID)
is equivalent to
where((p) => p.author.id).equalTo(forUserID)
You can read about this in the Advanced Queries section of the documentation.

Meteor: Implement facebook package outside of accounts-facebook

I've got a Meteor application with a multi-phase sign-up process. The accounts are based on the accounts-password package. In the step prior to account creation, the user needs to provide some profile information.
I'd like the user to be able to launch a Facebook OAuth flow which pre-populates the profile fields with information pulled from Facebook.
This all needs to happen pre-account-creation. I want to implement this with the facebook package that backs accounts-facebook.
At the moment I've got the OAuth flow happening by calling Facebook.requestCredential, but I'm not sure how to get an OAuth access token from the credential token that comes back. I suspect I need to pass this to the server and make an API call to get back an access token.
Any pointers as to how this should work would be much appreciated.
Facebook.requestCredential(function (credentialTokenOrError) {
if (credentialTokenOrError && credentialTokenOrError instanceof Error) {
// Error...
console.log(credentialTokenOrError);
} else {
// Credential Token string
console.log(credentialTokenOrError);
// Now perhaps a Meteor.call to a server method that
// 1. Retrieves an access token
// 2. Hits the graph API to get profile information and returns it to the client
}
});
Thanks,
Chris
I was having the same trouble of converting a credentialToken to an accessToken, only with Github. I've written up a gist that has code that should work very similarly. Essentially, there are two steps:
Within your Facebook.requestCredential callback function, call OAuth._retrieveCredentialSecret(tokenOrError), the result of which is the credentialSecret. Then use Meteor.call, passing in tokenOrError and credentialSecret, to call the Meteor.method you'll set up in the next step.
code (on client):
Github.requestCredential({
loginStyle: 'popup',
requestPermissions: ['gist']
}, function(tokenOrError) {
if (tokenOrError && tokenOrError instanceof Error) {
// Throw a Meteor error
console.log('error getting the token');
return;
}
var credentialSecret = OAuth._retrieveCredentialSecret(tokenOrError);
Meteor.call('getGithubAccessToken', tokenOrError, credentialSecret, function(err, accessToken) {});
});
On the server, set up a Meteor.method that takes your credentialToken and credentialSecret and calls Facebook.retrieveCredential. This function returns a credentials object from the _pendingCredentials Mongo Collection before deleting it from the collection. The access token is credentials.serviceData.accessToken. The credentials object could potentially be persisted in the user object in the Meteor.users collection (as it is in the accounts packages) or sent back to the user.
code (on server):
Meteor.methods({
getGithubAccessToken: function(credentialToken, credentialSecret) {
var credentials = Github.retrieveCredential(credentialToken, credentialSecret);
console.log('accessToken:', credentials.serviceData.accessToken);
return credentials.serviceData.accessToken;
}
});
I'm unfamiliar with the specifics of Facebook's Graph API so after these steps, you're on your own. Good luck!