Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for FastBoot authentication #100

Merged
merged 18 commits into from
Jun 29, 2019
Merged

Add support for FastBoot authentication #100

merged 18 commits into from
Jun 29, 2019

Conversation

mikkopaderes
Copy link
Owner

Resolves #99

@alexmasita
Copy link

@mikkopaderes. Clearly the works of masters! Have you merged this?

@mikkopaderes
Copy link
Owner Author

Still a work in progress (WIP). I still need to add the service worker part and test if things actually work.

@mikkopaderes
Copy link
Owner Author

Holding off this PR until this firebase/firebase-js-sdk#1906 gets resolved.

I'm unable to use any version lower than 6.2.2 in a Node environment as I'm getting not a function error for both firebase.firestore() and firebase.auth(). Not sure why.

@alexmasita
Copy link

@mikkopaderes Thanks for your efforts to resolve this. Let us see what happens with the firebase bug ...

@mikkopaderes mikkopaderes changed the title [WIP] Add support for FastBoot authentication Add support for FastBoot authentication Jun 27, 2019
@mikkopaderes mikkopaderes merged commit 2a28dcd into master Jun 29, 2019
@mikkopaderes mikkopaderes deleted the fastboot-auth branch June 29, 2019 04:41
@alexmasita
Copy link

alexmasita commented Jun 29, 2019

Thank you for your work on this. I see on the documentation you show how to set up the server side to authenticate in fastboot which is great. How though do you test this while in development as I assume when you ember serve, ember cli starts the 'hidden' fastboot server on your behalf?

I am using the following fastboot ready server here: Fastboot Server. And my server file created under the folder "fastboot/main.js" looks like this:

const FastBootAppServer = require('fastboot-app-server');
let server = new FastBootAppServer({
  distPath: 'dist',
  gzip: true
});

server.start();

An idea of how you would incorporate your server set up here and how you would run it in development would be great. Thanks.

@mikkopaderes
Copy link
Owner Author

@alexmasita

I don't use fastboot app server but from the look of things you'd insert that at the before middleware hook.

@alexmasita
Copy link

alexmasita commented Jun 30, 2019

@mikkopaderes Thank you for that. For the most part, I have everything set up. I am having trouble getting a valid token as seen from the following error:

[2019-06-30T21:35:35.372Z][w84297] starting HTTP server
[2019-06-30T21:35:35.382Z][w84297] HTTP server started; url=http://:::8000
Line 1: firebase verifyID Token get entered
Line 2: idToken:  Error: Your API key is invalid, please check you have copied it correctly.
Line 4: firebase Token error
{ Error: Decoding Firebase ID token failed. Make sure you passed the entire string JWT which represents an ID token. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.
    at FirebaseAuthError.FirebaseError [as constructor] (/Users/alexmasita/External/Personal/projects/Ember-Apps/3.10/ember310/node_modules/firebase-admin/lib/utils/error.js:42:28)
    at FirebaseAuthError.PrefixedFirebaseError [as constructor] (/Users/alexmasita/External/Personal/projects/Ember-Apps/3.10/ember310/node_modules/firebase-admin/lib/utils/error.js:88:28)
    at new FirebaseAuthError (/Users/alexmasita/External/Personal/projects/Ember-Apps/3.10/ember310/node_modules/firebase-admin/lib/utils/error.js:146:16)
    at FirebaseTokenVerifier.verifyJWT (/Users/alexmasita/External/Personal/projects/Ember-Apps/3.10/ember310/node_modules/firebase-admin/lib/auth/token-verifier.js:158:35)
    at Auth.BaseAuth.verifyIdToken (/Users/alexmasita/External/Personal/projects/Ember-Apps/3.10/ember310/node_modules/firebase-admin/lib/auth/auth.js:105:37)
    at app.get (/Users/alexmasita/External/Personal/projects/Ember-Apps/3.10/ember310/fastboot-main.js:18:45)
    at Layer.handle [as handle_request] (/Users/alexmasita/External/Personal/projects/Ember-Apps/3.10/ember310/node_modules/express/lib/router/layer.js:95:5)
    at next (/Users/alexmasita/External/Personal/projects/Ember-Apps/3.10/ember310/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/Users/alexmasita/External/Personal/projects/Ember-Apps/3.10/ember310/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/Users/alexmasita/External/Personal/projects/Ember-Apps/3.10/ember310/node_modules/express/lib/router/layer.js:95:5)
  errorInfo:
   { code: 'auth/argument-error',
     message:
      'Decoding Firebase ID token failed. Make sure you passed the entire string JWT which represents an ID token. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.' },
  codePrefix: 'auth' }

I got the error above from the beforeMiddleware hook as seen here below on Line 4 console log:

let server = new FastBootAppServer({
  beforeMiddleware: function (app) {
    app.get('/*', async (req, res, next) => {
      console.log('Line 1: firebase verifyID Token get entered');
      if (req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
        try {
          const idToken = req.headers.authorization.split('Bearer ')[1];
          console.log('Line 2: idToken: ', idToken);
          const auth = admin.auth();
          const decodedIdToken = await auth.verifyIdToken(idToken);
          const {
            uid
          } = decodedIdToken;
          const customToken = await auth.createCustomToken(uid);
          console.log('Line 3: firebase customToken: ', customToken);
          req.headers.authorization = `Bearer ${customToken}`;
        } catch (error) {
          console.log('Line 4: firebase Token error');
          console.log(error);
        }
      }

      next();
    });
  },
  distPath: 'dist',
  gzip: true
});

I looked at your repo dummy app to see if I had missed anything but could not see anything that could help me resolve my issue.
So I tried to drill for the issue and found my way into this addon's service worker file and put some console.log calls inside getIdToken() method as seen here:

function getIdToken() {
  console.log('Line 1 - Service Worker getIdToken Method Called');

  return new Promise((resolve) => {
    console.log('Line 2 - Service Worker getIdToken Promise Returned');
    const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
      unsubscribe();
      console.log('Line 3 - Service Worker onAuthStateChanged Callback Called', idToken);
      console.log('Line 4 - Service Worker User Object');
      console.log(user);
      if (user) {
        user.getIdToken().then(idToken => {
          console.log('Line 5 - Service Worker user.getIdToken Promise Returned', idToken);
          resolve(idToken);
        }).catch(() => resolve(null));
      } else {
        resolve(null);
      }
    });
  });
};

I found that as seen on this screenshot: Browser Console Snapshot, only line 1 and line 2 are logged to the console meaning that the user.getIdToken() never actually gets called on my end.

I created a completely fresh repo for this test which you can even pull, run and see for yourself if you have time: Firebase Authentication Sample Repo.

Thank you for all your time on this.

@mikkopaderes
Copy link
Owner Author

Line 2: idToken: Error: Your API key is invalid, please check you have copied it correctly.

Basing on the code snippet above, this doesn't look right. It should display the token, not some string message. What is the value of request.headers.authorization?

Your test repo is also 404.

@alexmasita
Copy link

alexmasita commented Jul 1, 2019

I have added a log call Line 1.1 as seen here:

let server = new FastBootAppServer({
  beforeMiddleware: function (app) {
    app.get('/*', async (req, res, next) => {
      console.log('Line 1: firebase verifyID Token get entered');
      console.log('Line 1.1: firebase req.headers.authorization');
      console.log(req.headers.authorization);
      if (req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
        try {
          const idToken = req.headers.authorization.split('Bearer ')[1];
          console.log('Line 2: idToken: ', idToken);
          const auth = admin.auth();
          const decodedIdToken = await auth.verifyIdToken(idToken);
          const {
            uid
          } = decodedIdToken;
          const customToken = await auth.createCustomToken(uid);
          console.log('Line 3: firebase customToken: ', customToken);
          req.headers.authorization = `Bearer ${customToken}`;
        } catch (error) {
          console.log('Line 4: firebase Token error');
          console.log(error);
        }
      }

      next();
    });
  },
  distPath: 'dist',
  gzip: true
});

The result of this: console.log(req.headers.authorization); is undefined.

I have made the Firebase Authentication Sample Repo public. Sorry for the oversight.

@mikkopaderes
Copy link
Owner Author

I won't be able to check on this yet. But quickly looking at things, I don't see Firebase as a devDependency to your ember app.

Can you try adding it?

@alexmasita
Copy link

Yes! What a somewhat obvious omission that was?! Done it and still the same issue here though.

@mikkopaderes
Copy link
Owner Author

Thanks for the report. See #101 for the fix.

@alexmasita
Copy link

Great. I can confirm the issue is resolved from my end. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support FastBoot authentication
2 participants