CodetrixStudio / CapacitorGoogleAuth

Capacitor plugin for Google Auth. Lightweight & no dependencies.
MIT License
283 stars 156 forks source link

iOS Ionic Angular - Running GoogleAuth.refresh() returns "user not logged in" #241

Open ucjallen opened 1 year ago

ucjallen commented 1 year ago

I am encountering an issue with refreshing my tokens.

I am able to do Google.signIn() and get a good response and invoke my lambda function using AWS IAM permissions and pass along the idToken.

If I do a refresh here, it works correctly.

The problem is, if I close my app or the access token expires after an hour (as it should), I am unable to refresh it.

I run GoogleAuth.refresh() and I get back errorMessage: "User not logged in.", message: "User not logged in."

Running GoogleAuth.signIn() again prompts the user to sign in again, which is not ideal.

I run this in my app.component.ts

GoogleAuth.initialize({
  clientId: 'XXXXXXXXX-XXXXXXXXXXXXXXXXX.apps.googleusercontent.com',
  scopes: ['profile', 'email'],
  grantOfflineAccess: true
});

My versions and deps:

"@angular/cdk": "^14.2.7",
"@angular/common": "^14.2.10",
"@angular/core": "^14.2.10",
"@codetrix-studio/capacitor-google-auth": "^3.2.0",
"@ionic-native/core": "^5.36.0",
"@ionic/angular": "^6.1.4",

What am I missing? Do I need to load the accessToken and refreshToken back into GoogleAuth after a restart?

ucjallen commented 1 year ago

Your documentation is total dog shit. I should not have to pioneer my own way through an established plugin thats been around this long. Absolutely awful

If you find this and you are trying to (Auto Login) refresh your token after a successful sign in but after the token has expired or the app has been closed (BASIC FUNCTIONALITY GUYS). Here is how:

Ensure this line is in both your GoogleAuth.initialize() params as well as your capacitor.config.json

"grantOfflineAccess": true

Don't ask me why it has to be in both, it may not need to be, but I'm so tired of this I don't even care anymore, it worked like this, so whatever.

Next, once you have logged in, your session is active. Close your app, or wait an hour, and GoogleAuth has no idea who you are, "user is not signed in", but wait, yes I am, I was just signed in 2 minutes ago (in the event you closed the app). Apparently someone added code to boot you out if no previous session, well GoogleAuth doesn't appear to manage your state between app closes, so there is never a session, huh, weird (hate you).

Also, there is no way at all to pass in your existing access and refresh tokens (stored yourself) to rebuild the instance, why would there be, that would be too easy.

Next, you will want to attempt a refresh (in my case, cognito still has me authed, but my access token is expired so I can't access my API, I need to refresh the token). Here's a simple example in Angular with a try catch:

async refreshGoogleToken() {

  try {

    const authCode = await GoogleAuth.refresh();
    console.log(authCode);

  } catch(err) {

    console.log(err);     // user is not signed in

    var user = await GoogleAuth.signIn();

    console.log(user);    // wowie look, there it is

  }

}

You will want to catch the error and probably determine if it is a user not signed in (Hint: I store the refresh and access tokens using Capacitor Preferences during the first GoogleAuth.signIn(), if they are present, I assume you are a google sign in and you just hit this lovely error or whatever the hell this is)

Then you will want to call GoogleAuth.signIn() again, yes, again.

Now here's the important part: DO NOT USE THIS forceCodeForRefreshToken: true

It was in tons of docs and examples, it basically forces the pop up window every time and makes the user select their email. If thats what you want, good, but I don't want to keep asking my users, so don't include.

The popup window will still occur on first sign in, but on the subsequent calls you make when the token refresh fails, it will not ask the user, it will just refresh and return the new creds.

Now, at this point, you should have a refreshed session and can make your API requests.

If anyone has any input on this, feel free to add, but based on the activity of this repo, this is as good as its gonna get.

alexcroox commented 8 months ago

does this plugin store the auth tokens somewhere itself then? It must do in order to be able to refresh right?