I have an ionic3 application using angularfire2 and firebase. I use firbase auth to login to my application, and for retrieving an object from firebase about "currentChallenges". When I use the logout function an error is thrown from Firebase.
Error message:
permission_denied at /currentChallenge: Client doesn't have permission
to access the desired data.
I use the following function for my logout, in my auth.service.ts:
logout() {
this.isLoggedIn = false;
this.firebaseAuth
.auth
.signOut().then(() => {
this.appCtrl.getRootNav().popToRoot(); //root is login page
});
}
I am not sure where/what exactly is causing the error. In my challenges.service.ts is where I make the initial observable object:
private dbCurrentChallengesObservable: FirebaseObjectObservable <any>;
constructor(db: AngularFireDatabase) {
this.dbCurrentChallengesObservable = db.object('/currentChallenge');
}
public getCurrentChallenges(){
return this.dbCurrentChallengesObservable;
}
And then, I use this object in my model (challenges.ts) like this:
ionViewCanEnter(): boolean{
return this.authService.isAuthenticated();
}
ionViewDidLoad() {
this.currentChallenge = this.challengesService.getCurrentChallenges();
this.currentChallenge.subscribe(data => {
if(data.challenge1completed > 0) this.challenge1Completed = true;
if(data.challenge2completed > 0) this.challenge2Completed = true;
});
}
At first I thought it was related to the subscribe and I added an subscribe().unsubscribe() in an on-ion-leave function in the challenges.ts, but that did not stop the error. But something must still be listening to firebase, which must be stopped upon or even before logout. I just don't know what/where/how.
Any help would be appreciated.
private afDatabase: AngularFireDatabase,//blabla
this.afDatabase.database.goOffline();//To solve the permission denied 문제.
add above statement before signout();
I too took a lot of time on this problem and not a single clue found.
Hope this helps
Related
I'm using firebase anonymous authantication for my unity project.
As i always did when project is started i'm sending request to firebase for authantication,
but on my last project (which uses firebase sdk 6.16.0) my request creates new user everytime.
Here is some code about how i'm sending my request
Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.SignInAnonymouslyAsync().ContinueWith((task =>
{
if (task.IsCanceled)
{
Debug.Log("task cancelled");
return;
}
if (task.IsFaulted)
{
Debug.Log("task cancelled");
return;
}
if (task.IsCompleted)
{
Firebase.Auth.FirebaseUser userr = task.Result;
firebaseUserId = userr.UserId;
Debug.Log("firebaseUserId");
Debug.Log(firebaseUserId);
//every opening returns new uniq id here.
}
}));
On firebase authantication panel i only activated anonymous login. any suggestions?
Or is there any way to downgrade unity firebase version? i've tried to import old version which i was using on my last game (sdk 6.15.2) but there is some errors on resolver.
Basically, every time you call SignInAnonymouslyAsync you'll create a new user and the last one will be basically lost (it's more or less a random hash - anonymous as it's name suggests).
I'll typically do something like:
using System;
using Firebase.Auth;
using UnityEngine;
using UnityEngine.Events;
public class Login : MonoBehaviour
{
public UnityEvent OnSignInFailed = new UnityEvent();
public UserSignedInEvent OnUserSignedIn = new UserSignedInEvent();
public async void TriggerLogin()
{
var auth = FirebaseAuth.DefaultInstance;
var user = auth.CurrentUser;
if (user == null)
{
try
{
user = await auth.SignInAnonymouslyAsync();
}
catch (Exception e)
{
Debug.LogException(e);
OnSignInFailed.Invoke();
return;
}
}
// user definitely should not be null!
if (user == null)
{
OnSignInFailed.Invoke();
Debug.LogWarning("User still null!?");
return;
}
var userName = user.UserId;
OnUserSignedIn.Invoke(userName);
Debug.Log($"Logged in as {userName}");
}
[Serializable]
public class UserSignedInEvent : UnityEvent<string>
{
}
}
Note that for this code snippet, TriggerLogin is a public method so I can chain it off of a UnityEvent in the Unity editor.
Try and Put it some kind of check to find if used is already logged in. If yes, then do a silent login, if no then use anonymous login.
Currently you are straightaway logging in user even if they logged in last time they opened the Application.
Try this link: https://github.com/firebase/quickstart-unity/issues/266#issuecomment-447981995
I am accessing my backend with an access token obtained from firebase auth the following way:
login via email & password
receive the current user object
obtain the token from the user object
store the token locally to allow furher access to my backend (which uses firebase admin to validate the token)
This works, as long as the access token is stale.
This may as well work, if the application remains open and an 403 due to an expired token can be catched (I can just reuse the current user object to obtain a new token). However, if the token expires while the app is closed, opening it again (no more user object) results in forcing the user to reenter its credentials, does it?
One way that came to my mind was using the custom tokens functionality:
I could send the refresh token to the client after a login, which then stores it and would use it to log in (in an automatic manner) instead of using the credentials.
But the word "custom" made me think that I am on the wrong way somehow. There surely must be an easy way to do this with the intended functions.
Can any one help me out with this?
Greetings,
Codehai
Using this listener refreshes the token automatically, won't work in editor.
For my code to work, somehow I have to add TaskScheduler.FromCurrentSynchronizationContext() on all Firebase Tasks..
void Start()
{
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.IdTokenChanged += IdTokenChanged;
}
void IdTokenChanged(object sender, System.EventArgs eventArgs)
{
Firebase.Auth.FirebaseAuth senderAuth = sender as Firebase.Auth.FirebaseAuth;
if (senderAuth == auth && senderAuth.CurrentUser != null && !fetchingToken)
{
fetchingToken = true;
senderAuth.CurrentUser.TokenAsync(true).ContinueWith(
task =>
{
if (task.IsCanceled)
{
Debug.Log("canceled");
}
if (task.IsFaulted)
{
foreach (var errors in task.Exception.InnerExceptions)
{
Debug.Log(errors.InnerException.Message);
}
}
Debug.Log("New Token: " + task.Result);
// save task.Result
fetchingToken = false;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
private void OnDestroy()
{
auth.IdTokenChanged -= IdTokenChanged;
}
In my Angular/Firebase app, I have a user service which supports sign-in and sign-out. After sign-in, I retrieve app-specific data for the user from my Angular database. The service publishes an observable called appUser$ which contains the current user object (or null, if no-one is signed in). Things look like this. I'm using switchMap to switch between different observables for my app's user data as users sign in and sign out.
constructor(
private angularFireAuth: AngularFireAuth,
private angularFireDatabase: AngularFireDatabase
) {
this.appUser$ = this.angularFireAuth.authState
.map(user => user && user.uid)
.switchMap(uid => uid ? this.angularFireDatabase.object(`/users/${uid}`) :
Observable.of(null);
}
signOut() { return this.angularFireAuth.auth.signOut(); }
The problem with this is that the instant sign-out occurs, the permissions for accessing the /users node in the database are lost, generating an permission denied run-time error. To deal with this, I tried creating my own Subject for Angular User and zero it out before calling signOut. I thought that this would trigger the switchMap and somehow cancel the pending object observable for the previous user's app data, thereby preventing the permission denied error.
user$: Subject;
constructor(
private angularFireAuth: AngularFireAuth,
private angularFireDatabase: AngularFireDatabase
) {
this.angularFireAuth.authState.subscribe(this.user$);
this.appUuser$ = this.user$
.map(user => user || user.uid)
.switchMap(uid => uid ? this.angularFireDatabase.object(`/users/${uid}`) :
Observable.of(null);
}
signOut() {
this.user$.next(null);
return this.angularFireAuth.auth.signOut();
}
But the same permission problem persists, even if I delay the call to signOut. It seems as if somehow the observable created by this.angularFireDatabase.object is somehow still "alive" even after the switchMap should have switched to the Observable.of(null), and Firebase is still unhappy about losing permissions to access it.
I could trap or suppress this error somehow, but is there some simple way to deal with this situation?
I'm trying to add an accountActive and accountExpirationDate to a user's profile when it is created. According to everything I've read, I should use Accounts.onCreateUser like so:
// Add accountActive and accountExpirationDate
Accounts.onCreateUser(function(options, user) {
if (options.profile) {
user.profile = options.profile;
user.profile.accountActive = false;
user.profile.accountExpirationDate = null;
}
return user;
});
The two fields are not being added and I'm receiving this error in Console.
Uncaught TypeError: Object #<Object> has no method 'onCreateUser'
What am I doing wrong?
The problem is that the Accounts.onCreateUser was running in the client folder. It cannot operate in the client, only on the server.
I am working on a project that retrieve Google Drive docs list using ASP.NET, but I'm getting an error:
An error occurred: Google.Apis.Requests.RequestError Daily Limit for
Unauthenticated Use Exceeded. Continued use requires signup. [403]
This is my site (getting error on this link) : http://www.netdesklive.com/
I am trying DrEdit code for this, but not working proper.
I set all the credential as per https://developers.google.com/drive/examples/dotnet but still i m getting an error
So Please, Suggest me
Code :
-> I am getting null value in state and code
public ActionResult Index(string state, string code)
{
try
{
IAuthenticator authenticator = Utils.GetCredentials(code, state);
// Store the authenticator and the authorized service in session
Session["authenticator"] = authenticator;
Session["service"] = Utils.BuildService(authenticator);
}
catch (CodeExchangeException)
{
if (Session["service"] == null || Session["authenticator"] == null)
{
Response.Redirect(Utils.GetAuthorizationUrl("", state));
}
}
catch (NoRefreshTokenException e)
{
Response.Redirect(e.AuthorizationUrl);
}
DriveState driveState = new DriveState();
if (!string.IsNullOrEmpty(state))
{
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
driveState = jsonSerializer.Deserialize<DriveState>(state);
}
if (driveState.action == "open")
{
return OpenWith(driveState);
}
else
{
return CreateNew(driveState);
}
}
Your error message suggests that your requests are not authorized. You should authorize them using Oauth2 :
Authorizing Drive requests
Google Oauth2 documentation