Blazor Server - Refresh User Roles without Logging Out? - asp.net

Say you're using the built in AspNetCore Identity implementation.
To access some data a User must have the "CanFetchData" role. If they don't, a "Get Access" button is displayed which upon being clicked gives the User the Role and now they can see the data. Without Loggin Out. That's all I'm trying to do.
So onclick we:
var authState = await authenticationStateTask;
var currUser = await UserManager.GetUserAsync(authState.User);
await UserManager.AddToRoleAsync(currUser, "CanFetchData");
And now the Role is in the db. But the only way to update the view is to fully logout.
I've tried using StateHasChanged(); and SignInManager.RefreshSignInAsync(currUser) and a number of other approaches.
I realized that if I add the Claim directly it will update properly:
var newIdentity = new ClaimsIdentity();
newIdentity.AddClaim(new Claim(ClaimTypes.Role, "CanFetchData"));
authState.User.AddIdentity(newIdentity);
But is there no built in function to just refresh from the db?

Related

What is the correct way to use next-auth with Google OAuth and users stored in the database?

I'm new to next-auth, and I'm looking for some help.
I have added the Google OAuth provider, and now when I run signIn("google") function on the frontend, it automatically takes me to the google's login page, and logs me in, somehow, without ever touching my database.
When the google authentication is complete, I need to be able to create a new user in my database, or retrieve the existing one if they have already signed up before (because I need to store all kinds of custom information about the user, not just their email).
And I want to make user's information available on the session object from useSession()hook. Right now I'm seeing some kind of default user info (with name, email, and image field which I didn't define).
When I was using a regular Express server and Passport, the code looked kinda like this:
const googleAuth = new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "/api/v1/profiles/google/callback",
},
async (req, accessToken, refreshToken, profile, done) => {
const existingProfile = await Profile.findOne({ email: profile.emails[0].value })
/* Found user, return him and move along. */
if (existingProfile) return done(null, existingProfile)
/* Haven't found profile with this googleId, create a new one. */
const newProfile = await new Profile({
googleId: profile.id,
email: profile.emails[0].value,
})
newProfile.save()
done(null, newProfile)
}
)
So I would still be creating the users in my database, and retrieving their information on log in, so that I could send it to the client.
Where does this kind of code supposed to go when I'm using the serverless next-auth?
And a second, but kind of related question - what's that default user object that gets provided to me in the session object? The one with the name, email, and image fields that next-auth seems to create for me? How can I make it use the user object I'm returning from my database instead?
(I've done my best to look through the tutorials and examples, but couldn't find one that explains this clearly.)
I don't know if you still need this, but I hope it helps someone:
Oauth kinda mixes up Sign In and Sign Up, so if you want to have Google authentication what you probably want to do is create a callback of the Sign In function in /api/auth/[...nextauth].js, then get the account and profile as parameters and access to its provider.
async signIn({account, profile}) {
if(account.provider === 'google') {
//check if user is in your database
if(user NOT in DB) {
//add your user in DB here with profile data (profile.email, profile.name)
}
return true
}
You always want to return true since you always want to log in independently if it is in your DB or not.
Regarding the session object, you can also add a callback and access to the default session (that you can modify), token and user. Here you can retrieve all information you want from your database, add it to the session object and return it.
async session({ session, token, user }) {
const newData = DB.find(...).data
session.newfield = newInfo
return session
}

Best way to force user to log in before accessing my website

I'm getting started with Firebase and I would like to have a suggestion concerning the best way to force a user to be logged to use my website.
I'm building a very simple app but i have to guarantee that content can be displayed only to logged people
Thank you!
Use auth().onAuthStateChanged
https://firebase.google.com/docs/auth/web/start#set_an_authentication_state_observer_and_get_user_data
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var providerData = user.providerData;
// ...
} else {
// User is signed out.
// ...
}
});
I assume you are using PHP to build your firebase website, in php there are session tokens that can be used to auto log in. once you got a session login you could use that to redirect them to the login page if they are not logged in. here a snip of code from one of my old college projects.
if(!isset($_SESSION['user_logged_in'])){
header("Location: ../login.php");
}else{
if($_SESSION['user_logged_in'] != true){
header("Location: ../login.php");
}
}
its been a while but this checks if I remember correctly the first line checks if there is no session token and the second line checks to see if that person is logged in. if either of this isn't true it will load the login page instead of the page they wanted and cause its all done in php they can't get around this. we put all this in an authentication template, I have uploaded the PHP file to google drive if you wish to example how logins are done, this is using an MYOB database so you will have to convert it but the code in here should be a good example.
https://drive.google.com/open?id=1_oKWU3LnpmfJg2pD5kHzYxFX2Ydl42e_
hope this helps

meteor-shopify User Creation/ Login after Auth callback

Assuming I want to create users upon authorizing the app, how would I grab their email during the onAuth callback...? Looks like the callback assumes the user is already logged in. Am I thinking about it correctly?
I noticed when installing the Fishbowl Prizes app, after auth I can click on the accounts tab and see that all my account info is pre-populated from my shopify store account (name, email, address, etc).
I'm not sure if I should go by the title or the content of the post in terms of answering your question, so I'll provide a very simple example of how to get the info from the API and do something with it here.
I have provided a more in depth answer related specifically to grabbing the details from the API for user account creation here: https://github.com/froatsnook/meteor-shopify/issues/15#issuecomment-177413630
Looks like the callback assumes the user is already logged in.
The userId param is undefined if there is no user. If your onAuth operations don't need to do anything with the user, you can just leave it out of the params. In your case you'll just want to handle it conditionally using an if/else block:
if(!userId){
// do stuff
} else {
// do other stuff
}
On to the example of grabbing those details from the API:
All the prepopulated information you are seeing is available from the Shopify API in the shop object. You already have the access token when onAuth callbacks are fired, so you can just grab it from the API immediately after you have inserted the shop's Keyset.
For the sake of simplicity, in this example we'll assume the user already exists and is logged in. In your server-side onAuth callback (after you have inserted the keyset) you can do something like this to add those fields to the user's profile object:
Shopify.onAuth(function(access_token, authConfig, userId) {
var shopUUID = uuid.new(); // Not secure to name keyset same as the shop!
Shopify.addKeyset(shopUUID, {
access_token: access_token
});
var api = new Shopify.API({
shop: authConfig.shop,
keyset: shopUUID
});
// get the Shop object from the API
var shopObj = api.getShop();
var userInfo = {
'profile.name': shopObj.shop_owner,
'profile.email': shopObj.email,
'profile.phone': shopObj.phone,
'profile.shopName': shopObj.name
};
Meteor.users.update({_id: userId}, {$set: userInfo})
});
Then you can use them in templates like this:
{{currentUser.profile.name}} or {{currentUser.profile.email}}
Or in functions like so:
var realName = Meteor.user().profile.name
or
var userEmail = Meteor.user().profile.email etc
For a more about using this data for user creation, see my explanation here:
https://github.com/froatsnook/meteor-shopify/issues/15#issuecomment-177413630

Firebase user counter

I'm trying to display the amount of users that are currently viewing my page using firebase and shopify's API. Haven't been able to find any documentation.
You could implement a presence system - see this Firebase blog post.
When a user logs in,
Authenticate the user
Set the onDisconnect listener to remove the presence object (#3) when the user disconnects.
Set the user's presence ref to true
Example (from blog post)
var amOnline = new Firebase('https://<demo>.firebaseio.com/.info/connected');
var userRef = new Firebase('https://<demo>.firebaseio.com/presence/' + userid);
amOnline.on('value', function(snapshot) {
if (snapshot.val()) {
userRef.onDisconnect().remove();
userRef.set(true);
}
});

Displaying text after login

I am designing a math problem site using Firebase and I want to display a problem when someone logs in.
What I want in pseudo code is,
if user logged in
document.write([problem])
else
document.write(Please login to see the problem)
Any ideas?
When using Firebase Simple Login, upon instantiation of the FirebaseAuthClient you will define a callback function that is invoked any time the login state of the user changes.
From https://www.firebase.com/docs/security/simple-login-overview.html:
var chatRef = new Firebase('https://SampleChat.firebaseIO-demo.com');
var authClient = new FirebaseAuthClient(chatRef, function(error, user) {
if (user) {
// user authenticated with Firebase
} else if (error) {
// an error occurred authenticating the user
} else {
// user is logged out
}
});
For your case, if you have a user object, you can hide any login-related UI and show the problem, otherwise, hide the problem and show any login-related UI.
Then, to log users in, choose one or more of the Firebase Simple Login authentication providers, configure that provider in Forge (accessed via https://<your-firebase>.firebaseio.com) and attempt to authenticate the user via:
authClient.login(<provider>, <options>);
I hope that helps!

Resources