I'm using the standard Email + Password auth-provider.
Through certain circumstances I have to create a firebase user manually. The flow would be something like calling a REST api with an defined email + generated password, and if succeeded sending a welcome email to the user with his password. Something like forward user registration.
I read through their docs and couldn't find much. (the new docs don't even offer a REST API section for user management.. well and just to be clear, the new "google" styled docs, pretty much suck anyway :) ).
Is there someone who has already done something similar and can help me out?
BTW: It would also be possible to create them client side through createUserWithEmailAndPassword(), but this function does automatically reauthenticate the new user, which must not happen in my scenario. Is it possible to use createUserWithEmailAndPassword() without automatically logging in the user?
You can create a new Firebase App context in your client and then call createUserWithEmailAndPassword() there:
var authApp = firebase.initializeApp({
// ...
}, 'authApp');
var detachedAuth = authApp.auth();
detachedAuth.createUserWithEmailAndPassword('foo#example.com', 'asuperrandompassword');
By adding a second argument to initializeApp you create a separate context that will not trigger re-authentication upon user creation.
Related
I recently moved from the deprecated gapi.auth2 to the new Google Identity Services, using the javascript client library, and noticed a big difference: if someone signs in, and then reloads the page, the session is lost, and has to sign in again, every time the page is loaded. This was not the case with the deprecated library.
The problem can be easily reproduced with the Calendar API example.
Is there any configuration option to keep the session persistent? Or do I need to store the access tokens somehow? I could not find anything relevant in the official docs.
UPDATE:
The migration guide states the following:
Previously, Google Sign-In helped you to manage user signed-in status using:
Callback handlers for Monitoring the user's session state.
Listeners for events and changes to signed-in status for a user's Google Account.
You are responsible for managing sign-in state and user sessions to your web app.
However there's absolutely no information on what needs to be done.
UPDATE 2
To be more specific, the actual issue is not making the session persistent. Managing the sign in state and user session is something I can solve.
The real problem is the access token used to call the Google APIs.
As mentioned in the comments, the access tokens are 1) short lived 2) are not stored anywhere, so even if not expired, they do not persist between page reloads.
Google provides the requestAccessToken method for this, however even if I specify prompt: '', it opens the sign-in popup. If I also specify the hint option with the signed in user's email address, than the popup opens, displays a loading animation briefly, and closes without user interaction. I could live with this, however this only works if triggered by a user interaction, otherwise the browser blocks the popup window, meaning that I cannot renew the token without user interaction, e.g. on page load. Any tips to solve this?
I faced all the same issues you described in your question.
In order to help:
Google 3P Authorization JavaScript Library: in this link we can check all the methods the new library has (it does not refresh token, etc..)
This doc says the library won't control the cookies to keep the state anymore.
Solution
Firstly I need to thanks #Sam O'Riil answer.
As Sam described: "you can somehow save access token and use it to speed-up things after page reload."
Given the the Google's exampe, we should call initTokenClient in order to configure the Google Auth and the requestAccessToken to popup the auth:
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
prompt: 'consent',
callback: tokenCallback
});
tokenClient.requestAccessToken({prompt: ''})
In your tokenCallback you can save the credentials you get somehow, e.g.:
const tokenCallback(credentials) => {
// save here the credentials using localStorage or cookies or whatever you want to.
}
Finally, when you restart/reload your application and you initialize the gapi.server again, you only need to get the credentials again and set token to gapi, like:
gapi.load('client', function() {
gapi.client.init({}).then(function() {
let credentials = // get your credentials from where you saved it
credentials = JSON.parse(credentials); // parse it if you got it as string
gapi.client.setToken(credentials);
... continue you app ...
}).catch(function(err) {
// do catch...
});
});
Doing it, your application will work after the reload. I know it could not be the best solution, but seeing what you have and the library offers, I think that's you can do.
p.s.: the token expires after 1 hour and there is no refresh token (using the implicit flow) so, you will have to ask the user to sign-in again.
I am trying to send a welcome mail to a user that converted from an anonymous to a permanent user using Firebase Cloud Functions.
Prevously i followed this sample code on github which sent an email when a user was created.
The sample code uses the hook onCreate:
exports.sendWelcomeEmail = functions.auth.user().onCreate(event => {
const user = event.data;
const email = user.email;
... send the email
});
This function would trigger when the anonymous user is created (which is not what i want, since at this time the user has no email specified).
When the anonymous user converts to a permanent user the onCreate does not trigger obviously, since the user is converted not created. What cloud function do i use that triggers when an anonymous user converts to a permanent user?
When looking at the firebase cloud function reference, specifically at the namespace for Firebase Authentication functions i find that there are only two methods to work with, onCreate and onDelete. So what are my options?
Edit: I went and asked in the google group for Firebase and got this answer:
Hey there,
Thank you for your request. Please file an official request
via support channels: https://firebase.google.com/support/ You can use
real-time database or Firestore to set some flag from the client when
an anonymous user is upgraded and then listen to that node's changes
in Cloud Functions. This should get you the functionality you need.
Best regards,
So basically could just create a custom listener for it.
I'm running into some problems when I attempt to refresh my session tokens, (Access, Id, Refresh). I have already read this question and the answer has helped me understand what is going on some. But I feel what I am trying to do isn't quite what getSession is for.
I am attempting to implement a session expiration message (done) that allows the user to extend their session (refreshes the tokens). From what I gather about getSession(), it returns either the old tokens, if they are still valid, or new tokens if they are not valid. Please correct me if I am wrong there.
I am attempting to give the user new/refreshed tokens every time they click on extend session. For dev purposes, I have a button which then displays the message with the extend session button. The tokens I receive when I call getSession() are the old ones, but I want them to be new ones.
So basically, nullifying the old session and giving them a new one.
My questions are:
Am I missing some understanding about getSession(), as previously mentioned?
Can I give the user new session tokens (Access, Id, Refresh)?
Can I do #2 without having the user sign in again?
Thank you.
EDIT 1:
It may help to know that I am not using any Federated Identities.
You can call cognitoUser.refreshSession. I've found a reasonable example for you over here:
Sample code: how to refresh session of Cognito User Pools with Node.js and Express
Look for the method called checkTokenExpiration, it explains perfectly well what you have to do to refresh the session.
I have a Torii adapter that is posting my e.g. Facebook and Twitter authorization tokens back to my API to establish sessions. In the open() method of my adapter, I'd like to know the name of the provider to write some logic around how to handle the different types of providers. For example:
// app/torii-adapters/application.js
export default Ember.Object.extend({
open(authorization) {
if (this.provider.name === 'facebook-connect') {
var provider = 'facebook';
// Facebook specific logic
var data = { ... };
}
else if (this.provider.name === 'twitter-oauth2') {
var provider = 'twitter';
// Twitter specific logic
var data = { ... };
}
else {
throw new Error(`Unable to handle unknown provider: ${this.provider.name}`);
}
return POST(`/api/auth/${provider}`, data);
}
}
But, of course, this.provider.name is not correct. Is there a way to get the name of the provider used from inside an adapter method? Thanks in advance.
UPDATE: I think there are a couple ways to do it. The first way would be to set the provider name in localStorage (or sessionStorage) before calling open(), and then use that value in the above logic. For example:
localStorage.setItem('providerName', 'facebook-connect');
this.get('session').open('facebook-connect');
// later ...
const providerName = localStorage.getItem('providerName');
if (providerName === 'facebook-connect') {
// ...
}
Another way is to create separate adapters for the different providers. There is code in Torii to look for e.g. app-name/torii-adapters/facebook-connect.js before falling back on app-name/torii-adapters/application.js. I'll put my provider-specific logic in separate files and that will do the trick. However, I have common logic for storing, fetching, and closing the session, so I'm not sure where to put that now.
UPDATE 2: Torii has trouble finding the different adapters under torii-adapters (e.g. facebook-connect.js, twitter-oauth2.js). I was attempting to create a parent class for all my adapters that would contain the common functionality. Back to the drawing board...
UPDATE 3: As #Brou points out, and as I learned talking to the Torii team, fetching and closing the session can be done—regardless of the provider—in a common application adapter (app-name/torii-adapters/application.js) file. If you need provider-specific session-opening logic, you can have multiple additional adapters (e.g. app-name/torii-adapters/facebook-oauth2.js) that may subclass the application adapter (or not).
Regarding the session lifecycle in Torii: https://github.com/Vestorly/torii/issues/219
Regarding the multiple adapters pattern: https://github.com/Vestorly/torii/issues/221
Regarding the new authenticatedRoute() DSL and auto-sesssion-fetching in Torii 0.6.0: https://github.com/Vestorly/torii/issues/222
UPDATE 4: I've written up my findings and solution on my personal web site. It encapsulates some of the ideas from my original post, from #brou, and other sources. Please let me know in the comments if you have any questions. Thank you.
I'm not an expert, but I've studied simple-auth and torii twice in the last weeks. First, I realized that I needed to level up on too many things at the same time, and ended up delaying my login feature. Today, I'm back on this work for a week.
My question is: What is your specific logic about?
I am also implementing provider-agnostic processing AND later common processing.
This is the process I start implementing:
User authentication.
Basically, calling torii default providers to get that OAuth2 token.
User info retrieval.
Getting canonical information from FB/GG/LI APIs, in order to create as few sessions as possible for a single user across different providers. This is thus API-agnotic.
➜ I'd then do: custom sub-providers calling this._super(), then doing this retrieval.
User session fetching or session updates via my API.
Using the previous canonical user info. This should then be the same for any provider.
➜ I'd then do: a single (application.js) torii adapter.
User session persistence against page refresh.
Theoretically, using simple-auth's session implementation is enough.
Maybe the only difference between our works is that I don't need any authorizer for the moment as my back-end is not yet secured (I still run local).
We can keep in touch about our respective progress: this is my week task, so don't hesitate!
I'm working with ember 1.13.
Hope it helped,
Enjoy coding! 8-)
I am using the user-accounts package to manage the Account System in my app.
I have also integrated Google, Github, Twitter and other 3rd party Services.
The package works fine, but now that I need a specific page for every user, and for SEO terms, I need the url to be like this:
https://domain.com/user/username
I also have the accounts-password package. And I have added a username field, and it works fine.
But if thirdparty services are used, the popup closes and the page is redirected with the user successfully created. I read about calling Accounts.onUserCreate,
and this is my code:
Accounts.onCreateUser(function(options, user) {
var email = options.profile.email;
var ist = email.indexOf("#");
var uname = email.slice(0,ist);
user.username = uname;
if(options.profile){
user.profile = options.profile;
}
return user;
});
But it gives an error : Cannot read indexOf of undefined.
How can this be achieved?
There either can be a page, to enter the username, for every new user, or this way, the email should be sliced for username creation. (Second method is preferred.)
The error message is telling you your variable email has not been set.
When using third-party login services with Meteor, the user information is not stored within the profile of the user document. Rather, you should look for the email within the services data of that user document. For example, for Facebook, you should find this within services.facebook.email.
You may also want to consider using the user argument to find this information as the documentation states: "The user argument is created on the server and contains a proposed user object with all the automatically generated fields".