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

How to authenticate SPA? More precisely how does the redirect works? #451

Closed
DaviTeodoro opened this Issue Mar 21, 2017 · 8 comments

Comments

Projects
None yet
5 participants
@DaviTeodoro
Copy link

DaviTeodoro commented Mar 21, 2017

Guys, I do not know if it's the right place to ask, but I can not get my head around this. I've been looking for some explanation around, but couldn't find any, so here it goes:

I have a SPA (vuejs) totally decoped from my rest-api (feathersjs) and I just using oauth0 feathers-authentication-oauth2 for authentication (google and facebook)
Currently my stream looks like:

+--------------------+               +----------------+
| JS Single Page App | - redirect -> | OAuth Provider | - user enters credentials
+--------------------+               +----------------+
+----------------+                                   +----------+
| OAuth Provider | - redirect with temporary code -> | REST API |
+----------------+                                   +----------+
+----------+                                      +----------------+
| REST API | - request access token using code -> | OAuth Provider |
+----------+ <- return access token ------------- +----------------+

What should I do now? My current understanding is that I should redirect the user upon receiving the access token to a page that will load the JS single page app again. It is that correct? If so, how do I do it? I cant understand how this process works. Thank you

@beanmoss

This comment has been minimized.

Copy link

beanmoss commented Mar 21, 2017

So your user provider is Auth0 and not Feathers?

@DaviTeodoro

This comment has been minimized.

Copy link
Author

DaviTeodoro commented Mar 21, 2017

I think I expressed myself wrong. I'm using feathers-authentication to generate the JTW. But I'm not using the local method, just google and facebook. With the local method I just need to send a post request to the correct endpoint and wait for a promisse holding the JWT, then I would store it in my SPA and use it in the subsequent requests.
My problem is with the google/facebook methods. Because in the client-side I have a link or a redirect to my authentication providers endpoint (ie. /auth/facebook), but I dont know how to send the JWT back to the SPA. It is not a big problem, I think, but it is my first time doing it, and I'm little confused.

@daffl

This comment has been minimized.

Copy link
Member

daffl commented Mar 21, 2017

What version are you using? Basically with oAuth what you have to do is enabled cookies, hit the auth endpoint, redirect back to your app and then call app.authenticate() (with no arguments) for auth to try to get the JWT from the cookie the oAuth flow has set for you.

@DaviTeodoro

This comment has been minimized.

Copy link
Author

DaviTeodoro commented Mar 21, 2017

Hello David , I'm using "feathers-authentication": "^1.1.1", "feathers-authentication-jwt": "^0.3.1" and "feathers-authentication-oauth2": "^0.2.3". I noticed that with version > 0.8.0 the redirection changed but can't figure out how to setup it correct.

@DaviTeodoro

This comment has been minimized.

Copy link
Author

DaviTeodoro commented Mar 21, 2017

OK, @marshall did help me to implement a custom handler that redirect JWT to the custom url in a different domain.
The handler:

const jwt = require('jsonwebtoken');

module.exports = function (options, jwtOptions) {
  const { secret } = options;
  if (!secret) {
    throw new Error(`You must provide a 'secret' attribute to the popups middleware options.`);
  }

  return function (req, res, next) {
    if (req.feathers && req.feathers.payload) {
      jwt.sign(req.feathers.payload, secret, jwtOptions, (err, token) => {
        if (err) {
          console.log(`Couldn't create JWT`, err);
        }
        // res.send(template);
        res.redirect(`${options.github.successRedirect}?token=${token}`);
      });
    }
  };
};

Now you have to use it in the authentication.js

'use strict';

const authentication = require('feathers-authentication');
const jwt = require('feathers-authentication-jwt');
const oauth2 = require('feathers-authentication-oauth2');
const GithubStrategy = require('passport-github');
const handlePopups = require('./popups-middleware');

module.exports = function () {
  const app = this;
  const config = app.get('authentication');
  const jwtConfig = app.get('jwt');

  config.github.Strategy = GithubStrategy;
  // Add the handler to the github auth config
  config.github.handler = handlePopups(config, jwtConfig);

  // Set up authentication with the secret
  app.configure(authentication(config));
  app.configure(jwt());
  app.configure(oauth2(config.github));

  app.service('authentication').hooks({
    before: {
      create: [
        authentication.hooks.authenticate(config.strategies)
      ],
      remove: [
        authentication.hooks.authenticate('jwt')
      ]
    }
  });
};

That is it.

@ekryski

This comment has been minimized.

Copy link
Member

ekryski commented Mar 22, 2017

@marshallswain you and I talked about putting the token in querystring by default when redirecting, did you have a PR planned for that?

@marshallswain

This comment has been minimized.

Copy link
Member

marshallswain commented Mar 22, 2017

@ekryski I was thinking of always using the query string, but I had a conversation with @daffl and he fixed my thinking. I'm focusing on another PR for auth right now, but I'll get to this after it. I'll see if I can set it up to redirect with a querystring any time we redirect to an external domain.

@marshallswain

This comment has been minimized.

Copy link
Member

marshallswain commented Apr 12, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.