I'm planning to write Firebase function on Authentication user creation. My goal is to get the long live access token for the Facebook user page's.
To do that I need user access token in Firebase functions. Tried below..,
exports.saveLongLiveToken = functions.auth.user().onCreate(event => {
console.log(event.providerData)
})
I though providerData will have the information about the Facebook credentials, but not instead I got only undefined.
Note: In the event, I got below
{ data:
{ displayName: 'Rob',
email: 'xxx#xyz.com',
metadata:
{ createdAt: 2017-08-23T18:58:34.000Z,
lastSignedInAt: 2017-08-23T18:58:34.000Z },
photoURL: 'http...',
providerData: [ [Object] ],
uid: 'xfff...' },
eventId: 'xxx',
eventType: 'providers/firebase.auth/eventTypes/user.create',
notSupported: {},
resource: 'projects/fiobot-4fa94',
timestamp: '2017-08-23T18:58:34.571Z',
params: {} }
If you are signing in with Firebase Auth signInWithPopup/Redirect, you will only get the access token after sign-in. Firebase Auth does not store it for you (neither does it store the Facebook refresh token). You will need to save it in the Database where only the specified user can access it and the Admin SDK via Firebase Functions can allow you access it. If you think Firebase Auth should manage OAuth tokens for providers, please file a request via Firebase Support channels.
If this is essential for your app functionality, you can use the Facebook API to sign in the user and get a Facebook access token and sign in with firebase.auth().signInWithCredential(firebase.auth.FacebookAuthProvider.credential(fbAccessToken))
Facebook client API can manage the OAuth token for you. You can also use a backend OAuth node.js library to refresh Facebook tokens via the Firebase Functions whenever you need one. You would need to get the Facebook refresh token though.
Related
I am trying to get a valid Google oauth2 token for a user that has logged in through Firebase. I need a Google token so I can authenticate this user through other Google services (not just Firebase).
I am currently using the firebase-admin for this on a server and passing that user's Firebase token to nodejs. I'm doing something like this:
admin.auth().verifyIdToken(tokenId)
.then((decoded) => {
const uid = decoded.uid;
console.log(tokenId);
admin.auth().createCustomToken(uid).then((t) => {
console.log(t);
})
}
However neither the token I'm passing to the admin or the custom token seems to work for other Google services. I'm able to create a custom token, just not sure if or how I can use that to get a google oauth token for that user.
I want to use a guard for my routes controller based on the access token of google, but I don't know how to implement this.
I retrieve this from my google oauth
{
"message": "User information from google",
"user": {
"email": "test#gmail.com",
"firstName": "John",
"lastName": "Kennedy",
"picture":
"https://lh3.googleusercontent.com/a-/mypicture",
"accessToken": "myaccesstoken"
}
}
Now I don't know how to use this access token for my other routes, example in a controller:
#UseGuards() // I don't know what to put here
#Get('/get_customer/:id')
async findCustomerById(#Param() params): Promise<Customer> {
try {
return await this.stripeService.findCustomerById(params.id);
} catch (e) {
throw new Error(e.message);
}
}
Short Answer:
Inside google's redirect endpoint, You can issue a JWT token to the user, which will hold their data as payload, and secure your endpoints with JWT verification guard.
See this
Long Answer:
What google basically does is just provide your application with the identity of the user who used that service to log in... Specifically, google provides you with the user's data(with the scopes you defined) and an access token.
at this point, you have multiple approaches to guard your routes:
Issue a JWT token that holds this user data you got from google and return it to the user(the client), each request the user sends with that token you would be able to identify the user and give them access to routes (stateless way: the token will hold everything encrypted inside it) See this.
Store a session of this user that contains the data you got from google, and give them the SessionId that will make you(the server) identify the user later on and give them access to routes (stateful way: you need to store the session data somewhere).
You might wonder what is the use of the access token in all of this... generally, this token can only be used by your application (which has ClientId+ClientSecret you got from google) to access user's google data(defined by scopes you chose) on behalf of them. So basically this token is a consent from the user so your app can access their google data.
This, for example, can be useful if you can't store user's data in our database(for legal reasons), so you can directly query their data from google without consulting them every single time.
I am trying to test my auth function for firestore in the emulator suite. Is it normal to get this error when trying to authenticate a user via google?
This doc from Firebase seems to suggest that google auth should work in the emulator suite. https://firebase.google.com/docs/emulator-suite/connect_auth
This is an excerpt from the document:
Note that the emulator only supports signInWithCredential authentication for credentials retrieved from Google Sign-In, Apple, and other providers that use ID tokens implemented as JSON Web Tokens (JWTs). Access tokens (e.g. those provided by Facebook or Twitter, which are not JWTs) are not supported. The next section discusses an alternative in these cases.
However I am getting this error:
Received a signed JWT. Auth Emulator does not validate JWTs and IS NOT SECURE
Appreciate any help on this! This is the function which is authenticating the user:
exports.createStripeCustomer = functions.auth.user().onCreate(async (user) => {
const customer = await stripe.customers.create({ email: user.email });
const intent = await stripe.setupIntents.create({
customer: customer.id,
});
await admin.firestore().collection('stripe_customers').doc(user.uid).set({
customer_id: customer.id,
setup_secret: intent.client_secret,
});
return;
});
A customer has been created in the stripe console when running this code, but it has not created a customer in the firestore
According to the Manage Users section in the Firebase docs, user profiles can be modified using the methods below
var user = firebase.auth().currentUser;
user.updateProfile({
displayName: "Jane Q. User",
photoURL: "https://example.com/jane-q-user/profile.jpg"
}).then(function() {
// Update successful.
}, function(error) {
// An error happened.
});
All of the examples in this guide seem tailored to only the currentUser that is signed in, but how can we modify other users programatically? Is there a getUser(uid) method that I'm not seeing?
It seems this can be done with the Firebase Admin Node.js SDK, but how can we do this from the Web?
The Web implementation of the Authentication API is intended to be used client-side only. To edit another user, you would have to authenticate/login as that user. Which would mean currentUser would be the user you require.
You should do this server-side using the Admin API. Which is a separate API.
Setup: https://firebase.google.com/docs/admin/setup/
Manage Users: https://firebase.google.com/docs/auth/admin/manage-users
I am trying to implement Facebook login SPA. I am using the JavaScript SDK for the login. Fb authorized the user and token is received. Token is send to the web API. When API try to fetch the data from the token only Facebook id and name return from the Facebook graph api. Even though I have set the scope for the different data in java script sdk. If i fetch the data using javascript sdk. In that case i am getting the complete data whatever in the scope.
I think your asking "why am I not getting all the data I requested?". If so the most common reason is because permissions aren't set. For instance if the user grants permission to "public_profile" then Facebook will authorize your app to obtain every field that that the "public_profile" permission permits, in this case the following:
id, name, first_name, last_name, age_range, link, gender, locale, picture, timezone, updated_time, verified
obtained via
FB.api('/me',
'GET',
{"fields":"id,name"}, //any of the other fields here
function(response) {
// Insert your code here
} );
however if added 'email' in as a field then the Facebook would return everything except the 'email' because there a permission specifically for granting access to the users email called email. You can see what permissions enable what data returns at https://developers.facebook.com/docs/facebook-login/permissions
and you can test it at https://developers.facebook.com/tools/explorer. I hope that's what you where trying to say in your question. Cheers!